v0.3.2 - Implement -p/--port CLI option for first-time startup port override

- Add cli_options_t structure for extensible command line options
- Implement port override in create_default_config_event()
- Update main() with robust CLI parsing and validation
- Add comprehensive help text documenting first-time only behavior
- Ensure CLI options only affect initial configuration event creation
- Maintain event-based configuration architecture for ongoing operation
- Include comprehensive error handling and input validation
- Add documentation in CLI_PORT_OVERRIDE_IMPLEMENTATION.md

Tested: First-time startup uses CLI port, subsequent startups use database config
This commit is contained in:
Your Name
2025-09-07 06:54:56 -04:00
parent be7ae2b580
commit 74a4dc2533
7 changed files with 216 additions and 11 deletions

View File

@@ -443,7 +443,8 @@ int generate_random_private_key_bytes(unsigned char* privkey_bytes) {
cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
const char* relay_privkey_hex,
const char* relay_pubkey_hex) {
const char* relay_pubkey_hex,
const cli_options_t* cli_options) {
if (!admin_privkey_bytes || !relay_privkey_hex || !relay_pubkey_hex) {
log_error("Invalid parameters for creating default config event");
return NULL;
@@ -475,11 +476,28 @@ cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
cJSON_AddItemToArray(relay_privkey_tag, cJSON_CreateString(relay_privkey_hex));
cJSON_AddItemToArray(tags, relay_privkey_tag);
// Add all default configuration values
// Add all default configuration values with command line overrides
for (size_t i = 0; i < DEFAULT_CONFIG_COUNT; i++) {
cJSON* tag = cJSON_CreateArray();
cJSON_AddItemToArray(tag, cJSON_CreateString(DEFAULT_CONFIG_VALUES[i].key));
cJSON_AddItemToArray(tag, cJSON_CreateString(DEFAULT_CONFIG_VALUES[i].value));
// Check for command line overrides
const char* value = DEFAULT_CONFIG_VALUES[i].value;
if (cli_options) {
// Override relay_port if specified on command line
if (cli_options->port_override > 0 && strcmp(DEFAULT_CONFIG_VALUES[i].key, "relay_port") == 0) {
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", cli_options->port_override);
cJSON_AddItemToArray(tag, cJSON_CreateString(port_str));
log_info("Using command line port override in configuration event");
printf(" Port: %d (overriding default %s)\n", cli_options->port_override, DEFAULT_CONFIG_VALUES[i].value);
} else {
cJSON_AddItemToArray(tag, cJSON_CreateString(value));
}
} else {
cJSON_AddItemToArray(tag, cJSON_CreateString(value));
}
cJSON_AddItemToArray(tags, tag);
}
@@ -516,7 +534,7 @@ cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
// IMPLEMENTED FUNCTIONS
// ================================
int first_time_startup_sequence(void) {
int first_time_startup_sequence(const cli_options_t* cli_options) {
log_info("Starting first-time startup sequence...");
// 1. Generate admin keypair using /dev/urandom + nostr_core_lib
@@ -566,7 +584,7 @@ int first_time_startup_sequence(void) {
}
// 5. Create initial configuration event using defaults
cJSON* config_event = create_default_config_event(admin_privkey_bytes, relay_privkey, relay_pubkey);
cJSON* config_event = create_default_config_event(admin_privkey_bytes, relay_privkey, relay_pubkey, cli_options);
if (!config_event) {
log_error("Failed to create default configuration event");
return -1;

View File

@@ -32,6 +32,12 @@ typedef struct {
char config_file_path[512]; // Temporary for compatibility
} config_manager_t;
// Command line options structure for first-time startup
typedef struct {
int port_override; // -1 = not set, >0 = port value
// Future CLI options can be added here
} cli_options_t;
// Global configuration manager
extern config_manager_t g_config_manager;
@@ -62,7 +68,7 @@ int get_config_bool(const char* key, int default_value);
// First-time startup functions
int is_first_time_startup(void);
int first_time_startup_sequence(void);
int first_time_startup_sequence(const cli_options_t* cli_options);
int startup_existing_relay(const char* relay_pubkey);
// Configuration application functions

View File

@@ -2,6 +2,7 @@
#define DEFAULT_CONFIG_EVENT_H
#include <cjson/cJSON.h>
#include "config.h" // For cli_options_t definition
/*
* Default Configuration Event Template
@@ -61,8 +62,9 @@ static const struct {
#define DEFAULT_CONFIG_COUNT (sizeof(DEFAULT_CONFIG_VALUES) / sizeof(DEFAULT_CONFIG_VALUES[0]))
// Function to create default configuration event
cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
const char* relay_privkey_hex,
const char* relay_pubkey_hex);
const char* relay_pubkey_hex,
const cli_options_t* cli_options);
#endif /* DEFAULT_CONFIG_EVENT_H */

View File

@@ -3132,14 +3132,19 @@ void print_usage(const char* program_name) {
printf("Options:\n");
printf(" -h, --help Show this help message\n");
printf(" -v, --version Show version information\n");
printf(" -p, --port PORT Override relay port (first-time startup only)\n");
printf("\n");
printf("Configuration:\n");
printf(" This relay uses event-based configuration stored in the database.\n");
printf(" On first startup, keys are automatically generated and printed once.\n");
printf(" Command line options like --port only apply during first-time setup.\n");
printf(" After initial setup, all configuration is managed via database events.\n");
printf(" Database file: <relay_pubkey>.db (created automatically)\n");
printf("\n");
printf("Examples:\n");
printf(" %s # Start relay (auto-configure on first run)\n", program_name);
printf(" %s -p 8080 # First-time setup with port 8080\n", program_name);
printf(" %s --port 9000 # First-time setup with port 9000\n", program_name);
printf(" %s --help # Show this help\n", program_name);
printf(" %s --version # Show version info\n", program_name);
printf("\n");
@@ -3154,7 +3159,12 @@ void print_version() {
}
int main(int argc, char* argv[]) {
// Parse minimal command line arguments (no configuration overrides)
// Initialize CLI options structure
cli_options_t cli_options = {
.port_override = -1 // -1 = not set
};
// Parse command line arguments
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
@@ -3162,6 +3172,30 @@ int main(int argc, char* argv[]) {
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
print_version();
return 0;
} 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.");
print_usage(argv[0]);
return 1;
}
// Parse port number
char* endptr;
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.");
print_usage(argv[0]);
return 1;
}
cli_options.port_override = (int)port;
i++; // Skip the port argument
char port_msg[128];
snprintf(port_msg, sizeof(port_msg), "Port override specified: %d", cli_options.port_override);
log_info(port_msg);
} else {
log_error("Unknown argument. Use --help for usage information.");
print_usage(argv[0]);
@@ -3194,7 +3228,7 @@ int main(int argc, char* argv[]) {
}
// Run first-time startup sequence (generates keys, creates database, etc.)
if (first_time_startup_sequence() != 0) {
if (first_time_startup_sequence(&cli_options) != 0) {
log_error("Failed to complete first-time startup sequence");
cleanup_configuration_system();
nostr_cleanup();