The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
listen.c
Go to the documentation of this file.
1/*
2 * This program 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
5 * (at 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: ec6b4205d319c3b7557436c0c96477806c617a69 $
19 *
20 * @brief Listener ids
21 * @file io/listen.c
22 *
23 * @copyright 2026 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24 */
25RCSID("$Id: ec6b4205d319c3b7557436c0c96477806c617a69 $")
26
27#include <freeradius-devel/io/listen.h>
28#include <freeradius-devel/util/debug.h>
29#include <freeradius-devel/util/rb.h>
30
31#include <pthread.h>
32
33/*
34 * Every listener gets an id, unique for the life of the process, so
35 * one thread can name it to another without passing a pointer.
36 *
37 * The table is filled while listeners are being set up, before the
38 * threads which read it start, so it has no lock. Ids start at one.
39 */
41static pthread_once_t listen_by_id_once = PTHREAD_ONCE_INIT;
43
44static fr_cmp_ret_t listen_id_cmp(void const *one, void const *two)
45{
46 fr_listen_t const *a = one, *b = two;
47
48 return CMP(a->id, b->id);
49}
50
51static void listen_by_id_init(void)
52{
54}
55
56/** Take a listener out of the table, as it is being freed
57 *
58 * The id itself is not reused: the counter only goes up.
59 */
60static int _listen_free(fr_listen_t *listen)
61{
62 (void) fr_rb_delete(&listen_by_id, listen);
63
64 return 0;
65}
66
67/** Allocate a listener, and give it its id
68 *
69 * @param[in] ctx to allocate the listener in.
70 * @param[in] listen_cs the listen section it came from.
71 * @param[in] server_cs the virtual server it is bound to.
72 * @param[in] app the application it belongs to, which encodes and decodes.
73 * @param[in] app_instance the application's instance data.
74 * @param[in] app_io the I/O path, which reads and writes.
75 * @param[in] app_io_instance the I/O path's instance data.
76 * @return the listener.
77 */
78fr_listen_t *fr_listen_alloc(TALLOC_CTX *ctx, CONF_SECTION *listen_cs, CONF_SECTION *server_cs,
79 fr_app_t const *app, void const *app_instance,
80 fr_app_io_t const *app_io, void const *app_io_instance)
81{
82 fr_listen_t *listen;
83
84 (void) pthread_once(&listen_by_id_once, listen_by_id_init);
85
86 MEM(listen = talloc_zero(ctx, fr_listen_t));
87 talloc_set_destructor(listen, _listen_free);
88
89 listen->cs = listen_cs;
90 listen->server_cs = server_cs;
91 listen->app = app;
92 listen->app_instance = app_instance;
93 listen->app_io = app_io;
94 listen->app_io_instance = app_io_instance;
95
96 listen->id = listen_next_id++;
97 if (!fr_cond_assert_msg(fr_rb_insert(&listen_by_id, listen) == 0, "Duplicate listener id %u", listen->id)) {
98 talloc_free(listen);
99 return NULL;
100 }
101
102 return listen;
103}
104
105/** Allocate a socket of a listener
106 *
107 * @param[in] ctx to allocate the socket in.
108 * @param[in] listen it is a socket of.
109 * @return the socket.
110 */
112{
114
115 MEM(li = talloc_zero(ctx, fr_listen_instance_t));
116 li->listen = listen;
117
118 return li;
119}
120
121/** Free a socket's thread instance along with it
122 *
123 * For sockets whose thread instance is not a talloc child of the
124 * socket. Set as the destructor by whoever made the socket.
125 */
127{
128 if (!li->thread_instance) return 0;
129
131 return 0;
132}
133
134/** Find a listener by its id
135 *
136 * @param[in] id of the listener.
137 * @return
138 * - NULL if no listener has that id.
139 * - the listener otherwise.
140 */
142{
143 fr_listen_t *found = NULL;
144 fr_listen_t key = {
145 .id = id
146 };
147
148 (void) pthread_once(&listen_by_id_once, listen_by_id_init);
149
150 (void) fr_rb_find((void **)&found, &listen_by_id, &key);
151
152 return found;
153}
Public structure describing an I/O path for a protocol.
Definition app_io.h:33
Describes a new application (protocol)
Definition application.h:71
#define RCSID(id)
Definition build.h:603
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:130
fr_cmp_ret_t
Result of an ordering comparison.
Definition build.h:113
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
#define MEM(x)
Definition debug.h:38
talloc_free(hp)
int fr_io_listen_free(fr_listen_instance_t *li)
Free a socket's thread instance along with it.
Definition listen.c:126
static pthread_once_t listen_by_id_once
Definition listen.c:41
fr_listen_t * fr_listen_alloc(TALLOC_CTX *ctx, CONF_SECTION *listen_cs, CONF_SECTION *server_cs, fr_app_t const *app, void const *app_instance, fr_app_io_t const *app_io, void const *app_io_instance)
Allocate a listener, and give it its id.
Definition listen.c:78
static int _listen_free(fr_listen_t *listen)
Take a listener out of the table, as it is being freed.
Definition listen.c:60
static uint32_t listen_next_id
Definition listen.c:42
static fr_cmp_ret_t listen_id_cmp(void const *one, void const *two)
Definition listen.c:44
static fr_rb_tree_t listen_by_id
Definition listen.c:40
fr_listen_instance_t * fr_listen_instance_alloc(TALLOC_CTX *ctx, fr_listen_t *listen)
Allocate a socket of a listener.
Definition listen.c:111
static void listen_by_id_init(void)
Definition listen.c:51
fr_listen_t * fr_listen_by_id(uint32_t id)
Find a listener by its id.
Definition listen.c:141
fr_listen_t * listen
the listener this is a socket of.
Definition listen.h:65
fr_app_io_t const * app_io
I/O path functions.
Definition listen.h:33
fr_app_t const * app
Definition listen.h:36
void const * app_instance
Definition listen.h:37
void const * app_io_instance
I/O path configuration context.
Definition listen.h:34
CONF_SECTION * cs
of this listener
Definition listen.h:39
void * thread_instance
thread / socket context
Definition listen.h:69
uint32_t id
Unique for the life of the process.
Definition listen.h:29
CONF_SECTION * server_cs
CONF_SECTION of the server.
Definition listen.h:40
unsigned int uint32_t
static fr_app_io_t app_io
int fr_rb_find(void **found, fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:586
int fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition rb.c:767
int fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:637
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Definition rb.h:178
The main red black tree structure.
Definition rb.h:71