The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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 
45 size_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 
81 ssize_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 
114 int 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:574
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
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static size_t used
fr_assert(0)