v1.0.6 - Working on cleaning up subscriptions which were piling up. Set a startup cleanup, and a connection age limit.

This commit is contained in:
Your Name
2025-12-05 07:37:57 -04:00
parent 137df6253d
commit ae0370b47f
10 changed files with 663 additions and 5 deletions

View File

@@ -1984,6 +1984,73 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
return 0;
}
// Check and disconnect connections that have exceeded max age
// This function works by checking connection age through the subscription system
static void check_connection_age(int max_connection_seconds) {
if (max_connection_seconds <= 0) {
return; // Feature disabled
}
time_t current_time = time(NULL);
// Lock the subscription manager to safely iterate through subscriptions
pthread_mutex_lock(&g_subscription_manager.subscriptions_lock);
// Track unique WSI pointers we've already checked to avoid duplicate checks
struct lws** checked_wsis = NULL;
int checked_count = 0;
int checked_capacity = 0;
subscription_t* sub = g_subscription_manager.active_subscriptions;
while (sub) {
if (!sub->active || !sub->wsi) {
sub = sub->next;
continue;
}
// Check if we've already processed this WSI
int already_checked = 0;
for (int i = 0; i < checked_count; i++) {
if (checked_wsis[i] == sub->wsi) {
already_checked = 1;
break;
}
}
if (!already_checked) {
// Get per-session data to check connection age
struct per_session_data *pss = (struct per_session_data *)lws_wsi_user(sub->wsi);
if (pss && pss->connection_established > 0) {
time_t connection_age = current_time - pss->connection_established;
if (connection_age >= max_connection_seconds) {
DEBUG_LOG("Disconnecting client %s: connection age %ld seconds exceeds limit %d seconds",
pss->client_ip, connection_age, max_connection_seconds);
// Close connection with normal closure status
lws_close_reason(sub->wsi, LWS_CLOSE_STATUS_NORMAL,
(unsigned char*)"Connection age limit reached", 28);
}
}
// Add to checked list
if (checked_count >= checked_capacity) {
checked_capacity = checked_capacity == 0 ? 64 : checked_capacity * 2;
checked_wsis = realloc(checked_wsis, checked_capacity * sizeof(struct lws*));
}
checked_wsis[checked_count++] = sub->wsi;
}
sub = sub->next;
}
pthread_mutex_unlock(&g_subscription_manager.subscriptions_lock);
// Cleanup
free(checked_wsis);
}
// WebSocket protocol definition
static struct lws_protocols protocols[] = {
{
@@ -2152,6 +2219,9 @@ int start_websocket_relay(int port_override, int strict_port) {
// Static variable for status post timing (initialize to 0 for immediate first post)
static time_t last_status_post_time = 0;
// Static variable for connection age check timing
static time_t last_connection_age_check = 0;
// Main event loop with proper signal handling
while (g_server_running && !g_shutdown_flag) {
@@ -2174,6 +2244,13 @@ int start_websocket_relay(int port_override, int strict_port) {
generate_and_post_status_event();
}
}
// Check connection age limits (every 60 seconds)
int max_connection_seconds = get_config_int("max_connection_seconds", 86400);
if (max_connection_seconds > 0 && (current_time - last_connection_age_check >= 60)) {
last_connection_age_check = current_time;
check_connection_age(max_connection_seconds);
}
}
lws_context_destroy(ws_context);