Implemented cooldown period in relay connection to prevent flapping

This commit is contained in:
Laan Tungir
2026-04-10 06:13:02 -04:00
parent 25bdce7337
commit ef8e68b952
4 changed files with 63 additions and 14 deletions

View File

@@ -1 +1 @@
0.5.14
0.5.15

View File

@@ -510,16 +510,32 @@ static void attempt_reconnect(relay_connection_t* relay) {
relay->reconnect_attempts++;
if (ensure_relay_connection(relay) == 0) {
// Success! Reset reconnection state
relay->reconnect_attempts = 0;
relay->next_reconnect_time = 0;
// Success. Keep reconnect_attempts until the connection proves stable.
// This prevents rapid connect->disconnect flapping from immediately resetting backoff.
int reset_after_s = relay->pool->reconnect_config.reconnect_reset_stability_seconds;
if (reset_after_s <= 0) {
// Backward-compatible behavior: reset immediately when cooldown is disabled.
relay->reconnect_attempts = 0;
relay->next_reconnect_time = 0;
} else {
int delay_ms = calculate_reconnect_delay(relay);
int delay_s = (delay_ms + 999) / 1000;
if (delay_s < 1) {
delay_s = 1;
}
relay->next_reconnect_time = time(NULL) + delay_s;
}
// Restore subscriptions on reconnect
restore_subscriptions_on_reconnect(relay);
} else {
// Failed - schedule next attempt with backoff
int delay_ms = calculate_reconnect_delay(relay);
relay->next_reconnect_time = time(NULL) + (delay_ms / 1000);
int delay_s = (delay_ms + 999) / 1000;
if (delay_s < 1) {
delay_s = 1;
}
relay->next_reconnect_time = time(NULL) + delay_s;
}
}
@@ -618,6 +634,7 @@ nostr_pool_reconnect_config_t* nostr_pool_reconnect_config_default(void) {
.initial_reconnect_delay_ms = 1000,
.max_reconnect_delay_ms = 30000,
.reconnect_backoff_multiplier = 2,
.reconnect_reset_stability_seconds = 30,
.ping_interval_seconds = 30,
.pong_timeout_seconds = 10
};
@@ -2033,6 +2050,21 @@ int nostr_relay_pool_poll(nostr_relay_pool_t* pool, int timeout_ms) {
relay->status = NOSTR_POOL_RELAY_CONNECTED;
// If the relay remains connected long enough, clear reconnect backoff.
if (relay->reconnect_attempts > 0) {
int reset_after_s = pool->reconnect_config.reconnect_reset_stability_seconds;
if (reset_after_s <= 0) {
relay->reconnect_attempts = 0;
relay->next_reconnect_time = 0;
} else if (relay->connect_time > 0) {
time_t now = time(NULL);
if (now - relay->connect_time >= reset_after_s) {
relay->reconnect_attempts = 0;
relay->next_reconnect_time = 0;
}
}
}
// Connection health monitoring (ping/pong)
check_connection_health(relay);

View File

@@ -354,6 +354,22 @@ cJSON* nostr_nip17_receive_dm(cJSON* gift_wrap,
// Unseal the rumor
cJSON* rumor = nostr_nip59_unseal_rumor(seal, sender_public_key, recipient_private_key);
cJSON_Delete(seal); // Seal is no longer needed
if (!rumor) {
return NULL;
}
// NIP-17 safety check: seal pubkey must match rumor pubkey to prevent impersonation
cJSON* rumor_pubkey_item = cJSON_GetObjectItem(rumor, "pubkey");
if (!rumor_pubkey_item || !cJSON_IsString(rumor_pubkey_item)) {
cJSON_Delete(rumor);
return NULL;
}
const char* rumor_pubkey_hex = cJSON_GetStringValue(rumor_pubkey_item);
if (!rumor_pubkey_hex || strcmp(sender_pubkey_hex, rumor_pubkey_hex) != 0) {
cJSON_Delete(rumor);
return NULL;
}
return rumor;
}

View File

@@ -2,10 +2,10 @@
#define NOSTR_CORE_H
// Version information (auto-updated by increment_and_push.sh)
#define VERSION "v0.5.14"
#define VERSION "v0.5.15"
#define VERSION_MAJOR 0
#define VERSION_MINOR 5
#define VERSION_PATCH 14
#define VERSION_PATCH 15
/*
* NOSTR Core Library - Complete API Reference
@@ -245,13 +245,14 @@ typedef struct nostr_pool_subscription nostr_pool_subscription_t;
// Reconnection configuration
typedef struct {
int enable_auto_reconnect; // 1 = enable, 0 = disable
int max_reconnect_attempts; // Max attempts per relay
int initial_reconnect_delay_ms; // Initial delay between attempts
int max_reconnect_delay_ms; // Max delay (cap exponential backoff)
int reconnect_backoff_multiplier; // Delay multiplier
int ping_interval_seconds; // How often to ping (0 = disable)
int pong_timeout_seconds; // How long to wait for pong before reconnecting
int enable_auto_reconnect; // 1 = enable, 0 = disable
int max_reconnect_attempts; // Max attempts per relay
int initial_reconnect_delay_ms; // Initial delay between attempts
int max_reconnect_delay_ms; // Max delay (cap exponential backoff)
int reconnect_backoff_multiplier; // Delay multiplier
int reconnect_reset_stability_seconds; // Connected time required before resetting reconnect_attempts
int ping_interval_seconds; // How often to ping (0 = disable)
int pong_timeout_seconds; // How long to wait for pong before reconnecting
} nostr_pool_reconnect_config_t;
// Relay pool management functions