]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
glue in activation routines
authorAlan T. DeKok <aland@freeradius.org>
Sat, 25 May 2024 19:11:06 +0000 (15:11 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 3 Jun 2024 12:43:47 +0000 (08:43 -0400)
src/bin/radclient-ng.c
src/lib/bio/packet.h
src/lib/bio/retry.c
src/lib/bio/retry.h
src/protocols/radius/client.c
src/protocols/radius/client.h

index 2333fd42556289386853b9db2f5de01fa2a533ce..4d8eb7673b8c41075322d940a9fbda5f50e2e51d 100644 (file)
@@ -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);
        }
index e320fc7d60507994393412eed2be71ee5e4cedb1..04ee60d33edec4cba6c08fc4acb6603042d8a0c0 100644 (file)
@@ -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;
 
index 1296477f0e8d9afb05822b0ac6cc0a4ae6ab3955..383d1657bf2f094cd13d70c2d40d78ceb5bdc3aa 100644 (file)
@@ -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);
index 0298752a97603f5b784588f605969a0b0382c61f..f8e5b4930f6f5c274d3428782ea87582b8b4fc17 100644 (file)
@@ -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;
index 25a9358a1b5437c985537cfbfbb79675fe7f5e03..94620dd0a7dc6766b52b06f8ac9fef6eacd8bccd 100644 (file)
@@ -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;
 
index 7d7543adbd149685c34a73ecceec055e0694a310..985185147938b9b277fe310af71589b243ed3787 100644 (file)
@@ -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);