.\" -*-nroff-*- .TH pkbuf 3 "16 July 2000" "Straylight/Edgeware" "mLib utilities library" .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 ", pkbuf_func *" func ", void *" p ); .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 .BI "pkbuf_func *" func The .I packet-handler function to which the packet buffer should pass packets of data when they're received. See .B "Packet breaking and the handler function" below. .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 .BR pkbuf_free / pkbuf_flush interface. .SS "Packet breaking and the handler function" 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. This has the signature .IP .nf .BI "void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" p , .BI " size_t *" keep ", void *" p ); .fi .PP It is 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, 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, a flags words called .BR f . A higher-level object wishing to disable the packet buffer simply clears the bit .B PKBUF_ENABLE in this 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,