The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
bio_mem_tests.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library 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 GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Tests for the memory bio
18 *
19 * @file src/lib/bio/test/bio_mem_tests.c
20 *
21 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
22 */
23#include <freeradius-devel/util/test/acutest_common_init.h>
24#include <freeradius-devel/util/test/acutest_helpers.h>
25
26#include <freeradius-devel/bio/bio_priv.h>
27#include <freeradius-devel/bio/mem.h>
28#include <freeradius-devel/bio/null.h>
29#include <freeradius-devel/bio/pipe.h>
30
31static int cb_noop(fr_bio_t *bio) { (void) bio; return 0; }
32static void cb_noop_void(fr_bio_t *bio) { (void) bio; }
33
36 .write_resume = cb_noop,
37 .read_blocked = cb_noop,
38 .write_blocked = cb_noop,
39 .eof = cb_noop_void,
40};
41
42/** Framing for the tests: the first byte of a packet is its total length.
43 */
44typedef struct {
45 bool fail; //!< return ERROR_CLOSE for the next packet
47
49 const void *buffer, size_t *size)
50{
51 test_verify_ctx_t *tctx = verify_ctx;
52 uint8_t const *p = buffer;
53
54 if (tctx->fail) return FR_BIO_VERIFY_ERROR_CLOSE;
55
56 if (*size < 1) {
57 *size = 1;
59 }
60
61 if (*size < (size_t) p[0]) {
62 *size = p[0];
64 }
65
66 *size = p[0];
67 return FR_BIO_VERIFY_OK;
68}
69
70/** Put bytes where the memory bio's reads will find them.
71 *
72 * fr_bio_write() requires the head of a chain, and the source is the tail, so this calls the
73 * source's own write routine.
74 */
75static ssize_t test_source_write(fr_bio_t *source, char const *data, size_t size)
76{
77 return source->write(source, NULL, data, size);
78}
79
80/** A memory bio in front of a pipe, which stands in for the network.
81 *
82 * Writing to the pipe puts bytes where the memory bio's reads will find them.
83 */
84static fr_bio_t *test_mem_alloc(TALLOC_CTX *ctx, fr_bio_t **source_p, test_verify_ctx_t *tctx)
85{
86 fr_bio_t *mem, *source;
87
88 source = fr_bio_pipe_alloc(ctx, &test_cb, 1024);
89 if (!source) return NULL;
90
91 mem = fr_bio_mem_alloc(ctx, 1024, 0, source);
92 if (!mem) return NULL;
93
94 if (tctx && (fr_bio_mem_set_verify(mem, test_verify, tctx, false) < 0)) return NULL;
95
96 if (source_p) *source_p = source;
97 return mem;
98}
99
100/** A complete packet is returned, and only one packet at a time.
101 */
102static void test_verify_one_packet(void)
103{
104 TALLOC_CTX *ctx = talloc_init_const("test");
105 test_verify_ctx_t tctx = {};
106 fr_bio_t *mem, *source;
107 uint8_t buf[64];
108 ssize_t slen;
109
110 mem = test_mem_alloc(ctx, &source, &tctx);
111 TEST_CHECK(mem != NULL);
112 if (!mem) goto done;
113
114 TEST_CHECK_RET((int) test_source_write(source, "\x05""abcd", 5), 5);
115
116 TEST_CASE("one whole packet comes back");
117 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
118 TEST_CHECK_RET((int) slen, 5);
119 if (slen == 5) TEST_CHECK(memcmp(buf, "\x05""abcd", 5) == 0);
120
121 TEST_CASE("there is nothing else to read");
122 TEST_CHECK_RET((int) fr_bio_read(mem, NULL, buf, sizeof(buf)), 0);
123
124done:
125 talloc_free(ctx);
126}
127
128/** A packet split across two reads is reassembled.
129 */
131{
132 TALLOC_CTX *ctx = talloc_init_const("test");
133 test_verify_ctx_t tctx = {};
134 fr_bio_t *mem, *source;
135 uint8_t buf[64];
136 ssize_t slen;
137
138 mem = test_mem_alloc(ctx, &source, &tctx);
139 TEST_CHECK(mem != NULL);
140 if (!mem) goto done;
141
142 TEST_CASE("half a packet is not a packet");
143 TEST_CHECK_RET((int) test_source_write(source, "\x05""ab", 3), 3);
144 TEST_CHECK_RET((int) fr_bio_read(mem, NULL, buf, sizeof(buf)), 0);
145
146 TEST_CASE("the rest of it completes the packet");
147 TEST_CHECK_RET((int) test_source_write(source, "cd", 2), 2);
148 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
149 TEST_CHECK_RET((int) slen, 5);
150 if (slen == 5) TEST_CHECK(memcmp(buf, "\x05""abcd", 5) == 0);
151
152done:
153 talloc_free(ctx);
154}
155
156/** Pipelined packets: a buffer holding more than one packet must still return the first.
157 *
158 * mem.md finding 1. The second path used to compare the whole buffer against the caller's size,
159 * and return BUFFER_TOO_SMALL although a complete packet was sitting at the front.
160 */
161static void test_verify_pipelined(void)
162{
163 TALLOC_CTX *ctx = talloc_init_const("test");
164 test_verify_ctx_t tctx = {};
165 fr_bio_t *mem, *source;
166 uint8_t buf[5];
167 ssize_t slen;
168
169 mem = test_mem_alloc(ctx, &source, &tctx);
170 TEST_CHECK(mem != NULL);
171 if (!mem) goto done;
172
173 TEST_CASE("two packets arrive in one go");
174 TEST_CHECK_RET((int) test_source_write(source, "\x05""abcd" "\x05""efgh", 10), 10);
175
176 TEST_CASE("a one-packet buffer gets the first packet, not an error");
177 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
178 TEST_MSG("returned %zd (%s)", slen, slen < 0 ? fr_bio_strerror(slen) : "no error");
179 TEST_CHECK_RET((int) slen, 5);
180 if (slen == 5) TEST_CHECK(memcmp(buf, "\x05""abcd", 5) == 0);
181
182 TEST_CASE("and the second packet on the next read");
183 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
184 TEST_CHECK_RET((int) slen, 5);
185 if (slen == 5) TEST_CHECK(memcmp(buf, "\x05""efgh", 5) == 0);
186
187done:
188 talloc_free(ctx);
189}
190
191/** A caller buffer smaller than the packet is an error, and loses nothing.
192 */
194{
195 TALLOC_CTX *ctx = talloc_init_const("test");
196 test_verify_ctx_t tctx = {};
197 fr_bio_t *mem, *source;
198 uint8_t small[3], big[64];
199 ssize_t slen;
200
201 mem = test_mem_alloc(ctx, &source, &tctx);
202 TEST_CHECK(mem != NULL);
203 if (!mem) goto done;
204
205 TEST_CHECK_RET((int) test_source_write(source, "\x05""abcd", 5), 5);
206
207 TEST_CASE("too small a buffer is reported as such");
208 TEST_CHECK(fr_bio_read(mem, NULL, small, sizeof(small)) == fr_bio_error(BUFFER_TOO_SMALL));
209
210 TEST_CASE("and the packet is still there for a bigger one");
211 slen = fr_bio_read(mem, NULL, big, sizeof(big));
212 TEST_CHECK_RET((int) slen, 5);
213 if (slen == 5) TEST_CHECK(memcmp(big, "\x05""abcd", 5) == 0);
214
215done:
216 talloc_free(ctx);
217}
218
219/** A verify function which says "close" shuts the chain down.
220 */
221static void test_verify_error_close(void)
222{
223 TALLOC_CTX *ctx = talloc_init_const("test");
224 test_verify_ctx_t tctx = {};
225 fr_bio_t *mem, *source;
226 uint8_t buf[64];
227
228 mem = test_mem_alloc(ctx, &source, &tctx);
229 TEST_CHECK(mem != NULL);
230 if (!mem) goto done;
231
232 TEST_CHECK_RET((int) test_source_write(source, "\x05""abcd", 5), 5);
233 tctx.fail = true;
234
235 TEST_CASE("a verify failure is reported as one");
236 TEST_CHECK(fr_bio_read(mem, NULL, buf, sizeof(buf)) == fr_bio_error(VERIFY));
237
238 TEST_CASE("and the chain is shut down");
239 TEST_CHECK(fr_bio_read(mem, NULL, buf, sizeof(buf)) == fr_bio_error(SHUTDOWN));
240
241done:
242 talloc_free(ctx);
243}
244
245/** Without a verify function the bio is a plain buffer, and hands back what it has.
246 *
247 * mem.md finding 9. A zero from the next bio means no more is coming, and the bytes already
248 * buffered still belong to the application.
249 */
251{
252 TALLOC_CTX *ctx = talloc_init_const("test");
253 fr_bio_t *mem, *source;
254 uint8_t buf[64];
255 ssize_t slen;
256
257 mem = test_mem_alloc(ctx, &source, NULL);
258 TEST_CHECK(mem != NULL);
259 if (!mem) goto done;
260
261 TEST_CHECK_RET((int) test_source_write(source, "abcde", 5), 5);
262
263 TEST_CASE("a small read buffers the rest");
264 slen = fr_bio_read(mem, NULL, buf, 2);
265 TEST_CHECK_RET((int) slen, 2);
266 if (slen == 2) TEST_CHECK(memcmp(buf, "ab", 2) == 0);
267
268 TEST_CASE("asking for more than is left still returns what is left");
269 TEST_MSG("the source has nothing more, but three bytes are buffered");
270 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
271 TEST_CHECK_RET((int) slen, 3);
272 if (slen == 3) TEST_CHECK(memcmp(buf, "cde", 3) == 0);
273
274 TEST_CASE("and then there is nothing");
275 TEST_CHECK_RET((int) fr_bio_read(mem, NULL, buf, sizeof(buf)), 0);
276
277done:
278 talloc_free(ctx);
279}
280
281/** A stub transport which fails recoverably or fatally, as each test chooses.
282 *
283 * On a recoverable failure, the stub returns an error and changes nothing else. On a fatal failure,
284 * the stub first shuts the chain down, as the fd bio does. Only the failing bio decides whether a
285 * failure is recoverable or fatal.
286 */
287typedef struct {
289 bool data_sent; //!< the first read has returned "abcde"
290 bool fatal; //!< shut the chain down before failing
291} stub_t;
292
293static int shutdown_count;
294
295static int cb_shutdown(fr_bio_t *bio) { (void) bio; shutdown_count++; return 0; }
296
299 .write_resume = cb_noop,
300 .read_blocked = cb_noop,
301 .write_blocked = cb_noop,
302 .eof = cb_noop_void,
303 .shutdown = cb_shutdown,
304};
305
306/** Return "abcde" once, and fail every read after that.
307 */
308static ssize_t stub_read(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
309{
310 stub_t *stub = (stub_t *) bio;
311
312 if (stub->data_sent || (size < 5)) {
313 if (stub->fatal) (void) fr_bio_shutdown(bio);
314
315 fr_strerror_const("stub read failure");
316 return fr_bio_error(GENERIC);
317 }
318
319 stub->data_sent = true;
320 memcpy(buffer, "abcde", 5);
321 return 5;
322}
323
324static ssize_t stub_write_fail(fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
325{
326 stub_t *stub = (stub_t *) bio;
327
328 if (stub->fatal) (void) fr_bio_shutdown(bio);
329
330 fr_strerror_const("stub write failure");
331 return fr_bio_error(GENERIC);
332}
333
334/** Accept one byte of each write, so the memory bio buffers the rest.
335 */
336static ssize_t stub_write_one(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
337{
338 return 1;
339}
340
341/** Accept every write in full.
342 */
343static ssize_t stub_write_all(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, size_t size)
344{
345 return size;
346}
347
348static fr_bio_t *stub_alloc(TALLOC_CTX *ctx)
349{
350 stub_t *stub;
351
352 shutdown_count = 0;
353
354 stub = talloc_zero(ctx, stub_t);
355 if (!stub) return NULL;
356
357 stub->bio.read = stub_read;
358 stub->bio.write = stub_write_fail;
359
360 return &stub->bio;
361}
362
363/** The memory bio passes a recoverable write error up to the application, and keeps working.
364 */
366{
367 TALLOC_CTX *ctx = talloc_init_const("test");
368 fr_bio_t *mem, *stub;
369
370 stub = stub_alloc(ctx);
371 TEST_CHECK(stub != NULL);
372 if (!stub) goto done;
373
374 mem = fr_bio_mem_alloc(ctx, 1024, 1024, stub);
375 TEST_CHECK(mem != NULL);
376 if (!mem) goto done;
377
378 fr_bio_cb_set(mem, &stub_cb);
379
380 TEST_CASE("the write gets the error from the stub");
381 TEST_CHECK(fr_bio_write(mem, NULL, "x", 1) == fr_bio_error(GENERIC));
382
383 TEST_CASE("the memory bio does not shut the chain down");
385
386 TEST_CASE("the next write reaches the stub again");
387 stub->write = stub_write_all;
388 TEST_CHECK_RET((int) fr_bio_write(mem, NULL, "x", 1), 1);
389
390done:
391 talloc_free(ctx);
392}
393
394/** The memory bio passes a recoverable flush error up to the application, and keeps the buffered data.
395 */
397{
398 TALLOC_CTX *ctx = talloc_init_const("test");
399 fr_bio_t *mem, *stub;
400
401 stub = stub_alloc(ctx);
402 TEST_CHECK(stub != NULL);
403 if (!stub) goto done;
404
405 mem = fr_bio_mem_alloc(ctx, 1024, 1024, stub);
406 TEST_CHECK(mem != NULL);
407 if (!mem) goto done;
408
409 fr_bio_cb_set(mem, &stub_cb);
410
411 TEST_CASE("a partial write leaves data in the write buffer");
412 stub->write = stub_write_one;
413 TEST_CHECK_RET((int) fr_bio_write(mem, NULL, "hello", 5), 5);
414
415 TEST_CASE("the flush gets the error from the stub");
416 stub->write = stub_write_fail;
417 TEST_CHECK(fr_bio_write(mem, NULL, NULL, SIZE_MAX) == fr_bio_error(GENERIC));
418
419 TEST_CASE("the memory bio does not shut the chain down");
421
422 TEST_CASE("a later flush sends the rest of the buffered data");
423 stub->write = stub_write_all;
424 TEST_CHECK_RET((int) fr_bio_write(mem, NULL, NULL, SIZE_MAX), 4);
425
426done:
427 talloc_free(ctx);
428}
429
430/** After a fatal read error in the next bio, the application still gets the buffered data.
431 *
432 * The stub decides that the error is fatal, and calls fr_bio_shutdown(). The memory bio passes
433 * the error up, and fr_bio_mem_eof() keeps the buffered data for the application.
434 */
435static void test_fatal_read_drains(void)
436{
437 TALLOC_CTX *ctx = talloc_init_const("test");
438 fr_bio_t *mem, *stub;
439 uint8_t buf[64];
440 ssize_t slen;
441
442 stub = stub_alloc(ctx);
443 TEST_CHECK(stub != NULL);
444 if (!stub) goto done;
445
446 mem = fr_bio_mem_alloc(ctx, 1024, 0, stub);
447 TEST_CHECK(mem != NULL);
448 if (!mem) goto done;
449
450 fr_bio_cb_set(mem, &stub_cb);
451
452 TEST_CASE("a small read buffers the rest");
453 slen = fr_bio_read(mem, NULL, buf, 2);
454 TEST_CHECK_RET((int) slen, 2);
455
456 TEST_CASE("the next read fails in the stub, which shuts the chain down");
457 ((stub_t *) stub)->fatal = true;
458 TEST_CHECK(fr_bio_read(mem, NULL, buf, sizeof(buf)) < 0);
459
460 TEST_CASE("writes stop at once, but the teardown waits for the drain");
461 TEST_CHECK(fr_bio_write(mem, NULL, "x", 1) == fr_bio_error(SHUTDOWN));
463
464 TEST_CASE("the application still gets the buffered data");
465 slen = fr_bio_read(mem, NULL, buf, sizeof(buf));
466 TEST_CHECK_RET((int) slen, 3);
467 if (slen == 3) TEST_CHECK(memcmp(buf, "cde", 3) == 0);
468
469 TEST_CASE("an empty buffer completes the shutdown");
470 TEST_CHECK_RET((int) fr_bio_read(mem, NULL, buf, sizeof(buf)), 0);
472
473 TEST_CASE("the chain reports SHUTDOWN once it is torn down");
474 TEST_CHECK(fr_bio_read(mem, NULL, buf, sizeof(buf)) == fr_bio_error(SHUTDOWN));
475
476done:
477 talloc_free(ctx);
478}
479
480/** With the datagram verify reader, the memory bio passes a recoverable read error up to the application.
481 */
483{
484 TALLOC_CTX *ctx = talloc_init_const("test");
485 fr_bio_t *mem, *stub;
486 test_verify_ctx_t tctx = { .fail = false };
487 uint8_t buf[64];
488
489 stub = stub_alloc(ctx);
490 TEST_CHECK(stub != NULL);
491 if (!stub) goto done;
492
493 ((stub_t *) stub)->data_sent = true;
494
495 mem = fr_bio_mem_alloc(ctx, 0, 0, stub);
496 TEST_CHECK(mem != NULL);
497 if (!mem) goto done;
498
499 TEST_CHECK(fr_bio_mem_set_verify(mem, test_verify, &tctx, true) == 0);
500 fr_bio_cb_set(mem, &stub_cb);
501
502 TEST_CASE("the read gets the error from the stub");
503 TEST_CHECK(fr_bio_read(mem, NULL, buf, sizeof(buf)) == fr_bio_error(GENERIC));
504
505 TEST_CASE("the memory bio does not shut the chain down");
507
508done:
509 talloc_free(ctx);
510}
511
513 { "verify_one_packet", test_verify_one_packet },
514 { "verify_partial_packet", test_verify_partial_packet },
515 { "verify_pipelined", test_verify_pipelined },
516 { "verify_buffer_too_small", test_verify_buffer_too_small },
517 { "verify_error_close", test_verify_error_close },
518 { "buffered_read_drains", test_buffered_read_drains },
519 { "recoverable_write_passes_up", test_recoverable_write_passes_up },
520 { "recoverable_flush_passes_up", test_recoverable_flush_passes_up },
521 { "fatal_read_drains", test_fatal_read_drains },
522 { "recoverable_read_datagram", test_recoverable_read_datagram },
524};
static int const char char buffer[256]
Definition acutest.h:641
#define TEST_CHECK(cond)
Definition acutest.h:101
#define TEST_CASE(name)
Definition acutest.h:203
#define TEST_TERMINATOR
Definition acutest.h:77
#define TEST_MSG(...)
Definition acutest.h:234
#define TEST_CHECK_RET(_got, _exp)
fr_bio_write_t _CONST write
write to the underlying bio
Definition base.h:117
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
Definition base.h:184
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
Definition base.h:161
fr_bio_io_t read_resume
"unblocked" is too similar to "blocked"
Definition base.h:97
#define fr_bio_error(_x)
Definition base.h:200
static int packet_ctx
the tests pass only the address of packet_ctx
static void test_verify_one_packet(void)
A complete packet is returned, and only one packet at a time.
TEST_LIST
static void test_recoverable_flush_passes_up(void)
The memory bio passes a recoverable flush error up to the application, and keeps the buffered data.
static void test_recoverable_read_datagram(void)
With the datagram verify reader, the memory bio passes a recoverable read error up to the application...
static void cb_noop_void(fr_bio_t *bio)
static ssize_t test_source_write(fr_bio_t *source, char const *data, size_t size)
Put bytes where the memory bio's reads will find them.
static fr_bio_cb_funcs_t test_cb
static fr_bio_t * test_mem_alloc(TALLOC_CTX *ctx, fr_bio_t **source_p, test_verify_ctx_t *tctx)
A memory bio in front of a pipe, which stands in for the network.
static ssize_t stub_read(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Return "abcde" once, and fail every read after that.
static ssize_t stub_write_one(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Accept one byte of each write, so the memory bio buffers the rest.
static ssize_t stub_write_all(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, size_t size)
Accept every write in full.
static void test_recoverable_write_passes_up(void)
The memory bio passes a recoverable write error up to the application, and keeps working.
static void test_verify_error_close(void)
A verify function which says "close" shuts the chain down.
static void test_buffered_read_drains(void)
Without a verify function the bio is a plain buffer, and hands back what it has.
static void test_fatal_read_drains(void)
After a fatal read error in the next bio, the application still gets the buffered data.
static void test_verify_pipelined(void)
Pipelined packets: a buffer holding more than one packet must still return the first.
static int cb_shutdown(fr_bio_t *bio)
static fr_bio_verify_action_t test_verify(UNUSED fr_bio_t *bio, void *verify_ctx, UNUSED void *packet_ctx, const void *buffer, size_t *size)
static fr_bio_t * stub_alloc(TALLOC_CTX *ctx)
static void test_verify_buffer_too_small(void)
A caller buffer smaller than the packet is an error, and loses nothing.
static ssize_t stub_write_fail(fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
static int shutdown_count
bool fail
return ERROR_CLOSE for the next packet
static int cb_noop(fr_bio_t *bio)
static fr_bio_cb_funcs_t stub_cb
static void test_verify_partial_packet(void)
A packet split across two reads is reassembled.
Framing for the tests: the first byte of a packet is its total length.
bool fatal
shut the chain down before failing
bool data_sent
the first read has returned "abcde"
A stub transport which fails recoverably or fatally, as each test chooses.
#define UNUSED
Definition build.h:415
talloc_free(hp)
char const * fr_bio_strerror(ssize_t error)
Definition base.c:225
void fr_bio_cb_set(fr_bio_t *bio, fr_bio_cb_funcs_t const *cb)
Definition base.c:260
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition base.c:158
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:679
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:856
fr_bio_verify_action_t
Status returned by the verification callback.
Definition mem.h:32
@ FR_BIO_VERIFY_ERROR_CLOSE
fatal error, the bio should be closed.
Definition mem.h:36
@ 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
long int ssize_t
unsigned char uint8_t
fr_bio_t * fr_bio_pipe_alloc(TALLOC_CTX *ctx, fr_bio_cb_funcs_t *cb, size_t buffer_size)
Allocate a thread-safe pipe which can be used for both reads and writes.
Definition pipe.c:187
static bool done
Definition radclient.c:80
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:127
#define VERIFY(_x)
Definition trie.c:130
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1366