The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
mem.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: e916be9b9487d777b10e365b4ba278fa9fc794d7 $
19  * @file lib/bio/mem.c
20  * @brief BIO abstractions for memory buffers
21  *
22  * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
23  */
24 
25 #include <freeradius-devel/bio/bio_priv.h>
26 #include <freeradius-devel/bio/null.h>
27 #include <freeradius-devel/bio/buf.h>
28 
29 #include <freeradius-devel/bio/mem.h>
30 
31 /** The memory buffer bio
32  *
33  * It is used to buffer reads / writes to a streaming socket.
34  */
35 typedef struct fr_bio_mem_s {
37 
38  fr_bio_verify_t verify; //!< verify data to see if we have a packet.
39 
40  fr_bio_buf_t read_buffer; //!< buffering for reads
41  fr_bio_buf_t write_buffer; //!< buffering for writes
43 
44 static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size);
45 
46 static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size) CC_HINT(nonnull(1,3));
47 
48 /** At EOF, read data from the buffer until it is empty.
49  *
50  * When "next" bio returns EOF, there may still be pending data in the memory buffer. Return that until it's
51  * empty, and then EOF from then on.
52  */
53 static ssize_t fr_bio_mem_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
54 {
55  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
56 
57  /*
58  * No more data: return EOF from now on.
59  */
60  if (fr_bio_buf_used(&my->read_buffer) == 0) {
61  my->bio.read = fr_bio_eof_read;
62  return fr_bio_error(EOF);
63  }
64 
65  /*
66  * Return whatever data we have available. One the buffer is empty, the next read will get EOF.
67  */
68  return fr_bio_buf_read(&my->read_buffer, buffer, size);
69 }
70 
71 /** Read from a memory BIO
72  *
73  * This bio reads as much data as possible into the memory buffer. On the theory that a few memcpy() or
74  * memmove() calls are much cheaper than a system call.
75  *
76  * If the read buffer has enough data to satisfy the read, then it is returned.
77  *
78  * Otherwise the next bio is called to re-fill the buffer. The next read call will try to get as much data
79  * as possible into the buffer, even if that results in reading more than "size" bytes.
80  *
81  * Once the next read has been done, then the data from the buffer is returned, even if it is less than
82  * "size".
83  */
84 static ssize_t fr_bio_mem_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
85 {
86  ssize_t rcode;
87  size_t used, room;
88  uint8_t *p;
89  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
90  fr_bio_t *next;
91 
92  /*
93  * We can satisfy the read from the memory buffer: do so.
94  */
96  if (size <= used) {
97  return fr_bio_buf_read(&my->read_buffer, buffer, size);
98  }
99 
100  /*
101  * There must be a next bio.
102  */
103  next = fr_bio_next(&my->bio);
104  fr_assert(next != NULL);
105 
106  /*
107  * If there's no room to store more data in the buffer. Just return whatever data we have in the
108  * buffer.
109  */
110  room = fr_bio_buf_write_room(&my->read_buffer);
111  if (!room) return fr_bio_buf_read(&my->read_buffer, buffer, size);
112 
113  /*
114  * We try to fill the buffer as much as possible from the network, even if that means reading
115  * more than "size" amount of data.
116  */
117  p = fr_bio_buf_write_reserve(&my->read_buffer, room);
118  fr_assert(p != NULL); /* otherwise room would be zero */
119 
120  rcode = next->read(next, packet_ctx, p, room);
121 
122  /*
123  * Ensure that whatever data we have read is marked as "used" in the buffer, and then return
124  * whatever data is available back to the caller.
125  */
126  if (rcode >= 0) {
127  if (rcode > 0) (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
128 
129  return fr_bio_buf_read(&my->read_buffer, buffer, size);
130  }
131 
132  /*
133  * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
134  * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
135  * the buffer is lost.
136  */
139  return rcode;
140 }
141 
142 /** Return data only if we have a complete packet.
143  *
144  */
145 static ssize_t fr_bio_mem_read_verify(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
146 {
147  ssize_t rcode;
148  size_t used, room, want;
149  uint8_t *p;
150  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
151  fr_bio_t *next;
152 
153  /*
154  * We may be able to satisfy the read from the memory buffer.
155  */
157  if (used) {
158  /*
159  * See if there are valid packets in the buffer.
160  */
161  rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
162  if (rcode < 0) {
163  rcode = fr_bio_error(VERIFY);
164  goto fail;
165  }
166 
167  /*
168  * There's at least one valid packet, return it.
169  */
170  if (rcode == 1) {
171  /*
172  * This isn't a fatal error. The caller should check how much room is needed by calling
173  * fr_bio_mem_call_verify(), and retry.
174  *
175  * But in general, the caller should make sure that the output buffer has enough
176  * room for at least one packet. The verify() function should also ensure that
177  * the packet is no larger than our application maximum, even if the protocol
178  * allows for it to be larger.
179  */
180  if (want > size) return fr_bio_error(BUFFER_TOO_SMALL);
181 
182  return fr_bio_buf_read(&my->read_buffer, buffer, want);
183  }
184 
185  /*
186  * Else we need to read more data to have a complete packet.
187  */
188  }
189 
190  /*
191  * There must be a next bio.
192  */
193  next = fr_bio_next(&my->bio);
194  fr_assert(next != NULL);
195 
196  /*
197  * If there's no room to store more data in the buffer, try to make some room.
198  */
199  room = fr_bio_buf_write_room(&my->read_buffer);
200  if (!room) {
201  room = fr_bio_buf_make_room(&my->read_buffer);
202 
203  /*
204  * We've tried to make room and failed. Which means that the buffer is full, AND there
205  * still isn't a complete packet in the buffer. This is therefore a fatal error. The
206  * application has not supplied us with enough read_buffer space to store a complete
207  * packet.
208  */
209  if (!room) {
210  rcode = fr_bio_error(BUFFER_FULL);
211  goto fail;
212  }
213  }
214 
215  /*
216  * We try to fill the buffer as much as possible from the network. The theory is that a few
217  * extra memcpy() or memmove()s are cheaper than a system call for reading each packet.
218  */
219  p = fr_bio_buf_write_reserve(&my->read_buffer, room);
220  fr_assert(p != NULL); /* otherwise room would be zero */
221 
222  rcode = next->read(next, packet_ctx, p, room);
223 
224  /*
225  * The next bio returned some data. See if it's a valid packet.
226  */
227  if (rcode > 0) {
228  (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
229 
230  want = fr_bio_buf_used(&my->read_buffer);
231  if (size <= want) want = size;
232 
233  /*
234  * See if there are valid packets in the buffer.
235  */
236  rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
237  if (rcode < 0) {
238  rcode = fr_bio_error(VERIFY);
239  goto fail;
240  }
241 
242  /*
243  * There's at least one valid packet, return it.
244  */
245  if (rcode == 1) return fr_bio_buf_read(&my->read_buffer, buffer, want);
246 
247  /*
248  * No valid packets. The next call to read will call verify again, which will return a
249  * partial packet. And then it will try to fill the buffer from the next bio.
250  */
251  return 0;
252  }
253 
254  /*
255  * No data was read from the next bio, we still don't have a packet. Return nothing.
256  */
257  if (rcode == 0) return 0;
258 
259  /*
260  * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
261  * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
262  * the buffer is lost.
263  */
264 fail:
267  return rcode;
268 }
269 
270 /** Return data only if we have a complete packet.
271  *
272  */
273 static ssize_t fr_bio_mem_read_verify_datagram(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
274 {
275  ssize_t rcode;
276  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
277  fr_bio_t *next;
278 
279  /*
280  * There must be a next bio.
281  */
282  next = fr_bio_next(&my->bio);
283  fr_assert(next != NULL);
284 
285  rcode = next->read(next, packet_ctx, buffer, size);
286  if (rcode > 0) {
287  size_t want = rcode;
288 
289  /*
290  * It's a datagram socket, there can only be one packet in the buffer.
291  *
292  * @todo - if we're allowed more than one packet in the buffer, we should just call
293  * fr_bio_mem_read_verify(), or this function should call fr_bio_mem_call_verify().
294  */
295  switch (my->verify((fr_bio_t *) my, packet_ctx, buffer, &want)) {
296  /*
297  * The data in the buffer is exactly a packet. Return that.
298  *
299  * @todo - if there are multiple packets, return the total size of packets?
300  */
301  case FR_BIO_VERIFY_OK:
302  fr_assert(want <= (size_t) rcode);
303  return want;
304 
305  /*
306  * The data in the buffer doesn't make up a complete packet, discard it. The
307  * called verify function should take care of logging.
308  */
310  return 0;
311 
313  return 0;
314 
315  /*
316  * Some kind of fatal validation error.
317  */
319  break;
320  }
321 
322  rcode = fr_bio_error(VERIFY);
323  goto fail;
324  }
325 
326  /*
327  * No data was read from the next bio, we still don't have a packet. Return nothing.
328  */
329  if (rcode == 0) return 0;
330 
331  /*
332  * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
333  * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
334  * the buffer is lost.
335  */
336 fail:
339  return rcode;
340 }
341 
342 
343 /** Pass writes to the next BIO
344  *
345  * For speed, we try to bypass the memory buffer and write directly to the next bio. However, if the next
346  * bio returns EWOULDBLOCK, we write the data to the memory buffer, even if it is partial data.
347  */
348 static ssize_t fr_bio_mem_write_next(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
349 {
350  ssize_t rcode;
351  size_t room, leftover;
352  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
353  fr_bio_t *next;
354 
355  /*
356  * We can't call the next bio if there's still cached data to flush.
357  *
358  * There must be a next bio.
359  */
361 
362  next = fr_bio_next(&my->bio);
363  fr_assert(next != NULL);
364 
365  /*
366  * The next bio may write all of the data. If so, we return that,
367  */
368  rcode = next->write(next, packet_ctx, buffer, size);
369  if ((size_t) rcode == size) return rcode;
370 
371  /*
372  * The next bio returned an error. Anything other than WOULD BLOCK is fatal. We can read from
373  * the memory buffer until it's empty, but we can no longer write to the memory buffer.
374  */
375  if ((rcode < 0) && (rcode != fr_bio_error(IO_WOULD_BLOCK))) {
378  return rcode;
379  }
380 
381  /*
382  * We were flushing the buffer, return however much data we managed to write.
383  *
384  * Note that flushes can never block.
385  */
386  if (!buffer) {
387  fr_assert(rcode != fr_bio_error(IO_WOULD_BLOCK));
388  return rcode;
389  }
390 
391  /*
392  * We had WOULD BLOCK, or wrote partial bytes. Save the data to the memory buffer, and ensure
393  * that future writes are ordered. i.e. they write to the memory buffer before writing to the
394  * next bio.
395  */
397 
398  /*
399  * Clamp the write to however much data is available in the buffer.
400  */
401  leftover = size - rcode;
402  room = fr_bio_buf_write_room(&my->write_buffer);
403 
404  /*
405  * If we have "used == 0" above, then we must also have "room > 0".
406  */
407  fr_assert(room > 0);
408 
409  if (room < leftover) leftover = room;
410 
411  /*
412  * Since we've clamped the write, this call can never fail.
413  */
414  (void) fr_bio_buf_write(&my->write_buffer, ((uint8_t const *) buffer) + rcode, leftover);
415 
416  /*
417  * Some of the data base been written to the next bio, and some to our cache. The caller has to
418  * ensure that the first subsequent write will send over the rest of the data.
419  */
420  return rcode + leftover;
421 }
422 
423 /** Flush the memory buffer.
424  *
425  */
427 {
428  int rcode;
429  size_t used;
430  fr_bio_t *next;
431 
432  /*
433  * Nothing to flush, don't do any writes.
434  *
435  * Instead, set the write function to write next, where data will be sent directly to the next
436  * bio, and will bypass the write buffer.
437  */
439  if (!used) {
440  my->bio.write = fr_bio_mem_write_next;
441  return 0;
442  }
443 
444  next = fr_bio_next(&my->bio);
445  fr_assert(next != NULL);
446 
447  /*
448  * Clamp the amount of data written. If the caller wants to write everything, it should
449  * pass SIZE_MAX.
450  */
451  if (used < size) used = size;
452 
453  /*
454  * Flush the buffer to the next bio in line. That function will write as much data as possible,
455  * but may return a partial write.
456  */
457  rcode = next->write(next, NULL, my->write_buffer.write, used);
458 
459  /*
460  * The next bio returned an error. Anything other than WOULD BLOCK is fatal. We can read from
461  * the memory buffer until it's empty, but we can no longer write to the memory buffer.
462  */
463  if ((rcode < 0) && (rcode != fr_bio_error(IO_WOULD_BLOCK))) {
464  my->bio.read = fr_bio_mem_read_eof;
465  my->bio.write = fr_bio_null_write;
466  return rcode;
467  }
468 
469  /*
470  * We didn't write anything, return that.
471  */
472  if ((rcode == 0) || (rcode == fr_bio_error(IO_WOULD_BLOCK))) return rcode;
473 
474  /*
475  * Tell the buffer that we've read a certain amount of data from it.
476  */
477  (void) fr_bio_buf_read(&my->write_buffer, NULL, (size_t) rcode);
478 
479  /*
480  * We haven't emptied the buffer, return the partial write.
481  */
482  if ((size_t) rcode < used) return rcode;
483 
484  /*
485  * We've flushed all of the buffer. Revert back to "pass through" writing.
486  */
488  my->bio.write = fr_bio_mem_write_next;
489  return rcode;
490 }
491 
492 /** Write to the memory buffer.
493  *
494  * The special buffer pointer of NULL means flush(). On flush, we call next->read(), and if that succeeds,
495  * go back to "pass through" mode for the buffers.
496  */
497 static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
498 {
499  size_t room;
500  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
501 
502  /*
503  * Flush the output buffer.
504  */
505  if (unlikely(!buffer)) return fr_bio_mem_write_flush(my, size);
506 
507  /*
508  * Clamp the write to however much data is available in the buffer.
509  */
510  room = fr_bio_buf_write_room(&my->write_buffer);
511 
512  /*
513  * The buffer is full. We're now blocked.
514  */
515  if (!room) return fr_bio_error(IO_WOULD_BLOCK);
516 
517  if (room < size) size = room;
518 
519  /*
520  * As we have clamped the write, we know that this call must succeed.
521  */
522  return fr_bio_buf_write(&my->write_buffer, buffer, size);
523 }
524 
525 /** Peek at the data in the read buffer
526  *
527  * Peeking at the data allows us to avoid many memory copies.
528  */
529 uint8_t const *fr_bio_mem_read_peek(fr_bio_t *bio, size_t *size)
530 {
531  size_t used;
532  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
533 
535 
536  if (!used) return NULL;
537 
538  *size = used;
539  return my->read_buffer.read;
540 }
541 
542 /** Discard data from the read buffer.
543  *
544  * Discarding allows the caller to silently omit packets, so that
545  * they are not passed up to previous bios.
546  */
548 {
549  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
550 
551  (void) fr_bio_buf_read(&my->read_buffer, NULL, size);
552 }
553 
554 /** Verify that a packet is OK.
555  *
556  * @todo - have this as a parameter to the read routines, so that they only return complete packets?
557  *
558  * @param bio the #fr_bio_mem_t
559  * @param packet_ctx the packet ctx
560  * @param[out] size how big the verified packet is
561  * @return
562  * - <0 on error, the caller should close the bio.
563  * - 0 for "we have a partial packet", the size to read is in *size
564  * - 1 for "we have at least one good packet", the size of it is in *size
565  */
566 static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size)
567 {
568  uint8_t *packet, *end;
569  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
570 
571  packet = my->read_buffer.read;
572  end = my->read_buffer.write;
573 
574  while (packet < end) {
575  size_t want;
576 #ifndef NDEBUG
577  size_t used;
578 
579  used = end - packet;
580 #endif
581 
582  want = end - packet;
583 
584  switch (my->verify((fr_bio_t *) my, packet_ctx, packet, &want)) {
585  /*
586  * The data in the buffer is exactly a packet. Return that.
587  *
588  * @todo - if there are multiple packets, return the total size of packets?
589  */
590  case FR_BIO_VERIFY_OK:
591  fr_assert(want <= used);
592  *size = want;
593  return 1;
594 
595  /*
596  * The packet needs more data. Return how much data we need for one packet.
597  */
599  fr_assert(want > used);
600  *size = want;
601  return 0;
602 
604  /*
605  * We don't call fr_bio_buf_read(), because that will move the memory around, and
606  * we want to avoid that if at all possible.
607  */
608  fr_assert(want <= used);
609  fr_assert(packet == my->read_buffer.read);
610  my->read_buffer.read += want;
611  continue;
612 
613  /*
614  * Some kind of fatal validation error.
615  */
617  break;
618  }
619  }
620 
621  return -1;
622 }
623 
624 /** Allocate a memory buffer bio for either reading or writing.
625  */
626 static bool fr_bio_mem_buf_alloc(fr_bio_mem_t *my, fr_bio_buf_t *buf, size_t size)
627 {
628  if (size < 1024) size = 1024;
629  if (size > (1 << 20)) size = 1 << 20;
630 
631  if (fr_bio_buf_alloc(my, buf, size) < 0) {
632  talloc_free(my);
633  return false;
634  }
635 
636  return true;
637 }
638 
639 /** Allocate a memory buffer bio
640  *
641  * The "read buffer" will cache reads from the next bio in the chain. If the next bio returns more data than
642  * the caller asked for, the extra data is cached in the read buffer.
643  *
644  * The "write buffer" will buffer writes to the next bio in the chain. If the caller writes more data than
645  * the next bio can process, the extra data is cached in the write buffer.
646  *
647  * When the bio is closed (or freed) any pending data in the buffers is lost. The same happens if the next
648  * bio returns a fatal error.
649  *
650  * At some point during a read, the next bio may return EOF. When that happens, the caller should not rely
651  * on the next FD being readable or writable. Instead, it should keep reading from the memory bio until it
652  * returns EOF. See fr_bio_fd_eof() for details.
653  *
654  * @param ctx the talloc ctx
655  * @param read_size size of the read buffer. Must be 1024..1^20
656  * @param write_size size of the write buffer. Must be 1024..1^20
657  * @param next the next bio which will perform the underlying reads and writes.
658  * - NULL on error, memory allocation failed
659  * - !NULL the bio
660  */
661 fr_bio_t *fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
662 {
663  fr_bio_mem_t *my;
664 
665  my = talloc_zero(ctx, fr_bio_mem_t);
666  if (!my) return NULL;
667 
668  /*
669  * The caller has to state that the API is caching data both ways.
670  */
671  if (!read_size) {
672  fr_strerror_const("Read size must be non-zero");
673  return NULL;
674  }
675 
676  if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) {
677  oom:
678  fr_strerror_const("Out of memory");
679  return NULL;
680  }
681  my->bio.read = fr_bio_mem_read;
682 
683  if (write_size) {
684  if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) goto oom;
685 
686  my->bio.write = fr_bio_mem_write_next;
687  } else {
688  my->bio.write = fr_bio_next_write;
689  }
690 
691  fr_bio_chain(&my->bio, next);
692 
693  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
694  return (fr_bio_t *) my;
695 }
696 
697 
698 /** Allocate a memory buffer which sources data from the callers application into the bio system.
699  *
700  * The caller writes data to the buffer, but never reads from it. This bio will call the "next" bio to sink
701  * the data.
702  */
703 fr_bio_t *fr_bio_mem_source_alloc(TALLOC_CTX *ctx, size_t write_size, fr_bio_t *next)
704 {
705  fr_bio_mem_t *my;
706 
707  my = talloc_zero(ctx, fr_bio_mem_t);
708  if (!my) return NULL;
709 
710  /*
711  * The caller has to state that the API is caching data.
712  */
713  if (!write_size) return NULL;
714 
715  if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) return NULL;
716 
717  my->bio.read = fr_bio_null_read; /* reading FROM this bio is not possible */
718  my->bio.write = fr_bio_mem_write_next;
719 
720  fr_bio_chain(&my->bio, next);
721 
722  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
723  return (fr_bio_t *) my;
724 }
725 
726 /** Read from a buffer which a previous bio has filled.
727  *
728  * This function is called by the application which wants to read from a sink.
729  */
730 static ssize_t fr_bio_mem_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
731 {
732  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
733 
734  return fr_bio_buf_read(&my->read_buffer, buffer, size);
735 }
736 
737 /** Write to the read buffer.
738  *
739  * This function is called by an upstream function which writes into our local buffer.
740  */
741 static ssize_t fr_bio_mem_write_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
742 {
743  size_t room;
744  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
745 
746  /*
747  * Clamp the write to however much data is available in the buffer.
748  */
749  room = fr_bio_buf_write_room(&my->read_buffer);
750 
751  /*
752  * The buffer is full. We're now blocked.
753  */
754  if (!room) return fr_bio_error(IO_WOULD_BLOCK);
755 
756  if (room < size) size = room;
757 
758  /*
759  * As we have clamped the write, we know that this call must succeed.
760  */
761  return fr_bio_buf_write(&my->read_buffer, buffer, size);
762 }
763 
764 /** Allocate a memory buffer which sinks data from a bio system into the callers application.
765  *
766  * The caller reads data from this bio, but never writes to it. Upstream bios will source the data.
767  */
768 fr_bio_t *fr_bio_mem_sink_alloc(TALLOC_CTX *ctx, size_t read_size)
769 {
770  fr_bio_mem_t *my;
771 
772  my = talloc_zero(ctx, fr_bio_mem_t);
773  if (!my) return NULL;
774 
775  /*
776  * The caller has to state that the API is caching data.
777  */
778  if (!read_size) return NULL;
779 
780  if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) return NULL;
781  my->bio.read = fr_bio_mem_read_buffer;
782  my->bio.write = fr_bio_mem_write_read_buffer; /* the upstream will write to our read buffer */
783 
784  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
785  return (fr_bio_t *) my;
786 }
787 
788 /** Set the verification function for memory bios.
789  *
790  * It is possible to add a verification function. It is not currently possible to remove one.
791  *
792  * @param bio the binary IO handler
793  * @param verify the verification function
794  * @param datagram whether or not this bio is a datagram one.
795  * @return
796  * - <0 on error
797  * - 0 on success
798  */
799 int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, bool datagram)
800 {
801  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
802 
803  if (my->bio.read != fr_bio_mem_read) {
804  fr_strerror_const("Cannot add verify to a memory sink bio");
805  return fr_bio_error(GENERIC);
806  }
807 
808  my->verify = verify;
809 
810  /*
811  * If we are writing datagrams, then we cannot buffer individual datagrams. We must write
812  * either all of the datagram out, or none of it.
813  */
814  if (datagram) {
815  my->bio.read = fr_bio_mem_read_verify_datagram;
816  my->bio.write = fr_bio_next_write;
817 
818  /*
819  * Might as well free the memory for the write buffer. It won't be used.
820  */
821  if (my->write_buffer.start) {
823  my->write_buffer = (fr_bio_buf_t) {};
824  }
825  } else {
826  my->bio.read = fr_bio_mem_read_verify;
827  /* don't touch the write function or the write buffer. */
828  }
829 
830  return 0;
831 }
static int const char char buffer[256]
Definition: acutest.h:574
fr_bio_write_t _CONST write
write to the underlying bio
Definition: base.h:107
fr_bio_read_t _CONST read
read from the underlying bio
Definition: base.h:106
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition: base.h:121
#define fr_bio_error(_x)
Definition: base.h:184
Definition: base.h:103
static void fr_bio_chain(fr_bio_t *first, fr_bio_t *second)
Chain one bio after another.
Definition: bio_priv.h:57
size_t fr_bio_buf_make_room(fr_bio_buf_t *bio_buf)
Definition: buf.c:28
size_t fr_bio_buf_read(fr_bio_buf_t *bio_buf, void *buffer, size_t size)
Definition: buf.c:45
int fr_bio_buf_alloc(TALLOC_CTX *ctx, fr_bio_buf_t *bio_buf, size_t size)
Definition: buf.c:114
ssize_t fr_bio_buf_write(fr_bio_buf_t *bio_buf, const void *buffer, size_t size)
Definition: buf.c:81
static size_t fr_bio_buf_write_room(fr_bio_buf_t const *bio_buf)
Definition: buf.h:82
uint8_t * start
start of the buffer
Definition: buf.h:30
static size_t fr_bio_buf_used(fr_bio_buf_t const *bio_buf)
Definition: buf.h:73
uint8_t * read
where in the buffer reads are taken from
Definition: buf.h:33
static uint8_t * fr_bio_buf_write_reserve(fr_bio_buf_t *bio_buf, size_t size)
Definition: buf.h:89
static int fr_bio_buf_write_alloc(fr_bio_buf_t *bio_buf, size_t size)
Definition: buf.h:98
uint8_t * write
where in the buffer writes are sent to
Definition: buf.h:34
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
ssize_t fr_bio_eof_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always returns EOF on fr_bio_read()
Definition: base.c:49
int fr_bio_destructor(fr_bio_t *bio)
Free this bio.
Definition: base.c:34
ssize_t fr_bio_next_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Internal bio function which just writes to the "next" bio.
Definition: base.c:82
static ssize_t fr_bio_mem_write_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
Write to the read buffer.
Definition: mem.c:741
static ssize_t fr_bio_mem_read_verify(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Return data only if we have a complete packet.
Definition: mem.c:145
void fr_bio_mem_read_discard(fr_bio_t *bio, size_t size)
Discard data from the read buffer.
Definition: mem.c:547
fr_bio_buf_t read_buffer
buffering for reads
Definition: mem.c:40
fr_bio_t * fr_bio_mem_source_alloc(TALLOC_CTX *ctx, size_t write_size, fr_bio_t *next)
Allocate a memory buffer which sources data from the callers application into the bio system.
Definition: mem.c:703
struct fr_bio_mem_s fr_bio_mem_t
The memory buffer bio.
static ssize_t fr_bio_mem_write_next(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Pass writes to the next BIO.
Definition: mem.c:348
static ssize_t fr_bio_mem_read_verify_datagram(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Return data only if we have a complete packet.
Definition: mem.c:273
fr_bio_t * fr_bio_mem_sink_alloc(TALLOC_CTX *ctx, size_t read_size)
Allocate a memory buffer which sinks data from a bio system into the callers application.
Definition: mem.c:768
static ssize_t fr_bio_mem_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Read from a buffer which a previous bio has filled.
Definition: mem.c:730
fr_bio_buf_t write_buffer
buffering for writes
Definition: mem.c:41
int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, bool datagram)
Set the verification function for memory bios.
Definition: mem.c:799
fr_bio_verify_t verify
verify data to see if we have a packet.
Definition: mem.c:38
FR_BIO_COMMON
Definition: mem.c:36
static ssize_t fr_bio_mem_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read from a memory BIO.
Definition: mem.c:84
static ssize_t fr_bio_mem_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
At EOF, read data from the buffer until it is empty.
Definition: mem.c:53
static bool fr_bio_mem_buf_alloc(fr_bio_mem_t *my, fr_bio_buf_t *buf, size_t size)
Allocate a memory buffer bio for either reading or writing.
Definition: mem.c:626
static ssize_t fr_bio_mem_write_flush(fr_bio_mem_t *my, size_t size)
Flush the memory buffer.
Definition: mem.c:426
static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size))
Verify that a packet is OK.
Definition: mem.c:566
fr_bio_t * fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
Allocate a memory buffer bio.
Definition: mem.c:661
static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
uint8_t const * fr_bio_mem_read_peek(fr_bio_t *bio, size_t *size)
Peek at the data in the read buffer.
Definition: mem.c:529
The memory buffer bio.
Definition: mem.c:35
talloc_free(reap)
@ FR_BIO_VERIFY_ERROR_CLOSE
fatal error, the bio should be closed.
Definition: mem.h:36
@ FR_BIO_VERIFY_DISCARD
the packet should be discarded
Definition: mem.h:34
@ FR_BIO_VERIFY_OK
packet is OK
Definition: mem.h:33
@ FR_BIO_VERIFY_WANT_MORE
not enough data for one packet
Definition: mem.h:35
fr_bio_verify_action_t(* fr_bio_verify_t)(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t *size)
Verifies the packet.
Definition: mem.h:50
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static size_t used
ssize_t fr_bio_null_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return 0 on write.
Definition: null.c:39
ssize_t fr_bio_null_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return 0 on read.
Definition: null.c:31
static fr_bio_t * bio
Definition: radclient-ng.c:86
fr_assert(0)
#define VERIFY(_x)
Definition: trie.c:130
#define fr_strerror_const(_msg)
Definition: strerror.h:223
int nonnull(2, 5))