]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add framework for RADIUS client bio write blocked / resume callbacks
authorAlan T. DeKok <aland@freeradius.org>
Tue, 14 May 2024 23:59:04 +0000 (19:59 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 15 May 2024 12:16:47 +0000 (08:16 -0400)
src/lib/bio/packet.h
src/protocols/radius/client.c
src/protocols/radius/client.h
src/protocols/radius/client_priv.h

index a5a0cb39e518b02391b1a5692d3e6ca98bbb0962..3809d3aa59825e68f454e778838b7f237936c400 100644 (file)
@@ -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
 };
index 5194b90645f425af0b165cdf0a1c189dde72ae8f..adc2b29dd370cb2a73e879c07b1a0a850e45c528 100644 (file)
@@ -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;
+}
index 6d7579705d5a00b06c4e5137ef4c18409b527934..cafde75784200c3b535d2e9d03baddf0df3b3e3d 100644 (file)
@@ -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);
index a0ae5d2a7c7ddca67971332a38f5ae615dcdbe83..c2e6580f95ba0ae7436cc366dcc8ca0e95f301dd 100644 (file)
@@ -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;