]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/buffer.c
Add delete methods.
[thirdparty/dhcp.git] / omapip / buffer.c
CommitLineData
61b844bf
TL
1/* buffer.c
2
3 Buffer access functions for the object management protocol... */
4
5/*
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23#include <omapip/omapip.h>
24
25/* Make sure that at least len bytes are in the input buffer, and if not,
26 read enough bytes to make up the difference. */
27
28isc_result_t omapi_connection_reader (omapi_object_t *h)
29{
30 omapi_buffer_t *buffer;
31 isc_result_t status;
32 int read_len, read_status;
33 omapi_connection_object_t *c;
34 int bytes_to_read;
35
36 if (!h || h -> type != omapi_type_connection)
37 return ISC_R_INVALIDARG;
38 c = (omapi_connection_object_t *)h;
39
40 /* Make sure c -> bytes_needed is valid. */
41 if (c -> bytes_needed < 0)
42 return ISC_R_INVALIDARG;
43
44 /* See if there are enough bytes. */
45 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
46 c -> in_bytes > c -> bytes_needed)
47 return ISC_R_SUCCESS;
48
49 if (c -> inbufs) {
50 for (buffer = c -> inbufs; buffer -> next;
51 buffer = buffer -> next)
52 ;
53 if (!BUFFER_BYTES_AVAIL (buffer)) {
54 status = omapi_buffer_new (&buffer -> next,
55 "omapi_private_read");
56 if (status != ISC_R_SUCCESS)
57 return status;
58 buffer = buffer -> next;
59 }
60 } else {
61 status = omapi_buffer_new (&c -> inbufs,
62 "omapi_private_read");
63 if (status != ISC_R_SUCCESS)
64 return status;
65 buffer = c -> inbufs;
66 }
67
68 bytes_to_read = BUFFER_BYTES_AVAIL (buffer);
69
70 while (bytes_to_read) {
71 if (buffer -> tail >= buffer -> head)
72 read_len = sizeof (buffer -> buf) - buffer -> tail - 1;
73 else
74 read_len = buffer -> tail - buffer -> head - 1;
75
76 read_status = read (c -> socket,
77 &buffer -> buf [buffer -> tail], read_len);
78 if (read_status < 0) {
79 if (errno == EWOULDBLOCK)
80 return ISC_R_NOMORE;
81 else if (errno == EIO)
82 return ISC_R_IOERROR;
83 else if (errno == EINVAL)
84 return ISC_R_INVALIDARG;
85 else if (errno == ECONNRESET) {
86 omapi_disconnect (h, 0);
87 return ISC_R_SHUTTINGDOWN;
88 } else
89 return ISC_R_UNEXPECTED;
90 }
91 if (read_status == 0) {
92 omapi_disconnect (h, 0);
93 return ISC_R_SHUTTINGDOWN;
94 }
95 buffer -> tail += read_status;
96 c -> in_bytes += read_status;
97 if (buffer -> tail == sizeof buffer -> buf)
98 buffer -> tail = 0;
99 if (read_status < read_len)
100 break;
101 bytes_to_read -= read_status;
102 }
103
581e37e4 104 if (c -> bytes_needed <= c -> in_bytes) {
61b844bf
TL
105 omapi_signal (h, "ready", c);
106 }
107 return ISC_R_SUCCESS;
108}
109
110/* Put some bytes into the output buffer for a connection. */
111
112isc_result_t omapi_connection_copyin (omapi_object_t *h,
113 unsigned char *bufp,
114 int len)
115{
116 omapi_buffer_t *buffer;
117 isc_result_t status;
118 int bytes_copied = 0;
119 int copy_len;
120 omapi_connection_object_t *c;
121
122 /* Make sure len is valid. */
123 if (len < 0)
124 return ISC_R_INVALIDARG;
125 if (!h || h -> type != omapi_type_connection)
126 return ISC_R_INVALIDARG;
127 c = (omapi_connection_object_t *)h;
128
129 if (c -> outbufs) {
130 for (buffer = c -> outbufs;
131 buffer -> next; buffer = buffer -> next)
132 ;
133 } else {
134 status = omapi_buffer_new (&c -> outbufs,
135 "omapi_private_buffer_copyin");
136 if (status != ISC_R_SUCCESS)
137 return status;
138 buffer = c -> outbufs;
139 }
140
141 while (bytes_copied < len) {
142 /* If there is no space available in this buffer,
143 allocate a new one. */
144 if (!BUFFER_BYTES_AVAIL (buffer)) {
145 status = (omapi_buffer_new
146 (&buffer -> next,
147 "omapi_private_buffer_copyin"));
148 if (status != ISC_R_SUCCESS)
149 return status;
150 buffer = buffer -> next;
151 }
152
153 if (buffer -> tail < buffer -> head)
154 copy_len = buffer -> tail - buffer -> head - 1;
155 else
156 copy_len = sizeof (buffer -> buf) - buffer -> tail - 1;
157 if (copy_len > (len - bytes_copied))
158 copy_len = len - bytes_copied;
159
160 memcpy (&buffer -> buf [buffer -> tail],
161 &bufp [bytes_copied], copy_len);
162 buffer -> tail += copy_len;
163 c -> out_bytes += copy_len;
164 bytes_copied += copy_len;
165 if (buffer -> tail == sizeof buffer -> buf)
166 buffer -> tail = 0;
167 }
168 return ISC_R_SUCCESS;
169}
170
171/* Copy some bytes from the input buffer, and advance the input buffer
172 pointer beyond the bytes copied out. */
173
174u_int32_t omapi_connection_copyout (unsigned char *buf,
175 omapi_object_t *h,
176 int size)
177{
178 int bytes_remaining;
179 int bytes_this_copy;
180 omapi_buffer_t *buffer;
181 unsigned char *bufp;
182 omapi_connection_object_t *c;
183
184 if (!h || h -> type != omapi_type_connection)
185 return ISC_R_INVALIDARG;
186 c = (omapi_connection_object_t *)h;
187
188 if (size > c -> in_bytes)
189 return ISC_R_NOMORE;
190 bufp = buf;
191 bytes_remaining = size;
192 buffer = c -> inbufs;
193
194 while (bytes_remaining) {
195 if (!buffer)
196 return ISC_R_UNEXPECTED;
197 if (buffer -> head != buffer -> tail) {
198 if (buffer -> head > buffer -> tail) {
199 bytes_this_copy = (sizeof buffer -> buf -
200 buffer -> head);
201 } else {
202 bytes_this_copy =
203 buffer -> tail - buffer -> head;
204 }
205 if (bytes_this_copy > bytes_remaining)
206 bytes_this_copy = bytes_remaining;
207 if (bufp) {
208 memcpy (bufp, &buffer -> buf [buffer -> head],
209 bytes_this_copy);
210 bufp += bytes_this_copy;
211 }
212 bytes_remaining -= bytes_this_copy;
213 buffer -> head += bytes_this_copy;
214 if (buffer -> head == sizeof buffer -> buf)
215 buffer -> head = 0;
216 c -> in_bytes -= bytes_this_copy;
217 }
218
219 if (buffer -> head == buffer -> tail)
220 buffer = buffer -> next;
221 }
222
223 /* Get rid of any input buffers that we emptied. */
224 buffer = (omapi_buffer_t *)0;
225 while (c -> inbufs &&
226 c -> inbufs -> head == c -> inbufs -> tail) {
227 if (c -> inbufs -> next) {
228 omapi_buffer_reference
229 (&buffer,
230 c -> inbufs -> next,
231 "omapi_private_buffer_copyout");
232 omapi_buffer_dereference
233 (&c -> inbufs -> next,
234 "omapi_private_buffer_copyout");
235 }
236 omapi_buffer_dereference (&c -> inbufs,
237 "omapi_private_buffer_copyout");
238 omapi_buffer_reference (&c -> inbufs,
239 buffer,
240 "omapi_private_buffer_copyout");
241 omapi_buffer_dereference (&buffer,
242 "omapi_private_buffer_copyout");
243 }
244 return ISC_R_SUCCESS;
245}
246
247u_int32_t omapi_connection_writer (omapi_object_t *h)
248{
249 int bytes_this_write;
250 int bytes_written;
251 omapi_buffer_t *buffer;
252 unsigned char *bufp;
253 omapi_connection_object_t *c;
254
255 if (!h || h -> type != omapi_type_connection)
256 return ISC_R_INVALIDARG;
257 c = (omapi_connection_object_t *)h;
258
259 /* Already flushed... */
260 if (!c -> out_bytes)
261 return ISC_R_SUCCESS;
262
263 buffer = c -> outbufs;
264
265 while (c -> out_bytes) {
266 if (!buffer)
267 return ISC_R_UNEXPECTED;
268 if (buffer -> head != buffer -> tail) {
269 if (buffer -> head > buffer -> tail) {
270 bytes_this_write = (sizeof buffer -> buf -
271 buffer -> head);
272 } else {
273 bytes_this_write =
274 (buffer -> tail - buffer -> head);
275 }
276 bytes_written = write (c -> socket,
277 &buffer -> buf [buffer -> head],
278 bytes_this_write);
279 /* If the write failed with EWOULDBLOCK or we wrote
280 zero bytes, a further write would block, so we have
281 flushed as much as we can for now. Other errors
282 are really errors. */
283 if (bytes_written < 0) {
284 if (errno == EWOULDBLOCK || errno == EAGAIN)
285 return ISC_R_SUCCESS;
286 else if (errno == EPIPE)
287 return ISC_R_NOCONN;
288 else if (errno == EFBIG || errno == EDQUOT)
289 return ISC_R_NORESOURCES;
290 else if (errno == ENOSPC)
291 return ISC_R_NOSPACE;
292 else if (errno == EIO)
293 return ISC_R_IOERROR;
294 else if (errno == EINVAL)
295 return ISC_R_INVALIDARG;
296 else if (errno == ECONNRESET)
297 return ISC_R_SHUTTINGDOWN;
298 else
299 return ISC_R_UNEXPECTED;
300 }
301 if (bytes_written == 0)
302 return ISC_R_SUCCESS;
303
304 buffer -> head += bytes_written;
305 if (buffer -> head == sizeof buffer -> buf)
306 buffer -> head = 0;
307 c -> out_bytes -= bytes_written;
308
309 /* If we didn't finish out the write, we filled the
310 O.S. output buffer and a further write would block,
311 so stop trying to flush now. */
312 if (bytes_written != bytes_this_write)
313 return ISC_R_SUCCESS;
314 }
315
316 if (buffer -> head == buffer -> tail)
317 buffer = buffer -> next;
318 }
319
320 /* Get rid of any output buffers we emptied. */
321 buffer = (omapi_buffer_t *)0;
322 while (c -> outbufs &&
323 c -> outbufs -> head == c -> outbufs -> tail) {
324 if (c -> outbufs -> next) {
325 omapi_buffer_reference
326 (&buffer, c -> outbufs -> next,
327 "omapi_private_flush");
328 omapi_buffer_dereference
329 (&c -> outbufs -> next, "omapi_private_flush");
330 }
331 omapi_buffer_dereference (&c -> outbufs,
332 "omapi_private_flush");
333 if (buffer) {
334 omapi_buffer_reference (&c -> outbufs, buffer,
335 "omapi_private_flush");
336 omapi_buffer_dereference (&buffer,
337 "omapi_private_flush");
338 }
339 }
340 return ISC_R_SUCCESS;
341}
342
343isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
344 u_int32_t *result)
345{
346 u_int32_t inbuf;
347 isc_result_t status;
348
349 status = omapi_connection_copyout ((unsigned char *)&inbuf,
350 c, sizeof inbuf);
351 if (status != ISC_R_SUCCESS)
352 return status;
353
354 *result = ntohl (inbuf);
355 return ISC_R_SUCCESS;
356}
357
358isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
359 u_int32_t value)
360{
361 u_int32_t inbuf;
362 isc_result_t status;
363
364 inbuf = htonl (value);
365
366 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
367 sizeof inbuf);
368}
369
370isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
371 u_int16_t *result)
372{
373 u_int16_t inbuf;
374 isc_result_t status;
375
376 status = omapi_connection_copyout ((unsigned char *)&inbuf,
377 c, sizeof inbuf);
378 if (status != ISC_R_SUCCESS)
379 return status;
380
381 *result = ntohs (inbuf);
382 return ISC_R_SUCCESS;
383}
384
385isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
386 u_int16_t value)
387{
388 u_int16_t inbuf;
389 isc_result_t status;
390
391 inbuf = htons (value);
392
393 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
394 sizeof inbuf);
395}
396
581e37e4
TL
397isc_result_t omapi_connection_write_typed_data (omapi_object_t *c,
398 omapi_typed_data_t *data)
399{
400 isc_result_t status;
401 omapi_handle_t handle;
402
403 switch (data -> type) {
404 case omapi_datatype_int:
405 status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
406 if (status != ISC_R_SUCCESS)
407 return status;
408 return omapi_connection_put_uint32 (c, data -> u.integer);
409
410 case omapi_datatype_string:
411 case omapi_datatype_data:
412 status = omapi_connection_put_uint32 (c, data -> u.buffer.len);
413 if (status != ISC_R_SUCCESS)
414 return status;
415 return omapi_connection_copyin (c, data -> u.buffer.value,
416 data -> u.buffer.len);
417
418 case omapi_datatype_object:
419 status = omapi_object_handle (&handle,
420 data -> u.object);
421 if (status != ISC_R_SUCCESS)
422 return status;
423 status = omapi_connection_put_uint32 (c, sizeof handle);
424 if (status != ISC_R_SUCCESS)
425 return status;
426 return omapi_connection_put_uint32 (c, handle);
427
428 }
429 return ISC_R_INVALIDARG;
430}
431
432isc_result_t omapi_connection_put_name (omapi_object_t *c, char *name)
433{
434 isc_result_t status;
435 int len = strlen (name);
436
437 status = omapi_connection_put_uint16 (c, len);
438 if (status != ISC_R_SUCCESS)
439 return status;
440 return omapi_connection_copyin (c, name, len);
441}
442
443isc_result_t omapi_connection_put_string (omapi_object_t *c, char *string)
444{
445 isc_result_t status;
446 int len;
447
448 len = strlen (string);
449
450 status = omapi_connection_put_uint32 (c, len);
451 if (status != ISC_R_SUCCESS)
452 return status;
453 return omapi_connection_copyin (c, string, len);
454}
455
456isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
457{
458 isc_result_t status;
459 omapi_handle_t handle;
460
461 status = omapi_object_handle (&handle, h);
462 if (status != ISC_R_SUCCESS)
463 return status;
464 status = omapi_connection_put_uint32 (c, sizeof handle);
465 if (status != ISC_R_SUCCESS)
466 return status;
467 return omapi_connection_put_uint32 (c, handle);
468}