*/
typedef fr_connection_state_t (*fr_connection_open_t)(int fd, fr_event_list_t *el, void *uctx);
-/** Notification that a connection attempt has timed out
+/** Notification that a connection attempt has failed
*
* @note If the callback frees the connection, it must return #FR_CONNECTION_STATE_HALTED.
*
* @param[in] fd That was successfully opened.
- * @param[in] el to use for inserting I/O events.
+ * @param[in] state the connection was in when it failed. Usually one of:
+ * - #FR_CONNECTION_STATE_CONNECTING the connection attempt explicitly failed.
+ * - #FR_CONNECTION_STATE_CONNECTED something called #fr_connection_reconnect.
+ * - #FR_CONNECTION_STATE_TIMEOUT the connection attempt timed out.
* @param[in] uctx User context.
* @return
- * - #FR_CONNECTION_STATE_FAILED to reattempt the connection after
- * the configured delay period.
+ * - #FR_CONNECTION_STATE_INIT to transition to the init state.
* - #FR_CONNECTION_STATE_HALTED To prevent further reconnection
* attempts Can be restarted with
* #fr_connection_start().
*/
-typedef fr_connection_state_t (*fr_connection_timeout_t)(int fd, void *uctx);
+typedef fr_connection_state_t (*fr_connection_failed_t)(int fd, fr_connection_state_t state, void *uctx);
/** Notification that the connection has errored and must be closed
*
fr_connection_close_t close,
char const *log_prefix,
void *uctx);
-void fr_connection_timeout_func(fr_connection_t *conn, fr_connection_timeout_t func);
+void fr_connection_failed_func(fr_connection_t *conn, fr_connection_failed_t func);
void fr_connection_start(fr_connection_t *conn);
int fr_connection_get_fd(fr_connection_t const *conn);
void fr_connection_reconnect(fr_connection_t *conn);
fr_connection_init_t init; //!< Callback for initialising a connection.
fr_connection_open_t open; //!< Callback for 'open' notification.
fr_connection_close_t close; //!< Callback to close a connection.
- fr_connection_timeout_t timeout; //!< Callback for 'timeout' notification.
+ fr_connection_failed_t failed; //!< Callback for 'failed' notification.
int fd; //!< File descriptor.
fr_event_list_t *el; //!< Event list for timers and I/O events.
prev = conn->state;
STATE_TRANSITION(FR_CONNECTION_STATE_FAILED);
+ /*
+ * If there's a failed callback, give it the
+ * opportunity to suspend/destroy the
+ * connection.
+ */
+ if (conn->failed) {
+ fr_connection_state_t ret;
+
+ /*
+ * Callback may free the connection, so we
+ * set this before calling the callback, so
+ * if the connection isn't freed it's in the
+ * correct state, without us needing to check.
+ */
+ conn->state = FR_CONNECTION_STATE_HALTED;
+ ret = conn->failed(conn->fd, prev, conn->uctx);
+ switch (ret) {
+ case FR_CONNECTION_STATE_INIT:
+ connection_state_init(conn, now);
+ break;
+
+ case FR_CONNECTION_STATE_HALTED: /* Do nothing */
+ STATE_TRANSITION(FR_CONNECTION_STATE_HALTED);
+ return;
+
+ default:
+ rad_assert(0);
+ }
+ }
+
switch (prev) {
case FR_CONNECTION_STATE_INIT: /* Failed during initialisation */
case FR_CONNECTION_STATE_CONNECTED: /* Failed after connecting */
break;
case FR_CONNECTION_STATE_TIMEOUT: /* Failed during connecting */
- if (conn->timeout) {
- fr_connection_state_t ret;
-
- /*
- * Callback may free the connection, so we
- * set this before calling the callback, so
- * if the connection isn't freed it's in the
- * correct state, without us needing to check.
- */
- STATE_TRANSITION(FR_CONNECTION_STATE_HALTED);
- ret = conn->timeout(conn->fd, conn->uctx);
- switch (ret) {
- case FR_CONNECTION_STATE_FAILED:
- connection_state_init(conn, now);
- break;
-
- case FR_CONNECTION_STATE_HALTED: /* Do nothing */
- break;
-
- default:
- rad_assert(0);
- }
- }
+ connection_state_init(conn, now);
break;
default:
return conn;
}
-/** Set an (optional) callback to be called on connection timeout
+/** Set an (optional) callback to be called on connection timeout/failure
*
*/
-void fr_connection_timeout_func(fr_connection_t *conn, fr_connection_timeout_t func)
+void fr_connection_failed_func(fr_connection_t *conn, fr_connection_failed_t func)
{
- conn->timeout = func;
+ conn->failed = func;
}
/** Start a new or halted connection