The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
packet.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: bdf72473a940e88b13b624668bd3e0cb605e88a4 $
19 * @file lib/bio/packet.c
20 * @brief BIO PACKET handlers
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/packet.h>
27
28/** Inform all of the BIOs that the write is blocked.
29 *
30 * This function should be set as the BIO layer "write_blocked" callback for all BIOs created as part
31 * of a #fr_bio_packet_t. The application should also set bio->uctx=bio_packet for all BIOs.
32 */
34{
35 fr_bio_packet_t *my = bio->uctx;
36
37 /*
38 * This function must be callable multiple times, as different portions of the BIOs can block at
39 * different times.
40 */
41 if (my->write_blocked) return 1;
42 my->write_blocked = true;
43
44 /*
45 * The application doesn't want to know that it's blocked, so we just return.
46 */
47 if (!my->cb.write_blocked) return 1;
48
49 /*
50 * Tell the application that IO is blocked.
51 */
52 return my->cb.write_blocked(my);
53}
54
56{
57 fr_bio_packet_t *my = bio->uctx;
58 fr_bio_t *next;
59 int rcode;
60
61 if (!my->write_blocked) return 1;
62 my->write_blocked = false;
63
64 /*
65 * Inform each underlying BIO that it can be resumed. Note that we might be called from a
66 * lower-layer BIO, so we have to start from the top of the chain.
67 *
68 * Note that if the callback returns 0, saying "I couldn't resume", then the BIO is still marked
69 * as blocked.
70 */
71 for (next = my->bio;
72 next != NULL;
73 next = fr_bio_next(next)) {
74
75 if (!((fr_bio_common_t *) next)->priv_cb.write_resume) continue;
76
77 rcode = ((fr_bio_common_t *) next)->priv_cb.write_resume(next);
78 if (rcode < 0) return rcode;
79
80 if (rcode == 0) {
81 my->write_blocked = true;
82 return 0;
83 }
84 }
85
86 rcode = my->cb.write_resume(my);
87 if (rcode < 0) return rcode;
88
89 my->write_blocked = (rcode == 0);
90
91 return rcode;
92}
93
95{
96 fr_bio_packet_t *my = bio->uctx;
97
98 my->read_blocked = true;
99
100 return my->cb.read_blocked(my);
101}
102
104{
105 fr_bio_packet_t *my = bio->uctx;
106
107 my->read_blocked = false;
108
109 return my->cb.read_resume(my);
110}
111
112/** Called when a particular BIO is connected.
113 *
114 * We see if we can connect the previous BIOs.
115 */
117{
118 fr_bio_packet_t *my = bio->uctx;
119
120 fr_assert(!my->connected);
121
122 /*
123 * Run the internal connected callback for previous BIOs. If one returns "not connected", then
124 * the packet BIO as a whole is not connected.
125 */
126 while ((bio = fr_bio_prev(bio)) != NULL) {
127 if (!((fr_bio_common_t *) bio)->priv_cb.connected) continue;
128
129 /*
130 * Tell this BIO that everything it needs has been connected.
131 */
132 if (((fr_bio_common_t *) bio)->priv_cb.connected(bio) == 0) return;
133 }
134
135 /*
136 * The top-level BIO is connected. This means that the entire chain is now connected, and is
137 * usable by the application.
138 */
139 my->connected = true;
140
141 /*
142 * Stop any connection timeout.
143 */
144 if (my->ev) talloc_const_free(&my->ev);
145
146 /*
147 * Tell the application that the packet BIO is now usable.
148 */
149 my->cb.connected(my);
150}
151
153{
154 fr_bio_packet_t *my = bio->uctx;
155
156 if (my->cb.shutdown) my->cb.shutdown(my);
157 my->cb.shutdown = NULL;
158}
159
161{
162 fr_bio_packet_t *my = bio->uctx;
163
164 if (my->cb.eof) my->cb.eof(my);
165 my->cb.eof = NULL;
166}
167
169{
170 fr_bio_packet_t *my = bio->uctx;
171
172 if (my->cb.failed) my->cb.failed(my);
173 my->cb.failed = NULL;
174}
175
176
178{
179 fr_bio_t *bio = my->bio;
180
181 fr_bio_cb_funcs_t bio_cb = {
183 .shutdown = fr_bio_packet_shutdown,
184 .eof = fr_bio_packet_eof,
185 .failed = fr_bio_packet_failed,
186
187 .write_blocked = fr_bio_packet_write_blocked,
188 .write_resume = fr_bio_packet_write_resume,
189 .read_blocked = fr_bio_packet_read_blocked,
190 .read_resume = fr_bio_packet_read_resume,
191 };
192
193 /*
194 * Every participating BIO has us set as the bio->uctx, and we handle all BIO callbacks.
195 *
196 * The application sets its own pointer my->uctx and sets itself via our callbacks.
197 */
198 while (bio) {
199 bio->uctx = my;
200
201 fr_bio_cb_set(bio, &bio_cb);
202 bio = fr_bio_next(bio);
203 }
204}
static fr_bio_t * fr_bio_prev(fr_bio_t *bio)
Definition base.h:121
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition base.h:130
fr_bio_callback_t connected
called when the BIO is ready to be used
Definition base.h:88
void * uctx
user ctx, caller can manually set it.
Definition base.h:113
fr_bio_shutdown & my
Definition fd_errno.h:59
void fr_bio_cb_set(fr_bio_t *bio, fr_bio_cb_funcs_t const *cb)
Definition base.c:225
void fr_bio_packet_init(fr_bio_packet_t *my)
Definition packet.c:177
void fr_bio_packet_connected(fr_bio_t *bio)
Called when a particular BIO is connected.
Definition packet.c:116
static void fr_bio_packet_failed(fr_bio_t *bio)
Definition packet.c:168
static void fr_bio_packet_shutdown(fr_bio_t *bio)
Definition packet.c:152
static void fr_bio_packet_eof(fr_bio_t *bio)
Definition packet.c:160
static int fr_bio_packet_write_blocked(fr_bio_t *bio)
Inform all of the BIOs that the write is blocked.
Definition packet.c:33
static int fr_bio_packet_read_resume(fr_bio_t *bio)
Definition packet.c:103
static int fr_bio_packet_read_blocked(fr_bio_t *bio)
Definition packet.c:94
static int fr_bio_packet_write_resume(fr_bio_t *bio)
Definition packet.c:55
#define fr_assert(_expr)
Definition rad_assert.h:38
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:224