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: e34e743e033b441655d36b65ae0628d82dd09568 $
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) {
36 fr_bio_buf_reset(bio_buf);
37 return fr_bio_buf_write_room(bio_buf);
38 }
39
40 memmove(bio_buf->start, bio_buf->read, used);
41
42 bio_buf->read = bio_buf->start;
43 bio_buf->write = bio_buf->read + used;
44
45 return fr_bio_buf_write_room(bio_buf);
46}
47
48size_t fr_bio_buf_read(fr_bio_buf_t *bio_buf, void *buffer, size_t size)
49{
50 size_t used;
51
52 fr_bio_buf_verify(bio_buf);
53
54 used = bio_buf->write - bio_buf->read;
55 if (!used || !size) return 0;
56
57 /*
58 * Clamp the data to read at how much data is in the buffer.
59 */
60 if (size > used) size = used;
61
62 if (buffer) memcpy(buffer, bio_buf->read, size);
63
64 bio_buf->read += size;
65 if (bio_buf->read == bio_buf->write) {
66 fr_bio_buf_reset(bio_buf);
67
68 } else if ((bio_buf->end - bio_buf->read) < (bio_buf->read - bio_buf->start)) {
69 /*
70 * The "read" pointer is closer to the end of the
71 * buffer than to the start. Shift the data
72 * around to give more room for reading.
73 *
74 * @todo - change the check instead to "(end - write) < min_room"
75 *
76 * @todo - what about pending packets which point to the buffer?
77 */
78 fr_bio_buf_make_room(bio_buf);
79 }
80
81 return size;
82}
83
84ssize_t fr_bio_buf_write(fr_bio_buf_t *bio_buf, const void *buffer, size_t size)
85{
86 size_t room;
87
88 fr_bio_buf_verify(bio_buf);
89
90 room = fr_bio_buf_write_room(bio_buf);
91
92 if (room < size) {
93 return -room; /* how much more room we would need */
94 }
95
96 /*
97 * The data might already be in the buffer, in which case we can skip the memcpy().
98 *
99 * But the data MUST be at the current "write" position. i.e. we can't have overlapping /
100 * conflicting writes.
101 *
102 * @todo - if it's after the current write position, maybe still allow it? That's so
103 * fr_bio_mem_write() and friends can write partial packets into the buffer. Maybe add a
104 * fr_bio_buf_write_partial() API, which takes (packet, already_written, size), and then does the
105 * right thing. If the packet is not within the buffer, then it devolves to fr_bio_buf_write(),
106 * otherwise it moves the write ptr in the buffer to after the packet.
107 */
108 if (buffer != bio_buf->write) {
110 memcpy(bio_buf->write, buffer, size);
111 }
112 bio_buf->write += size;
113
114 return size;
115}
116
117int fr_bio_buf_alloc(TALLOC_CTX *ctx, fr_bio_buf_t *bio_buf, size_t size)
118{
119 void *ptr;
120
121 ptr = talloc_array(ctx, uint8_t, size);
122 if (!ptr) return -1;
123
124 if (bio_buf->start) talloc_free(bio_buf->start);
125
126 fr_bio_buf_init(bio_buf, ptr, size);
127
128 return 0;
129}
static int const char char buffer[256]
Definition acutest.h:578
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:48
int fr_bio_buf_alloc(TALLOC_CTX *ctx, fr_bio_buf_t *bio_buf, size_t size)
Definition buf.c:117
ssize_t fr_bio_buf_write(fr_bio_buf_t *bio_buf, const void *buffer, size_t size)
Definition buf.c:84
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(hp)
long int ssize_t
unsigned char uint8_t
static size_t used
#define fr_assert(_expr)
Definition rad_assert.h:38