]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add a timer event to retry sending of queued change packets
authorNick Porter <nick@portercomputing.co.uk>
Thu, 17 Nov 2022 19:45:41 +0000 (19:45 +0000)
committerNick Porter <nick@portercomputing.co.uk>
Fri, 18 Nov 2022 18:08:52 +0000 (18:08 +0000)
src/listen/ldap_sync/proto_ldap_sync.c
src/listen/ldap_sync/proto_ldap_sync.h
src/listen/ldap_sync/proto_ldap_sync_ldap.c
src/listen/ldap_sync/proto_ldap_sync_ldap.h

index 17d0b355e7c9c5043a0876a0f33edb83f7f8ea7d..8ad8b00cffb744df46acdf32b14830a01b00bc8f 100644 (file)
@@ -55,6 +55,7 @@ static CONF_PARSER const proto_ldap_sync_config[] = {
        { FR_CONF_OFFSET("num_messages", FR_TYPE_UINT32, proto_ldap_sync_t, num_messages) },
        { FR_CONF_OFFSET("cookie_interval", FR_TYPE_TIME_DELTA, proto_ldap_sync_t, cookie_interval), .dflt = "10" },
        { FR_CONF_OFFSET("cookie_changes", FR_TYPE_UINT32, proto_ldap_sync_t, cookie_changes), .dflt = "100" },
+       { FR_CONF_OFFSET("retry_interval", FR_TYPE_TIME_DELTA, proto_ldap_sync_t, retry_interval), .dflt = "1" },
 
        /*
         *      Areas of the DIT to listen on
index 35b2b7a8bfb6a7f438325ebe9037ce7a1e58498e..4f5504d84336430af6bc94e9fd9b840c06945abd 100644 (file)
@@ -57,6 +57,7 @@ typedef struct {
        fr_time_delta_t         cookie_interval;                //!< Interval between storing cookies.
        uint32_t                cookie_changes;                 //!< Number of LDAP changes to process between
                                                                //!< each cookie store operation.
+       fr_time_delta_t         retry_interval;                 //!< Interval between retrying failed change packets.
 
        fr_schedule_t           *sc;
 
index 6ac1512f4e7709259557c2f2c6843f172cb3291c..17b75cb9285ae0512bd65f44bccfe550024ae2b4 100644 (file)
@@ -334,6 +334,36 @@ static int ldap_sync_entry_send_network(sync_packet_ctx_t *sync_packet_ctx)
        return 0;
 }
 
+/** Event to handle sending of any change packets which failed to send.
+ *
+ * Looks at the head of the list of pending sync packets for unsent
+ * change packets and sends any up to the first cookie.
+ */
+static void ldap_sync_retry_event(fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
+{
+       sync_state_t            *sync = talloc_get_type_abort(uctx, sync_state_t);
+       sync_packet_ctx_t       *sync_packet_ctx = NULL;
+
+       while ((sync_packet_ctx = fr_dlist_next(&sync->pending, sync_packet_ctx))) {
+               if (sync_packet_ctx->type != SYNC_PACKET_TYPE_CHANGE) break;
+               if (sync_packet_ctx->status != SYNC_PACKET_PENDING) continue;
+
+               /*
+                *      Retry sending packet.  Don't try any more if it fails.
+                */
+               if (ldap_sync_entry_send_network(sync_packet_ctx) < 0) break;
+       }
+
+       /*
+        *      We didn't run through the whole list, so there may be other pending
+        *      packets - reschedule a retry event.
+        */
+       if (sync_packet_ctx) {
+               (void) fr_event_timer_in(sync, el, &sync->retry_ev, sync->inst->retry_interval,
+                                        ldap_sync_retry_event, sync);
+       }
+}
+
 static fr_ldap_sync_packet_code_t const sync_packet_code_table[4] = {
        FR_LDAP_SYNC_CODE_PRESENT,
        FR_LDAP_SYNC_CODE_ADD,
@@ -446,7 +476,17 @@ int ldap_sync_entry_send(sync_state_t *sync, uint8_t const uuid[SYNC_UUID_LENGTH
        ldap_msgfree(msg);
 
        if (fr_dlist_insert_tail(&sync->pending, sync_packet_ctx) < 0) goto error;
-       return ldap_sync_entry_send_network(sync_packet_ctx);
+
+       /*
+        *      Send the packet and if it fails to send add a retry event
+        */
+       if ((ldap_sync_entry_send_network(sync_packet_ctx) < 0) &&
+           (fr_event_timer_in(sync, sync->conn->conn->el, &sync->retry_ev,
+                              sync->inst->retry_interval, ldap_sync_retry_event, sync) < 0)) {
+               PERROR("Inserting LDAP sync retry timer failed");
+       }
+
+       return 0;
 }
 
 static void _proto_ldap_socket_init(fr_connection_t *conn, UNUSED fr_connection_state_t prev,
index b918c98e08e10f26de71833f1f2a45710874e256..3f4090f045eb6aff816ddb6010fc4d3b0efe9398 100644 (file)
@@ -70,6 +70,7 @@ struct sync_state_s {
                                                                //!< the last cookie was stored.
 
        fr_event_timer_t const          *cookie_ev;     //!< Timer event for sending cookies.
+       fr_event_timer_t const          *retry_ev;      //!< Timer event for retrying failed changes.
 };
 
 typedef struct sync_state_s sync_state_t;