The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
buf.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: 652f82e254f00e2df041b0e1488de7551d54becb $
19 * @file lib/bio/buf.c
20 * @brief BIO abstractions for file descriptors
21 *
22 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
23 */
24
25#include <freeradius-devel/util/debug.h>
26#include <freeradius-devel/bio/buf.h>
27
29{
30 size_t used;
31
32 if (bio_buf->read == bio_buf->start) return fr_bio_buf_write_room(bio_buf);
33
34 used = bio_buf->write - bio_buf->read;
35 if (!used) return fr_bio_buf_write_room(bio_buf);
36
37 memmove(bio_buf->start, bio_buf->read, used);
38
39 bio_buf->read = bio_buf->start;
40 bio_buf->write = bio_buf->read + used;
41
42 return fr_bio_buf_write_room(bio_buf);
43}
44
45size_t fr_bio_buf_read(fr_bio_buf_t *bio_buf, void *buffer, size_t size)
46{
47 size_t used;
48
49 fr_bio_buf_verify(bio_buf);
50
51 used = bio_buf->write - bio_buf->read;
52 if (!used || !size) return 0;
53
54 /*
55 * Clamp the data to read at how much data is in the buffer.
56 */
57 if (size > used) size = used;
58
59 if (buffer) memcpy(buffer, bio_buf->read, size);
60
61 bio_buf->read += size;
62 if (bio_buf->read == bio_buf->write) {
63 fr_bio_buf_reset(bio_buf);
64
65 } else if ((bio_buf->end - bio_buf->read) < (bio_buf->read - bio_buf->start)) {
66 /*
67 * The "read" pointer is closer to the end of the
68 * buffer than to the start. Shift the data
69 * around to give more room for reading.
70 *
71 * @todo - change the check instead to "(end - write) < min_room"
72 *
73 * @todo - what about pending packets which point to the buffer?
74 */
75 fr_bio_buf_make_room(bio_buf);
76 }
77
78 return size;
79}
80
81ssize_t fr_bio_buf_write(fr_bio_buf_t *bio_buf, const void *buffer, size_t size)
82{
83 size_t room;
84
85 fr_bio_buf_verify(bio_buf);
86
87 room = fr_bio_buf_write_room(bio_buf);
88
89 if (room < size) {
90 return -room; /* how much more room we would need */
91 }
92
93 /*
94 * The data might already be in the buffer, in which case we can skip the memcpy().
95 *
96 * But the data MUST be at the current "write" position. i.e. we can't have overlapping /
97 * conflicting writes.
98 *
99 * @todo - if it's after the current write position, maybe still allow it? That's so
100 * fr_bio_mem_write() and friends can write partial packets into the buffer. Maybe add a
101 * fr_bio_buf_write_partial() API, which takes (packet, already_written, size), and then does the
102 * right thing. If the packet is not within the buffer, then it devolves to fr_bio_buf_write(),
103 * otherwise it moves the write ptr in the buffer to after the packet.
104 */
105 if (buffer != bio_buf->write) {
107 memcpy(bio_buf->write, buffer, size);
108 }
109 bio_buf->write += size;
110
111 return size;
112}
113
114int fr_bio_buf_alloc(TALLOC_CTX *ctx, fr_bio_buf_t *bio_buf, size_t size)
115{
116 void *ptr;
117
118 ptr = talloc_array(ctx, uint8_t, size);
119 if (!ptr) return -1;
120
121 if (bio_buf->start) talloc_free(bio_buf->start);
122
123 fr_bio_buf_init(bio_buf, ptr, size);
124
125 return 0;
126}
static int const char char buffer[256]
Definition acutest.h:576
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 bool fr_bio_buf_contains(fr_bio_buf_t *bio_buf, void const *buffer)
Definition buf.h:125
static void fr_bio_buf_init(fr_bio_buf_t *bio_buf, uint8_t *buffer, size_t size)
Definition buf.h:37
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
uint8_t * end
end of the buffer
Definition buf.h:31
static void fr_bio_buf_reset(fr_bio_buf_t *bio_buf)
Definition buf.h:61
static void fr_bio_buf_verify(fr_bio_buf_t const *bio_buf)
Definition buf.h:50
uint8_t * read
where in the buffer reads are taken from
Definition buf.h:33
uint8_t * write
where in the buffer writes are sent to
Definition buf.h:34
talloc_free(reap)
long int ssize_t
unsigned char uint8_t
static size_t used
#define fr_assert(_expr)
Definition rad_assert.h:38