From: Nick Porter Date: Thu, 17 Nov 2022 19:45:41 +0000 (+0000) Subject: Add a timer event to retry sending of queued change packets X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e850aab3fb88788bc96aa35b3c7447c5eb18b72;p=thirdparty%2Ffreeradius-server.git Add a timer event to retry sending of queued change packets --- diff --git a/src/listen/ldap_sync/proto_ldap_sync.c b/src/listen/ldap_sync/proto_ldap_sync.c index 17d0b355e7c..8ad8b00cffb 100644 --- a/src/listen/ldap_sync/proto_ldap_sync.c +++ b/src/listen/ldap_sync/proto_ldap_sync.c @@ -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 diff --git a/src/listen/ldap_sync/proto_ldap_sync.h b/src/listen/ldap_sync/proto_ldap_sync.h index 35b2b7a8bfb..4f5504d8433 100644 --- a/src/listen/ldap_sync/proto_ldap_sync.h +++ b/src/listen/ldap_sync/proto_ldap_sync.h @@ -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; diff --git a/src/listen/ldap_sync/proto_ldap_sync_ldap.c b/src/listen/ldap_sync/proto_ldap_sync_ldap.c index 6ac1512f4e7..17b75cb9285 100644 --- a/src/listen/ldap_sync/proto_ldap_sync_ldap.c +++ b/src/listen/ldap_sync/proto_ldap_sync_ldap.c @@ -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, diff --git a/src/listen/ldap_sync/proto_ldap_sync_ldap.h b/src/listen/ldap_sync/proto_ldap_sync_ldap.h index b918c98e08e..3f4090f045e 100644 --- a/src/listen/ldap_sync/proto_ldap_sync_ldap.h +++ b/src/listen/ldap_sync/proto_ldap_sync_ldap.h @@ -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;