The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
connection.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or (at
6  * your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /**
19  * $Id: 524f5d1ca431424c85351c91d0ea390f4a54e23f $
20  * @file lib/server/connection.h
21  * @brief Simple state machine for managing connection states.
22  *
23  * @copyright 2017-2020 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  */
25 RCSIDH(connection_h, "$Id: 524f5d1ca431424c85351c91d0ea390f4a54e23f $")
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <freeradius-devel/util/event.h>
32 #include <freeradius-devel/util/table.h>
33 #include <freeradius-devel/util/talloc.h>
34 
35 #ifdef _CONST
36 # error _CONST can only be defined in the local header
37 #endif
38 #ifndef _CONNECTION_PRIVATE
39 typedef struct connection_pub_s connection_t; /* We use the private version of the connection_t */
40 # define _CONST const
41 #else
42 # define _CONST
43 #endif
44 
45 typedef enum {
46  CONNECTION_STATE_HALTED = 0, //!< The connection is in a halted stat. It does not have
47  ///< a valid file descriptor, and it will not try and
48  ///< and create one.
49  CONNECTION_STATE_INIT, //!< Init state, sets up connection.
50  CONNECTION_STATE_CONNECTING, //!< Waiting for connection to establish.
51  CONNECTION_STATE_TIMEOUT, //!< Timeout during #CONNECTION_STATE_CONNECTING.
52  CONNECTION_STATE_CONNECTED, //!< File descriptor is open (ready for writing).
53  CONNECTION_STATE_SHUTDOWN, //!< Connection is shutting down.
54  CONNECTION_STATE_FAILED, //!< Connection has failed.
55  CONNECTION_STATE_CLOSED, //!< Connection has been closed.
58 
59 /** Public fields for the connection
60  *
61  * This saves the overhead of using accessors for commonly used fields in
62  * connections.
63  *
64  * Though these fields are public, they should _NOT_ be modified by clients of
65  * the connection API.
66  */
68  char const * _CONST name; //!< Prefix to add to log messages.
69 
70  connection_state_t _CONST state; //!< Current connection state.
71  connection_state_t _CONST prev; //!< The previous state the connection was in.
72  uint64_t _CONST id; //!< Unique identifier for the connection.
73  void * _CONST h; //!< Connection handle
74  fr_event_list_t * _CONST el; //!< Event list for timers and I/O events.
75 
76  uint64_t _CONST reconnected; //!< How many times we've attempted to establish or
77  ///< re-establish this connection.
78  uint64_t _CONST timed_out; //!< How many times has this connection timed out when
79  ///< connecting.
80  bool _CONST triggers; //!< do we run the triggers?
81 };
82 
83 typedef enum {
84  CONNECTION_FAILED = 0, //!< Connection is being reconnected because it failed.
85  CONNECTION_EXPIRED //!< Connection is being reconnected because it's at
86  ///< the end of its life. In this case we enter the
87  ///< closing state and try and close the connection
88  ///< gracefully.
90 
91 typedef struct {
92  fr_time_delta_t connection_timeout; //!< How long to wait for the connection to open
93  //!< or for shutdown to close the connection.
94  fr_time_delta_t reconnection_delay; //!< How long to wait after failures.
96 
98 
100 extern size_t connection_states_len;
101 
102 /** Callback for the initialise state
103  *
104  * Should attempt to open a non-blocking connection and return it in fd_out.
105  *
106  * @param[out] h_out Where to write the new handle.
107  * @param[in] conn If integrating with a 3rd party library
108  * that will trigger connection API state transitions,
109  * the connection should be passed as the uctx argument
110  * for library I/O callbacks.
111  * @param[in] uctx User context.
112  * @return
113  * - #CONNECTION_STATE_CONNECTING if a handle was successfully created.
114  * - #CONNECTION_STATE_FAILED if we could not create a handle.
115  */
116 typedef connection_state_t (*connection_init_t)(void **h_out, connection_t *conn, void *uctx);
117 
118 /** Notification that the connection is now open
119  *
120  * This should be used to add any additional I/O events for the file descriptor
121  * to call other code if it becomes readable or writable.
122  *
123  * @param[in] el to use for inserting I/O events.
124  * @param[in] h Handle that was successfully opened.
125  * @param[in] uctx User context.
126  * @return
127  * - #CONNECTION_STATE_CONNECTED if the handle is usable.
128  * - #CONNECTION_STATE_FAILED if the handle is unusable.
129  */
131 
132 /** Start the process of gracefully shutting down the connection
133  *
134  * This function is called when the connection is signalled to gracefully
135  * disconnect. It should place the connection in a state where pending
136  * I/O operations complete, and buffers are flushed.
137  *
138  * After all pending events are complete, the connection should be signalled
139  * that the handle is in the closed state.
140  *
141  * @param[in] el to use for inserting I/O events.
142  * @param[in] h Handle that needs to be closed.
143  * @param[in] uctx User context.
144  * @return
145  * - #CONNECTION_STATE_SHUTDOWN if the handle has shutdown.
146  * - #CONNECTION_STATE_FAILED if the handle is unusable, and we
147  * should just transition directly to failed.
148  */
150 
151 /** Notification that a connection attempt has failed
152  *
153  * @note If the callback frees the connection, it must return #CONNECTION_STATE_HALTED.
154  *
155  * @param[in] h Handle that failed.
156  * @param[in] state the connection was in when it failed. Usually one of:
157  * - #CONNECTION_STATE_CONNECTING the connection attempt explicitly failed.
158  * - #CONNECTION_STATE_CONNECTED something called #connection_signal_reconnect.
159  * - #CONNECTION_STATE_TIMEOUT the connection attempt timed out.
160  * @param[in] uctx User context.
161  * @return
162  * - #CONNECTION_STATE_INIT to transition to the init state.
163  * - #CONNECTION_STATE_HALTED To prevent further reconnection
164  * attempts Can be restarted with
165  * #connection_signal_init().
166  */
168 
169 /** Notification that the connection has errored and must be closed
170  *
171  * This should be used to close the file descriptor. It is assumed
172  * that the file descriptor is invalid after this callback has been executed.
173  *
174  * If this callback does not close the file descriptor, the server will leak
175  * file descriptors.
176  *
177  * @param[in] el to use for inserting I/O events.
178  * @param[in] h Handle to close.
179  * @param[in] uctx User context.
180  */
181 typedef void (*connection_close_t)(fr_event_list_t *el, void *h, void *uctx);
182 
183 /** Holds a complete set of functions for a connection
184  *
185  */
186 typedef struct {
193 
194 /** Receive a notification when a connection enters a particular state
195  *
196  * It is permitted for watchers to signal state changes, and/or to free the
197  * connection. The actual free will be deferred until the watcher returns.
198  *
199  * @param[in] conn Being watched.
200  * @param[in] prev State we came from.
201  * @param[in] state State that was entered (the current state)
202  * @param[in] uctx that was passed to connection_add_watch_*.
203  */
204 typedef void(*connection_watch_t)(connection_t *conn,
205  connection_state_t prev, connection_state_t state, void *uctx);
206 
207 /** @name Add watcher functions that get called before (pre) the state callback and after (post)
208  * @{
209  */
211  connection_watch_t watch, bool oneshot, void const *uctx);
212 
214  connection_watch_t watch, bool oneshot, void const *uctx);
215 
217  connection_watch_t watch);
218 
220  connection_watch_t watch);
221 
223 
225 
227 
229 
231 /** @} */
232 
233 /** @name Statistics
234  * @{
235  */
236 uint64_t connection_get_num_reconnected(connection_t const *conn);
237 
238 uint64_t connection_get_num_timed_out(connection_t const *conn);
239 /** @} */
240 
241 /** @name Signal the connection to change states
242  * @{
243  */
245 
247 
249 
251 
253 
255 
257 /** @} */
258 
259 /** @name Install generic I/O events on an FD to signal state changes
260  * @{
261  */
262 int connection_signal_on_fd(connection_t *conn, int fd);
263 /** @} */
264 
265 /** @name Allocate a new connection
266  * @{
267  */
269  connection_funcs_t const *funcs, connection_conf_t const *conf,
270  char const *log_prefix, void const *uctx);
271 /** @} */
272 
273 #undef _CONST
274 
275 #ifdef __cplusplus
276 }
277 #endif
#define RCSIDH(h, id)
Definition: build.h:482
void connection_signal_shutdown(connection_t *conn)
Shuts down a connection gracefully.
Definition: connection.c:1228
void(* connection_watch_t)(connection_t *conn, connection_state_t prev, connection_state_t state, void *uctx)
Receive a notification when a connection enters a particular state.
Definition: connection.h:204
void connection_watch_enable(connection_watch_entry_t *entry)
Enable a watcher.
Definition: connection.c:544
connection_state_t(* connection_failed_t)(void *h, connection_state_t state, void *uctx)
Notification that a connection attempt has failed.
Definition: connection.h:167
uint64_t connection_get_num_timed_out(connection_t const *conn)
Return the number of times this connection has timed out whilst connecting.
Definition: connection.c:613
uint64_t _CONST timed_out
How many times has this connection timed out when connecting.
Definition: connection.h:78
void connection_watch_disable(connection_watch_entry_t *entry)
Disable a watcher.
Definition: connection.c:554
void(* connection_close_t)(fr_event_list_t *el, void *h, void *uctx)
Notification that the connection has errored and must be closed.
Definition: connection.h:181
int connection_del_watch_post(connection_t *conn, connection_state_t state, connection_watch_t watch)
Remove a watch function from a post list.
Definition: connection.c:472
fr_event_list_t *_CONST el
Event list for timers and I/O events.
Definition: connection.h:74
connection_state_t(* connection_init_t)(void **h_out, connection_t *conn, void *uctx)
Callback for the initialise state.
Definition: connection.h:116
bool connection_watch_is_enabled(connection_watch_entry_t *entry)
Return the state of a watch entry.
Definition: connection.c:590
void connection_signal_halt(connection_t *conn)
Shuts down a connection ungracefully.
Definition: connection.c:1291
connection_state_t
Definition: connection.h:45
@ CONNECTION_STATE_FAILED
Connection has failed.
Definition: connection.h:54
@ CONNECTION_STATE_HALTED
The connection is in a halted stat.
Definition: connection.h:46
@ CONNECTION_STATE_CLOSED
Connection has been closed.
Definition: connection.h:55
@ CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
Definition: connection.h:52
@ CONNECTION_STATE_TIMEOUT
Timeout during CONNECTION_STATE_CONNECTING.
Definition: connection.h:51
@ CONNECTION_STATE_INIT
Init state, sets up connection.
Definition: connection.h:49
@ CONNECTION_STATE_MAX
Definition: connection.h:56
@ CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
Definition: connection.h:50
@ CONNECTION_STATE_SHUTDOWN
Connection is shutting down.
Definition: connection.h:53
void connection_signals_resume(connection_t *conn)
Resume processing of deferred signals.
Definition: connection.c:319
uint64_t connection_get_num_reconnected(connection_t const *conn)
Return the number of times we've attempted to establish or re-establish this connection.
Definition: connection.c:601
uint64_t _CONST reconnected
How many times we've attempted to establish or re-establish this connection.
Definition: connection.h:76
void *_CONST h
Connection handle.
Definition: connection.h:73
bool _CONST triggers
do we run the triggers?
Definition: connection.h:80
connection_reason_t
Definition: connection.h:83
@ CONNECTION_EXPIRED
Connection is being reconnected because it's at the end of its life.
Definition: connection.h:85
@ CONNECTION_FAILED
Connection is being reconnected because it failed.
Definition: connection.h:84
connection_state_t(* connection_open_t)(fr_event_list_t *el, void *h, void *uctx)
Notification that the connection is now open.
Definition: connection.h:130
void connection_watch_set_uctx(connection_watch_entry_t *entry, void const *uctx)
Change the uctx of an entry.
Definition: connection.c:577
connection_state_t _CONST state
Current connection state.
Definition: connection.h:70
connection_init_t init
Definition: connection.h:187
void connection_signal_reconnect(connection_t *conn, connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
Definition: connection.c:1167
#define _CONST
Definition: connection.h:40
connection_watch_entry_t * connection_add_watch_pre(connection_t *conn, connection_state_t state, connection_watch_t watch, bool oneshot, void const *uctx)
Add a callback to be executed before a state function has been called.
Definition: connection.c:510
char const *_CONST name
Prefix to add to log messages.
Definition: connection.h:68
connection_state_t _CONST prev
The previous state the connection was in.
Definition: connection.h:71
fr_table_num_ordered_t const connection_states[]
Definition: connection.c:46
int connection_signal_on_fd(connection_t *conn, int fd)
Setup the connection to change states to connected or failed based on I/O events.
Definition: connection.c:1405
void connection_signal_init(connection_t *conn)
Asynchronously signal a halted connection to start.
Definition: connection.c:1107
connection_watch_entry_t * connection_add_watch_post(connection_t *conn, connection_state_t state, connection_watch_t watch, bool oneshot, void const *uctx)
Add a callback to be executed after a state function has been called.
Definition: connection.c:532
connection_shutdown_t shutdown
Definition: connection.h:189
connection_failed_t failed
Definition: connection.h:190
size_t connection_states_len
Definition: connection.c:56
connection_t * connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, connection_funcs_t const *funcs, connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
Definition: connection.c:1512
int connection_del_watch_pre(connection_t *conn, connection_state_t state, connection_watch_t watch)
Remove a watch function from a pre list.
Definition: connection.c:455
fr_time_delta_t reconnection_delay
How long to wait after failures.
Definition: connection.h:94
void connection_watch_enable_set_uctx(connection_watch_entry_t *entry, void const *uctx)
Enable a watcher and replace the uctx.
Definition: connection.c:565
void connection_signal_connected(connection_t *conn)
Asynchronously signal that the connection is open.
Definition: connection.c:1137
connection_open_t open
Definition: connection.h:188
void connection_signals_pause(connection_t *conn)
Pause processing of deferred signals.
Definition: connection.c:310
fr_time_delta_t connection_timeout
How long to wait for the connection to open or for shutdown to close the connection.
Definition: connection.h:92
uint64_t _CONST id
Unique identifier for the connection.
Definition: connection.h:72
connection_close_t close
Definition: connection.h:191
connection_state_t(* connection_shutdown_t)(fr_event_list_t *el, void *h, void *uctx)
Start the process of gracefully shutting down the connection.
Definition: connection.h:149
Holds a complete set of functions for a connection.
Definition: connection.h:186
Public fields for the connection.
Definition: connection.h:67
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
Stores all information relating to an event list.
Definition: event.c:411
static rs_t * conf
Definition: radsniff.c:53
An entry in a watch function list.
Definition: connection.c:78
An element in an arbitrarily ordered array of name to num mappings.
Definition: table.h:57
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
static fr_event_list_t * el