| PUFFS_FRAMEBUF(3) | Library Functions Manual | PUFFS_FRAMEBUF(3) | 
puffs_framebuf —
#include <puffs.h>
struct puffs_framebuf *
  
  puffs_framebuf_make();
void
  
  puffs_framebuf_destroy(struct
    puffs_framebuf *pufbuf);
void
  
  puffs_framebuf_recycle(struct
    puffs_framebuf *pufbuf);
int
  
  puffs_framebuf_reserve_space(struct
    puffs_framebuf *pufbuf,
    size_t space);
int
  
  puffs_framebuf_putdata(struct
    puffs_framebuf *pufbuf, const void *data,
    size_t dlen);
int
  
  puffs_framebuf_putdata_atoff(struct
    puffs_framebuf *pufbuf, size_t offset,
    const void *data, size_t
  dlen);
int
  
  puffs_framebuf_getdata(struct
    puffs_framebuf *pufbuf, void *data,
    size_t dlen);
int
  
  puffs_framebuf_getdata_atoff(struct
    puffs_framebuf *pufbuf, size_t offset,
    void *data, size_t dlen);
size_t
  
  puffs_framebuf_telloff(struct
    puffs_framebuf *pufbuf);
size_t
  
  puffs_framebuf_tellsize(struct
    puffs_framebuf *pufbuf);
size_t
  
  puffs_framebuf_remaining(struct
    puffs_framebuf *pufbuf);
int
  
  puffs_framebuf_seekset(struct
    puffs_framebuf *pufbuf,
    size_t offset);
int
  
  puffs_framebuf_getwindow(struct
    puffs_framebuf *pufbuf, size_t offset,
    void **winp, size_t
  *winlen);
int
  
  puffs_framev_enqueue_cc(struct
    puffs_cc *pcc, int fd, struct
    puffs_framebuf *pufbuf, int flags);
void
  
  puffs_framev_cb(struct puffs_usermount
    *pu, int fd, struct
    puffs_framebuf *pufbuf, void *arg,
    int flags, int error);
void
  
  puffs_framev_enqueue_cb(struct
    puffs_usermount *pu, int fd,
    struct puffs_framebuf *pufbuf,
    puffs_framebuf_cb fcb, void
    *fcb_arg, int flags);
void
  
  puffs_framev_enqueue_justsend(struct
    puffs_usermount *pu, int fd,
    struct puffs_framebuf *pufbuf, int
    waitreply, int flags);
void
  
  puffs_framev_enqueue_directsend(struct
    puffs_usermount *pu, int fd,
    struct puffs_framebuf *pufbuf, int
    flags);
void
  
  puffs_framev_enqueue_directreceive(struct
    puffs_usermount *pu, int fd,
    struct puffs_framebuf *pufbuf, int
    flags);
int
  
  puffs_framev_framebuf_ccpromote(struct
    puffs_framebuf *pufbuf, struct puffs_cc
  *pcc);
int
  
  puffs_framev_enqueue_waitevent(struct
    puffs_cc *pcc, int
    fd, int *what);
int
  
  puffs_framev_readframe_fn(struct
    puffs_usermount *pu, struct puffs_framebuf
    *pufbuf, int fd, int
    *done);
int
  
  puffs_framev_writeframe_fn(struct
    puffs_usermount *pu, struct puffs_framebuf
    *pufbuf, int fd, int
    *done);
int
  
  puffs_framev_cmpframe_fn(struct
    puffs_usermount *pu, struct puffs_framebuf
    *cmp1, struct puffs_framebuf *cmp2,
    int *notresp);
void
  
  puffs_framev_gotframe_fn(struct
    puffs_usermount *pu, struct puffs_framebuf
    *pufbuf);
void
  
  puffs_framev_fdnotify_fn(struct
    puffs_usermount *pu, int fd, int
    what);
void
  
  puffs_framev_init(struct
    puffs_usermount *pu, puffs_framev_readframe_fn
    rfb, puffs_framev_writeframe_fn wfb,
    puffs_framev_cmpframe_fn cmpfb,
    puffs_framev_gotframe_fn gotfb,
    puffs_framev_fdnotify_fn fdnotfn);
int
  
  puffs_framev_addfd(struct
    puffs_usermount *pu, int
    fd, int what);
int
  
  puffs_framev_enablefd(struct
    puffs_usermount *pu, int
    fd, int what);
int
  
  puffs_framev_disablefd(struct
    puffs_usermount *pu, int
    fd, int what);
int
  
  puffs_framev_removefd(struct
    puffs_usermount *pu, int
    fd, int error);
void
  
  puffs_framev_unmountonclose(struct
    puffs_usermount *pu, int fd, int
    what);
puffs_framebuf routines provide buffering and an
  event loop structured around the buffers. It operates on top of the puffs
  continuation framework,
  puffs_cc(3), and multiplexes
  execution automatically to an instance whenever one is runnable.
The file system is entered in three different ways:
puffs_framebuf is used by defining various
    callbacks and providing I/O descriptors, which are then monitored for
    activity by the library. A descriptor, when present, can be either enabled
    or disabled for input and output. If a descriptor is not enabled for a
    certain direction, the callbacks will not be called even if there were
    activity on the descriptor. For example, even if a network socket has been
    added and there is input data in the socket buffer, the read callback will
    be called only if the socket has been enabled for reading.
File descriptors are treated like sockets: they have two sides, a read side and a write side. The framework determines that one side of the descriptor has been closed if the supplied I/O callbacks return an error or if the I/O multiplexing call says a side has been closed. It is still possible, from the framework perspective, to write to a file descriptor whose read side is closed. However, it is not possible to wait for a response on such a file descriptor. Conversely, it is possible to read responses from a descriptor whose write side is closed. It should be stressed that the implementation underlying the file descriptor might not support this.
The following callbacks can be defined, cf.
    puffs_framev_init(), and all are optional. None of
    them should block, because this would cause the entire file server to block.
    One option is to make the descriptors non-blocking before adding them.
Better descriptions for each callback are given below.
The buffers of puffs_framebuf provide
    automatic memory management of buffers for the file servers. They provide a
    cursor to the current buffer offset. Reading or writing data through the
    normal routines will advance that cursor. Additionally, the buffer size is
    provided to the user. It represents the maximum offset where data was
    written.
Generally the write functions will fail if the cannot allocate enough memory to satisfy the buffer length requirements. Read functions will fail if the amount of data written to the buffer is not large enough to satisfy the read.
puffs_framebuf_make()NULL in case no memory was available.puffs_framebuf_destroy(pufbuf)puffs_framebuf_recycle(pufbuf)puffs_framebuf_reserve_space(pufbuf,
    space)puffs_framebuf_putdata(pufbuf,
    data, dlen)puffs_framebuf_putdata_atoff(pufbuf,
    offset, data,
    dlen)puffs_framebuf_putdata(), except writes data
      at buffer offset offset. It is legal to write past
      the current end of the buffer. Does NOT modify the current offset
    cursor.puffs_framebuf_getdata(pufbuf,
    data, dlen)puffs_framebuf_getdata_atoff(pufbuf,
    offset, data,
    dlen)puffs_framebuf_telloff(pufbuf)puffs_framebuf_tellsize(pufbuf)puffs_framebuf_remaining(pufbuf)puffs_framebuf_seekset(pufbuf,
    offset)puffs_framebuf_getwindow(pufbuf,
    offset, winp,
    winlen)puffs_framebuf() call operating on
      the buffer in question.puffs_framev_enqueue_cc(pcc,
    fd, pufbuf,
    flags)Usually the buffer is placed at the end of the output queue.
        However, if flags contains
        PUFFS_FBQUEUE_URGENT,
        pufbuf is placed in the front of the queue to be
        sent immediately after the current PDU (if any) has been sent.
puffs_framev_enqueue_cb(pu,
    fd, pufbuf,
    fcb, fcb_arg,
    flags)fcb() will be called with the argument
      fcb_arg. The callback function
      fcb() is responsible for freeing the buffer.
      Returns 0 if the buffer was successfully enqueued (not necessarily
      delivered) and non-zero to signal a non-recoverable error.
    See puffs_framev_enqueue_cc() for
        flags.
puffs_framev_cb(pu,
    pufbuf, arg,
    error)puffs_framev_enqueue_justsend(pu,
    fd, pufbuf,
    waitreply, flags)See puffs_framev_enqueue_cc() for
        flags.
puffs_framev_enqueue_directsend(pcc,
    fd, pufbuf,
    flags)puffs_framev_enqueue_justsend() with the
      exception that the call yields until the frame has been sent. As opposed
      to puffs_framev_enqueue_cc(), the routine does not
      wait for input, but returns immediately after sending the frame.
    See puffs_framev_enqueue_cc() for
        flags.
puffs_framev_enqueue_directreceive(pcc,
    fd, pufbuf,
    flags)See puffs_framev_enqueue_cc() for
        flags.
puffs_framev_framebuf_ccpromote(pufbuf,
    pcc)puffs_framev_enqueue_cb() or
      puffs_framev_enqueue_justsend() to a wait using
      pcc and yield until the result arrives. The response
      from the file server for pufbuf must not yet have
      arrived. If sent with
      puffs_framev_enqueue_justsend(), the call must be
      expecting a response.puffs_framev_enqueue_waitevent(pcc,
    fd, what)PUFFS_FBIO_READ,
      PUFFS_FBIO_WRITE, and
      PUFFS_FBIO_ERROR, specifying read, write and error
      conditions, respectively. Error is always checked.
    This call does not depend on if the events were previously enabled on the file descriptor - the specified events are always checked regardless.
There is currently no other way to cancel or timeout a call except by removing the file descriptor in question. This may change in the future.
puffs_framev_readframe_fn(pu,
    pufbuf, fd,
    done)errno to signal a fatal error. In case a fatal
      error is returned, the read side of the file descriptor is marked closed.
      This routine will be called with the same buffer argument until a complete
      frame has been read. May not block.puffs_framev_writeframe_fn(pu,
    pufbuf, fd,
    done)errno to signal a fatal
      error. In case a fatal error is returned, the write side of the file
      descriptor is marked closed. This routine will be called with the same
      buffer argument until the complete frame has been written. May not block.
    It is a good idea to make sure that this function can handle a
        possible SIGPIPE caused by a closed connection.
        For example, the file server can opt to trap
        SIGPIPE or, if writing to a socket, call
        send() with the flag
        MSG_NOSIGNAL instead of using
        write().
puffs_framev_cmpframe_fn(pu,
    pufbuf_cmp1, pufbuf_cmp2,
    notresp)puffs_framebuf to skip the test of the buffer
      against the rest of the outstanding request. May not block.puffs_framev_gotframe_fn(pu,
    pufbuf)puffs_framev_fdnotify_fn(pu,
    fd, what)PUFFS_FBIO_READ and
      PUFFS_FBIO_WRITE for read and write,
    respectively.puffs_framev_init(pu,
    rfb, wfb,
    cmpfb, gotfb,
    fdnotfn)puffs_mainloop() is called. The framework provides
      the routines puffs_framev_removeonclose() and
      puffs_framev_unmountonclose(), which can be given
      as fdnotfn. The first one removes the file
      descriptor once both sides are closed while the second one unmounts the
      file system and exits the mainloop.puffs_framev_addfd(pu,
    fd, what)puffs_mainloop() or at time when running. The
      parameter what controls enabling of input and output
      events and can be a bitwise combination of
      PUFFS_FBIO_READ and
      PUFFS_FBIO_WRITE. If not specified, the descriptor
      will be in a disabled state.puffs_framev_enablefd(pu,
    fd, what)puffs_framev_disablefd(pu,
    fd, what)puffs_framev_removefd(pu,
    fd, error)ECONNRESET is used.
    The file system must explicitly remove each
        fd it has added. A good place to do this is
        puffs_framev_fdnotify_fn() or
        puffs_node_reclaim(), depending a little on the
        structure of the file system.
puffs_framev_unmountonclose(pu,
    fd, what)puffs_framev_fdnotify_fn(). It unmounts the file
      system when both the read and write side are closed. It is useful for file
      systems such as
      mount_psshfs(8) which
      depend on a single connection.errno to indicate the type of error.
puffs_framebuf in the tree are
  mount_psshfs(8) and
  mount_9p(8). See
  src/usr.sbin/puffs/mount_psshfs and
  src/usr.sbin/puffs/mount_9p for the respective usage
  examples.
Antti Kantee, Using puffs for Implementing Client-Server Distributed File Systems, Helsinki University of Technology, Tech Report TKK-TKO-B157, September 2007.
Antti Kantee, Send and Receive of File System Protocols: Userspace Approach With puffs, Proceedings of AsiaBSDCon 2008, pp. 55-70, March 2008.
| September 6, 2008 | NetBSD 10.0 |