v0.7.39 - Set dm's back 2 days to adjust for timestamp ramdomization of giftwraps.
This commit is contained in:
@@ -950,10 +950,8 @@ button:disabled {
|
|||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-family: var(--font-family);
|
font-family: var(--font-family);
|
||||||
max-width: 200px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sql-results-table th {
|
.sql-results-table th {
|
||||||
|
|||||||
28
api/index.js
28
api/index.js
@@ -1064,7 +1064,7 @@ async function subscribeToConfiguration() {
|
|||||||
"#p": [userPubkey], // Only DMs directed to this user
|
"#p": [userPubkey], // Only DMs directed to this user
|
||||||
limit: 50
|
limit: 50
|
||||||
}, {
|
}, {
|
||||||
since: Math.floor(Date.now() / 1000), // Start from current time
|
since: Math.floor(Date.now() / 1000) - (2 * 24 * 60 * 60), // Look back 2 days for NIP-59 randomized timestamps
|
||||||
kinds: [1059], // NIP-17 GiftWrap events
|
kinds: [1059], // NIP-17 GiftWrap events
|
||||||
"#p": [userPubkey], // Only GiftWrap events addressed to this user
|
"#p": [userPubkey], // Only GiftWrap events addressed to this user
|
||||||
limit: 50
|
limit: 50
|
||||||
@@ -1080,7 +1080,7 @@ async function subscribeToConfiguration() {
|
|||||||
if (event.kind === 24567) {
|
if (event.kind === 24567) {
|
||||||
const dTag = event.tags.find(tag => tag[0] === 'd');
|
const dTag = event.tags.find(tag => tag[0] === 'd');
|
||||||
const dataType = dTag ? dTag[1] : 'unknown';
|
const dataType = dTag ? dTag[1] : 'unknown';
|
||||||
console.log(`📊 Monitoring event: ${dataType}`);
|
// console.log(`📊 Monitoring event: ${dataType}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`📨 Event received: kind ${event.kind}`);
|
console.log(`📨 Event received: kind ${event.kind}`);
|
||||||
}
|
}
|
||||||
@@ -1111,20 +1111,32 @@ async function subscribeToConfiguration() {
|
|||||||
|
|
||||||
// Handle NIP-17 GiftWrap DMs
|
// Handle NIP-17 GiftWrap DMs
|
||||||
if (event.kind === 1059) {
|
if (event.kind === 1059) {
|
||||||
|
console.log(`📨 RECEIVED KIND 1059 EVENT:`, {
|
||||||
|
id: event.id,
|
||||||
|
pubkey: event.pubkey,
|
||||||
|
created_at: event.created_at,
|
||||||
|
content: event.content.substring(0, 100) + '...',
|
||||||
|
tags: event.tags
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Unwrap gift wrap to get seal
|
// Step 1: Unwrap gift wrap to get seal
|
||||||
const sealJson = await window.nostr.nip44.decrypt(event.pubkey, event.content);
|
const sealJson = await window.nostr.nip44.decrypt(event.pubkey, event.content);
|
||||||
|
console.log(`🔓 STEP 1 - Unwrapped gift wrap:`, sealJson.substring(0, 100) + '...');
|
||||||
const seal = safeJsonParse(sealJson);
|
const seal = safeJsonParse(sealJson);
|
||||||
if (!seal || seal.kind !== 13) {
|
if (!seal || seal.kind !== 13) {
|
||||||
throw new Error('Unwrapped content is not a valid seal (kind 13)');
|
throw new Error('Unwrapped content is not a valid seal (kind 13)');
|
||||||
}
|
}
|
||||||
|
console.log(`✅ Seal validated:`, { kind: seal.kind, pubkey: seal.pubkey.substring(0, 16) + '...' });
|
||||||
|
|
||||||
// Step 2: Unseal to get rumor
|
// Step 2: Unseal to get rumor
|
||||||
const rumorJson = await window.nostr.nip44.decrypt(seal.pubkey, seal.content);
|
const rumorJson = await window.nostr.nip44.decrypt(seal.pubkey, seal.content);
|
||||||
|
console.log(`🔓 STEP 2 - Unsealed rumor:`, rumorJson.substring(0, 100) + '...');
|
||||||
const rumor = safeJsonParse(rumorJson);
|
const rumor = safeJsonParse(rumorJson);
|
||||||
if (!rumor || rumor.kind !== 14) {
|
if (!rumor || rumor.kind !== 14) {
|
||||||
throw new Error('Unsealed content is not a valid rumor (kind 14)');
|
throw new Error('Unsealed content is not a valid rumor (kind 14)');
|
||||||
}
|
}
|
||||||
|
console.log(`✅ Rumor validated:`, { kind: rumor.kind, pubkey: rumor.pubkey.substring(0, 16) + '...', content: rumor.content.substring(0, 50) + '...' });
|
||||||
|
|
||||||
log(`Received NIP-17 DM from relay: ${rumor.content.substring(0, 50)}...`, 'INFO');
|
log(`Received NIP-17 DM from relay: ${rumor.content.substring(0, 50)}...`, 'INFO');
|
||||||
|
|
||||||
@@ -1137,6 +1149,7 @@ async function subscribeToConfiguration() {
|
|||||||
logTestEvent('RECV', `NIP-17 DM: ${rumor.content}`, 'DM');
|
logTestEvent('RECV', `NIP-17 DM: ${rumor.content}`, 'DM');
|
||||||
}
|
}
|
||||||
} catch (unwrapError) {
|
} catch (unwrapError) {
|
||||||
|
console.error(`❌ NIP-17 DM UNWRAP FAILED:`, unwrapError);
|
||||||
log(`Failed to unwrap NIP-17 DM: ${unwrapError.message}`, 'ERROR');
|
log(`Failed to unwrap NIP-17 DM: ${unwrapError.message}`, 'ERROR');
|
||||||
if (typeof logTestEvent === 'function') {
|
if (typeof logTestEvent === 'function') {
|
||||||
logTestEvent('ERROR', `Failed to unwrap DM: ${unwrapError.message}`, 'DM');
|
logTestEvent('ERROR', `Failed to unwrap DM: ${unwrapError.message}`, 'DM');
|
||||||
@@ -2106,8 +2119,8 @@ if (relayPubkeyContainer) {
|
|||||||
const relayPubkeyElement = document.getElementById('relay-pubkey');
|
const relayPubkeyElement = document.getElementById('relay-pubkey');
|
||||||
if (relayPubkeyElement && relayPubkeyElement.textContent !== 'Loading...') {
|
if (relayPubkeyElement && relayPubkeyElement.textContent !== 'Loading...') {
|
||||||
try {
|
try {
|
||||||
// Get the full npub (remove line breaks for clipboard)
|
// Get the full npub (remove all whitespace for continuous string)
|
||||||
const fullNpub = relayPubkeyElement.textContent.replace(/\n/g, '');
|
const fullNpub = relayPubkeyElement.textContent.replace(/\s/g, '');
|
||||||
|
|
||||||
await navigator.clipboard.writeText(fullNpub);
|
await navigator.clipboard.writeText(fullNpub);
|
||||||
|
|
||||||
@@ -3536,6 +3549,13 @@ async function sendNIP17DM() {
|
|||||||
throw new Error('Failed to sign gift wrap event');
|
throw new Error('Failed to sign gift wrap event');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEBUG: Log NIP-17 event details when created
|
||||||
|
console.log('=== NIP-17 EVENT CREATED ===');
|
||||||
|
console.log('Full event:', JSON.stringify(signedGiftWrap, null, 2));
|
||||||
|
console.log('Timestamp:', signedGiftWrap.created_at);
|
||||||
|
console.log('Local date time:', new Date(signedGiftWrap.created_at * 1000).toLocaleString());
|
||||||
|
console.log('=== END NIP-17 EVENT DEBUG ===');
|
||||||
|
|
||||||
log('NIP-17 DM event created and signed with ephemeral key, publishing...', 'INFO');
|
log('NIP-17 DM event created and signed with ephemeral key, publishing...', 'INFO');
|
||||||
|
|
||||||
// Publish via SimplePool
|
// Publish via SimplePool
|
||||||
|
|||||||
209
docs/subscription_matching_debug_plan.md
Normal file
209
docs/subscription_matching_debug_plan.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# Subscription Matching Debug Plan
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
The relay is not matching kind 1059 (NIP-17 gift wrap) events to subscriptions, even though a subscription exists with `kinds:[1059]` filter. The log shows:
|
||||||
|
```
|
||||||
|
Event broadcast complete: 0 subscriptions matched
|
||||||
|
```
|
||||||
|
|
||||||
|
But we have this subscription:
|
||||||
|
```
|
||||||
|
sub:3 146.70.187.119 0x78edc9b43210 8m 27s kinds:[1059], since:10/23/2025, 4:27:59 PM, limit:50
|
||||||
|
```
|
||||||
|
|
||||||
|
## Investigation Strategy
|
||||||
|
|
||||||
|
### 1. Add Debug Output to `event_matches_filter()` (lines 386-564)
|
||||||
|
Add debug logging at each filter check to trace the matching logic:
|
||||||
|
|
||||||
|
- **Entry point**: Log the event kind and filter being tested
|
||||||
|
- **Kinds filter check** (lines 392-415): Log whether kinds filter exists, the event kind value, and each filter kind being compared
|
||||||
|
- **Authors filter check** (lines 417-442): Log if authors filter exists and matching results
|
||||||
|
- **IDs filter check** (lines 444-469): Log if IDs filter exists and matching results
|
||||||
|
- **Since filter check** (lines 471-482): Log the event timestamp vs filter since value
|
||||||
|
- **Until filter check** (lines 484-495): Log the event timestamp vs filter until value
|
||||||
|
- **Tag filters check** (lines 497-561): Log tag filter matching details
|
||||||
|
- **Exit point**: Log whether the overall filter matched
|
||||||
|
|
||||||
|
### 2. Add Debug Output to `event_matches_subscription()` (lines 567-581)
|
||||||
|
Add logging to show:
|
||||||
|
- How many filters are in the subscription
|
||||||
|
- Which filter (if any) matched
|
||||||
|
- Overall subscription match result
|
||||||
|
|
||||||
|
### 3. Add Debug Output to `broadcast_event_to_subscriptions()` (lines 584-726)
|
||||||
|
Add logging to show:
|
||||||
|
- The event being broadcast (kind, id, created_at)
|
||||||
|
- Total number of active subscriptions being checked
|
||||||
|
- How many subscriptions matched after the first pass
|
||||||
|
|
||||||
|
### 4. Key Areas to Focus On
|
||||||
|
|
||||||
|
Based on the code analysis, the most likely issues are:
|
||||||
|
|
||||||
|
1. **Kind matching logic** (lines 392-415): The event kind might not be extracted correctly, or the comparison might be failing
|
||||||
|
2. **Since timestamp** (lines 471-482): The subscription has a `since` filter - if the event timestamp is before this, it won't match
|
||||||
|
3. **Event structure**: The event JSON might not have the expected structure
|
||||||
|
|
||||||
|
### 5. Specific Debug Additions
|
||||||
|
|
||||||
|
#### In `event_matches_filter()` at line 386:
|
||||||
|
```c
|
||||||
|
// Add at start of function
|
||||||
|
cJSON* event_kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||||
|
cJSON* event_id_obj = cJSON_GetObjectItem(event, "id");
|
||||||
|
cJSON* event_created_at_obj = cJSON_GetObjectItem(event, "created_at");
|
||||||
|
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Testing event kind=%d id=%.8s created_at=%ld",
|
||||||
|
event_kind_obj ? (int)cJSON_GetNumberValue(event_kind_obj) : -1,
|
||||||
|
event_id_obj && cJSON_IsString(event_id_obj) ? cJSON_GetStringValue(event_id_obj) : "null",
|
||||||
|
event_created_at_obj ? (long)cJSON_GetNumberValue(event_created_at_obj) : 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### In kinds filter check (after line 392):
|
||||||
|
```c
|
||||||
|
if (filter->kinds && cJSON_IsArray(filter->kinds)) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Checking kinds filter with %d kinds", cJSON_GetArraySize(filter->kinds));
|
||||||
|
|
||||||
|
cJSON* event_kind = cJSON_GetObjectItem(event, "kind");
|
||||||
|
if (!event_kind || !cJSON_IsNumber(event_kind)) {
|
||||||
|
DEBUG_WARN("FILTER_MATCH: Event has no valid kind field");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int event_kind_val = (int)cJSON_GetNumberValue(event_kind);
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Event kind=%d", event_kind_val);
|
||||||
|
|
||||||
|
int kind_match = 0;
|
||||||
|
cJSON* kind_item = NULL;
|
||||||
|
cJSON_ArrayForEach(kind_item, filter->kinds) {
|
||||||
|
if (cJSON_IsNumber(kind_item)) {
|
||||||
|
int filter_kind = (int)cJSON_GetNumberValue(kind_item);
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Comparing event kind %d with filter kind %d", event_kind_val, filter_kind);
|
||||||
|
if (filter_kind == event_kind_val) {
|
||||||
|
kind_match = 1;
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Kind matched!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kind_match) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: No kind match, filter rejected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Kinds filter passed");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### In since filter check (after line 472):
|
||||||
|
```c
|
||||||
|
if (filter->since > 0) {
|
||||||
|
cJSON* event_created_at = cJSON_GetObjectItem(event, "created_at");
|
||||||
|
if (!event_created_at || !cJSON_IsNumber(event_created_at)) {
|
||||||
|
DEBUG_WARN("FILTER_MATCH: Event has no valid created_at field");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long event_timestamp = (long)cJSON_GetNumberValue(event_created_at);
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Checking since filter: event_ts=%ld filter_since=%ld",
|
||||||
|
event_timestamp, filter->since);
|
||||||
|
|
||||||
|
if (event_timestamp < filter->since) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Event too old (before since), filter rejected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Since filter passed");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### At end of `event_matches_filter()` (before line 563):
|
||||||
|
```c
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: All filters passed, event matches!");
|
||||||
|
return 1; // All filters passed
|
||||||
|
```
|
||||||
|
|
||||||
|
#### In `event_matches_subscription()` at line 567:
|
||||||
|
```c
|
||||||
|
int event_matches_subscription(cJSON* event, subscription_t* subscription) {
|
||||||
|
if (!event || !subscription || !subscription->filters) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Testing subscription '%s'", subscription->id);
|
||||||
|
|
||||||
|
int filter_num = 0;
|
||||||
|
subscription_filter_t* filter = subscription->filters;
|
||||||
|
while (filter) {
|
||||||
|
filter_num++;
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Testing filter #%d", filter_num);
|
||||||
|
|
||||||
|
if (event_matches_filter(event, filter)) {
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Filter #%d matched! Subscription '%s' matches",
|
||||||
|
filter_num, subscription->id);
|
||||||
|
return 1; // Match found (OR logic)
|
||||||
|
}
|
||||||
|
filter = filter->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE("SUB_MATCH: No filters matched for subscription '%s'", subscription->id);
|
||||||
|
return 0; // No filters matched
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### In `broadcast_event_to_subscriptions()` at line 584:
|
||||||
|
```c
|
||||||
|
int broadcast_event_to_subscriptions(cJSON* event) {
|
||||||
|
if (!event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log event details
|
||||||
|
cJSON* event_kind = cJSON_GetObjectItem(event, "kind");
|
||||||
|
cJSON* event_id = cJSON_GetObjectItem(event, "id");
|
||||||
|
cJSON* event_created_at = cJSON_GetObjectItem(event, "created_at");
|
||||||
|
|
||||||
|
DEBUG_TRACE("BROADCAST: Event kind=%d id=%.8s created_at=%ld",
|
||||||
|
event_kind ? (int)cJSON_GetNumberValue(event_kind) : -1,
|
||||||
|
event_id && cJSON_IsString(event_id) ? cJSON_GetStringValue(event_id) : "null",
|
||||||
|
event_created_at ? (long)cJSON_GetNumberValue(event_created_at) : 0);
|
||||||
|
|
||||||
|
// ... existing expiration check code ...
|
||||||
|
|
||||||
|
// After line 611 (before pthread_mutex_lock):
|
||||||
|
pthread_mutex_lock(&g_subscription_manager.subscriptions_lock);
|
||||||
|
|
||||||
|
int total_subs = 0;
|
||||||
|
subscription_t* count_sub = g_subscription_manager.active_subscriptions;
|
||||||
|
while (count_sub) {
|
||||||
|
total_subs++;
|
||||||
|
count_sub = count_sub->next;
|
||||||
|
}
|
||||||
|
DEBUG_TRACE("BROADCAST: Checking %d active subscriptions", total_subs);
|
||||||
|
|
||||||
|
subscription_t* sub = g_subscription_manager.active_subscriptions;
|
||||||
|
// ... rest of matching logic ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Expected Outcome
|
||||||
|
|
||||||
|
With these debug additions, we should see output like:
|
||||||
|
```
|
||||||
|
BROADCAST: Event kind=1059 id=abc12345 created_at=1729712279
|
||||||
|
BROADCAST: Checking 1 active subscriptions
|
||||||
|
SUB_MATCH: Testing subscription 'sub:3'
|
||||||
|
SUB_MATCH: Testing filter #1
|
||||||
|
FILTER_MATCH: Testing event kind=1059 id=abc12345 created_at=1729712279
|
||||||
|
FILTER_MATCH: Checking kinds filter with 1 kinds
|
||||||
|
FILTER_MATCH: Event kind=1059
|
||||||
|
FILTER_MATCH: Comparing event kind 1059 with filter kind 1059
|
||||||
|
FILTER_MATCH: Kind matched!
|
||||||
|
FILTER_MATCH: Kinds filter passed
|
||||||
|
FILTER_MATCH: Checking since filter: event_ts=1729712279 filter_since=1729708079
|
||||||
|
FILTER_MATCH: Since filter passed
|
||||||
|
FILTER_MATCH: All filters passed, event matches!
|
||||||
|
SUB_MATCH: Filter #1 matched! Subscription 'sub:3' matches
|
||||||
|
Event broadcast complete: 1 subscriptions matched
|
||||||
|
```
|
||||||
|
|
||||||
|
This will help us identify exactly where the matching is failing.
|
||||||
@@ -814,7 +814,7 @@ int first_time_startup_sequence(const cli_options_t* cli_options, char* admin_pu
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int startup_existing_relay(const char* relay_pubkey, const cli_options_t* cli_options) {
|
int startup_existing_relay(const char* relay_pubkey, const cli_options_t* cli_options __attribute__((unused))) {
|
||||||
if (!relay_pubkey) {
|
if (!relay_pubkey) {
|
||||||
DEBUG_ERROR("Invalid relay pubkey for existing relay startup");
|
DEBUG_ERROR("Invalid relay pubkey for existing relay startup");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
33
src/main.c
33
src/main.c
@@ -217,11 +217,9 @@ void send_notice_message(struct lws* wsi, const char* message) {
|
|||||||
char* msg_str = cJSON_Print(notice_msg);
|
char* msg_str = cJSON_Print(notice_msg);
|
||||||
if (msg_str) {
|
if (msg_str) {
|
||||||
size_t msg_len = strlen(msg_str);
|
size_t msg_len = strlen(msg_str);
|
||||||
unsigned char* buf = malloc(LWS_PRE + msg_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, NULL, msg_str, msg_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, msg_str, msg_len);
|
DEBUG_ERROR("Failed to queue NOTICE message");
|
||||||
lws_write(wsi, buf + LWS_PRE, msg_len, LWS_WRITE_TEXT);
|
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(msg_str);
|
free(msg_str);
|
||||||
}
|
}
|
||||||
@@ -935,12 +933,11 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
|||||||
char* msg_str = cJSON_Print(event_msg);
|
char* msg_str = cJSON_Print(event_msg);
|
||||||
if (msg_str) {
|
if (msg_str) {
|
||||||
size_t msg_len = strlen(msg_str);
|
size_t msg_len = strlen(msg_str);
|
||||||
unsigned char* buf = malloc(LWS_PRE + msg_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, NULL, msg_str, msg_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, msg_str, msg_len);
|
DEBUG_ERROR("Failed to queue config EVENT message");
|
||||||
lws_write(wsi, buf + LWS_PRE, msg_len, LWS_WRITE_TEXT);
|
} else {
|
||||||
config_events_sent++;
|
config_events_sent++;
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(msg_str);
|
free(msg_str);
|
||||||
}
|
}
|
||||||
@@ -978,11 +975,9 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
|||||||
char* closed_str = cJSON_Print(closed_msg);
|
char* closed_str = cJSON_Print(closed_msg);
|
||||||
if (closed_str) {
|
if (closed_str) {
|
||||||
size_t closed_len = strlen(closed_str);
|
size_t closed_len = strlen(closed_str);
|
||||||
unsigned char* buf = malloc(LWS_PRE + closed_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, pss, closed_str, closed_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, closed_str, closed_len);
|
DEBUG_ERROR("Failed to queue CLOSED message");
|
||||||
lws_write(wsi, buf + LWS_PRE, closed_len, LWS_WRITE_TEXT);
|
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(closed_str);
|
free(closed_str);
|
||||||
}
|
}
|
||||||
@@ -1312,11 +1307,9 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
|||||||
char* msg_str = cJSON_Print(event_msg);
|
char* msg_str = cJSON_Print(event_msg);
|
||||||
if (msg_str) {
|
if (msg_str) {
|
||||||
size_t msg_len = strlen(msg_str);
|
size_t msg_len = strlen(msg_str);
|
||||||
unsigned char* buf = malloc(LWS_PRE + msg_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, pss, msg_str, msg_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, msg_str, msg_len);
|
DEBUG_ERROR("Failed to queue EVENT message for sub=%s", sub_id);
|
||||||
lws_write(wsi, buf + LWS_PRE, msg_len, LWS_WRITE_TEXT);
|
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(msg_str);
|
free(msg_str);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
#define MAIN_H
|
#define MAIN_H
|
||||||
|
|
||||||
// Version information (auto-updated by build system)
|
// Version information (auto-updated by build system)
|
||||||
#define VERSION "v0.7.38"
|
#define VERSION "v0.7.39"
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 7
|
#define VERSION_MINOR 7
|
||||||
#define VERSION_PATCH 38
|
#define VERSION_PATCH 39
|
||||||
|
|
||||||
// Relay metadata (authoritative source for NIP-11 information)
|
// Relay metadata (authoritative source for NIP-11 information)
|
||||||
#define RELAY_NAME "C-Relay"
|
#define RELAY_NAME "C-Relay"
|
||||||
|
|||||||
@@ -70,11 +70,9 @@ void send_nip42_auth_challenge(struct lws* wsi, struct per_session_data* pss) {
|
|||||||
char* msg_str = cJSON_Print(auth_msg);
|
char* msg_str = cJSON_Print(auth_msg);
|
||||||
if (msg_str) {
|
if (msg_str) {
|
||||||
size_t msg_len = strlen(msg_str);
|
size_t msg_len = strlen(msg_str);
|
||||||
unsigned char* buf = malloc(LWS_PRE + msg_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, pss, msg_str, msg_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, msg_str, msg_len);
|
DEBUG_ERROR("Failed to queue AUTH challenge message");
|
||||||
lws_write(wsi, buf + LWS_PRE, msg_len, LWS_WRITE_TEXT);
|
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(msg_str);
|
free(msg_str);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,30 +388,48 @@ int event_matches_filter(cJSON* event, subscription_filter_t* filter) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug: Log event details being tested
|
||||||
|
cJSON* event_kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||||
|
cJSON* event_id_obj = cJSON_GetObjectItem(event, "id");
|
||||||
|
cJSON* event_created_at_obj = cJSON_GetObjectItem(event, "created_at");
|
||||||
|
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Testing event kind=%d id=%.8s created_at=%ld",
|
||||||
|
event_kind_obj ? (int)cJSON_GetNumberValue(event_kind_obj) : -1,
|
||||||
|
event_id_obj && cJSON_IsString(event_id_obj) ? cJSON_GetStringValue(event_id_obj) : "null",
|
||||||
|
event_created_at_obj ? (long)cJSON_GetNumberValue(event_created_at_obj) : 0);
|
||||||
|
|
||||||
// Check kinds filter
|
// Check kinds filter
|
||||||
if (filter->kinds && cJSON_IsArray(filter->kinds)) {
|
if (filter->kinds && cJSON_IsArray(filter->kinds)) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Checking kinds filter with %d kinds", cJSON_GetArraySize(filter->kinds));
|
||||||
|
|
||||||
cJSON* event_kind = cJSON_GetObjectItem(event, "kind");
|
cJSON* event_kind = cJSON_GetObjectItem(event, "kind");
|
||||||
if (!event_kind || !cJSON_IsNumber(event_kind)) {
|
if (!event_kind || !cJSON_IsNumber(event_kind)) {
|
||||||
|
DEBUG_WARN("FILTER_MATCH: Event has no valid kind field");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int event_kind_val = (int)cJSON_GetNumberValue(event_kind);
|
int event_kind_val = (int)cJSON_GetNumberValue(event_kind);
|
||||||
int kind_match = 0;
|
DEBUG_TRACE("FILTER_MATCH: Event kind=%d", event_kind_val);
|
||||||
|
|
||||||
|
int kind_match = 0;
|
||||||
cJSON* kind_item = NULL;
|
cJSON* kind_item = NULL;
|
||||||
cJSON_ArrayForEach(kind_item, filter->kinds) {
|
cJSON_ArrayForEach(kind_item, filter->kinds) {
|
||||||
if (cJSON_IsNumber(kind_item)) {
|
if (cJSON_IsNumber(kind_item)) {
|
||||||
int filter_kind = (int)cJSON_GetNumberValue(kind_item);
|
int filter_kind = (int)cJSON_GetNumberValue(kind_item);
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Comparing event kind %d with filter kind %d", event_kind_val, filter_kind);
|
||||||
if (filter_kind == event_kind_val) {
|
if (filter_kind == event_kind_val) {
|
||||||
kind_match = 1;
|
kind_match = 1;
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Kind matched!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kind_match) {
|
if (!kind_match) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: No kind match, filter rejected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Kinds filter passed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check authors filter
|
// Check authors filter
|
||||||
@@ -472,13 +490,19 @@ int event_matches_filter(cJSON* event, subscription_filter_t* filter) {
|
|||||||
if (filter->since > 0) {
|
if (filter->since > 0) {
|
||||||
cJSON* event_created_at = cJSON_GetObjectItem(event, "created_at");
|
cJSON* event_created_at = cJSON_GetObjectItem(event, "created_at");
|
||||||
if (!event_created_at || !cJSON_IsNumber(event_created_at)) {
|
if (!event_created_at || !cJSON_IsNumber(event_created_at)) {
|
||||||
|
DEBUG_WARN("FILTER_MATCH: Event has no valid created_at field");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long event_timestamp = (long)cJSON_GetNumberValue(event_created_at);
|
long event_timestamp = (long)cJSON_GetNumberValue(event_created_at);
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Checking since filter: event_ts=%ld filter_since=%ld",
|
||||||
|
event_timestamp, filter->since);
|
||||||
|
|
||||||
if (event_timestamp < filter->since) {
|
if (event_timestamp < filter->since) {
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Event too old (before since), filter rejected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: Since filter passed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check until filter
|
// Check until filter
|
||||||
@@ -560,6 +584,7 @@ int event_matches_filter(cJSON* event, subscription_filter_t* filter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE("FILTER_MATCH: All filters passed, event matches!");
|
||||||
return 1; // All filters passed
|
return 1; // All filters passed
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,14 +594,23 @@ int event_matches_subscription(cJSON* event, subscription_t* subscription) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Testing subscription '%s'", subscription->id);
|
||||||
|
|
||||||
|
int filter_num = 0;
|
||||||
subscription_filter_t* filter = subscription->filters;
|
subscription_filter_t* filter = subscription->filters;
|
||||||
while (filter) {
|
while (filter) {
|
||||||
|
filter_num++;
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Testing filter #%d", filter_num);
|
||||||
|
|
||||||
if (event_matches_filter(event, filter)) {
|
if (event_matches_filter(event, filter)) {
|
||||||
|
DEBUG_TRACE("SUB_MATCH: Filter #%d matched! Subscription '%s' matches",
|
||||||
|
filter_num, subscription->id);
|
||||||
return 1; // Match found (OR logic)
|
return 1; // Match found (OR logic)
|
||||||
}
|
}
|
||||||
filter = filter->next;
|
filter = filter->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE("SUB_MATCH: No filters matched for subscription '%s'", subscription->id);
|
||||||
return 0; // No filters matched
|
return 0; // No filters matched
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,6 +633,16 @@ int broadcast_event_to_subscriptions(cJSON* event) {
|
|||||||
|
|
||||||
int broadcasts = 0;
|
int broadcasts = 0;
|
||||||
|
|
||||||
|
// Log event details
|
||||||
|
cJSON* event_kind = cJSON_GetObjectItem(event, "kind");
|
||||||
|
cJSON* event_id = cJSON_GetObjectItem(event, "id");
|
||||||
|
cJSON* event_created_at = cJSON_GetObjectItem(event, "created_at");
|
||||||
|
|
||||||
|
DEBUG_TRACE("BROADCAST: Event kind=%d id=%.8s created_at=%ld",
|
||||||
|
event_kind ? (int)cJSON_GetNumberValue(event_kind) : -1,
|
||||||
|
event_id && cJSON_IsString(event_id) ? cJSON_GetStringValue(event_id) : "null",
|
||||||
|
event_created_at ? (long)cJSON_GetNumberValue(event_created_at) : 0);
|
||||||
|
|
||||||
// Create a temporary list of matching subscriptions to avoid holding lock during I/O
|
// Create a temporary list of matching subscriptions to avoid holding lock during I/O
|
||||||
typedef struct temp_sub {
|
typedef struct temp_sub {
|
||||||
struct lws* wsi;
|
struct lws* wsi;
|
||||||
@@ -613,6 +657,14 @@ int broadcast_event_to_subscriptions(cJSON* event) {
|
|||||||
// First pass: collect matching subscriptions while holding lock
|
// First pass: collect matching subscriptions while holding lock
|
||||||
pthread_mutex_lock(&g_subscription_manager.subscriptions_lock);
|
pthread_mutex_lock(&g_subscription_manager.subscriptions_lock);
|
||||||
|
|
||||||
|
int total_subs = 0;
|
||||||
|
subscription_t* count_sub = g_subscription_manager.active_subscriptions;
|
||||||
|
while (count_sub) {
|
||||||
|
total_subs++;
|
||||||
|
count_sub = count_sub->next;
|
||||||
|
}
|
||||||
|
DEBUG_TRACE("BROADCAST: Checking %d active subscriptions", total_subs);
|
||||||
|
|
||||||
subscription_t* sub = g_subscription_manager.active_subscriptions;
|
subscription_t* sub = g_subscription_manager.active_subscriptions;
|
||||||
while (sub) {
|
while (sub) {
|
||||||
if (sub->active && sub->wsi && event_matches_subscription(event, sub)) {
|
if (sub->active && sub->wsi && event_matches_subscription(event, sub)) {
|
||||||
|
|||||||
@@ -562,11 +562,9 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
|
|||||||
char *error_str = cJSON_Print(error_response);
|
char *error_str = cJSON_Print(error_response);
|
||||||
if (error_str) {
|
if (error_str) {
|
||||||
size_t error_len = strlen(error_str);
|
size_t error_len = strlen(error_str);
|
||||||
unsigned char *buf = malloc(LWS_PRE + error_len);
|
// Use proper message queue system instead of direct lws_write
|
||||||
if (buf) {
|
if (queue_message(wsi, pss, error_str, error_len, LWS_WRITE_TEXT) != 0) {
|
||||||
memcpy(buf + LWS_PRE, error_str, error_len);
|
DEBUG_ERROR("Failed to queue error response message");
|
||||||
lws_write(wsi, buf + LWS_PRE, error_len, LWS_WRITE_TEXT);
|
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
free(error_str);
|
free(error_str);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user