188 lines
6.3 KiB
C
188 lines
6.3 KiB
C
/*
|
|
* Simple WebSocket Debug Tool for NIP-17 Testing
|
|
*
|
|
* Connects to a relay and sends a subscription request to see what responses we get.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
#include "../nostr_core/nostr_core.h"
|
|
#include "../nostr_websocket/nostr_websocket_tls.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc < 2) {
|
|
fprintf(stderr, "Usage: %s <relay_url> [event_id]\n", argv[0]);
|
|
fprintf(stderr, "Example: %s wss://relay.laantungir.net 06cdf2cdd095ddb1ebe15d5b3c736b27a34de2683e847b871fe37d86ac998772\n");
|
|
return 1;
|
|
}
|
|
|
|
const char* relay_url = argv[1];
|
|
const char* event_id = (argc >= 3) ? argv[2] : NULL;
|
|
|
|
printf("🔍 WebSocket Debug Tool\n");
|
|
printf("=======================\n");
|
|
printf("Relay: %s\n", relay_url);
|
|
if (event_id) {
|
|
printf("Looking for event: %s\n", event_id);
|
|
}
|
|
printf("\n");
|
|
|
|
// Initialize crypto
|
|
if (nostr_init() != NOSTR_SUCCESS) {
|
|
fprintf(stderr, "Failed to initialize crypto\n");
|
|
return 1;
|
|
}
|
|
|
|
// Connect to relay
|
|
printf("🔌 Connecting to relay...\n");
|
|
nostr_ws_client_t* client = nostr_ws_connect(relay_url);
|
|
if (!client) {
|
|
fprintf(stderr, "Failed to connect to relay - nostr_ws_connect returned NULL\n");
|
|
return 1;
|
|
}
|
|
|
|
// Check initial state
|
|
nostr_ws_state_t initial_state = nostr_ws_get_state(client);
|
|
printf("Initial connection state: %d\n", (int)initial_state);
|
|
|
|
// Wait for connection
|
|
time_t start_time = time(NULL);
|
|
while (time(NULL) - start_time < 10) { // 10 second timeout
|
|
nostr_ws_state_t state = nostr_ws_get_state(client);
|
|
if (state == NOSTR_WS_CONNECTED) {
|
|
printf("✅ Connected!\n");
|
|
break;
|
|
} else if (state == NOSTR_WS_ERROR) {
|
|
fprintf(stderr, "❌ Connection failed\n");
|
|
nostr_ws_close(client);
|
|
return 1;
|
|
}
|
|
usleep(100000); // 100ms
|
|
}
|
|
|
|
if (nostr_ws_get_state(client) != NOSTR_WS_CONNECTED) {
|
|
fprintf(stderr, "❌ Connection timeout\n");
|
|
nostr_ws_close(client);
|
|
return 1;
|
|
}
|
|
|
|
// Send subscription request
|
|
printf("📡 Sending subscription request...\n");
|
|
|
|
// Create filter for kind 1059 events
|
|
cJSON* filter = cJSON_CreateObject();
|
|
cJSON* kinds = cJSON_CreateArray();
|
|
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1059));
|
|
cJSON_AddItemToObject(filter, "kinds", kinds);
|
|
|
|
// If we have a specific event ID, add it to the filter
|
|
if (event_id) {
|
|
cJSON* ids = cJSON_CreateArray();
|
|
cJSON_AddItemToArray(ids, cJSON_CreateString(event_id));
|
|
cJSON_AddItemToObject(filter, "ids", ids);
|
|
}
|
|
|
|
char* filter_json = cJSON_PrintUnformatted(filter);
|
|
printf("Filter: %s\n", filter_json);
|
|
|
|
// Send REQ message
|
|
char subscription_id[32];
|
|
snprintf(subscription_id, sizeof(subscription_id), "debug_%ld", time(NULL));
|
|
|
|
if (nostr_relay_send_req(client, subscription_id, filter) < 0) {
|
|
fprintf(stderr, "Failed to send subscription request\n");
|
|
cJSON_Delete(filter);
|
|
free(filter_json);
|
|
nostr_ws_close(client);
|
|
return 1;
|
|
}
|
|
|
|
cJSON_Delete(filter);
|
|
free(filter_json);
|
|
|
|
printf("✅ Subscription sent (ID: %s)\n", subscription_id);
|
|
printf("⏳ Listening for responses (30 seconds)...\n");
|
|
printf("Press Ctrl+C to stop\n\n");
|
|
|
|
// Listen for responses
|
|
start_time = time(NULL);
|
|
int message_count = 0;
|
|
|
|
while (time(NULL) - start_time < 30) { // 30 second timeout
|
|
char buffer[16384];
|
|
int len = nostr_ws_receive(client, buffer, sizeof(buffer) - 1, 1000); // 1 second timeout
|
|
|
|
if (len > 0) {
|
|
buffer[len] = '\0';
|
|
message_count++;
|
|
|
|
printf("📨 Message %d:\n", message_count);
|
|
printf("%s\n", buffer);
|
|
|
|
// Parse the message
|
|
char* msg_type = NULL;
|
|
cJSON* parsed = NULL;
|
|
|
|
if (nostr_parse_relay_message(buffer, &msg_type, &parsed) == 0) {
|
|
if (msg_type && strcmp(msg_type, "EVENT") == 0) {
|
|
printf(" → EVENT received\n");
|
|
if (cJSON_IsArray(parsed) && cJSON_GetArraySize(parsed) >= 3) {
|
|
cJSON* event = cJSON_GetArrayItem(parsed, 2);
|
|
if (event) {
|
|
cJSON* kind_item = cJSON_GetObjectItem(event, "kind");
|
|
cJSON* id_item = cJSON_GetObjectItem(event, "id");
|
|
if (kind_item && cJSON_IsNumber(kind_item)) {
|
|
printf(" → Kind: %d\n", (int)cJSON_GetNumberValue(kind_item));
|
|
}
|
|
if (id_item && cJSON_IsString(id_item)) {
|
|
printf(" → ID: %.12s...\n", cJSON_GetStringValue(id_item));
|
|
}
|
|
}
|
|
}
|
|
} else if (msg_type && strcmp(msg_type, "EOSE") == 0) {
|
|
printf(" → EOSE (End of Stored Events)\n");
|
|
} else if (msg_type && strcmp(msg_type, "NOTICE") == 0) {
|
|
printf(" → NOTICE from relay\n");
|
|
if (cJSON_IsArray(parsed) && cJSON_GetArraySize(parsed) >= 2) {
|
|
cJSON* notice_msg = cJSON_GetArrayItem(parsed, 1);
|
|
if (notice_msg && cJSON_IsString(notice_msg)) {
|
|
printf(" → Message: %s\n", cJSON_GetStringValue(notice_msg));
|
|
}
|
|
}
|
|
} else if (msg_type) {
|
|
printf(" → %s\n", msg_type);
|
|
}
|
|
|
|
if (msg_type) free(msg_type);
|
|
if (parsed) cJSON_Delete(parsed);
|
|
}
|
|
|
|
printf("\n");
|
|
} else if (len < 0) {
|
|
printf("❌ Receive error\n");
|
|
break;
|
|
}
|
|
|
|
// Small delay to prevent busy waiting
|
|
usleep(10000); // 10ms
|
|
}
|
|
|
|
printf("📊 Total messages received: %d\n", message_count);
|
|
|
|
// Send CLOSE message
|
|
printf("🔌 Closing subscription...\n");
|
|
nostr_relay_send_close(client, subscription_id);
|
|
|
|
// Close connection
|
|
nostr_ws_close(client);
|
|
nostr_cleanup();
|
|
|
|
printf("✅ Done\n");
|
|
return 0;
|
|
} |