.\" $NetBSD: puffs_framebuf.3,v 1.7 2007/05/20 16:24:37 pooka Exp $ .\" .\" Copyright (c) 2007 Antti Kantee. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .Dd May 16, 2007 .Dt PUFFS_FRAMEBUF 3 .Os .Sh NAME .Nm puffs_framebuf .Nd buffering and event handling for networked file systems .Sh LIBRARY .Lb libpuffs .Sh SYNOPSIS .In puffs.h .Ft struct puffs_framebuf * .Fn puffs_framebuf_make .Ft void .Fn puffs_framebuf_destroy "struct puffs_framebuf *pufbuf" .Ft void .Fn puffs_framebuf_recycle "struct puffs_framebuf *pufbuf" .Ft int .Fn puffs_framebuf_reserve_space "struct puffs_framebuf *pufbuf" "size_t space" .Ft int .Fo puffs_framebuf_putdata .Fa "struct puffs_framebuf *pufbuf" "const void *data" "size_t dlen" .Fc .Ft int .Fo puffs_framebuf_putdata_atoff .Fa "struct puffs_framebuf *pufbuf" "size_t offset" "const void *data" .Fa "size_t dlen" .Fc .Ft int .Fo puffs_framebuf_getdata .Fa "struct puffs_framebuf *pufbuf" "void *data" "size_t dlen" .Fc .Ft int .Fo puffs_framebuf_getdata_atoff .Fa "struct puffs_framebuf *pufbuf" "size_t offset" .Fa "void *data" "size_t dlen" .Fc .Ft size_t .Fn puffs_framebuf_telloff "struct puffs_framebuf *pufbuf" .Ft size_t .Fn puffs_framebuf_tellsize "struct puffs_framebuf *pufbuf" .Ft size_t .Fn puffs_framebuf_remaining "struct puffs_framebuf *pufbuf" .Ft int .Fn puffs_framebuf_seekset "struct puffs_framebuf *pufbuf" "size_t offset" .Ft int .Fo puffs_framebuf_getwindow .Fa "struct puffs_framebuf *pufbuf" "size_t offset" .Fa "void **winp" "size_t *winlen" .Fc .Ft int .Fo puffs_framev_enqueue_cc .Fa "struct puffs_cc *pcc" "struct puffs_framebuf *pufbuf" .Fc .Ft void .Fo puffs_framev_cb .Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" "void *arg" .Fa "int error" .Fc .Ft void .Fo puffs_framev_enqueue_cb .Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" .Fa "puffs_framebuf_cb fcb" "void *fcb_arg" .Fc .Ft void .Fo puffs_framev_enqueue_justsend .Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" "int waitreply" .Fc .Ft int .Fo puffs_framev_readframe_fn .Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" .Fa "int fd" "int *done" .Fc .Ft int .Fo puffs_framev_writeframe_fn .Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" .Fa "int fd" "int *done" .Fc .Ft int .Fo puffs_framev_cmpframe_fn .Fa "struct puffs_usermount *pu" .Fa "struct puffs_framebuf *cmp1" "struct puffs_framebuf *cmp2" .Fc .Ft int .Fo puffs_framev_fdnotify_fn .Fa "struct puffs_usermount *pu" "int fd" "int what" .Fc .Ft int .Fo puffs_framev_init .Fa "struct puffs_usermount *pu" .Fa "puffs_framebuf_readframe_fn rfb" "puffs_framebuf_writeframe_fn wfb" .Fa "puffs_framebuf_cmpframe_fn cmpfb" .Fa "puffs_framebuf_fdnotify_fn fdnotfn" .Fc .Ft int .Fn puffs_framev_addfd "struct puffs_usermount *pu" "int fd" .Ft int .Fn puffs_framev_removefd "struct puffs_usermount *pu" "int fd" "int error" .Ft void .Fo puffs_framev_unmountonclose .Fa "struct puffs_usermount *pu" "int fd" "int what" .Fc .Sh DESCRIPTION .Em IMPORTANT NOTE! This document describes interfaces which are not yet guaranteed to be stable. In case you update your system sources, please recompile everything and fix complation errors. If your sources are out-of-sync, incorrect operation may result. .Pp The .Nm routines provide buffering and an event loop structured around the buffers. It operates on top of the puffs continuation framework, .Xr puffs_cc 3 , and multiplexes execution automatically to an instance whenever one is runnable. Currently only request-response type "client pull" protocols are supported, but support for protocols which also feature "server push" type messaging may be added at a later date. .Pp The file system is entered in two different ways: .Bl -bullet -offset indent .It An event arrives from the kernel and the .Xr puffs_ops 3 callbacks are called to start processing the event. .It A file system which has sent out a request receives a response. Execution is resumed from the place where the file system yielded. .El .Pp For a file server to use .Nm , it must implemented three different routines: .Bl -tag -width "xcmpfbx" .It rfb Read a frame onto the specified buffer. .It wfb Write a frame from the specified buffer. .It cmpfb Identify if a buffer is the response to the specified buffer. .El .Pp Additionally, a fourth optional one called .Fn fdnotfn may be specified. It is used as a notify callback from the event loop to the file server when the event loop detects that the write or read side of the file descriptor has been closed. See .Fn puffs_framev_fdnotify_fn for more information. .Pp 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 close 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. .Pp The buffers of .Nm 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. .Pp 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. .Bl -tag -width xxxx .It Fn puffs_framebuf_make Create a buffer. Return the address of the buffer or .Dv NULL in case no memory was available. .It Fn puffs_framebuf_destroy pufbuf Free memory used by buffer. .It Fn puffs_framebuf_recycle pufbuf Reset offsets so that buffer can be reused. Does not free memory or reallocate memory. .It Fn puffs_framebuf_reserver_space pufbuf space Make sure that the buffer has .Ar space bytes of available memory starting from the current offset. This is not strictly necessary, but can be used for optimizations where it is known in advance how much memory will be required. .It Fn puffs_framebuf_putdata pufbuf data dlen Write .Ar dlen amount of data from the address .Ar data into the buffer. Moves the offset cursor forward .Ar dlen bytes. .It Fn puffs_framebuf_putdata_atoff pufbuf offset data dlen Like .Fn puffs_framebuf_putdata , except writes data at buffer offset .Ar offset . It is legal to write past the current end of the buffer. Does NOT modify the current offset cursor. .It Fn puffs_framebuf_getdata pufbuf data dlen Read .Ar dlen bytes of data from the buffer into .Ar data . Advances the offset cursor. .It Fn puffs_framebuf_getdata_atoff pufbuf offset data dlen Read data from buffer position .Ar offset . Does NOT modify the offset cursor. .It Fn puffs_framebuf_telloff pufbuf Return the offset into the buffer. .It Fn puffs_framebuf_tellsize pufbuf Return the maximum offset where data has been written, i.e. buffer size. .It Fn puffs_framebuf_remaining pufbuf Distance from current offset to the end of the buffer, i.e. size-offset. .It Fn puffs_framebuf_seekset pufbuf offset Set the offset cursor to the position .Ar offset . This does NOT modify the buffer size, but reserves at least enough memory memory for a write to .Ar offset and will fail if memory cannot be allocated. .It Fn puffs_framebuf_getwindow pufbuf offset winp winlen Get a direct memory window into the buffer starting from .Ar offset . The maximum mapped window size will be .Ar winlen bytes, but this routine might return a smaller window and the caller should always check the actual mapped size after the call. The window is returned in .Ar winp . This function not modify the buffer offset, but it DOES set the buffer size to .Ar offset + .Ar winlen in case that value is greater than the current size. The window is valid until the next until the next .Fn puffs_framebuf call operating on the buffer in question. .It Fn puffs_framev_enqueue_cc pcc pufbuf Add the buffer .Ar pufbuf to outgoing queue and yield with the continuation .Ar pcc . Execution is resumed once a response is received. Returns 0 if the buffer was succesfully enqueued (not necessarily delivered) and non-zero to signal a non-recoverable error. .It Fn puffs_framev_cb pu pufbuf arg error Callback function. Called when a response to a specific request arrives from the server. If .Ar error is non-zero, the framework was unable to obtain a response and the function should not examine the contents of .Ar pufbuf , only do resource cleanup. May not block. .It Fn puffs_framev_enqueue_cb pu pufbuf fcb fcb_arg Enqueue the buffer .Ar pufbuf for outgoing data and immediately return. Once a response arrives, the callback .Fn fcb will be called with the argument .Ar fcb_arg . The callback function .Fn fcb is responsible for freeing the buffer. Returns 0 if the buffer was succesfully enqueued (not necessarily delivered) and non-zero to signal a non-recoverable error. .It Fn puffs_framev_enqueue_justsend pu pufbuf waitreply Enqueue the buffer .Ar pufbuf for outgoing traffic and immediately return. The parameter .Ar waitreply can be used to control if the buffer is to be freed immediately after sending of if a response is expected and the buffer should be freed only after the response arrives (receiving an unexpected message from the server is treated as an error). Returns 0 if the buffer was succesfully enqueued (not necessarily delivered) and non-zero to signal a non-recoverable error. .It Fn puffs_framev_readframe_fn pu pufbuf fd done Callback function. Read at most one frame from file descriptor .Ar fd into the buffer .Ar pufbuf. If a complete frame is read, the value pointed to by .Ar done must be set to 1. This function should return 0 on success (even if a complete frame was not yet read) and a non-zero .Er 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. .It Fn puffs_framev_writeframe_fn pu pufbuf fd done Write the frame contained in .Ar pufbuf to the file descriptor .Ar fd . In case the entire frame is succesfully written, .Ar *done should be set to 1. This function should return 0 on success (even if a complete frame was not yet written) and a non-zero .Er 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. .Pp It is a good idea to make sure that this function can handle a possible .Dv SIGPIPE caused by a closed connection. For example, the file server can opt to trap .Dv SIGPIPE or, if writing to a socket, call .Fn send with the flag .Dv MSG_NOSIGNAL instead of using .Fn write . .It Fn puffs_framev_cmpframe_fn pu pufbuf_cmp1 pufbuf_cmp2 Compare the file system internal request tags in .Ar pufbuf_cmp1 and .Ar pufbuf_cmp2 . Should return 0 if the tags are equal, 1 if first buffer's tag is greater than the second and \-1 if it is smaller. The definitions "greater" and "smaller" are used transparently by the library, e.g. like .Xr qsort 3 . May not block. .It Fn puffs_framev_fdnotify_fn pu fd what Is called when the read- or write side of the file descriptor .Ar fd is closed. It is called once for each side, the bitmask parameter .Ar what specified what is currently closed: .Dv PUFFS_FBGONE_READ and .Dv PUFFS_FBGONE_WRITE for read and write, respectively. It is possible to test for both using .Fn PUFFS_FBGONE_BOTH what . .It Fn puffs_framev_init pu rfb wfb cmpfb fdnotfn Initializes the given callbacks to the system. They will be used when .Fn puffs_mainloop is called. .Ar rfb , .Ar wfb and .Ar cmpfb are mandatory. If .Ar fdnotfn is not given, a routine which calls .Fn puffs_framev_removefd when both sides are closed is used. .It Fn puffs_framev_addfd pu fd Add file descriptor .Ar fd to be handled by the framework. It is legal to add a file descriptor either before calling .Fn puffs_mainloop or at time when running. .It Fn puffs_framev_removefd pu fd error Remove file descriptor .Ar fd from the list of descriptors handled by the framework. Removing a file descriptor causes all operations blocked either on output or input to be released with the error value .Ar error . In case 0 is supplied as this parameter, .Er ECONNRESET is used. .Pp The file system .B must explicitly remove each fd it has added. A good place to do this is .Fn puffs_framev_fdnotify_fn . .It Fn puffs_framev_unmountonclose pu fd what This is library provided convinience routine for .Fn 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 .Xr mount_psshfs 8 , which depend on a single connection. .El .Sh CODE REFERENCES The current users of .Nm in the tree are .Xr mount_psshfs 8 and .Xr mount_9p 8 . See .Pa src/usr.sbin/puffs/mount_psshfs and .Pa src/usr.sbin/puffs/mount_9p for the respective usage examples. .Sh RETURN VALUES These functions generally return \-1 to signal error and set .Er errno to indicate the type of error. .Sh SEE ALSO .Xr puffs 3 , .Xr puffs_cc 3 , .Xr puffs_ops 3