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: c66df4f187d40d34e23024b6dd53cf5529c3df32 $
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  void *verify_ctx; //!< verify context
40 
41  fr_bio_buf_t read_buffer; //!< buffering for reads
42  fr_bio_buf_t write_buffer; //!< buffering for writes
44 
45 static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size);
46 
47 static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size) CC_HINT(nonnull(1,3));
48 
49 /** At EOF, read data from the buffer until it is empty.
50  *
51  * When "next" bio returns EOF, there may still be pending data in the memory buffer. Return that until it's
52  * empty, and then EOF from then on.
53  */
54 static ssize_t fr_bio_mem_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
55 {
56  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
57 
58  /*
59  * No more data: return EOF from now on.
60  */
61  if (fr_bio_buf_used(&my->read_buffer) == 0) {
62 
63  /*
64  * Don't call our EOF function. But do tell the other BIOs that we're at EOF.
65  */
66  my->priv_cb.eof = NULL;
67  fr_bio_eof(&my->bio);
68  return 0;
69  }
70 
71  /*
72  * Return whatever data we have available. One the buffer is empty, the next read will get EOF.
73  */
74  return fr_bio_buf_read(&my->read_buffer, buffer, size);
75 }
76 
77 static int fr_bio_mem_eof(fr_bio_t *bio)
78 {
79  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
80 
81  /*
82  * Nothing more for us to read, tell fr_bio_eof() that it can continue with poking other BIOs.
83  */
84  if (fr_bio_buf_used(&my->read_buffer) == 0) {
85  return 1;
86  }
87 
88  my->bio.read = fr_bio_mem_read_eof;
89 
90  return 0;
91 }
92 
93 /** Read from a memory BIO
94  *
95  * This bio reads as much data as possible into the memory buffer. On the theory that a few memcpy() or
96  * memmove() calls are much cheaper than a system call.
97  *
98  * If the read buffer has enough data to satisfy the read, then it is returned.
99  *
100  * Otherwise the next bio is called to re-fill the buffer. The next read call will try to get as much data
101  * as possible into the buffer, even if that results in reading more than "size" bytes.
102  *
103  * Once the next read has been done, then the data from the buffer is returned, even if it is less than
104  * "size".
105  */
106 static ssize_t fr_bio_mem_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
107 {
108  ssize_t rcode;
109  size_t used, room;
110  uint8_t *p;
111  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
112  fr_bio_t *next;
113 
114  /*
115  * We can satisfy the read from the memory buffer: do so.
116  */
117  used = fr_bio_buf_used(&my->read_buffer);
118  if (size <= used) {
119  return fr_bio_buf_read(&my->read_buffer, buffer, size);
120  }
121 
122  /*
123  * There must be a next bio.
124  */
125  next = fr_bio_next(&my->bio);
126  fr_assert(next != NULL);
127 
128  /*
129  * If there's no room to store more data in the buffer. Just return whatever data we have in the
130  * buffer.
131  */
132  room = fr_bio_buf_write_room(&my->read_buffer);
133  if (!room) return fr_bio_buf_read(&my->read_buffer, buffer, size);
134 
135  /*
136  * We try to fill the buffer as much as possible from the network, even if that means reading
137  * more than "size" amount of data.
138  */
139  p = fr_bio_buf_write_reserve(&my->read_buffer, room);
140  fr_assert(p != NULL); /* otherwise room would be zero */
141 
142  rcode = next->read(next, packet_ctx, p, room);
143 
144  /*
145  * Ensure that whatever data we have read is marked as "used" in the buffer, and then return
146  * whatever data is available back to the caller.
147  */
148  if (rcode >= 0) {
149  if (rcode > 0) (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
150 
151  return fr_bio_buf_read(&my->read_buffer, buffer, size);
152  }
153 
154  /*
155  * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
156  * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
157  * the buffer is lost.
158  */
159  bio->read = fr_bio_mem_read_eof;
160  bio->write = fr_bio_null_write;
161  return rcode;
162 }
163 
164 /** Return data only if we have a complete packet.
165  *
166  */
167 static ssize_t fr_bio_mem_read_verify(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
168 {
169  ssize_t rcode;
170  size_t used, room, want;
171  uint8_t *p;
172  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
173  fr_bio_t *next;
174 
175  /*
176  * We may be able to satisfy the read from the memory buffer.
177  */
178  used = fr_bio_buf_used(&my->read_buffer);
179  if (used) {
180  /*
181  * See if there are valid packets in the buffer.
182  */
183  rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
184  if (rcode < 0) {
185  rcode = fr_bio_error(VERIFY);
186  goto fail;
187  }
188 
189  /*
190  * There's at least one valid packet, return it.
191  */
192  if (rcode == 1) {
193  /*
194  * This isn't a fatal error. The caller should check how much room is needed by calling
195  * fr_bio_mem_call_verify(), and retry.
196  *
197  * But in general, the caller should make sure that the output buffer has enough
198  * room for at least one packet. The verify() function should also ensure that
199  * the packet is no larger than our application maximum, even if the protocol
200  * allows for it to be larger.
201  */
202  if (want > size) return fr_bio_error(BUFFER_TOO_SMALL);
203 
204  return fr_bio_buf_read(&my->read_buffer, buffer, want);
205  }
206 
207  /*
208  * Else we need to read more data to have a complete packet.
209  */
210  }
211 
212  /*
213  * There must be a next bio.
214  */
215  next = fr_bio_next(&my->bio);
216  fr_assert(next != NULL);
217 
218  /*
219  * If there's no room to store more data in the buffer, try to make some room.
220  */
221  room = fr_bio_buf_write_room(&my->read_buffer);
222  if (!room) {
223  room = fr_bio_buf_make_room(&my->read_buffer);
224 
225  /*
226  * We've tried to make room and failed. Which means that the buffer is full, AND there
227  * still isn't a complete packet in the buffer. This is therefore a fatal error. The
228  * application has not supplied us with enough read_buffer space to store a complete
229  * packet.
230  */
231  if (!room) {
232  rcode = fr_bio_error(BUFFER_FULL);
233  goto fail;
234  }
235  }
236 
237  /*
238  * We try to fill the buffer as much as possible from the network. The theory is that a few
239  * extra memcpy() or memmove()s are cheaper than a system call for reading each packet.
240  */
241  p = fr_bio_buf_write_reserve(&my->read_buffer, room);
242  fr_assert(p != NULL); /* otherwise room would be zero */
243 
244  rcode = next->read(next, packet_ctx, p, room);
245 
246  /*
247  * The next bio returned some data. See if it's a valid packet.
248  */
249  if (rcode > 0) {
250  (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
251 
252  want = fr_bio_buf_used(&my->read_buffer);
253  if (size <= want) want = size;
254 
255  /*
256  * See if there are valid packets in the buffer.
257  */
258  rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
259  if (rcode < 0) {
260  rcode = fr_bio_error(VERIFY);
261  goto fail;
262  }
263 
264  /*
265  * There's at least one valid packet, return it.
266  */
267  if (rcode == 1) return fr_bio_buf_read(&my->read_buffer, buffer, want);
268 
269  /*
270  * No valid packets. The next call to read will call verify again, which will return a
271  * partial packet. And then it will try to fill the buffer from the next bio.
272  */
273  return 0;
274  }
275 
276  /*
277  * No data was read from the next bio, we still don't have a packet. Return nothing.
278  */
279  if (rcode == 0) return 0;
280 
281  /*
282  * The next bio returned an error either when our buffer was empty, or else it had only a partial
283  * packet in it. We can no longer read full packets from this BIO, and we can't read from the
284  * next one, either. So shut down the BIO completely.
285  */
286 fail:
287  bio->read = fr_bio_fail_read;
288  bio->write = fr_bio_fail_write;
289  return rcode;
290 }
291 
292 /** Return data only if we have a complete packet.
293  *
294  */
295 static ssize_t fr_bio_mem_read_verify_datagram(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
296 {
297  ssize_t rcode;
298  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
299  fr_bio_t *next;
300 
301  /*
302  * There must be a next bio.
303  */
304  next = fr_bio_next(&my->bio);
305  fr_assert(next != NULL);
306 
307  rcode = next->read(next, packet_ctx, buffer, size);
308  if (rcode > 0) {
309  size_t want = rcode;
310 
311  /*
312  * It's a datagram socket, there can only be one packet in the buffer.
313  *
314  * @todo - if we're allowed more than one packet in the buffer, we should just call
315  * fr_bio_mem_read_verify(), or this function should call fr_bio_mem_call_verify().
316  */
317  switch (my->verify((fr_bio_t *) my, my->verify_ctx, packet_ctx, buffer, &want)) {
318  /*
319  * The data in the buffer is exactly a packet. Return that.
320  *
321  * @todo - if there are multiple packets, return the total size of packets?
322  */
323  case FR_BIO_VERIFY_OK:
324  fr_assert(want <= (size_t) rcode);
325  return want;
326 
327  /*
328  * The data in the buffer doesn't make up a complete packet, discard it. The
329  * called verify function should take care of logging.
330  */
332  return 0;
333 
335  return 0;
336 
337  /*
338  * Some kind of fatal validation error.
339  */
341  break;
342  }
343 
344  rcode = fr_bio_error(VERIFY);
345  goto fail;
346  }
347 
348  /*
349  * No data was read from the next bio, we still don't have a packet. Return nothing.
350  */
351  if (rcode == 0) return 0;
352 
353  /*
354  * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
355  * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
356  * the buffer is lost.
357  */
358 fail:
359  bio->read = fr_bio_mem_read_eof;
360  bio->write = fr_bio_null_write;
361  return rcode;
362 }
363 
364 
365 /** Pass writes to the next BIO
366  *
367  * For speed, we try to bypass the memory buffer and write directly to the next bio. However, if the next
368  * bio returns EWOULDBLOCK, we write the data to the memory buffer, even if it is partial data.
369  */
370 static ssize_t fr_bio_mem_write_next(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
371 {
372  int error;
373  ssize_t rcode;
374  size_t room, leftover;
375  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
376  fr_bio_t *next;
377 
378  /*
379  * We can't call the next bio if there's still cached data to flush.
380  *
381  * There must be a next bio.
382  */
383  fr_assert(fr_bio_buf_used(&my->write_buffer) == 0);
384 
385  next = fr_bio_next(&my->bio);
386  fr_assert(next != NULL);
387 
388  /*
389  * The next bio may write all of the data. If so, we return that,
390  */
391  rcode = next->write(next, packet_ctx, buffer, size);
392  if ((size_t) rcode == size) return rcode;
393 
394  /*
395  * The next bio returned an error. Anything other than WOULD BLOCK is fatal. We can read from
396  * the memory buffer until it's empty, but we can no longer write to the memory buffer.
397  */
398  if ((rcode < 0) && (rcode != fr_bio_error(IO_WOULD_BLOCK))) {
399  bio->read = fr_bio_mem_read_eof;
400  bio->write = fr_bio_null_write;
401  return rcode;
402  }
403 
404  /*
405  * We were flushing the BIO, return however much data we managed to write.
406  *
407  * Note that flushes should never block.
408  */
409  if (!buffer) {
410  fr_assert(rcode != fr_bio_error(IO_WOULD_BLOCK));
411  return rcode;
412  }
413 
414  /*
415  * Tell previous BIOs in the chain that they are blocked.
416  */
417  error = fr_bio_write_blocked(bio);
418  if (error < 0) return error;
419 
420  fr_assert(error != 0); /* what to do? */
421 
422  /*
423  * We had WOULD BLOCK, or wrote partial bytes. Save the data to the memory buffer, and ensure
424  * that future writes are ordered. i.e. they write to the memory buffer before writing to the
425  * next bio.
426  */
428 
429  /*
430  * Clamp the write to however much data is available in the buffer.
431  */
432  leftover = size - rcode;
433  room = fr_bio_buf_write_room(&my->write_buffer);
434 
435  /*
436  * If we have "used == 0" above, then we must also have "room > 0".
437  */
438  fr_assert(room > 0);
439 
440  if (room < leftover) leftover = room;
441 
442  /*
443  * Since we've clamped the write, this call can never fail.
444  */
445  (void) fr_bio_buf_write(&my->write_buffer, ((uint8_t const *) buffer) + rcode, leftover);
446 
447  /*
448  * Some of the data base been written to the next bio, and some to our cache. The caller has to
449  * ensure that the first subsequent write will send over the rest of the data.
450  *
451  * However, we tell the caller that we wrote the entire packet. Because we are now responsible
452  * for writing the remaining bytes.
453  */
454  return size;
455 }
456 
457 /** Flush the memory buffer.
458  *
459  */
461 {
462  int rcode;
463  size_t used;
464  fr_bio_t *next;
465 
466  /*
467  * Nothing to flush, don't do any writes.
468  *
469  * Instead, set the write function to write next, where data will be sent directly to the next
470  * bio, and will bypass the write buffer.
471  */
472  used = fr_bio_buf_used(&my->write_buffer);
473  if (!used) {
474  my->bio.write = fr_bio_mem_write_next;
475  return 0;
476  }
477 
478  next = fr_bio_next(&my->bio);
479  fr_assert(next != NULL);
480 
481  /*
482  * Clamp the amount of data written. If the caller wants to write everything, it should
483  * pass SIZE_MAX.
484  */
485  if (used < size) used = size;
486 
487  /*
488  * Flush the buffer to the next bio in line. That function will write as much data as possible,
489  * but may return a partial write.
490  */
491  rcode = next->write(next, NULL, my->write_buffer.write, used);
492 
493  /*
494  * We didn't write anything, the bio is blocked.
495  */
496  if ((rcode == 0) || (rcode == fr_bio_error(IO_WOULD_BLOCK))) return fr_bio_error(IO_WOULD_BLOCK);
497 
498  /*
499  * All other errors are fatal. We can read from the memory buffer until it's empty, but we can
500  * no longer write to the memory buffer.
501  */
502  if (rcode < 0) return rcode;
503 
504  /*
505  * Tell the buffer that we've read a certain amount of data from it.
506  */
507  (void) fr_bio_buf_read(&my->write_buffer, NULL, (size_t) rcode);
508 
509  /*
510  * We haven't emptied the buffer, any further IO is blocked.
511  */
512  if ((size_t) rcode < used) return fr_bio_error(IO_WOULD_BLOCK);
513 
514  /*
515  * We've flushed all of the buffer. Revert back to "pass through" writing.
516  */
517  fr_assert(fr_bio_buf_used(&my->write_buffer) == 0);
518  my->bio.write = fr_bio_mem_write_next;
519  return rcode;
520 }
521 
522 /** Write to the memory buffer.
523  *
524  * The special buffer pointer of NULL means flush(). On flush, we call next->read(), and if that succeeds,
525  * go back to "pass through" mode for the buffers.
526  */
527 static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
528 {
529  size_t room;
530  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
531 
532  /*
533  * Flush the output buffer.
534  */
535  if (unlikely(!buffer)) return fr_bio_mem_write_flush(my, size);
536 
537  /*
538  * Clamp the write to however much data is available in the buffer.
539  */
540  room = fr_bio_buf_write_room(&my->write_buffer);
541 
542  /*
543  * The buffer is full, we can't write anything.
544  */
545  if (!room) return fr_bio_error(IO_WOULD_BLOCK);
546 
547  /*
548  * If we're asked to write more bytes than are available in the buffer, then tell the caller that
549  * writes are now blocked, and we can't write any more data.
550  *
551  * Return an WOULD_BLOCK error instead of breaking our promise by writing part of the data,
552  * instead of accepting a full application write.
553  */
554  if (room < size) {
555  int rcode;
556 
557  rcode = fr_bio_write_blocked(bio);
558  if (rcode < 0) return rcode;
559 
560  return fr_bio_error(IO_WOULD_BLOCK);
561  }
562 
563  /*
564  * As we have clamped the write, we know that this call must succeed.
565  */
566  (void) fr_bio_buf_write(&my->write_buffer, buffer, size);
567 
568  /*
569  * If we've filled the buffer, tell the caller that writes are now blocked, and we can't write
570  * any more data. However, we still return the amount of data we wrote.
571  */
572  if (room == size) {
573  int rcode;
574 
575  rcode = fr_bio_write_blocked(bio);
576  if (rcode < 0) return rcode;
577  }
578 
579  return size;
580 }
581 
582 /** Peek at the data in the read buffer
583  *
584  * Peeking at the data allows us to avoid many memory copies.
585  */
586 uint8_t const *fr_bio_mem_read_peek(fr_bio_t *bio, size_t *size)
587 {
588  size_t used;
589  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
590 
591  used = fr_bio_buf_used(&my->read_buffer);
592 
593  if (!used) return NULL;
594 
595  *size = used;
596  return my->read_buffer.read;
597 }
598 
599 /** Discard data from the read buffer.
600  *
601  * Discarding allows the caller to silently omit packets, so that
602  * they are not passed up to previous bios.
603  */
604 void fr_bio_mem_read_discard(fr_bio_t *bio, size_t size)
605 {
606  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
607 
608  (void) fr_bio_buf_read(&my->read_buffer, NULL, size);
609 }
610 
611 /** Verify that a packet is OK.
612  *
613  * @todo - have this as a parameter to the read routines, so that they only return complete packets?
614  *
615  * @param bio the #fr_bio_mem_t
616  * @param packet_ctx the packet ctx
617  * @param[out] size how big the verified packet is
618  * @return
619  * - <0 for FR_BIO_VERIFY_ERROR_CLOSE, the caller should close the bio.
620  * - 0 for "we have a partial packet", the size to read is in *size
621  * - 1 for "we have at least one good packet", the size of it is in *size
622  */
623 static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size)
624 {
625  uint8_t *packet, *end;
626  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
627 
628  packet = my->read_buffer.read;
629  end = my->read_buffer.write;
630 
631  while (packet < end) {
632  size_t want;
633 #ifndef NDEBUG
634  size_t used;
635 
636  used = end - packet;
637 #endif
638 
639  want = end - packet;
640 
641  switch (my->verify((fr_bio_t *) my, my->verify_ctx, packet_ctx, packet, &want)) {
642  /*
643  * The data in the buffer is exactly a packet. Return that.
644  *
645  * @todo - if there are multiple packets, return the total size of packets?
646  */
647  case FR_BIO_VERIFY_OK:
648  fr_assert(want <= used);
649  *size = want;
650  return 1;
651 
652  /*
653  * The packet needs more data. Return how much data we need for one packet.
654  */
656  fr_assert(want > used);
657  *size = want;
658  return 0;
659 
661  /*
662  * We don't call fr_bio_buf_read(), because that will move the memory around, and
663  * we want to avoid that if at all possible.
664  */
665  fr_assert(want <= used);
666  fr_assert(packet == my->read_buffer.read);
667  my->read_buffer.read += want;
668  continue;
669 
670  /*
671  * Some kind of fatal validation error.
672  */
674  break;
675  }
676  }
677 
678  return -1;
679 }
680 
681 /*
682  * The application can read from the BIO until EOF, but cannot write to it.
683  */
684 static void fr_bio_mem_shutdown(fr_bio_t *bio)
685 {
686  bio->read = fr_bio_mem_read_eof;
687  bio->write = fr_bio_null_write;
688 }
689 
690 /** Allocate a memory buffer bio for either reading or writing.
691  */
692 static bool fr_bio_mem_buf_alloc(fr_bio_mem_t *my, fr_bio_buf_t *buf, size_t size)
693 {
694  if (size < 1024) size = 1024;
695  if (size > (1 << 20)) size = 1 << 20;
696 
697  if (fr_bio_buf_alloc(my, buf, size) < 0) {
698  talloc_free(my);
699  return false;
700  }
701 
702  return true;
703 }
704 
705 /** Allocate a memory buffer bio
706  *
707  * The "read buffer" will cache reads from the next bio in the chain. If the next bio returns more data than
708  * the caller asked for, the extra data is cached in the read buffer.
709  *
710  * The "write buffer" will buffer writes to the next bio in the chain. If the caller writes more data than
711  * the next bio can process, the extra data is cached in the write buffer.
712  *
713  * When the bio is closed (or freed) any pending data in the buffers is lost. The same happens if the next
714  * bio returns a fatal error.
715  *
716  * At some point during a read, the next bio may return EOF. When that happens, the caller should not rely
717  * on the next FD being readable or writable. Instead, it should keep reading from the memory bio until it
718  * returns EOF. See fr_bio_fd_eof() for details.
719  *
720  * @param ctx the talloc ctx
721  * @param read_size size of the read buffer. Must be 1024..1^20
722  * @param write_size size of the write buffer. Can be zero. If non-zero, must be 1024..1^20
723  * @param next the next bio which will perform the underlying reads and writes.
724  * - NULL on error, memory allocation failed
725  * - !NULL the bio
726  */
727 fr_bio_t *fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
728 {
729  fr_bio_mem_t *my;
730 
731  /*
732  * The caller has to state that the API is caching data both ways.
733  */
734  if (!read_size) {
735  fr_strerror_const("Read size must be non-zero");
736  return NULL;
737  }
738 
739  my = talloc_zero(ctx, fr_bio_mem_t);
740  if (!my) return NULL;
741 
742  if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) {
743  oom:
744  fr_strerror_const("Out of memory");
745  return NULL;
746  }
747  my->bio.read = fr_bio_mem_read;
748 
749  if (write_size) {
750  if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) goto oom;
751 
752  my->bio.write = fr_bio_mem_write_next;
753  } else {
754  my->bio.write = fr_bio_next_write;
755  }
756  my->priv_cb.eof = fr_bio_mem_eof;
757  my->priv_cb.write_resume = fr_bio_mem_write_resume;
758  my->priv_cb.shutdown = fr_bio_mem_shutdown;
759 
760  fr_bio_chain(&my->bio, next);
761 
762  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
763  return (fr_bio_t *) my;
764 }
765 
766 
767 /** Allocate a memory buffer which sources data from the callers application into the bio system.
768  *
769  * The caller writes data to the buffer, but never reads from it. This bio will call the "next" bio to sink
770  * the data.
771  */
772 fr_bio_t *fr_bio_mem_source_alloc(TALLOC_CTX *ctx, size_t write_size, fr_bio_t *next)
773 {
774  fr_bio_mem_t *my;
775 
776  /*
777  * The caller has to state that the API is caching data.
778  */
779  if (!write_size) return NULL;
780 
781  my = talloc_zero(ctx, fr_bio_mem_t);
782  if (!my) return NULL;
783 
784  if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) {
785  talloc_free(my);
786  return NULL;
787  }
788 
789  my->bio.read = fr_bio_null_read; /* reading FROM this bio is not possible */
790  my->bio.write = fr_bio_mem_write_next;
791 
792  /*
793  * @todo - have write pause / write resume callbacks?
794  */
795  my->priv_cb.shutdown = fr_bio_mem_shutdown;
796 
797  fr_bio_chain(&my->bio, next);
798 
799  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
800  return (fr_bio_t *) my;
801 }
802 
803 /** Read from a buffer which a previous bio has filled.
804  *
805  * This function is called by the application which wants to read from a sink.
806  */
807 static ssize_t fr_bio_mem_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
808 {
809  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
810 
811  return fr_bio_buf_read(&my->read_buffer, buffer, size);
812 }
813 
814 /** Write to the read buffer.
815  *
816  * This function is called by an upstream function which writes into our local buffer.
817  */
818 static ssize_t fr_bio_mem_write_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
819 {
820  size_t room;
821  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
822 
823  /*
824  * Clamp the write to however much data is available in the buffer.
825  */
826  room = fr_bio_buf_write_room(&my->read_buffer);
827 
828  /*
829  * The buffer is full. We're now blocked.
830  */
831  if (!room) return fr_bio_error(IO_WOULD_BLOCK);
832 
833  if (room < size) size = room;
834 
835  /*
836  * As we have clamped the write, we know that this call must succeed.
837  */
838  return fr_bio_buf_write(&my->read_buffer, buffer, size);
839 }
840 
841 /** Allocate a memory buffer which sinks data from a bio system into the callers application.
842  *
843  * The caller reads data from this bio, but never writes to it. Upstream BIOs will source the data.
844  */
845 fr_bio_t *fr_bio_mem_sink_alloc(TALLOC_CTX *ctx, size_t read_size)
846 {
847  fr_bio_mem_t *my;
848 
849  /*
850  * The caller has to state that the API is caching data.
851  */
852  if (!read_size) return NULL;
853 
854  my = talloc_zero(ctx, fr_bio_mem_t);
855  if (!my) return NULL;
856 
857  if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) {
858  talloc_free(my);
859  return NULL;
860  }
861 
862  my->bio.read = fr_bio_mem_read_buffer;
863  my->bio.write = fr_bio_mem_write_read_buffer; /* the upstream will write to our read buffer */
864 
865  talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
866  return (fr_bio_t *) my;
867 }
868 
869 /** Set the verification function for memory bios.
870  *
871  * It is possible to add a verification function. It is not currently possible to remove one.
872  *
873  * @param bio the binary IO handler
874  * @param verify the verification function
875  * @param datagram whether or not this bio is a datagram one.
876  * @return
877  * - <0 on error
878  * - 0 on success
879  */
880 int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
881 {
882  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
883 
884  if (my->bio.read != fr_bio_mem_read) {
885  fr_strerror_const("Cannot add verify to a memory sink bio");
886  return fr_bio_error(GENERIC);
887  }
888 
889  my->verify = verify;
890  my->verify_ctx = verify_ctx;
891 
892  /*
893  * If we are writing datagrams, then we cannot buffer individual datagrams. We must write
894  * either all of the datagram out, or none of it.
895  */
896  if (datagram) {
898  my->bio.write = fr_bio_next_write;
899 
900  /*
901  * Might as well free the memory for the write buffer. It won't be used.
902  */
903  if (my->write_buffer.start) {
904  talloc_free(my->write_buffer.start);
905  my->write_buffer = (fr_bio_buf_t) {};
906  }
907  } else {
908  my->bio.read = fr_bio_mem_read_verify;
909  /* don't touch the write function or the write buffer. */
910  }
911 
912  return 0;
913 }
914 
915 /*
916  * There's no fr_bio_mem_write_blocked()
917  */
918 
919 /** See if we can resume writes to the memory bio.
920  *
921  * Note that there is no equivalent fr_bio_mem_write_blocked(), as that function wouldn't do anything.
922  * Perhaps it could swap the write function to fr_bio_mem_write_buffer(), but the fr_bio_mem_write_next()
923  * function should automatically do that when the write to the next bio only writes part of the data,
924  * or if it returns fr_bio_error(IO_WOULD_BLOCK)
925  */
927 {
928  fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
929  ssize_t rcode;
930 
931  if (bio->write != fr_bio_mem_write_buffer) return 1;
932 
933  /*
934  * Flush the buffer, and then reset the write routine if we were successful.
935  */
936  rcode = fr_bio_mem_write_flush(my, SIZE_MAX);
937  if (rcode <= 0) return rcode;
938 
939  if (fr_bio_buf_used(&my->write_buffer) > 0) return 0;
940 
941  if (!my->cb.write_resume) return 1;
942 
943  return my->cb.write_resume(bio);
944 }
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:116
fr_bio_read_t _CONST read
read from the underlying bio
Definition: base.h:115
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition: base.h:130
#define fr_bio_error(_x)
Definition: base.h:192
Definition: base.h:112
static void fr_bio_chain(fr_bio_t *first, fr_bio_t *second)
Chain one bio after another.
Definition: bio_priv.h:69
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
static size_t fr_bio_buf_used(fr_bio_buf_t const *bio_buf)
Definition: buf.h:73
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
#define unlikely(_x)
Definition: build.h:379
#define UNUSED
Definition: build.h:313
next
Definition: dcursor.h:178
fr_bio_shutdown & my
Definition: fd_errno.h:59
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
Definition: base.c:293
void fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
Definition: base.c:244
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:74
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:818
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:167
void * verify_ctx
verify context
Definition: mem.c:39
void fr_bio_mem_read_discard(fr_bio_t *bio, size_t size)
Discard data from the read buffer.
Definition: mem.c:604
fr_bio_buf_t read_buffer
buffering for reads
Definition: mem.c:41
static int fr_bio_mem_eof(fr_bio_t *bio)
Definition: mem.c:77
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:772
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:370
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:295
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:845
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:807
int fr_bio_mem_write_resume(fr_bio_t *bio)
See if we can resume writes to the memory bio.
Definition: mem.c:926
fr_bio_buf_t write_buffer
buffering for writes
Definition: mem.c:42
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:106
int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
Set the verification function for memory bios.
Definition: mem.c:880
static void fr_bio_mem_shutdown(fr_bio_t *bio)
Definition: mem.c:684
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:54
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:692
static ssize_t fr_bio_mem_write_flush(fr_bio_mem_t *my, size_t size)
Flush the memory buffer.
Definition: mem.c:460
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:623
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:727
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:586
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 *verify_ctx, void *packet_ctx, const void *buffer, size_t *size)
Verifies the packet.
Definition: mem.h:51
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
ssize_t fr_bio_fail_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return error on read.
Definition: null.c:47
ssize_t fr_bio_fail_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:56
fr_assert(0)
#define VERIFY(_x)
Definition: trie.c:130
#define fr_strerror_const(_msg)
Definition: strerror.h:223
int nonnull(2, 5))