@@@ man wip
[mLib] / buf / pkbuf.3
1 .\" -*-nroff-*-
2 .TH pkbuf 3 "16 July 2000" "Straylight/Edgeware" "mLib utilities library"
3 .SH "NAME"
4 pkbuf \- split packets out of asynchronously received blocks
5 .\" @pkbuf_flush
6 .\" @pkbuf_close
7 .\" @pkbuf_free
8 .\" @pkbuf_snarf
9 .\" @pkbuf_want
10 .\" @pkbuf_init
11 .\" @pkbuf_destroy
12 .SH "SYNOPSIS"
13 .nf
14 .ta 2n
15 .B "#include <mLib/pkbuf.h>"
16
17 .B "enum {"
18 .B " PKBUF_ENABLE = ..."
19 .B "};"
20
21 .B "typedef struct {"
22 .B " unsigned f;"
23 .B " ..."
24 .B "} pkbuf;"
25
26 .ta \w'\fBtypedef void pkbuf_func('u
27 .B "typedef void pkbuf_func(octet *" b ", size_t " sz ", pkbuf *" p ,
28 .BI " size_t *" keep ", void *" p );
29
30 .BI "void pkbuf_flush(pkbuf *" pk ", octet *" p ", size_t " len );
31 .BI "void pkbuf_close(pkbuf *" pk );
32 .BI "size_t pkbuf_free(pkbuf *" pk ", octet **" p );
33 .BI "void pkbuf_snarf(pkbuf *" pk ", const void *" p ", size_t " sz );
34 .BI "void pkbuf_want(pkbuf *" pk ", size_t " want );
35 .BI "void pkbuf_init(pkbuf *" pk ", pkbuf_func *" func ", void *" p );
36 .BI "void pkbuf_destroy(pkbuf *" pk );
37 .fi
38 .SH "DESCRIPTION"
39 The declarations in
40 .B <mLib/pkbuf.h>
41 implement a
42 .IR "packet buffer" .
43 Given unpredictably-sized chunks of data, the packet buffer extracts
44 completed packets of data, with sizes ascertained by a handler
45 function.
46 .PP
47 The state of a packet buffer is stored in an object of type
48 .BR pkbuf .
49 This is a structure which must be allocated by the caller. The
50 structure should normally be considered opaque (see the section on
51 .B Disablement
52 for an exception to this).
53 .SS "Initialization and finalization"
54 The function
55 .B pkbuf_init
56 initializes a packet buffer ready for use. It is given three arguments:
57 .TP
58 .BI "pkbuf *" pk
59 A pointer to the block of memory to use for the packet buffer. The packet
60 buffer will allocate memory to store incoming data automatically: this
61 structure just contains bookkeeping information.
62 .TP
63 .BI "pkbuf_func *" func
64 The
65 .I packet-handler
66 function to which the packet buffer should pass packets of data when
67 they're received. See
68 .B "Packet breaking and the handler function"
69 below.
70 .TP
71 .BI "void *" p
72 A pointer argument to be passed to the function when a packet arrives.
73 .PP
74 By default, the buffer is
75 allocated from the current arena,
76 .BR arena_global (3);
77 this may be changed by altering the buffer's
78 .B a
79 member to refer to a different arena at any time when the buffer is
80 unallocated.
81 .PP
82 A packet buffer must be destroyed after use by calling
83 .BR pkbuf_destroy ,
84 passing it the address of the buffer block.
85 .SS "Inserting data into the buffer"
86 There are two interfaces for inserting data into the buffer. One's much
87 simpler than the other, although it's less expressive.
88 .PP
89 The simple interface is
90 .BR pkbuf_snarf .
91 This function is given three arguments: a pointer
92 .I pk
93 to a packet buffer structure; a pointer
94 .I p
95 to a chunk of data to read; and the size
96 .I sz
97 of the chunk of data. The data is pushed through the packet buffer and
98 any complete packets are passed on to the packet handler.
99 .PP
100 The complex interface is the pair of functions
101 .I pkbuf_free
102 and
103 .IR pkbuf_flush .
104 .PP
105 The
106 .B pkbuf_free
107 function returns the address and size of a free portion of the packet
108 buffer's memory into which data may be written. The function is passed
109 the address
110 .I pk
111 of the packet buffer. Its result is the size of the free area, and it
112 writes the base address of this free space to the location pointed to by
113 the argument
114 .IR p .
115 The caller's data must be written to ascending memory locations starting
116 at
117 .BI * p
118 and no data may be written beyond the end of the free space. However,
119 it isn't necessary to completely fill the buffer.
120 .PP
121 Once the free area has had some data written to it,
122 .B pkbuf_flush
123 is called to examine the new data and break it into packets. This is
124 given three arguments:
125 .TP
126 .BI "pkbuf *" pk
127 The address of the packet buffer.
128 .TP
129 .BI "octet *" p
130 The address at which the new data has been written. This must be the
131 base address returned from
132 .BR pkbuf_free .
133 .TP
134 .BI "size_t " len
135 The number of bytes which have been written to the buffer.
136 .PP
137 The
138 .B pkbuf_flush
139 function breaks the new data into packets as described below, and passes
140 each one in turn to the packet-handler function.
141 .PP
142 The
143 .B pkbuf_snarf
144 function is trivially implemented in terms of the more complex
145 .BR pkbuf_free / pkbuf_flush
146 interface.
147 .SS "Packet breaking and the handler function"
148 The function
149 .B pkbuf_want
150 is used to inform the packet buffer of the expected length of the next
151 packet. It is given the pointer
152 .I pk
153 to the packet buffer and a size
154 .I sz
155 of the packet.
156 .PP
157 When enough data has arrived, the packet-handler function is called. It
158 is passed:
159 .TP
160 .BI "octet *" b
161 A pointer to the packet data in the buffer, or zero to signify
162 end-of-file.
163 .TP
164 .BI "size_t " sz
165 The size of the packet, as previously configured via
166 .BR pkbuf_want .
167 .TP
168 .BI "pkbuf *" pk
169 A pointer to the packet buffer.
170 .TP
171 .BI "size_t *" keep
172 A location in which to store the number of bytes of the current packet
173 to be retained. The bytes kept are from the end of the current packet:
174 if you want to keep bytes from the beginning of the packet, you should
175 move them into the right place.
176 .TP
177 .BI "void *" p
178 The pointer which was set up in the call to
179 .BR pkbuf_init .
180 .PP
181 .SS "Flushing the remaining data"
182 When the client program knows that there's no more data arriving (for
183 example, an end-of-file condition exists on its data source) it should
184 call the function
185 .BR pkbuf_close .
186 This will call the handler one final time with a null pointer to inform
187 it of the end-of-file.
188 .SS "Disablement"
189 The packet buffer is intended to be used in higher-level program
190 objects, such as the packet selector described in
191 .BR selpk (3).
192 Unfortunately, a concept from this high level needs to exist at the
193 packet buffer level, which complicates the description somewhat. The
194 idea is that, when a packet-handler attached to some higher-level object
195 decides that it's read enough, it can
196 .I disable
197 the object so that it doesn't see any more data.
198 .PP
199 Clearly, since an
200 .B pkbuf_flush
201 call can emit more than one packet, it must be aware that the packet
202 handler isn't interested in any more packet. However, this fact must
203 also be signalled to the higher-level object so that it can detach
204 itself from its data source.
205 .PP
206 Rather than invent some complex interface for this, the packet buffer
207 exports one of its structure members, a flags words called
208 .BR f .
209 A higher-level object wishing to disable the packet buffer simply clears
210 the bit
211 .B PKBUF_ENABLE
212 in this flags word.
213 .PP
214 Disabling a buffer causes an immediate return from
215 .BR pkbuf_flush .
216 However, it is not permitted for the functions
217 .B pkbuf_flush
218 or
219 .B pkbuf_close
220 to be called on a disabled buffer. (This condition isn't checked for;
221 it'll just do the wrong thing.) Furthermore, the
222 .B pkbuf_snarf
223 function does not handle disablement at all, because it would complicate
224 the interface so much that it wouldn't have any advantage over the more
225 general
226 .BR pkbuf_free / pkbuf_flush .
227 .SH "SEE ALSO"
228 .BR lbuf (3),
229 .BR selpk (3),
230 .BR mLib (3).
231 .SH "AUTHOR"
232 Mark Wooding, <mdw@distorted.org.uk>