From: Alan T. DeKok Date: Sat, 25 May 2024 19:11:06 +0000 (-0400) Subject: glue in activation routines X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c97fbc04d0bc5843c50407ac498134a1297c95e;p=thirdparty%2Ffreeradius-server.git glue in activation routines --- diff --git a/src/bin/radclient-ng.c b/src/bin/radclient-ng.c index 2333fd42556..4d8eb7673b8 100644 --- a/src/bin/radclient-ng.c +++ b/src/bin/radclient-ng.c @@ -957,7 +957,7 @@ static void cleanup(fr_bio_packet_t *client, rc_request_t *request) } } -static void client_retry_log(UNUSED fr_bio_packet_t *client, fr_packet_t *packet) +static void client_packet_retry_log(UNUSED fr_bio_packet_t *client, fr_packet_t *packet) { rc_request_t *request = packet->uctx; @@ -968,7 +968,7 @@ static void client_retry_log(UNUSED fr_bio_packet_t *client, fr_packet_t *packet fr_radius_packet_log(&default_log, request->packet, &request->request_pairs, false); } -static void client_release(fr_bio_packet_t *client, fr_packet_t *packet) +static void client_packet_release(fr_bio_packet_t *client, fr_packet_t *packet) { rc_request_t *request = packet->uctx; @@ -1255,26 +1255,19 @@ static void client_write(fr_event_list_t *el, int fd, UNUSED int flags, void *uc } } -static void client_connect(fr_event_list_t *el, int fd, UNUSED int flags, void *uctx) +static int client_bio_activate(fr_bio_packet_t *client) { - int rcode; - fr_bio_packet_t *client = uctx; + fr_radius_client_bio_info_t const *info; - rcode = fr_radius_client_bio_connect(client); - if (rcode < 0) { - /* - * We may need to try again. If so, do that. - */ - if (rcode == fr_bio_error(IO_WOULD_BLOCK)) return; + info = fr_radius_client_bio_info(client); - ERROR("Failed connecting socket: %s", fr_strerror()); - fr_exit_now(1); - } - - if (fr_event_fd_insert(autofree, NULL, el, fd, client_read, client_write, client_error, client) < 0) { + if (fr_event_fd_insert(autofree, NULL, info->retry_info->el, info->fd_info->socket.fd, + client_read, client_write, client_error, client) < 0) { fr_perror("radclient"); fr_exit_now(1); } + + return 0; } @@ -1733,11 +1726,13 @@ int main(int argc, char **argv) * paused or resumed when the socket becomes writeable. */ client_config.packet_cb_cfg = (fr_bio_packet_cb_funcs_t) { - .write_blocked = client_bio_write_pause, - .write_resume = client_bio_write_resume, + .activate = client_bio_activate, + + .write_blocked = client_bio_write_pause, + .write_resume = client_bio_write_resume, - .retry = (fr_debug_lvl > 0) ? client_retry_log : NULL, - .release = client_release, + .retry = (fr_debug_lvl > 0) ? client_packet_retry_log : NULL, + .release = client_packet_release, }; /* @@ -1778,7 +1773,7 @@ int main(int argc, char **argv) * Once the connect() passes, we start reading from the request list, and processing packets. */ if (fr_event_fd_insert(autofree, NULL, client_config.retry_cfg.el, client_info->fd_info->socket.fd, NULL, - client_connect, client_error, client_bio) < 0) { + fr_radius_client_bio_connect, client_error, client_bio) < 0) { fr_perror("radclient"); fr_exit_now(1); } diff --git a/src/lib/bio/packet.h b/src/lib/bio/packet.h index e320fc7d605..04ee60d33ed 100644 --- a/src/lib/bio/packet.h +++ b/src/lib/bio/packet.h @@ -66,6 +66,8 @@ typedef void (*fr_bio_packet_signal_t)(fr_bio_packet_t *bio, fr_packet_t *packet typedef int (*fr_bio_packet_io_t)(fr_bio_packet_t *bio); typedef struct { + fr_bio_packet_io_t activate; + fr_bio_packet_io_t read_blocked; fr_bio_packet_io_t write_blocked; diff --git a/src/lib/bio/retry.c b/src/lib/bio/retry.c index 1296477f0e8..383d1657bf2 100644 --- a/src/lib/bio/retry.c +++ b/src/lib/bio/retry.c @@ -67,7 +67,6 @@ FR_DLIST_FUNCS(fr_bio_retry_list, fr_bio_retry_entry_t, entry) struct fr_bio_retry_s { FR_BIO_COMMON; - fr_event_list_t *el; fr_rb_tree_t timer_tree; fr_rb_tree_t expiry_tree; @@ -138,7 +137,7 @@ static int fr_bio_retry_expiry_timer_reset(fr_bio_retry_t *my) /* * Update the timer. This should never fail. */ - if (fr_event_timer_at(my, my->el, &my->ev, first->retry.end, fr_bio_retry_expiry_timer, my) < 0) return -1; + if (fr_event_timer_at(my, my->info.el, &my->ev, first->retry.end, fr_bio_retry_expiry_timer, my) < 0) return -1; my->timer_item = first; return 0; @@ -178,7 +177,7 @@ static int fr_bio_retry_timer_reset(fr_bio_retry_t *my) /* * Update the timer. This should never fail. */ - if (fr_event_timer_at(my, my->el, &my->ev, first->retry.next, fr_bio_retry_timer, my) < 0) return -1; + if (fr_event_timer_at(my, my->info.el, &my->ev, first->retry.next, fr_bio_retry_timer, my) < 0) return -1; my->timer_item = first; return 0; @@ -1008,14 +1007,15 @@ fr_bio_t *fr_bio_retry_alloc(TALLOC_CTX *ctx, size_t max_saved, my->response = response; my->release = release; - my->el = cfg->el; my->info.last_idle = fr_time(); + my->info.el = cfg->el; + my->info.cfg = cfg; + my->retry_config = cfg->retry_config; my->bio.write = fr_bio_retry_write; my->bio.read = fr_bio_retry_read; - fr_bio_chain(&my->bio, next); talloc_set_destructor(my, fr_bio_retry_destructor); diff --git a/src/lib/bio/retry.h b/src/lib/bio/retry.h index 0298752a976..f8e5b4930f6 100644 --- a/src/lib/bio/retry.h +++ b/src/lib/bio/retry.h @@ -48,6 +48,8 @@ typedef struct { } fr_bio_retry_config_t; typedef struct { + fr_event_list_t *el; //!< event list + fr_time_t mrs_time; //!< Most recent sent time which had a reply. fr_time_t last_reply; //!< When we last received a reply. fr_time_t first_sent; //!< first time we sent a packet since going idle @@ -55,6 +57,8 @@ typedef struct { fr_time_t last_idle; //!< last time we had nothing to do bool write_blocked; //!< are writes blocked? + + fr_bio_retry_config_t const *cfg; //!< so we know what was asked } fr_bio_retry_info_t; typedef struct fr_bio_retry_entry_s fr_bio_retry_entry_t; diff --git a/src/protocols/radius/client.c b/src/protocols/radius/client.c index 25a9358a1b5..94620dd0a7d 100644 --- a/src/protocols/radius/client.c +++ b/src/protocols/radius/client.c @@ -45,14 +45,6 @@ static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **r static void radius_client_retry_release(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED fr_bio_retry_release_reason_t reason); static ssize_t radius_client_retry(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED const void *buffer, NDEBUG_UNUSED size_t size); -static int fr_radius_client_bio_write_blocked(fr_bio_t *bio); -static int fr_radius_client_bio_write_resume(fr_bio_t *bio); - -static const fr_bio_cb_funcs_t client_bio_cb_funcs = { - .write_blocked = fr_radius_client_bio_write_blocked, - .write_resume = fr_radius_client_bio_write_resume, -}; - fr_bio_packet_t *fr_radius_client_bio_alloc(TALLOC_CTX *ctx, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg) { fr_assert(fd_cfg->type == FR_BIO_FD_CONNECTED); @@ -140,8 +132,12 @@ fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t /* * Inform all BIOs about the write pause / resume callbacks + * + * @todo - these callbacks are set AFTER the BIOs have been initialized, so the activate() + * callback is never set, and therefore is never run. We should add all of the callbacks to the + * various bio "cfg" data structures. */ - fr_radius_client_bio_cb_set(bio, cfg->packet_cb_cfg); + fr_radius_client_bio_cb_set(&my->common, &cfg->packet_cb_cfg); /* * Set up the connected status. @@ -626,62 +622,56 @@ int fr_radius_client_bio_force_id(fr_bio_packet_t *bio, int code, int id) return fr_radius_code_id_force(my->codes, code, id); } - -/** Try to connect a socket. - * - * Calls fr_bio_fd_connect() - * - * @param bio the packet bio - * @return - * - 0 for "connected, can continue" - * - fr_bio_error(IO_WOULD_BLOCK) for "not yet connected, please try again" - * - <0 for other fr_bio_error() +/** Callback for when the FD is activated, i.e. connected. * */ -int fr_radius_client_bio_connect(fr_bio_packet_t *bio) +static int fr_radius_client_bio_activate(fr_bio_t *bio) { - int rcode; - fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t); + fr_radius_client_fd_bio_t *my = bio->uctx; - if (my->info.connected) return 0; + fr_assert(!my->info.connected); - switch (my->info.fd_info->type) { - default: - fr_strerror_const("Invalid RADIUS client bio for connect"); - return fr_bio_error(GENERIC); + my->info.connected = true; - case FR_BIO_FD_UNCONNECTED: - return 0; + fr_assert(0); - case FR_BIO_FD_CONNECTED: - break; - } - switch(my->info.fd_info->state) { - case FR_BIO_FD_STATE_INVALID: - fr_strerror_const("Invalid RADIUS client bio state"); - return fr_bio_error(GENERIC); + return 0; +} - case FR_BIO_FD_STATE_CLOSED: - fr_strerror_const("RADIUS client bio is closed"); - return fr_bio_error(GENERIC); +void fr_radius_client_bio_connect(NDEBUG_UNUSED fr_event_list_t *el, NDEBUG_UNUSED int fd, UNUSED int flags, void *uctx) +{ + fr_radius_client_fd_bio_t *my = talloc_get_type_abort(uctx, fr_radius_client_fd_bio_t); + int rcode; - case FR_BIO_FD_STATE_OPEN: - return 0; + fr_assert(my->common.cb.activate); + fr_assert(my->info.retry_info->el == el); + fr_assert(my->info.fd_info->socket.fd == fd); - case FR_BIO_FD_STATE_CONNECTING: - break; - } + /* + * The socket is already connected, go activate it. This happens when the FD bio opens an + * unconnected socket. It calls our activation routine before the application has a chance to + * call our connect routine. + */ + if (my->info.connected) goto activate; + + fr_assert(my->info.fd_info->type == FR_BIO_FD_CONNECTED); + fr_assert(my->info.fd_info->state == FR_BIO_FD_STATE_CONNECTING); /* * Try to connect it. */ rcode = fr_bio_fd_connect(my->fd); + fr_assert(rcode >= 0); - my->info.connected = (rcode == 0); - return rcode; + my->info.connected = true; + +activate: + (void) my->common.cb.activate(&my->common); } + + /** Callback for when the writes are blocked. * */ @@ -782,6 +772,7 @@ void fr_radius_client_bio_cb_set(fr_bio_packet_t *bio, fr_bio_packet_cb_funcs_t fr_assert((cb->write_blocked != NULL) == (cb->write_resume != NULL)); fr_assert((cb->read_blocked != NULL) == (cb->read_resume != NULL)); + bio_cb.activate = fr_radius_client_bio_activate; bio_cb.write_blocked = fr_radius_client_bio_write_blocked; bio_cb.write_resume = fr_radius_client_bio_write_resume; diff --git a/src/protocols/radius/client.h b/src/protocols/radius/client.h index 7d7543adbd1..98518514793 100644 --- a/src/protocols/radius/client.h +++ b/src/protocols/radius/client.h @@ -58,8 +58,6 @@ typedef struct { fr_bio_packet_t *fr_radius_client_bio_alloc(TALLOC_CTX *ctx, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg) CC_HINT(nonnull); -int fr_radius_client_bio_connect(fr_bio_packet_t *bio) CC_HINT(nonnull); - int fr_radius_client_fd_bio_cancel(fr_bio_packet_t *bio, fr_packet_t *packet) CC_HINT(nonnull); fr_radius_client_bio_info_t const *fr_radius_client_bio_info(fr_bio_packet_t *bio) CC_HINT(nonnull); @@ -69,3 +67,5 @@ size_t fr_radius_client_bio_outstanding(fr_bio_packet_t *bio) CC_HINT(nonnull); int fr_radius_client_bio_force_id(fr_bio_packet_t *bio, int code, int id); void fr_radius_client_bio_cb_set(fr_bio_packet_t *bio, fr_bio_packet_cb_funcs_t const *cb); + +void fr_radius_client_bio_connect(fr_event_list_t *el, int fd, int flags, void *uctx);