From 1e7e4330a3130359d8d0ecadb4ce418b82978e18 Mon Sep 17 00:00:00 2001 Message-Id: <1e7e4330a3130359d8d0ecadb4ce418b82978e18.1715134953.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sun, 16 Jul 2000 18:56:47 +0000 Subject: [PATCH] New manual pages. Organization: Straylight/Edgeware From: mdw --- man/pkbuf.3 | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++ man/selpk.3 | 111 ++++++++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 man/pkbuf.3 create mode 100644 man/selpk.3 diff --git a/man/pkbuf.3 b/man/pkbuf.3 new file mode 100644 index 0000000..2bf9d17 --- /dev/null +++ b/man/pkbuf.3 @@ -0,0 +1,222 @@ +.\" -*-nroff-*- +.TH pkbuf 3 "16 July 2000" mLib +.SH "NAME" +pkbuf \- split packets out of asynchronously received blocks +.\" @pkbuf_flush +.\" @pkbuf_close +.\" @pkbuf_free +.\" @pkbuf_snarf +.\" @pkbuf_want +.\" @pkbuf_init +.\" @pkbuf_destroy +.SH "SYNOPSIS" +.nf +.B "#include " + +.BI "void pkbuf_flush(pkbuf *" pk ", octet *" p ", size_t " len ); +.BI "void pkbuf_close(pkbuf *" pk ); +.BI "size_t pkbuf_free(pkbuf *" pk ", octet **" p ); +.BI "void pkbuf_snarf(pkbuf *" pk ", const void *" p ", size_t " sz ); +.BI "void pkbuf_want(pkbuf *" pk ", size_t " want ); +.BI "void pkbuf_init(pkbuf *" pk , +.BI " void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" pk , +.BI " size_t *" keep ", void *" p ), +.BI " void *" pk ); +.BI "void pkbuf_destroy(pkbuf *" pk ); +.fi +.SH "DESCRIPTION" +The declarations in +.B +implement a +.IR "packet buffer" . +Given unpredictably-sized chunks of data, the packet buffer extracts +completed packets of data, with sizes ascertained by a handler +function. +.PP +The state of a packet buffer is stored in an object of type +.BR pkbuf . +This is a structure which must be allocated by the caller. The +structure should normally be considered opaque (see the section on +.B Disablement +for an exception to this). +.SS "Initialization and finalization" +The function +.B pkbuf_init +initializes a packet buffer ready for use. It is given three arguments: +.TP +.BI "pkbuf *" pk +A pointer to the block of memory to use for the packet buffer. The packet +buffer will allocate memory to store incoming data automatically: this +structure just contains bookkeeping information. +.TP +.nf +.BI "void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" p , +.BI " size_t *" keep ", void *" p ) +.fi +The +.I packet-handler +function to which the packet buffer should pass packets of data when +they're received. +.TP +.BI "void *" p +A pointer argument to be passed to the function when a packet arrives. +.PP +By default, the buffer is +allocated from the current arena, +.BR arena_global (3); +this may be changed by altering the buffer's +.B a +member to refer to a different arena at any time when the buffer is +unallocated. +.PP +A packet buffer must be destroyed after use by calling +.BR pkbuf_destroy , +passing it the address of the buffer block. +.SS "Inserting data into the buffer" +There are two interfaces for inserting data into the buffer. One's much +simpler than the other, although it's less expressive. +.PP +The simple interface is +.BR pkbuf_snarf . +This function is given three arguments: a pointer +.I pk +to a packet buffer structure; a pointer +.I p + to a chunk of data to read; and the size +.I sz +of the chunk of data. The data is pushed through the packet buffer and +any complete packets are passed on to the packet handler. +.PP +The complex interface is the pair of functions +.I pkbuf_free +and +.IR pkbuf_flush . +.PP +The +.B pkbuf_free +function returns the address and size of a free portion of the packet +buffer's memory into which data may be written. The function is passed +the address +.I pk +of the packet buffer. Its result is the size of the free area, and it +writes the base address of this free space to the location pointed to by +the argument +.IR p . +The caller's data must be written to ascending memory locations starting +at +.BI * p +and no data may be written beyond the end of the free space. However, +it isn't necessary to completely fill the buffer. +.PP +Once the free area has had some data written to it, +.B pkbuf_flush +is called to examine the new data and break it into packets. This is +given three arguments: +.TP +.BI "pkbuf *" pk +The address of the packet buffer. +.TP +.BI "octet *" p +The address at which the new data has been written. This must be the +base address returned from +.BR pkbuf_free . +.TP +.BI "size_t " len +The number of bytes which have been written to the buffer. +.PP +The +.B pkbuf_flush +function breaks the new data into packets as described below, and passes +each one in turn to the packet-handler function. +.PP +The +.B pkbuf_snarf +function is trivially implemented in terms of the more complex +.B pkbuf_free / pkbuf_flush +interface. +.SS "Packet breaking and the handler fucntion" +The function +.B pkbuf_want +is used to inform the packet buffer of the expected length of the next +packet. It is given the pointer +.I pk +to the packet buffer and a size +.I sz +of the packet. +.PP +When enough data has arrived, the packet-handler function is called, and +passed: +.TP +.BI "octet *" b +A pointer to the packet data in the buffer, or zero to signify +end-of-file. +.TP +.BI "size_t " sz +The size of the packet, as previously configured via +.BR pkbuf_want . +.TP +.BI "pkbuf *" pk +A pointer to the packet buffer. +.TP +.BI "size_t *" keep +A location in which to store the number of bytes of the current packet +to be retained. The bytes kept are from the end of the current packet: +if you want to keep bytes from the beginning of the packet, you should +move them into the right place. +.TP +.BI "void *" p +The pointer which was set up in the call to +.BR pkbuf_init . +.PP +.SS "Flushing the remaining data" +When the client program knows that there's no more data arriving (for +example, an end-of-file condition exists on its data source) it should +call the function +.BR pkbuf_close . +This will call the handler one final time with a null pointer to inform +it of the end-of-file. +.SS "Disablement" +The packet buffer is intended to be used in higher-level program +objects, such as the packet selector described in +.BR selpk (3). +Unfortunately, a concept from this high level needs to exist at the +packet buffer level, which complicates the description somewhat. The +idea is that, when a packet-handler attached to some higher-level object +decides that it's read enough, it can +.I disable +the object so that it doesn't see any more data. +.PP +Clearly, since an +.B pkbuf_flush +call can emit more than one packet, so it must be aware that the packet +handler isn't interested in any more packet. However, this fact must +also be signalled to the higher-level object so that it can detach +itself from its data source. +.PP +Rather than invent some complex interface for this, the packet buffer +exports one of its structure members, +.BR flags . +A higher-level object wishing to disable the packet buffer simply clears +the bit +.B PKBUF_ENABLE +in the flags word. +.PP +Disabling a buffer causes an immediate return from +.BR pkbuf_flush . +However, it is not permitted for the functions +.B pkbuf_flush +or +.B pkbuf_close +to be called on a disabled buffer. (This condition isn't checked for; +it'll just do the wrong thing.) Furthermore, the +.B pkbuf_snarf +function does not handle disablement at all, because it would complicate +the interface so much that it wouldn't have any advantage over the more +general +.BR pkbuf_free / pkbuf_flush . +.SH "SEE ALSO" +.BR lbuf (3), +.BR selpk (3), +.BR mLib (3). +.SH "AUTHOR" +Mark Wooding, diff --git a/man/selpk.3 b/man/selpk.3 new file mode 100644 index 0000000..57574fb --- /dev/null +++ b/man/selpk.3 @@ -0,0 +1,111 @@ +.\" -*-nroff-*- +.TH selpk 3 "23 May 1999" mLib +.SH NAME +selpk \- packet-buffering input selector +.\" @selpk_enable +.\" @selpk_disable +.\" @selpk_want +.\" @selpk_init +.\" @selpk_destroy +.SH SYNOPSIS +.nf +.B "#include " + +.BI "void selpk_enable(selpk *" pk ); +.BI "void selpk_disable(selpk *" pk ); +.BI "void selpk_want(selpk *" pk ", size_t " sz ); +.BI "void selpk_init(selpk *" pk , +.BI " sel_state *" s , +.BI " int " fd , +.BI " void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" pk , +.BI " size_t *" keep ", void *" p ), +.BI " void *" p ); +.BI "void selpk_destroy(selpk *" b ); +.fi +.SH DESCRIPTION +The +.B selpk +subsystem is a selector which integrates with the +.BR sel (3) +system for I/O multiplexing. It reads packets from a file descriptor +and passes them to a caller-defined function. It uses the packet buffer +described in +.BR pkbuf (3) +to do its work: you should read about it in order to understand exactly +how the packet buffer decides how much data is in each packet and the +exact rules about what your packet handling function should and +shouldn't do. +.PP +The data for a packet selector is stored in an object of type +.BR selpk . +This object must be allocated by the caller, and initialized using the +.B selpk_init +function. This requires a fair few arguments: +.TP +.BI "selpk *" pk +Pointer to the +.B selpk +object to initialize. +.TP +.BI "sel_state *" s +Pointer to a multiplexor object (type +.BR sel_state ) +to which this selector should be attached. See +.BR sel (3) +for more details about multiplexors, and how this whole system works. +.TP +.BI "int " fd +The file descriptor of the stream the selector should read from. +.TP +.nf +.BI "void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" p , +.BI " size_t *" keep ", void *" p ) +.fi +The +.I "packet handler" +function. It is passed a pointer to each packet read from the file (or +null to indicate end-of-file) and an arbitrary pointer (the +.I p +argument to +.B selpk_init +described below). +.TP +.BI "void *" p +A pointer argument passed to +.I func +for each packet read from the file. Apart from this, the pointer is not +used at all. +.PP +The +.B selpk +selector is immediately active. Subsequent calls to +.B sel_select +on the same multiplexor will cause any packets read from the file to be +passed to your handling function. This function can at any time call +.B selpk_disable +to stop itself from being called any more. The selector is then +disengaged from the I/O multiplexor and won't do anything until +.B selpk_enable +is called. Note that +.B selpk_enable +may well immediately start emitting complete packets of text which were +queued up from the last I/O operation: it doesn't necessarily wait for +the next +.B sel_select +call. +.PP +The size of packets read by the buffer is set by calling +.BR selpk_want . +See +.BR pkbuf (3) +for more details about how packet buffering works. +.PP +When it's finished with, a packet selector must be destroyed by calling +.BR selpk_destroy . +.SH "SEE ALSO" +.BR pkbuf (3), +.BR sel (3), +.BR selbuf (3), +.BR mLib (3). +.SH AUTHOR +Mark Wooding, -- [mdw]