v0.7.12 - Implemented comprehensive debug system with 6 levels (0-5), file:line tracking at TRACE level, deployment script integration, and default level 5 for development
This commit is contained in:
240
src/main.c
240
src/main.c
@@ -24,6 +24,7 @@
|
||||
#include "sql_schema.h" // Embedded database schema
|
||||
#include "websockets.h" // WebSocket protocol implementation
|
||||
#include "subscriptions.h" // Subscription management system
|
||||
#include "debug.h" // Debug system
|
||||
|
||||
// Forward declarations for unified request validator
|
||||
int nostr_validate_unified_request(const char* json_string, size_t json_length);
|
||||
@@ -95,11 +96,7 @@ extern subscription_manager_t g_subscription_manager;
|
||||
|
||||
|
||||
|
||||
// Forward declarations for logging functions
|
||||
void log_info(const char* message);
|
||||
void log_success(const char* message);
|
||||
void log_error(const char* message);
|
||||
void log_warning(const char* message);
|
||||
// Forward declarations for logging functions - REMOVED (replaced by debug system)
|
||||
|
||||
// Forward declaration for subscription manager configuration
|
||||
void update_subscription_manager_config(void);
|
||||
@@ -189,41 +186,7 @@ int validate_event_expiration(cJSON* event, char* error_message, size_t error_si
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Helper function to get current timestamp string
|
||||
static void get_timestamp_string(char* buffer, size_t buffer_size) {
|
||||
time_t now = time(NULL);
|
||||
struct tm* local_time = localtime(&now);
|
||||
strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", local_time);
|
||||
}
|
||||
|
||||
// Logging functions
|
||||
void log_info(const char* message) {
|
||||
char timestamp[32];
|
||||
get_timestamp_string(timestamp, sizeof(timestamp));
|
||||
printf("[%s] [INFO] %s\n", timestamp, message);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void log_success(const char* message) {
|
||||
char timestamp[32];
|
||||
get_timestamp_string(timestamp, sizeof(timestamp));
|
||||
printf("[%s] [SUCCESS] %s\n", timestamp, message);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void log_error(const char* message) {
|
||||
char timestamp[32];
|
||||
get_timestamp_string(timestamp, sizeof(timestamp));
|
||||
printf("[%s] [ERROR] %s\n", timestamp, message);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void log_warning(const char* message) {
|
||||
char timestamp[32];
|
||||
get_timestamp_string(timestamp, sizeof(timestamp));
|
||||
printf("[%s] [WARNING] %s\n", timestamp, message);
|
||||
fflush(stdout);
|
||||
}
|
||||
// Logging functions - REMOVED (replaced by debug system in debug.c)
|
||||
|
||||
// Update subscription manager configuration from config system
|
||||
void update_subscription_manager_config(void) {
|
||||
@@ -300,27 +263,27 @@ static void cleanup_stale_wal_files(const char* db_path) {
|
||||
int has_shm = (access(shm_path, F_OK) == 0);
|
||||
|
||||
if (has_wal || has_shm) {
|
||||
log_warning("Detected stale SQLite WAL files from previous unclean shutdown");
|
||||
DEBUG_WARN("Detected stale SQLite WAL files from previous unclean shutdown");
|
||||
|
||||
// Try to remove WAL file
|
||||
if (has_wal) {
|
||||
if (unlink(wal_path) == 0) {
|
||||
log_info("Removed stale WAL file");
|
||||
DEBUG_INFO("Removed stale WAL file");
|
||||
} else {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Failed to remove WAL file: %s", strerror(errno));
|
||||
log_warning(error_msg);
|
||||
DEBUG_WARN(error_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to remove SHM file
|
||||
if (has_shm) {
|
||||
if (unlink(shm_path) == 0) {
|
||||
log_info("Removed stale SHM file");
|
||||
DEBUG_INFO("Removed stale SHM file");
|
||||
} else {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Failed to remove SHM file: %s", strerror(errno));
|
||||
log_warning(error_msg);
|
||||
DEBUG_WARN(error_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,25 +291,30 @@ static void cleanup_stale_wal_files(const char* db_path) {
|
||||
|
||||
// Initialize database connection and schema
|
||||
int init_database(const char* database_path_override) {
|
||||
DEBUG_TRACE("Entering init_database()");
|
||||
|
||||
// Priority 1: Command line database path override
|
||||
const char* db_path = database_path_override;
|
||||
|
||||
|
||||
// Priority 2: Configuration system (if available)
|
||||
if (!db_path) {
|
||||
db_path = get_config_value("database_path");
|
||||
}
|
||||
|
||||
|
||||
// Priority 3: Default path
|
||||
if (!db_path) {
|
||||
db_path = DEFAULT_DATABASE_PATH;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_LOG("Initializing database: %s", db_path);
|
||||
|
||||
// Clean up stale WAL files before opening database
|
||||
cleanup_stale_wal_files(db_path);
|
||||
|
||||
|
||||
int rc = sqlite3_open(db_path, &g_db);
|
||||
if (rc != SQLITE_OK) {
|
||||
log_error("Cannot open database");
|
||||
DEBUG_ERROR("Cannot open database");
|
||||
DEBUG_TRACE("Exiting init_database() - failed to open database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -379,7 +347,7 @@ int init_database(const char* database_path_override) {
|
||||
} else {
|
||||
char warning_msg[256];
|
||||
snprintf(warning_msg, sizeof(warning_msg), "Unknown database schema version: %s", db_version);
|
||||
log_warning(warning_msg);
|
||||
DEBUG_WARN(warning_msg);
|
||||
}
|
||||
} else {
|
||||
needs_migration = 1;
|
||||
@@ -422,7 +390,7 @@ int init_database(const char* database_path_override) {
|
||||
char error_log[512];
|
||||
snprintf(error_log, sizeof(error_log), "Failed to create auth_rules table: %s",
|
||||
error_msg ? error_msg : "unknown error");
|
||||
log_error(error_log);
|
||||
DEBUG_ERROR(error_log);
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
return -1;
|
||||
}
|
||||
@@ -439,7 +407,7 @@ int init_database(const char* database_path_override) {
|
||||
char index_error_log[512];
|
||||
snprintf(index_error_log, sizeof(index_error_log), "Failed to create auth_rules indexes: %s",
|
||||
index_error_msg ? index_error_msg : "unknown error");
|
||||
log_error(index_error_log);
|
||||
DEBUG_ERROR(index_error_log);
|
||||
if (index_error_msg) sqlite3_free(index_error_msg);
|
||||
return -1;
|
||||
}
|
||||
@@ -458,7 +426,7 @@ int init_database(const char* database_path_override) {
|
||||
char error_log[512];
|
||||
snprintf(error_log, sizeof(error_log), "Failed to update schema version: %s",
|
||||
error_msg ? error_msg : "unknown error");
|
||||
log_error(error_log);
|
||||
DEBUG_ERROR(error_log);
|
||||
if (error_msg) sqlite3_free(error_msg);
|
||||
return -1;
|
||||
}
|
||||
@@ -474,7 +442,7 @@ int init_database(const char* database_path_override) {
|
||||
char error_log[512];
|
||||
snprintf(error_log, sizeof(error_log), "Failed to initialize database schema: %s",
|
||||
error_msg ? error_msg : "unknown error");
|
||||
log_error(error_log);
|
||||
DEBUG_ERROR(error_log);
|
||||
if (error_msg) {
|
||||
sqlite3_free(error_msg);
|
||||
}
|
||||
@@ -483,7 +451,7 @@ int init_database(const char* database_path_override) {
|
||||
|
||||
}
|
||||
} else {
|
||||
log_error("Failed to check existing database schema");
|
||||
DEBUG_ERROR("Failed to check existing database schema");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -493,36 +461,41 @@ int init_database(const char* database_path_override) {
|
||||
if (rc != SQLITE_OK) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Failed to enable WAL mode: %s",
|
||||
wal_error ? wal_error : "unknown error");
|
||||
log_warning(error_msg);
|
||||
wal_error ? wal_error : "unknown error");
|
||||
DEBUG_WARN(error_msg);
|
||||
if (wal_error) sqlite3_free(wal_error);
|
||||
// Continue anyway - WAL mode is optional
|
||||
} else {
|
||||
log_info("SQLite WAL mode enabled");
|
||||
DEBUG_LOG("SQLite WAL mode enabled");
|
||||
}
|
||||
|
||||
|
||||
DEBUG_TRACE("Exiting init_database() - success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Close database connection with proper WAL checkpoint
|
||||
void close_database() {
|
||||
DEBUG_TRACE("Entering close_database()");
|
||||
|
||||
if (g_db) {
|
||||
// Perform WAL checkpoint to minimize stale files on next startup
|
||||
log_info("Performing WAL checkpoint before database close");
|
||||
DEBUG_LOG("Performing WAL checkpoint before database close");
|
||||
char* checkpoint_error = NULL;
|
||||
int rc = sqlite3_exec(g_db, "PRAGMA wal_checkpoint(TRUNCATE);", NULL, NULL, &checkpoint_error);
|
||||
if (rc != SQLITE_OK) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "WAL checkpoint warning: %s",
|
||||
checkpoint_error ? checkpoint_error : "unknown error");
|
||||
log_warning(error_msg);
|
||||
checkpoint_error ? checkpoint_error : "unknown error");
|
||||
DEBUG_WARN(error_msg);
|
||||
if (checkpoint_error) sqlite3_free(checkpoint_error);
|
||||
}
|
||||
|
||||
|
||||
sqlite3_close(g_db);
|
||||
g_db = NULL;
|
||||
log_info("Database connection closed");
|
||||
DEBUG_LOG("Database connection closed");
|
||||
}
|
||||
|
||||
DEBUG_TRACE("Exiting close_database()");
|
||||
}
|
||||
|
||||
// Event type classification
|
||||
@@ -691,7 +664,7 @@ int store_event(cJSON* event) {
|
||||
cJSON* tags = cJSON_GetObjectItem(event, "tags");
|
||||
|
||||
if (!id || !pubkey || !created_at || !kind || !content || !sig) {
|
||||
log_error("Invalid event - missing required fields");
|
||||
DEBUG_ERROR("Invalid event - missing required fields");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -707,7 +680,7 @@ int store_event(cJSON* event) {
|
||||
}
|
||||
|
||||
if (!tags_json) {
|
||||
log_error("Failed to serialize tags to JSON");
|
||||
DEBUG_ERROR("Failed to serialize tags to JSON");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -719,7 +692,7 @@ int store_event(cJSON* event) {
|
||||
sqlite3_stmt* stmt;
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
log_error("Failed to prepare event insert statement");
|
||||
DEBUG_ERROR("Failed to prepare event insert statement");
|
||||
free(tags_json);
|
||||
return -1;
|
||||
}
|
||||
@@ -740,13 +713,13 @@ int store_event(cJSON* event) {
|
||||
|
||||
if (rc != SQLITE_DONE) {
|
||||
if (rc == SQLITE_CONSTRAINT) {
|
||||
log_warning("Event already exists in database");
|
||||
DEBUG_WARN("Event already exists in database");
|
||||
free(tags_json);
|
||||
return 0; // Not an error, just duplicate
|
||||
}
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Failed to insert event: %s", sqlite3_errmsg(g_db));
|
||||
log_error(error_msg);
|
||||
DEBUG_ERROR(error_msg);
|
||||
free(tags_json);
|
||||
return -1;
|
||||
}
|
||||
@@ -815,7 +788,7 @@ cJSON* retrieve_event(const char* event_id) {
|
||||
|
||||
int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, struct per_session_data *pss) {
|
||||
if (!cJSON_IsArray(filters)) {
|
||||
log_error("REQ filters is not an array");
|
||||
DEBUG_ERROR("REQ filters is not an array");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -859,7 +832,7 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
||||
|
||||
// Check session subscription limits
|
||||
if (pss->subscription_count >= g_subscription_manager.max_subscriptions_per_client) {
|
||||
log_error("Maximum subscriptions per client exceeded");
|
||||
DEBUG_ERROR("Maximum subscriptions per client exceeded");
|
||||
|
||||
// Update rate limiting counters for failed attempt
|
||||
pss->failed_subscription_attempts++;
|
||||
@@ -953,13 +926,13 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
||||
// Create persistent subscription
|
||||
subscription_t* subscription = create_subscription(sub_id, wsi, filters, pss ? pss->client_ip : "unknown");
|
||||
if (!subscription) {
|
||||
log_error("Failed to create subscription");
|
||||
DEBUG_ERROR("Failed to create subscription");
|
||||
return has_config_request ? config_events_sent : 0;
|
||||
}
|
||||
|
||||
// Add to global manager
|
||||
if (add_subscription_to_manager(subscription) != 0) {
|
||||
log_error("Failed to add subscription to global manager");
|
||||
DEBUG_ERROR("Failed to add subscription to global manager");
|
||||
free_subscription(subscription);
|
||||
|
||||
// Send CLOSED notice
|
||||
@@ -1007,7 +980,7 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
||||
for (int i = 0; i < cJSON_GetArraySize(filters); i++) {
|
||||
cJSON* filter = cJSON_GetArrayItem(filters, i);
|
||||
if (!filter || !cJSON_IsObject(filter)) {
|
||||
log_warning("Invalid filter object");
|
||||
DEBUG_WARN("Invalid filter object");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1250,7 +1223,7 @@ int handle_req_message(const char* sub_id, cJSON* filters, struct lws *wsi, stru
|
||||
if (rc != SQLITE_OK) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Failed to prepare subscription query: %s", sqlite3_errmsg(g_db));
|
||||
log_error(error_msg);
|
||||
DEBUG_ERROR(error_msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1395,7 +1368,7 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
|
||||
// Step 3: Verify admin signature authorization
|
||||
cJSON *pubkey_json = cJSON_GetObjectItem(event, "pubkey");
|
||||
if (!pubkey_json || !cJSON_IsString(pubkey_json)) {
|
||||
log_warning("Unauthorized admin event attempt: missing or invalid pubkey");
|
||||
DEBUG_WARN("Unauthorized admin event attempt: missing or invalid pubkey");
|
||||
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: missing pubkey");
|
||||
return -1;
|
||||
}
|
||||
@@ -1403,19 +1376,19 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
|
||||
// Get admin pubkey from configuration
|
||||
const char* admin_pubkey = get_config_value("admin_pubkey");
|
||||
if (!admin_pubkey || strlen(admin_pubkey) == 0) {
|
||||
log_warning("Unauthorized admin event attempt: no admin pubkey configured");
|
||||
DEBUG_WARN("Unauthorized admin event attempt: no admin pubkey configured");
|
||||
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: no admin configured");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Compare pubkeys
|
||||
if (strcmp(pubkey_json->valuestring, admin_pubkey) != 0) {
|
||||
log_warning("Unauthorized admin event attempt: pubkey mismatch");
|
||||
DEBUG_WARN("Unauthorized admin event attempt: pubkey mismatch");
|
||||
char warning_msg[256];
|
||||
snprintf(warning_msg, sizeof(warning_msg),
|
||||
"Unauthorized admin event attempt from pubkey: %.32s...", pubkey_json->valuestring);
|
||||
log_warning(warning_msg);
|
||||
log_info("DEBUG: Pubkey comparison failed - event pubkey != admin pubkey");
|
||||
DEBUG_WARN(warning_msg);
|
||||
DEBUG_INFO("DEBUG: Pubkey comparison failed - event pubkey != admin pubkey");
|
||||
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: invalid admin pubkey");
|
||||
return -1;
|
||||
}
|
||||
@@ -1423,7 +1396,7 @@ int is_authorized_admin_event(cJSON* event, char* error_buffer, size_t error_buf
|
||||
|
||||
// Step 4: Verify event signature
|
||||
if (nostr_verify_event_signature(event) != 0) {
|
||||
log_warning("Unauthorized admin event attempt: invalid signature");
|
||||
DEBUG_WARN("Unauthorized admin event attempt: invalid signature");
|
||||
snprintf(error_buffer, error_buffer_size, "Unauthorized admin event attempt: signature verification failed");
|
||||
return -1;
|
||||
}
|
||||
@@ -1455,6 +1428,8 @@ void print_usage(const char* program_name) {
|
||||
printf(" --strict-port Fail if exact port is unavailable (no port increment)\n");
|
||||
printf(" -a, --admin-pubkey KEY Override admin public key (64-char hex or npub)\n");
|
||||
printf(" -r, --relay-privkey KEY Override relay private key (64-char hex or nsec)\n");
|
||||
printf(" --debug-level=N Set debug output level (0-5, default: 0)\n");
|
||||
printf(" 0=none, 1=errors, 2=warnings, 3=info, 4=debug, 5=trace\n");
|
||||
printf("\n");
|
||||
printf("Configuration:\n");
|
||||
printf(" This relay uses event-based configuration stored in the database.\n");
|
||||
@@ -1492,7 +1467,8 @@ int main(int argc, char* argv[]) {
|
||||
.port_override = -1, // -1 = not set
|
||||
.admin_pubkey_override = {0}, // Empty string = not set
|
||||
.relay_privkey_override = {0}, // Empty string = not set
|
||||
.strict_port = 0 // 0 = allow port increment (default)
|
||||
.strict_port = 0, // 0 = allow port increment (default)
|
||||
.debug_level = 0 // 0 = no debug output (default)
|
||||
};
|
||||
|
||||
// Parse command line arguments
|
||||
@@ -1506,7 +1482,7 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--port") == 0) {
|
||||
// Port override option
|
||||
if (i + 1 >= argc) {
|
||||
log_error("Port option requires a value. Use --help for usage information.");
|
||||
DEBUG_ERROR("Port option requires a value. Use --help for usage information.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1516,7 +1492,7 @@ int main(int argc, char* argv[]) {
|
||||
long port = strtol(argv[i + 1], &endptr, 10);
|
||||
|
||||
if (endptr == argv[i + 1] || *endptr != '\0' || port < 1 || port > 65535) {
|
||||
log_error("Invalid port number. Port must be between 1 and 65535.");
|
||||
DEBUG_ERROR("Invalid port number. Port must be between 1 and 65535.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1529,7 +1505,7 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--admin-pubkey") == 0) {
|
||||
// Admin public key override option
|
||||
if (i + 1 >= argc) {
|
||||
log_error("Admin pubkey option requires a value. Use --help for usage information.");
|
||||
DEBUG_ERROR("Admin pubkey option requires a value. Use --help for usage information.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1547,7 +1523,7 @@ int main(int argc, char* argv[]) {
|
||||
hex_ptr += 2;
|
||||
}
|
||||
} else {
|
||||
log_error("Invalid admin public key format. Must be 64 hex characters or valid npub format.");
|
||||
DEBUG_ERROR("Invalid admin public key format. Must be 64 hex characters or valid npub format.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1559,7 +1535,7 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--relay-privkey") == 0) {
|
||||
// Relay private key override option
|
||||
if (i + 1 >= argc) {
|
||||
log_error("Relay privkey option requires a value. Use --help for usage information.");
|
||||
DEBUG_ERROR("Relay privkey option requires a value. Use --help for usage information.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1577,7 +1553,7 @@ int main(int argc, char* argv[]) {
|
||||
hex_ptr += 2;
|
||||
}
|
||||
} else {
|
||||
log_error("Invalid relay private key format. Must be 64 hex characters or valid nsec format.");
|
||||
DEBUG_ERROR("Invalid relay private key format. Must be 64 hex characters or valid nsec format.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
@@ -1589,13 +1565,28 @@ int main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[i], "--strict-port") == 0) {
|
||||
// Strict port mode option
|
||||
cli_options.strict_port = 1;
|
||||
} else if (strncmp(argv[i], "--debug-level=", 14) == 0) {
|
||||
// Debug level option
|
||||
char* endptr;
|
||||
int debug_level = (int)strtol(argv[i] + 14, &endptr, 10);
|
||||
|
||||
if (endptr == argv[i] + 14 || *endptr != '\0' || debug_level < 0 || debug_level > 5) {
|
||||
DEBUG_ERROR("Invalid debug level. Debug level must be between 0 and 5.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cli_options.debug_level = debug_level;
|
||||
} else {
|
||||
log_error("Unknown argument. Use --help for usage information.");
|
||||
DEBUG_ERROR("Unknown argument. Use --help for usage information.");
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initialize debug system
|
||||
debug_init(cli_options.debug_level);
|
||||
|
||||
// Set up signal handlers
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
@@ -1603,49 +1594,56 @@ int main(int argc, char* argv[]) {
|
||||
printf(BLUE BOLD "=== C Nostr Relay Server ===" RESET "\n");
|
||||
|
||||
|
||||
DEBUG_TRACE("Starting main initialization sequence");
|
||||
|
||||
// Initialize nostr library FIRST (required for key generation and event creation)
|
||||
if (nostr_init() != 0) {
|
||||
log_error("Failed to initialize nostr library");
|
||||
DEBUG_ERROR("Failed to initialize nostr library");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_LOG("Nostr library initialized");
|
||||
|
||||
// Check if this is first-time startup or existing relay
|
||||
if (is_first_time_startup()) {
|
||||
DEBUG_LOG("First-time startup detected");
|
||||
|
||||
// Initialize event-based configuration system
|
||||
if (init_configuration_system(NULL, NULL) != 0) {
|
||||
log_error("Failed to initialize event-based configuration system");
|
||||
DEBUG_ERROR("Failed to initialize event-based configuration system");
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run first-time startup sequence (generates keys, sets up database path, but doesn't store private key yet)
|
||||
if (first_time_startup_sequence(&cli_options) != 0) {
|
||||
log_error("Failed to complete first-time startup sequence");
|
||||
DEBUG_ERROR("Failed to complete first-time startup sequence");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialize database with the generated relay pubkey
|
||||
DEBUG_TRACE("Initializing database for first-time startup");
|
||||
if (init_database(g_database_path) != 0) {
|
||||
log_error("Failed to initialize database after first-time setup");
|
||||
DEBUG_ERROR("Failed to initialize database after first-time setup");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
DEBUG_LOG("Database initialized for first-time startup");
|
||||
|
||||
// Now that database is available, store the relay private key securely
|
||||
const char* relay_privkey = get_temp_relay_private_key();
|
||||
if (relay_privkey) {
|
||||
if (store_relay_private_key(relay_privkey) != 0) {
|
||||
log_error("Failed to store relay private key securely after database initialization");
|
||||
DEBUG_ERROR("Failed to store relay private key securely after database initialization");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
log_error("Relay private key not available from first-time startup");
|
||||
DEBUG_ERROR("Relay private key not available from first-time startup");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
@@ -1656,7 +1654,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Populate default config values in table
|
||||
if (populate_default_config_values() != 0) {
|
||||
log_error("Failed to populate default config values");
|
||||
DEBUG_ERROR("Failed to populate default config values");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1668,7 +1666,7 @@ int main(int argc, char* argv[]) {
|
||||
char port_str[16];
|
||||
snprintf(port_str, sizeof(port_str), "%d", cli_options.port_override);
|
||||
if (update_config_in_table("relay_port", port_str) != 0) {
|
||||
log_error("Failed to update relay port override in config table");
|
||||
DEBUG_ERROR("Failed to update relay port override in config table");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1679,7 +1677,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Add pubkeys to config table (single authoritative call)
|
||||
if (add_pubkeys_to_config_table() != 0) {
|
||||
log_error("Failed to add pubkeys to config table");
|
||||
DEBUG_ERROR("Failed to add pubkeys to config table");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1689,7 +1687,7 @@ int main(int argc, char* argv[]) {
|
||||
// Find existing database file
|
||||
char** existing_files = find_existing_db_files();
|
||||
if (!existing_files || !existing_files[0]) {
|
||||
log_error("No existing relay database found");
|
||||
DEBUG_ERROR("No existing relay database found");
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
@@ -1697,7 +1695,7 @@ int main(int argc, char* argv[]) {
|
||||
// Extract relay pubkey from filename
|
||||
char* relay_pubkey = extract_pubkey_from_filename(existing_files[0]);
|
||||
if (!relay_pubkey) {
|
||||
log_error("Failed to extract relay pubkey from database filename");
|
||||
DEBUG_ERROR("Failed to extract relay pubkey from database filename");
|
||||
// Free the files array
|
||||
for (int i = 0; existing_files[i]; i++) {
|
||||
free(existing_files[i]);
|
||||
@@ -1709,7 +1707,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Initialize event-based configuration system
|
||||
if (init_configuration_system(NULL, NULL) != 0) {
|
||||
log_error("Failed to initialize event-based configuration system");
|
||||
DEBUG_ERROR("Failed to initialize event-based configuration system");
|
||||
free(relay_pubkey);
|
||||
for (int i = 0; existing_files[i]; i++) {
|
||||
free(existing_files[i]);
|
||||
@@ -1721,7 +1719,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Setup existing relay (sets database path and loads config)
|
||||
if (startup_existing_relay(relay_pubkey) != 0) {
|
||||
log_error("Failed to setup existing relay");
|
||||
DEBUG_ERROR("Failed to setup existing relay");
|
||||
cleanup_configuration_system();
|
||||
free(relay_pubkey);
|
||||
for (int i = 0; existing_files[i]; i++) {
|
||||
@@ -1739,7 +1737,8 @@ int main(int argc, char* argv[]) {
|
||||
sqlite3_stmt* stmt;
|
||||
if (sqlite3_prepare_v2(temp_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
// Row count check completed
|
||||
int row_count = sqlite3_column_int(stmt, 0);
|
||||
printf(" Config table row count before database initialization: %d\n", row_count);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
@@ -1748,8 +1747,9 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
// Initialize database with existing database path
|
||||
DEBUG_TRACE("Initializing existing database");
|
||||
if (init_database(g_database_path) != 0) {
|
||||
log_error("Failed to initialize existing database");
|
||||
DEBUG_ERROR("Failed to initialize existing database");
|
||||
cleanup_configuration_system();
|
||||
free(relay_pubkey);
|
||||
for (int i = 0; existing_files[i]; i++) {
|
||||
@@ -1759,13 +1759,15 @@ int main(int argc, char* argv[]) {
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
DEBUG_LOG("Existing database initialized");
|
||||
|
||||
// Check config table row count after database initialization
|
||||
{
|
||||
sqlite3_stmt* stmt;
|
||||
if (sqlite3_prepare_v2(g_db, "SELECT COUNT(*) FROM config", -1, &stmt, NULL) == SQLITE_OK) {
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
// Row count check completed
|
||||
int row_count = sqlite3_column_int(stmt, 0);
|
||||
printf(" Config table row count after database initialization: %d\n", row_count);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
@@ -1775,14 +1777,14 @@ int main(int argc, char* argv[]) {
|
||||
// This must be done AFTER database initialization
|
||||
// COMMENTED OUT: Don't modify existing database config on restart
|
||||
// if (populate_default_config_values() != 0) {
|
||||
// log_warning("Failed to populate default config values for existing relay - continuing");
|
||||
// DEBUG_WARN("Failed to populate default config values for existing relay - continuing");
|
||||
// }
|
||||
|
||||
// Load configuration from database
|
||||
cJSON* config_event = load_config_event_from_database(relay_pubkey);
|
||||
if (config_event) {
|
||||
if (apply_configuration_from_event(config_event) != 0) {
|
||||
log_warning("Failed to apply configuration from database");
|
||||
DEBUG_WARN("Failed to apply configuration from database");
|
||||
}
|
||||
cJSON_Delete(config_event);
|
||||
} else {
|
||||
@@ -1799,14 +1801,14 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Check if admin_pubkey is missing or invalid
|
||||
if (!admin_pubkey_from_table || strlen(admin_pubkey_from_table) != 64) {
|
||||
log_warning("Admin pubkey missing or invalid in config table - will regenerate from cache");
|
||||
DEBUG_WARN("Admin pubkey missing or invalid in config table - will regenerate from cache");
|
||||
need_to_add_pubkeys = 1;
|
||||
}
|
||||
if (admin_pubkey_from_table) free((char*)admin_pubkey_from_table);
|
||||
|
||||
// Check if relay_pubkey is missing or invalid
|
||||
if (!relay_pubkey_from_table || strlen(relay_pubkey_from_table) != 64) {
|
||||
log_warning("Relay pubkey missing or invalid in config table - will regenerate from cache");
|
||||
DEBUG_WARN("Relay pubkey missing or invalid in config table - will regenerate from cache");
|
||||
need_to_add_pubkeys = 1;
|
||||
}
|
||||
if (relay_pubkey_from_table) free((char*)relay_pubkey_from_table);
|
||||
@@ -1814,7 +1816,7 @@ int main(int argc, char* argv[]) {
|
||||
// If either pubkey is missing, call add_pubkeys_to_config_table to populate both
|
||||
if (need_to_add_pubkeys) {
|
||||
if (add_pubkeys_to_config_table() != 0) {
|
||||
log_error("Failed to add pubkeys to config table for existing relay");
|
||||
DEBUG_ERROR("Failed to add pubkeys to config table for existing relay");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1827,7 +1829,7 @@ int main(int argc, char* argv[]) {
|
||||
char port_str[16];
|
||||
snprintf(port_str, sizeof(port_str), "%d", cli_options.port_override);
|
||||
if (update_config_in_table("relay_port", port_str) != 0) {
|
||||
log_error("Failed to update relay port override in config table for existing relay");
|
||||
DEBUG_ERROR("Failed to update relay port override in config table for existing relay");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1846,7 +1848,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Verify database is now available
|
||||
if (!g_db) {
|
||||
log_error("Database not available after initialization");
|
||||
DEBUG_ERROR("Database not available after initialization");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
@@ -1857,7 +1859,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Initialize unified request validator system
|
||||
if (ginxsom_request_validator_init(g_database_path, "c-relay") != 0) {
|
||||
log_error("Failed to initialize unified request validator");
|
||||
DEBUG_ERROR("Failed to initialize unified request validator");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1877,7 +1879,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Initialize subscription manager mutexes
|
||||
if (pthread_mutex_init(&g_subscription_manager.subscriptions_lock, NULL) != 0) {
|
||||
log_error("Failed to initialize subscription manager subscriptions lock");
|
||||
DEBUG_ERROR("Failed to initialize subscription manager subscriptions lock");
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
close_database();
|
||||
@@ -1885,7 +1887,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&g_subscription_manager.ip_tracking_lock, NULL) != 0) {
|
||||
log_error("Failed to initialize subscription manager IP tracking lock");
|
||||
DEBUG_ERROR("Failed to initialize subscription manager IP tracking lock");
|
||||
pthread_mutex_destroy(&g_subscription_manager.subscriptions_lock);
|
||||
cleanup_configuration_system();
|
||||
nostr_cleanup();
|
||||
@@ -1912,7 +1914,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (result == 0) {
|
||||
} else {
|
||||
log_error("Server shutdown with errors");
|
||||
DEBUG_ERROR("Server shutdown with errors");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user