From 50f193174940187f23e9b68881a796582e0758a0 Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Tue, 14 May 2024 19:59:04 -0400 Subject: [PATCH] add framework for RADIUS client bio write blocked / resume callbacks --- src/lib/bio/packet.h | 15 +++++-- src/protocols/radius/client.c | 66 +++++++++++++++++++++++++++++- src/protocols/radius/client.h | 2 + src/protocols/radius/client_priv.h | 1 - 4 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/lib/bio/packet.h b/src/lib/bio/packet.h index a5a0cb39e5..3809d3aa59 100644 --- a/src/lib/bio/packet.h +++ b/src/lib/bio/packet.h @@ -68,17 +68,24 @@ typedef int (*fr_bio_packet_release_t)(fr_bio_packet_t *bio, fr_packet_t *packet typedef void (*fr_bio_packet_signal_t)(fr_bio_packet_t *bio); +typedef struct { + fr_bio_packet_signal_t read_blocked; + fr_bio_packet_signal_t write_blocked; + + fr_bio_packet_signal_t read_resume; + fr_bio_packet_signal_t write_resume; +} fr_bio_packet_cb_funcs_t; + struct fr_bio_packet_s { void *uctx; //!< user ctx, caller can manually set it. fr_bio_packet_read_t read; //!< read from the underlying bio fr_bio_packet_write_t write; //!< write to the underlying bio - fr_bio_packet_signal_t read_blocked; - fr_bio_packet_signal_t write_blocked; + fr_bio_packet_cb_funcs_t cb; - fr_bio_packet_signal_t read_resume; - fr_bio_packet_signal_t write_resume; + bool write_blocked; + bool read_blocked; fr_bio_t *bio; //!< underlying bio for IO }; diff --git a/src/protocols/radius/client.c b/src/protocols/radius/client.c index 5194b90645..adc2b29dd3 100644 --- a/src/protocols/radius/client.c +++ b/src/protocols/radius/client.c @@ -146,7 +146,7 @@ int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, void *request_c all_ids_used: my->all_ids_used = true; - if (my->common.write_blocked) my->common.write_blocked(&my->common); + if (my->common.cb.write_blocked) my->common.cb.write_blocked(&my->common); fr_strerror_const("All IDs are in use"); return fr_bio_error(GENERIC); @@ -313,7 +313,7 @@ static void radius_client_retry_release(fr_bio_t *bio, fr_bio_retry_entry_t *ret if (my->all_ids_used) { my->all_ids_used = false; - if (!my->write_blocked && my->common.write_resume) my->common.write_resume(&my->common); + if (!my->common.write_blocked && my->common.cb.write_resume) my->common.cb.write_resume(&my->common); } } @@ -501,3 +501,65 @@ int fr_radius_client_bio_connect(fr_bio_packet_t *bio) my->info.connected = (rcode == 0); return rcode; } + +/* + * Debounce functions to get to the right callback. + */ +static void fr_bio_write_blocked(fr_bio_t *bio) +{ + fr_radius_client_fd_bio_t *my = bio->uctx; + + my->common.write_blocked = true; + + my->common.cb.write_blocked(&my->common); +} + +static void fr_bio_write_resume(fr_bio_t *bio) +{ + fr_radius_client_fd_bio_t *my = bio->uctx; + + /* + * IO is unblocked, but we don't have any free IDs. So we can't yet resume writes. + */ + if (my->all_ids_used) return; + + my->common.write_blocked = false; + + my->common.cb.write_resume(&my->common); +} + +static void fr_bio_read_blocked(fr_bio_t *bio) +{ + fr_radius_client_fd_bio_t *my = bio->uctx; + + my->common.read_blocked = true; + + my->common.cb.read_blocked(&my->common); +} + +static void fr_bio_read_resume(fr_bio_t *bio) +{ + fr_radius_client_fd_bio_t *my = bio->uctx; + + my->common.read_blocked = false; + + my->common.cb.read_resume(&my->common); +} + +int fr_radius_client_bio_cb_set(fr_bio_packet_t *bio, fr_bio_packet_cb_funcs_t const *cb) +{ + fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t); + fr_bio_cb_funcs_t bio_cb = {}; + +#undef SET +#define SET(_x) if (cb->_x) bio_cb._x = fr_bio_ ## _x + + SET(write_blocked); + SET(read_blocked); + SET(write_resume); + SET(read_resume); + + (void) fr_bio_cb_set(my->fd, &bio_cb); + + return 0; +} diff --git a/src/protocols/radius/client.h b/src/protocols/radius/client.h index 6d7579705d..cafde75784 100644 --- a/src/protocols/radius/client.h +++ b/src/protocols/radius/client.h @@ -62,3 +62,5 @@ fr_radius_client_bio_info_t const *fr_radius_client_bio_info(fr_bio_packet_t *bi 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); + +int fr_radius_client_bio_cb_set(fr_bio_packet_t *bio, fr_bio_packet_cb_funcs_t const *cb); diff --git a/src/protocols/radius/client_priv.h b/src/protocols/radius/client_priv.h index a0ae5d2a7c..c2e6580f95 100644 --- a/src/protocols/radius/client_priv.h +++ b/src/protocols/radius/client_priv.h @@ -46,7 +46,6 @@ typedef struct { fr_bio_t *fd; bool all_ids_used; //!< ALL IDs are used. - bool write_blocked; fr_radius_client_bio_info_t info; -- 2.47.3