Implemented cooldown period in relay connection to prevent flapping
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user