Compare commits

..
3 Commits
6 changed files with 31 additions and 28 deletions
+20 -22
View File
@@ -1328,12 +1328,24 @@ async function subscribeToConfiguration() {
},
onclose(reason) {
console.log('Subscription closed:', reason);
// Reset subscription state to allow re-subscription
isSubscribed = false;
isSubscribing = false;
isRelayConnected = false;
updateConfigStatus(false);
log('WebSocket connection closed - subscription state reset', 'WARNING');
// Only reset state if the admin relay itself closed (not external relays timing out)
// reason is an array of close reasons, one per relay in the subscription
const adminUrl = relayConnectionUrl.value.trim();
const reasons = Array.isArray(reason) ? reason : [reason];
// Check if the admin relay's connection closed (not just external relays timing out)
// If all reasons are 'connection timed out', these are external relays, not our relay
const allTimeout = reasons.every(r => r === 'connection timed out');
if (!allTimeout) {
// Admin relay actually closed — reset state
isSubscribed = false;
isSubscribing = false;
isRelayConnected = false;
updateConfigStatus(false);
log('WebSocket connection closed - subscription state reset', 'WARNING');
} else {
// External relays timed out — keep admin relay state intact
log('External relay connections timed out (admin relay still connected)', 'INFO');
}
}
});
@@ -6193,27 +6205,13 @@ async function loadIpBans() {
// Execute SQL query and handle IP bans response
async function executeSqlQueryRaw(query, queryId) {
if (!pool || pool.length === 0) {
if (!relayPool) {
log('Not connected to relay', 'ERROR');
return;
}
const relay = pool[0];
if (!relay) {
log('No relay connection available', 'ERROR');
return;
}
// Create a kind 23456 event with SQL query
const event = {
kind: 23456,
content: query,
tags: [['t', 'sql_query'], ['id', queryId]],
created_at: Math.floor(Date.now() / 1000)
};
try {
await relay.publish(event);
await sendAdminCommand(['sql_query', query, queryId]);
log('Loading IP bans...', 'INFO');
} catch (error) {
log('Failed to load IP bans: ' + error.message, 'ERROR');
+1 -1
View File
@@ -1 +1 @@
2284646
2370279
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -13,8 +13,8 @@
// Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define CRELAY_VERSION_MAJOR 1
#define CRELAY_VERSION_MINOR 2
#define CRELAY_VERSION_PATCH 34
#define CRELAY_VERSION "v1.2.34"
#define CRELAY_VERSION_PATCH 37
#define CRELAY_VERSION "v1.2.37"
// Relay metadata (authoritative source for NIP-11 information)
#define RELAY_NAME "C-Relay"
+5 -1
View File
@@ -634,6 +634,9 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
pss->challenge_created = 0;
pss->challenge_expires = 0;
// Mark as WebSocket connection (not HTTP)
pss->is_websocket = 1;
// Register in global connection list for idle tracking
connection_list_add(wsi, pss);
@@ -2260,7 +2263,8 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
// This catches:
// 1. Idle connections that timed out (never sent REQ/EVENT/AUTH)
// 2. Early disconnects (client closed before sending REQ/EVENT/AUTH)
if (!pss->session_active && strlen(pss->client_ip) > 0) {
// Only record for WebSocket connections, not HTTP requests (NIP-11, embedded files)
if (!pss->session_active && pss->is_websocket && strlen(pss->client_ip) > 0) {
// Use separate idle failure recording (has its own threshold/duration)
ip_ban_record_idle_failure(pss->client_ip);
DEBUG_LOG("Recording idle/early-disconnect failure for IP %s (connected %ld seconds)",
+1
View File
@@ -93,6 +93,7 @@ struct per_session_data {
// Session activity tracking for idle connection banning
int session_active; // 1 if client sent REQ or EVENT, 0 otherwise
int idle_timeout_sec; // Timeout value for this session (copied from config)
int is_websocket; // 1 if this is a WebSocket connection, 0 for HTTP
};
// NIP-11 HTTP session data structure for managing buffer lifetime