Skip to content

Commit 646c2ee

Browse files
committed
Add idle socket cleanup for proxy connections
Implement a mechanism to reclaim proxy sockets that have been idle for a specified timeout period. Introduced `fr_packet_list_socket_find_stale` to identify stale sockets and integrated it into the main event loop for periodic cleanup. This enhances resource management by ensuring unused sockets are removed efficiently.
1 parent be18920 commit 646c2ee

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

src/include/packet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ bool fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd, int proto,
6161
fr_ipaddr_t *dst_ipaddr, uint16_t dst_port,
6262
void *ctx);
6363
bool fr_packet_list_socket_del(fr_packet_list_t *pl, int sockfd);
64+
int fr_packet_list_socket_find_stale(fr_packet_list_t *pl, int idle_timeout, void **ctx);
6465
bool fr_packet_list_socket_freeze(fr_packet_list_t *pl, int sockfd);
6566
bool fr_packet_list_socket_thaw(fr_packet_list_t *pl, int sockfd);
6667
int fr_packet_list_walk(fr_packet_list_t *pl, void *ctx, rb_walker_t callback);

src/lib/packet.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ typedef struct fr_packet_socket_t {
277277
uint32_t counter;
278278
#endif
279279

280+
time_t last_idle;
280281
uint8_t id[32];
281282
} fr_packet_socket_t;
282283

@@ -375,6 +376,35 @@ bool fr_packet_list_socket_del(fr_packet_list_t *pl, int sockfd)
375376
}
376377

377378

379+
/*
380+
* Find a destination-specific socket with no outstanding requests
381+
* that has been idle for at least idle_timeout seconds.
382+
* Returns the sockfd, or -1 if none found. Skips wildcard sockets
383+
* (the default proxy socket) so they are never reclaimed.
384+
*/
385+
int fr_packet_list_socket_find_stale(fr_packet_list_t *pl, int idle_timeout, void **ctx)
386+
{
387+
int i;
388+
time_t now = time(NULL);
389+
390+
if (!pl) return -1;
391+
392+
for (i = 0; i < MAX_SOCKETS; i++) {
393+
if (pl->sockets[i].sockfd == -1) continue;
394+
if (pl->sockets[i].num_outgoing != 0) continue;
395+
if (pl->sockets[i].dont_use) continue;
396+
if (pl->sockets[i].dst_any && (pl->sockets[i].dst_port == 0)) continue;
397+
if (pl->sockets[i].last_idle == 0) continue;
398+
if ((now - pl->sockets[i].last_idle) < idle_timeout) continue;
399+
400+
if (ctx) *ctx = pl->sockets[i].ctx;
401+
return pl->sockets[i].sockfd;
402+
}
403+
404+
return -1;
405+
}
406+
407+
378408
bool fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd, int proto,
379409
#ifdef WITH_RADIUSV11
380410
bool radiusv11,
@@ -945,6 +975,10 @@ bool fr_packet_list_id_free(fr_packet_list_t *pl,
945975
ps->num_outgoing--;
946976
pl->num_outgoing--;
947977

978+
if (ps->num_outgoing == 0) {
979+
ps->last_idle = time(NULL);
980+
}
981+
948982
request->id = -1;
949983
request->src_ipaddr.af = AF_UNSPEC; /* id_alloc checks this */
950984
request->src_port = 0;

src/main/process.c

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3920,6 +3920,17 @@ static int request_proxy_anew(REQUEST *request)
39203920
/*
39213921
* Find a live home server for the request.
39223922
*/
3923+
if (request->home_pool == NULL) {
3924+
REDEBUG2("Failed to find live home server for request");
3925+
if (setup_post_proxy_fail(request)) {
3926+
ASSERT_MASTER;
3927+
request_queue_or_run(request, proxy_running); /* network thread - timer */
3928+
} else {
3929+
gettimeofday(&request->reply->timestamp, NULL);
3930+
request_cleanup_delay_init(request);
3931+
}
3932+
return 0;
3933+
}
39233934
home = home_server_ldb(NULL, request->home_pool, request);
39243935
if (!home) {
39253936
REDEBUG2("Failed to find live home server for request");
@@ -6012,9 +6023,8 @@ static void event_new_fd(void *ctx)
60126023
fr_packet_list_walk(proxy_list, this, eol_proxy_listener);
60136024

60146025
if (!fr_packet_list_socket_del(proxy_list, this->fd)) {
6015-
ERROR("Fatal error removing socket %s: %s",
6016-
buffer, fr_strerror());
6017-
fr_exit(1);
6026+
WARN("Proxy socket %s already removed from packet list",
6027+
buffer);
60186028
}
60196029

60206030
#ifdef WITH_TLS
@@ -6360,6 +6370,53 @@ static void create_default_proxy_listener(int af)
63606370
radius_update_listener(this);
63616371
}
63626372

6373+
#define PROXY_IDLE_TIMEOUT 5
6374+
6375+
static fr_event_t *proxy_idle_ev = NULL;
6376+
6377+
/*
6378+
* Periodic timer to reclaim proxy sockets that have been idle
6379+
* (num_outgoing == 0) for longer than PROXY_IDLE_TIMEOUT seconds.
6380+
* Runs in the main event loop thread.
6381+
*/`
6382+
static void proxy_idle_socket_cleanup(UNUSED void *ctx)
6383+
{
6384+
struct timeval when;
6385+
void *stale_ctx;
6386+
int stale_fd;
6387+
6388+
ASSERT_MASTER;
6389+
6390+
PTHREAD_MUTEX_LOCK(&proxy_mutex);
6391+
6392+
while ((stale_fd = fr_packet_list_socket_find_stale(proxy_list, PROXY_IDLE_TIMEOUT, &stale_ctx)) >= 0) {
6393+
rad_listen_t *stale = stale_ctx;
6394+
6395+
fr_packet_list_socket_del(proxy_list, stale_fd);
6396+
stale->status = RAD_LISTEN_STATUS_REMOVE_NOW;
6397+
6398+
#ifdef HAVE_PTHREAD_H
6399+
proxy_no_new_sockets = false;
6400+
#endif
6401+
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
6402+
6403+
event_new_fd(stale);
6404+
6405+
PTHREAD_MUTEX_LOCK(&proxy_mutex);
6406+
}
6407+
6408+
PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
6409+
6410+
gettimeofday(&when, NULL);
6411+
when.tv_sec += PROXY_IDLE_TIMEOUT;
6412+
6413+
ASSERT_MASTER;
6414+
if (!fr_event_insert(el, proxy_idle_socket_cleanup, NULL, &when,
6415+
&proxy_idle_ev)) {
6416+
ERROR("Failed re-inserting proxy idle cleanup timer");
6417+
}
6418+
}
6419+
63636420
/*
63646421
* See if we automatically need to open a proxy socket.
63656422
*/
@@ -6557,6 +6614,18 @@ int radius_event_start(CONF_SECTION *cs, bool have_children)
65576614

65586615
#ifdef WITH_PROXY
65596616
check_proxy(head);
6617+
6618+
if (main_config.proxy_requests && proxy_list) {
6619+
struct timeval when;
6620+
6621+
gettimeofday(&when, NULL);
6622+
when.tv_sec += PROXY_IDLE_TIMEOUT;
6623+
6624+
if (!fr_event_insert(el, proxy_idle_socket_cleanup, NULL,
6625+
&when, &proxy_idle_ev)) {
6626+
ERROR("Failed inserting proxy idle cleanup timer");
6627+
}
6628+
}
65606629
#endif
65616630

65626631
/*

0 commit comments

Comments
 (0)