From 78d6e2d58b4e4e18e6a3045e0d8b3b29392d8238 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Wed, 30 Dec 2015 21:49:00 -0500 Subject: Change log levels Some of them were set incorrectly, e.g. something that caused the daemon to exit was marked as just a warning, instead of an error. Removed debug level as it was hard to decide whether something should go into info or debug. This is mostly because the use of the debug level wasn't well defined. Debug should be used for information that could help a user to debug an issue, but messages marked as debug were by the most part the "success" log messages, which could go into info level instead. --- other/bootstrap_daemon/tox-bootstrapd.c | 58 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/other/bootstrap_daemon/tox-bootstrapd.c b/other/bootstrap_daemon/tox-bootstrapd.c index 267e7238..71b1386d 100644 --- a/other/bootstrap_daemon/tox-bootstrapd.c +++ b/other/bootstrap_daemon/tox-bootstrapd.c @@ -144,7 +144,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int int i; for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - syslog(LOG_WARNING, "Port #%d: %u\n", i, default_ports[i]); + syslog(LOG_INFO, "Port #%d: %u\n", i, default_ports[i]); } // similar procedure to the one of reading config file below @@ -176,7 +176,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } if (config_setting_is_array(ports_array) == CONFIG_FALSE) { - syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", + syslog(LOG_ERR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", NAME_TCP_RELAY_PORTS); return; } @@ -184,7 +184,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int int config_port_count = config_setting_length(ports_array); if (config_port_count == 0) { - syslog(LOG_WARNING, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); + syslog(LOG_ERR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); return; } @@ -357,34 +357,34 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k config_destroy(&cfg); - syslog(LOG_DEBUG, "Successfully read:\n"); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); - syslog(LOG_DEBUG, "'%s': %d\n", NAME_PORT, *port); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + syslog(LOG_INFO, "Successfully read:\n"); + syslog(LOG_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); + syslog(LOG_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); + syslog(LOG_INFO, "'%s': %d\n", NAME_PORT, *port); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); - syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); // show info about tcp ports only if tcp relay is enabled if (*enable_tcp_relay) { if (*tcp_relay_port_count == 0) { - syslog(LOG_DEBUG, "No TCP ports could be read.\n"); + syslog(LOG_ERR, "No TCP ports could be read.\n"); } else { - syslog(LOG_DEBUG, "Read %d TCP ports:\n", *tcp_relay_port_count); + syslog(LOG_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); int i; for (i = 0; i < *tcp_relay_port_count; i ++) { - syslog(LOG_DEBUG, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); + syslog(LOG_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); } } } - syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); if (*enable_motd) { - syslog(LOG_DEBUG, "'%s': %s\n", NAME_MOTD, *motd); + syslog(LOG_INFO, "'%s': %s\n", NAME_MOTD, *motd); } return 1; @@ -483,7 +483,7 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) goto next; } - syslog(LOG_DEBUG, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); + syslog(LOG_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); next: // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly @@ -541,7 +541,7 @@ int main(int argc, char *argv[]) if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_ipv4_fallback, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { - syslog(LOG_DEBUG, "General config read successfully\n"); + syslog(LOG_INFO, "General config read successfully\n"); } else { syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); return 1; @@ -556,7 +556,7 @@ int main(int argc, char *argv[]) FILE *pid_file; if ((pid_file = fopen(pid_file_path, "r"))) { - syslog(LOG_ERR, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); + syslog(LOG_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); fclose(pid_file); } @@ -567,17 +567,17 @@ int main(int argc, char *argv[]) if (net == NULL) { if (enable_ipv6 && enable_ipv4_fallback) { - syslog(LOG_DEBUG, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); + syslog(LOG_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); enable_ipv6 = 0; ip_init(&ip, enable_ipv6); net = new_networking(ip, port); if (net == NULL) { - syslog(LOG_DEBUG, "Couldn't fallback to IPv4. Exiting.\n"); + syslog(LOG_ERR, "Couldn't fallback to IPv4. Exiting.\n"); return 1; } } else { - syslog(LOG_DEBUG, "Couldn't initialize networking. Exiting.\n"); + syslog(LOG_ERR, "Couldn't initialize networking. Exiting.\n"); return 1; } } @@ -600,7 +600,7 @@ int main(int argc, char *argv[]) if (enable_motd) { if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) { - syslog(LOG_DEBUG, "Set MOTD successfully.\n"); + syslog(LOG_INFO, "Set MOTD successfully.\n"); } else { syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); return 1; @@ -610,7 +610,7 @@ int main(int argc, char *argv[]) } if (manage_keys(dht, keys_file_path)) { - syslog(LOG_DEBUG, "Keys are managed successfully.\n"); + syslog(LOG_INFO, "Keys are managed successfully.\n"); } else { syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); return 1; @@ -630,7 +630,7 @@ int main(int argc, char *argv[]) free(tcp_relay_ports); if (tcp_server != NULL) { - syslog(LOG_DEBUG, "Initialized Tox TCP server successfully.\n"); + syslog(LOG_INFO, "Initialized Tox TCP server successfully.\n"); } else { syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); return 1; @@ -638,7 +638,7 @@ int main(int argc, char *argv[]) } if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { - syslog(LOG_DEBUG, "List of bootstrap nodes read successfully.\n"); + syslog(LOG_INFO, "List of bootstrap nodes read successfully.\n"); } else { syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); return 1; @@ -663,7 +663,7 @@ int main(int argc, char *argv[]) if (pid > 0) { fprintf(pidf, "%d", pid); fclose(pidf); - syslog(LOG_DEBUG, "Forked successfully: PID: %d.\n", pid); + syslog(LOG_INFO, "Forked successfully: PID: %d.\n", pid); return 0; } else { fclose(pidf); @@ -701,7 +701,7 @@ int main(int argc, char *argv[]) if (enable_lan_discovery) { LANdiscovery_init(dht); - syslog(LOG_DEBUG, "Initialized LAN discovery.\n"); + syslog(LOG_INFO, "Initialized LAN discovery.\n"); } while (1) { @@ -719,7 +719,7 @@ int main(int argc, char *argv[]) networking_poll(dht->net); if (waiting_for_dht_connection && DHT_isconnected(dht)) { - syslog(LOG_DEBUG, "Connected to other bootstrap node successfully.\n"); + syslog(LOG_INFO, "Connected to other bootstrap node successfully.\n"); waiting_for_dht_connection = 0; } -- cgit v1.2.3 From bfc3c4eaac4eec6a2e714b7483b646d8ee21efc9 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Wed, 30 Dec 2015 23:43:04 -0500 Subject: Add logger object to be able to support multiple logging backends --- other/bootstrap_daemon/src/global.h | 30 ++ other/bootstrap_daemon/src/logger.c | 112 +++++ other/bootstrap_daemon/src/logger.h | 63 +++ other/bootstrap_daemon/src/tox-bootstrapd.c | 730 ++++++++++++++++++++++++++++ other/bootstrap_daemon/tox-bootstrapd.c | 730 ---------------------------- 5 files changed, 935 insertions(+), 730 deletions(-) create mode 100644 other/bootstrap_daemon/src/global.h create mode 100644 other/bootstrap_daemon/src/logger.c create mode 100644 other/bootstrap_daemon/src/logger.h create mode 100644 other/bootstrap_daemon/src/tox-bootstrapd.c delete mode 100644 other/bootstrap_daemon/tox-bootstrapd.c diff --git a/other/bootstrap_daemon/src/global.h b/other/bootstrap_daemon/src/global.h new file mode 100644 index 00000000..7aa42780 --- /dev/null +++ b/other/bootstrap_daemon/src/global.h @@ -0,0 +1,30 @@ +/* global.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef GLOBAL_H +#define GLOBAL_H + +#define DAEMON_NAME "tox-bootstrapd" +#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day + +#endif // GLOBAL_H diff --git a/other/bootstrap_daemon/src/logger.c b/other/bootstrap_daemon/src/logger.c new file mode 100644 index 00000000..3cf18fd6 --- /dev/null +++ b/other/bootstrap_daemon/src/logger.c @@ -0,0 +1,112 @@ +/* logger.c + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "logger.h" + +#include "global.h" + +#include + +#include +#include + +typedef struct Logger { + LOGGER_BACKEND backend; +} Logger; + +Logger* new_logger(LOGGER_BACKEND backend) +{ + if (backend == LOGGER_BACKEND_SYSLOG) { + openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); + } + + Logger* logger = malloc(sizeof(Logger)); + + if (logger == NULL) { + return NULL; + } + + logger->backend = backend; + + return logger; +} + +void kill_logger(Logger* logger) +{ + if (backend == LOGGER_BACKEND_SYSLOG) { + closelog(); + } + + free(logger); +} + +int level_syslog(LOG_LEVEL level) +{ + switch (level) { + case LOG_LEVEL_INFO: + return LOG_INFO; + case LOG_LEVEL_WARNING: + return LOG_WARNING; + case LOG_LEVEL_ERROR: + return LOG_ERR; + } +} + +void log_syslog(LOG_LEVEL level, const char *format, va_list args) +{ + vsyslog(level_syslog(level), format, args); +} + +FILE* level_stdout(LOG_LEVEL level) +{ + switch (level) { + case LOG_LEVEL_INFO: + return stdout; + case LOG_LEVEL_WARNING: // intentional fallthrough + case LOG_LEVEL_ERROR: + return stderr; + + } +} + +void log_stdout(LOG_LEVEL level, const char *format, va_list args) +{ + vfprintf(level_stdout(level), format, args); +} + +void log(Logger* logger, LOG_LEVEL level, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (logger->backend) { + case LOGGER_BACKEND_SYSLOG: + log_syslog(level, format, args); + break; + case LOGGER_BACKEND_STDOUT: + log_stdout(level, format, args); + break; + } + + va_end(args); +} diff --git a/other/bootstrap_daemon/src/logger.h b/other/bootstrap_daemon/src/logger.h new file mode 100644 index 00000000..174d3445 --- /dev/null +++ b/other/bootstrap_daemon/src/logger.h @@ -0,0 +1,63 @@ +/* logger.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef LOGGER_H +#define LOGGER_H + +typedef enum LOGGER_BACKEND { + LOGGER_BACKEND_SYSLOG, + LOGGER_BACKEND_STDOUT +} LOGGER_BACKEND; + +typedef enum LOG_LEVEL { + LOG_LEVEL_INFO, + LOG_LEVEL_WARNING, + LOG_LEVEL_ERROR +} LOG_LEVEL; + +typedef struct Logger Logger; + +/** + * Creates new logger. + * @param backend Specifies which backend the logger should use. + * @return Logger object on success, NULL on failure. + */ +Logger* new_logger(LOGGER_BACKEND backend); + +/** + * Destroys a logger object, releasing all used resources. + * @param logger Logger object to destroy. + */ +void kill_logger(Logger* logger); + +/** + * Logs a message. + * @param logger Logger object to use. + * @param level Log level to use. + * @param format printf-like format string. + * @param ... Zero or more arguments, similar to printf function. + */ +void log(Logger* logger, LOG_LEVEL level, const char *format, ...); + + +#endif // LOGGER_H diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c new file mode 100644 index 00000000..71b1386d --- /dev/null +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -0,0 +1,730 @@ +/* tox-bootstrapd.c + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2014 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +// system provided +#include +#include +#include +#include +#include + +// C +#include +#include +#include + +// 3rd party +#include + +// ./configure +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// toxcore +#include "../../toxcore/LAN_discovery.h" +#include "../../toxcore/onion_announce.h" +#include "../../toxcore/TCP_server.h" +#include "../../toxcore/util.h" + +// misc +#include "../bootstrap_node_packets.c" +#include "../../testing/misc_tools.c" + + +#define DAEMON_NAME "tox-bootstrapd" +#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day + +#define SLEEP_TIME_MILLISECONDS 30 +#define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) + +#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid" +#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys" +#define DEFAULT_PORT 33445 +#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false +#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly +#define DEFAULT_TCP_RELAY_PORTS_COUNT 3 +#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false +#define DEFAULT_MOTD DAEMON_NAME + +#define MIN_ALLOWED_PORT 1 +#define MAX_ALLOWED_PORT 65535 + + +// Uses the already existing key or creates one if it didn't exist +// +// retirns 1 on success +// 0 on failure - no keys were read or stored + +int manage_keys(DHT *dht, char *keys_file_path) +{ + const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; + uint8_t keys[KEYS_SIZE]; + FILE *keys_file; + + // Check if file exits, proceed to open and load keys + keys_file = fopen(keys_file_path, "r"); + + if (keys_file != NULL) { + const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); + + if (read_size != KEYS_SIZE) { + fclose(keys_file); + return 0; + } + + memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); + memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); + } else { + // Otherwise save new keys + memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); + + keys_file = fopen(keys_file_path, "w"); + + if (!keys_file) + return 0; + + const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); + + if (write_size != KEYS_SIZE) { + fclose(keys_file); + return 0; + } + } + + fclose(keys_file); + + return 1; +} + +// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array +// +// Supposed to be called from get_general_config only +// +// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` + +void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) +{ + const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; + + *tcp_relay_port_count = 0; + + config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); + + if (ports_array == NULL) { + syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); + syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); + + uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; + + int i; + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + syslog(LOG_INFO, "Port #%d: %u\n", i, default_ports[i]); + } + + // similar procedure to the one of reading config file below + *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + + (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; + + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT + || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + if ((*tcp_relay_port_count) > 0) { + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); + } else { + free(*tcp_relay_ports); + *tcp_relay_ports = NULL; + } + + return; + } + + if (config_setting_is_array(ports_array) == CONFIG_FALSE) { + syslog(LOG_ERR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", + NAME_TCP_RELAY_PORTS); + return; + } + + int config_port_count = config_setting_length(ports_array); + + if (config_port_count == 0) { + syslog(LOG_ERR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); + return; + } + + *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); + + int i; + + for (i = 0; i < config_port_count; i ++) { + config_setting_t *elem = config_setting_get_elem(ports_array, i); + + if (elem == NULL) { + // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be + syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); + break; + } + + if (config_setting_is_number(elem) == CONFIG_FALSE) { + syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i); + continue; + } + + (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); + + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT + || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + if ((*tcp_relay_port_count) > 0) { + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); + } else { + free(*tcp_relay_ports); + *tcp_relay_ports = NULL; + } +} + +// Gets general config options +// +// Important: you are responsible for freeing `pid_file_path` and `keys_file_path` +// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` +// and also `motd` iff `enable_motd` is set +// +// returns 1 on success +// 0 on failure, doesn't modify any data pointed by arguments + +int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, + int *enable_ipv6, + int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, + int *tcp_relay_port_count, int *enable_motd, char **motd) +{ + config_t cfg; + + const char *NAME_PORT = "port"; + const char *NAME_PID_FILE_PATH = "pid_file_path"; + const char *NAME_KEYS_FILE_PATH = "keys_file_path"; + const char *NAME_ENABLE_IPV6 = "enable_ipv6"; + const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback"; + const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; + const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; + const char *NAME_ENABLE_MOTD = "enable_motd"; + const char *NAME_MOTD = "motd"; + + config_init(&cfg); + + // Read the file. If there is an error, report it and exit. + if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { + syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return 0; + } + + // Get port + if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); + syslog(LOG_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); + *port = DEFAULT_PORT; + } + + // Get PID file location + const char *tmp_pid_file; + + if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); + tmp_pid_file = DEFAULT_PID_FILE_PATH; + } + + *pid_file_path = malloc(strlen(tmp_pid_file) + 1); + strcpy(*pid_file_path, tmp_pid_file); + + // Get keys file location + const char *tmp_keys_file; + + if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); + tmp_keys_file = DEFAULT_KEYS_FILE_PATH; + } + + *keys_file_path = malloc(strlen(tmp_keys_file) + 1); + strcpy(*keys_file_path, tmp_keys_file); + + // Get IPv6 option + if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); + *enable_ipv6 = DEFAULT_ENABLE_IPV6; + } + + // Get IPv4 fallback option + if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, + DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false"); + *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK; + } + + // Get LAN discovery option + if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, + DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false"); + *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; + } + + // Get TCP relay option + if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, + DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); + *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; + } + + if (*enable_tcp_relay) { + parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); + } else { + *tcp_relay_port_count = 0; + } + + // Get MOTD option + if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, + DEFAULT_ENABLE_MOTD ? "true" : "false"); + *enable_motd = DEFAULT_ENABLE_MOTD; + } + + if (*enable_motd) { + // Get MOTD + const char *tmp_motd; + + if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); + tmp_motd = DEFAULT_MOTD; + } + + size_t tmp_motd_length = strlen(tmp_motd) + 1; + size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; + *motd = malloc(motd_length); + strncpy(*motd, tmp_motd, motd_length); + (*motd)[motd_length - 1] = '\0'; + } + + config_destroy(&cfg); + + syslog(LOG_INFO, "Successfully read:\n"); + syslog(LOG_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); + syslog(LOG_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); + syslog(LOG_INFO, "'%s': %d\n", NAME_PORT, *port); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); + + // show info about tcp ports only if tcp relay is enabled + if (*enable_tcp_relay) { + if (*tcp_relay_port_count == 0) { + syslog(LOG_ERR, "No TCP ports could be read.\n"); + } else { + syslog(LOG_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); + int i; + + for (i = 0; i < *tcp_relay_port_count; i ++) { + syslog(LOG_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); + } + } + } + + syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); + + if (*enable_motd) { + syslog(LOG_INFO, "'%s': %s\n", NAME_MOTD, *motd); + } + + return 1; +} + +// Bootstraps nodes listed in the config file +// +// returns 1 on success, some or no bootstrap nodes were added +// 0 on failure, a error accured while parsing config file + +int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) +{ + const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; + + const char *NAME_PUBLIC_KEY = "public_key"; + const char *NAME_PORT = "port"; + const char *NAME_ADDRESS = "address"; + + config_t cfg; + + config_init(&cfg); + + if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { + syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return 0; + } + + config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); + + if (node_list == NULL) { + syslog(LOG_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); + config_destroy(&cfg); + return 1; + } + + if (config_setting_length(node_list) == 0) { + syslog(LOG_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); + config_destroy(&cfg); + return 1; + } + + int bs_port; + const char *bs_address; + const char *bs_public_key; + + config_setting_t *node; + + int i = 0; + + while (config_setting_length(node_list)) { + + node = config_setting_get_elem(node_list, 0); + + if (node == NULL) { + config_destroy(&cfg); + return 0; + } + + // Check that all settings are present + if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) { + syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); + goto next; + } + + if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) { + syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); + goto next; + } + + if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) { + syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); + goto next; + } + + // Process settings + if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) { + syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, + bs_public_key); + goto next; + } + + if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, + bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + goto next; + } + + uint8_t *bs_public_key_bin = hex_string_to_bin((char *)bs_public_key); + const int address_resolved = DHT_bootstrap_from_address(dht, bs_address, enable_ipv6, htons(bs_port), + bs_public_key_bin); + free(bs_public_key_bin); + + if (!address_resolved) { + syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); + goto next; + } + + syslog(LOG_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); + +next: + // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly + // though it's freed when the element is removed, so we free it right away in order to keep memory + // consumption minimal + config_setting_remove_elem(node_list, 0); + i++; + } + + config_destroy(&cfg); + + return 1; +} + +// Prints public key + +void print_public_key(const uint8_t *public_key) +{ + char buffer[2 * crypto_box_PUBLICKEYBYTES + 1]; + int index = 0; + + size_t i; + + for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { + index += sprintf(buffer + index, "%02hhX", public_key[i]); + } + + syslog(LOG_INFO, "Public Key: %s\n", buffer); + + return; +} + +int main(int argc, char *argv[]) +{ + openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); + + syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); + + if (argc < 2) { + syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); + return 1; + } + + const char *cfg_file_path = argv[1]; + char *pid_file_path, *keys_file_path; + int port; + int enable_ipv6; + int enable_ipv4_fallback; + int enable_lan_discovery; + int enable_tcp_relay; + uint16_t *tcp_relay_ports; + int tcp_relay_port_count; + int enable_motd; + char *motd; + + if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_ipv4_fallback, + &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { + syslog(LOG_INFO, "General config read successfully\n"); + } else { + syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); + return 1; + } + + if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) { + syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + return 1; + } + + // Check if the PID file exists + FILE *pid_file; + + if ((pid_file = fopen(pid_file_path, "r"))) { + syslog(LOG_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); + fclose(pid_file); + } + + IP ip; + ip_init(&ip, enable_ipv6); + + Networking_Core *net = new_networking(ip, port); + + if (net == NULL) { + if (enable_ipv6 && enable_ipv4_fallback) { + syslog(LOG_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); + enable_ipv6 = 0; + ip_init(&ip, enable_ipv6); + net = new_networking(ip, port); + + if (net == NULL) { + syslog(LOG_ERR, "Couldn't fallback to IPv4. Exiting.\n"); + return 1; + } + } else { + syslog(LOG_ERR, "Couldn't initialize networking. Exiting.\n"); + return 1; + } + } + + + DHT *dht = new_DHT(net); + + if (dht == NULL) { + syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); + return 1; + } + + Onion *onion = new_onion(dht); + Onion_Announce *onion_a = new_onion_announce(dht); + + if (!(onion && onion_a)) { + syslog(LOG_ERR, "Couldn't initialize Tox Onion. Exiting.\n"); + return 1; + } + + if (enable_motd) { + if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) { + syslog(LOG_INFO, "Set MOTD successfully.\n"); + } else { + syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); + return 1; + } + + free(motd); + } + + if (manage_keys(dht, keys_file_path)) { + syslog(LOG_INFO, "Keys are managed successfully.\n"); + } else { + syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); + return 1; + } + + TCP_Server *tcp_server = NULL; + + if (enable_tcp_relay) { + if (tcp_relay_port_count == 0) { + syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n"); + return 1; + } + + tcp_server = new_TCP_server(enable_ipv6, tcp_relay_port_count, tcp_relay_ports, dht->self_secret_key, onion); + + // tcp_relay_port_count != 0 at this point + free(tcp_relay_ports); + + if (tcp_server != NULL) { + syslog(LOG_INFO, "Initialized Tox TCP server successfully.\n"); + } else { + syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); + return 1; + } + } + + if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { + syslog(LOG_INFO, "List of bootstrap nodes read successfully.\n"); + } else { + syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); + return 1; + } + + print_public_key(dht->self_public_key); + + // Write the PID file + FILE *pidf = fopen(pid_file_path, "a+"); + + if (pidf == NULL) { + syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); + return 1; + } + + free(pid_file_path); + free(keys_file_path); + + // Fork off from the parent process + const pid_t pid = fork(); + + if (pid > 0) { + fprintf(pidf, "%d", pid); + fclose(pidf); + syslog(LOG_INFO, "Forked successfully: PID: %d.\n", pid); + return 0; + } else { + fclose(pidf); + } + + if (pid < 0) { + syslog(LOG_ERR, "Forking failed. Exiting.\n"); + return 1; + } + + // Change the file mode mask + umask(0); + + // Create a new SID for the child process + if (setsid() < 0) { + syslog(LOG_ERR, "SID creation failure. Exiting.\n"); + return 1; + } + + // Change the current working directory + if ((chdir("/")) < 0) { + syslog(LOG_ERR, "Couldn't change working directory to '/'. Exiting.\n"); + return 1; + } + + // Go quiet + close(STDOUT_FILENO); + close(STDIN_FILENO); + close(STDERR_FILENO); + + uint64_t last_LANdiscovery = 0; + const uint16_t htons_port = htons(port); + + int waiting_for_dht_connection = 1; + + if (enable_lan_discovery) { + LANdiscovery_init(dht); + syslog(LOG_INFO, "Initialized LAN discovery.\n"); + } + + while (1) { + do_DHT(dht); + + if (enable_lan_discovery && is_timeout(last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) { + send_LANdiscovery(htons_port, dht); + last_LANdiscovery = unix_time(); + } + + if (enable_tcp_relay) { + do_TCP_server(tcp_server); + } + + networking_poll(dht->net); + + if (waiting_for_dht_connection && DHT_isconnected(dht)) { + syslog(LOG_INFO, "Connected to other bootstrap node successfully.\n"); + waiting_for_dht_connection = 0; + } + + sleep; + } + + return 1; +} diff --git a/other/bootstrap_daemon/tox-bootstrapd.c b/other/bootstrap_daemon/tox-bootstrapd.c deleted file mode 100644 index 71b1386d..00000000 --- a/other/bootstrap_daemon/tox-bootstrapd.c +++ /dev/null @@ -1,730 +0,0 @@ -/* tox-bootstrapd.c - * - * Tox DHT bootstrap daemon. - * - * Copyright (C) 2014 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -// system provided -#include -#include -#include -#include -#include - -// C -#include -#include -#include - -// 3rd party -#include - -// ./configure -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// toxcore -#include "../../toxcore/LAN_discovery.h" -#include "../../toxcore/onion_announce.h" -#include "../../toxcore/TCP_server.h" -#include "../../toxcore/util.h" - -// misc -#include "../bootstrap_node_packets.c" -#include "../../testing/misc_tools.c" - - -#define DAEMON_NAME "tox-bootstrapd" -#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day - -#define SLEEP_TIME_MILLISECONDS 30 -#define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) - -#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid" -#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys" -#define DEFAULT_PORT 33445 -#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false -#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly -#define DEFAULT_TCP_RELAY_PORTS_COUNT 3 -#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false -#define DEFAULT_MOTD DAEMON_NAME - -#define MIN_ALLOWED_PORT 1 -#define MAX_ALLOWED_PORT 65535 - - -// Uses the already existing key or creates one if it didn't exist -// -// retirns 1 on success -// 0 on failure - no keys were read or stored - -int manage_keys(DHT *dht, char *keys_file_path) -{ - const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; - uint8_t keys[KEYS_SIZE]; - FILE *keys_file; - - // Check if file exits, proceed to open and load keys - keys_file = fopen(keys_file_path, "r"); - - if (keys_file != NULL) { - const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); - - if (read_size != KEYS_SIZE) { - fclose(keys_file); - return 0; - } - - memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); - memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); - } else { - // Otherwise save new keys - memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); - - keys_file = fopen(keys_file_path, "w"); - - if (!keys_file) - return 0; - - const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); - - if (write_size != KEYS_SIZE) { - fclose(keys_file); - return 0; - } - } - - fclose(keys_file); - - return 1; -} - -// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array -// -// Supposed to be called from get_general_config only -// -// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` - -void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) -{ - const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; - - *tcp_relay_port_count = 0; - - config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); - - if (ports_array == NULL) { - syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); - syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); - - uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; - - int i; - - for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - syslog(LOG_INFO, "Port #%d: %u\n", i, default_ports[i]); - } - - // similar procedure to the one of reading config file below - *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); - - for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - - (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; - - if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT - || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, - (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - continue; - } - - (*tcp_relay_port_count) ++; - } - - // the loop above skips invalid ports, so we adjust the allocated memory size - if ((*tcp_relay_port_count) > 0) { - *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); - } else { - free(*tcp_relay_ports); - *tcp_relay_ports = NULL; - } - - return; - } - - if (config_setting_is_array(ports_array) == CONFIG_FALSE) { - syslog(LOG_ERR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", - NAME_TCP_RELAY_PORTS); - return; - } - - int config_port_count = config_setting_length(ports_array); - - if (config_port_count == 0) { - syslog(LOG_ERR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); - return; - } - - *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); - - int i; - - for (i = 0; i < config_port_count; i ++) { - config_setting_t *elem = config_setting_get_elem(ports_array, i); - - if (elem == NULL) { - // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be - syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); - break; - } - - if (config_setting_is_number(elem) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i); - continue; - } - - (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); - - if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT - || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, - (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - continue; - } - - (*tcp_relay_port_count) ++; - } - - // the loop above skips invalid ports, so we adjust the allocated memory size - if ((*tcp_relay_port_count) > 0) { - *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); - } else { - free(*tcp_relay_ports); - *tcp_relay_ports = NULL; - } -} - -// Gets general config options -// -// Important: you are responsible for freeing `pid_file_path` and `keys_file_path` -// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` -// and also `motd` iff `enable_motd` is set -// -// returns 1 on success -// 0 on failure, doesn't modify any data pointed by arguments - -int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, - int *enable_ipv6, - int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, - int *tcp_relay_port_count, int *enable_motd, char **motd) -{ - config_t cfg; - - const char *NAME_PORT = "port"; - const char *NAME_PID_FILE_PATH = "pid_file_path"; - const char *NAME_KEYS_FILE_PATH = "keys_file_path"; - const char *NAME_ENABLE_IPV6 = "enable_ipv6"; - const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback"; - const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; - const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; - const char *NAME_ENABLE_MOTD = "enable_motd"; - const char *NAME_MOTD = "motd"; - - config_init(&cfg); - - // Read the file. If there is an error, report it and exit. - if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return 0; - } - - // Get port - if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); - syslog(LOG_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); - *port = DEFAULT_PORT; - } - - // Get PID file location - const char *tmp_pid_file; - - if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); - tmp_pid_file = DEFAULT_PID_FILE_PATH; - } - - *pid_file_path = malloc(strlen(tmp_pid_file) + 1); - strcpy(*pid_file_path, tmp_pid_file); - - // Get keys file location - const char *tmp_keys_file; - - if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); - tmp_keys_file = DEFAULT_KEYS_FILE_PATH; - } - - *keys_file_path = malloc(strlen(tmp_keys_file) + 1); - strcpy(*keys_file_path, tmp_keys_file); - - // Get IPv6 option - if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); - *enable_ipv6 = DEFAULT_ENABLE_IPV6; - } - - // Get IPv4 fallback option - if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, - DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false"); - *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK; - } - - // Get LAN discovery option - if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, - DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false"); - *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; - } - - // Get TCP relay option - if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, - DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); - *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; - } - - if (*enable_tcp_relay) { - parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); - } else { - *tcp_relay_port_count = 0; - } - - // Get MOTD option - if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, - DEFAULT_ENABLE_MOTD ? "true" : "false"); - *enable_motd = DEFAULT_ENABLE_MOTD; - } - - if (*enable_motd) { - // Get MOTD - const char *tmp_motd; - - if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); - tmp_motd = DEFAULT_MOTD; - } - - size_t tmp_motd_length = strlen(tmp_motd) + 1; - size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; - *motd = malloc(motd_length); - strncpy(*motd, tmp_motd, motd_length); - (*motd)[motd_length - 1] = '\0'; - } - - config_destroy(&cfg); - - syslog(LOG_INFO, "Successfully read:\n"); - syslog(LOG_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); - syslog(LOG_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); - syslog(LOG_INFO, "'%s': %d\n", NAME_PORT, *port); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); - - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); - - // show info about tcp ports only if tcp relay is enabled - if (*enable_tcp_relay) { - if (*tcp_relay_port_count == 0) { - syslog(LOG_ERR, "No TCP ports could be read.\n"); - } else { - syslog(LOG_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); - int i; - - for (i = 0; i < *tcp_relay_port_count; i ++) { - syslog(LOG_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); - } - } - } - - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); - - if (*enable_motd) { - syslog(LOG_INFO, "'%s': %s\n", NAME_MOTD, *motd); - } - - return 1; -} - -// Bootstraps nodes listed in the config file -// -// returns 1 on success, some or no bootstrap nodes were added -// 0 on failure, a error accured while parsing config file - -int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) -{ - const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; - - const char *NAME_PUBLIC_KEY = "public_key"; - const char *NAME_PORT = "port"; - const char *NAME_ADDRESS = "address"; - - config_t cfg; - - config_init(&cfg); - - if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return 0; - } - - config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); - - if (node_list == NULL) { - syslog(LOG_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); - config_destroy(&cfg); - return 1; - } - - if (config_setting_length(node_list) == 0) { - syslog(LOG_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); - config_destroy(&cfg); - return 1; - } - - int bs_port; - const char *bs_address; - const char *bs_public_key; - - config_setting_t *node; - - int i = 0; - - while (config_setting_length(node_list)) { - - node = config_setting_get_elem(node_list, 0); - - if (node == NULL) { - config_destroy(&cfg); - return 0; - } - - // Check that all settings are present - if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); - goto next; - } - - if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); - goto next; - } - - if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); - goto next; - } - - // Process settings - if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, - bs_public_key); - goto next; - } - - if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, - bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - goto next; - } - - uint8_t *bs_public_key_bin = hex_string_to_bin((char *)bs_public_key); - const int address_resolved = DHT_bootstrap_from_address(dht, bs_address, enable_ipv6, htons(bs_port), - bs_public_key_bin); - free(bs_public_key_bin); - - if (!address_resolved) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); - goto next; - } - - syslog(LOG_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); - -next: - // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly - // though it's freed when the element is removed, so we free it right away in order to keep memory - // consumption minimal - config_setting_remove_elem(node_list, 0); - i++; - } - - config_destroy(&cfg); - - return 1; -} - -// Prints public key - -void print_public_key(const uint8_t *public_key) -{ - char buffer[2 * crypto_box_PUBLICKEYBYTES + 1]; - int index = 0; - - size_t i; - - for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { - index += sprintf(buffer + index, "%02hhX", public_key[i]); - } - - syslog(LOG_INFO, "Public Key: %s\n", buffer); - - return; -} - -int main(int argc, char *argv[]) -{ - openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); - - syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); - - if (argc < 2) { - syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); - return 1; - } - - const char *cfg_file_path = argv[1]; - char *pid_file_path, *keys_file_path; - int port; - int enable_ipv6; - int enable_ipv4_fallback; - int enable_lan_discovery; - int enable_tcp_relay; - uint16_t *tcp_relay_ports; - int tcp_relay_port_count; - int enable_motd; - char *motd; - - if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_ipv4_fallback, - &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { - syslog(LOG_INFO, "General config read successfully\n"); - } else { - syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); - return 1; - } - - if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) { - syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - return 1; - } - - // Check if the PID file exists - FILE *pid_file; - - if ((pid_file = fopen(pid_file_path, "r"))) { - syslog(LOG_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); - fclose(pid_file); - } - - IP ip; - ip_init(&ip, enable_ipv6); - - Networking_Core *net = new_networking(ip, port); - - if (net == NULL) { - if (enable_ipv6 && enable_ipv4_fallback) { - syslog(LOG_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); - enable_ipv6 = 0; - ip_init(&ip, enable_ipv6); - net = new_networking(ip, port); - - if (net == NULL) { - syslog(LOG_ERR, "Couldn't fallback to IPv4. Exiting.\n"); - return 1; - } - } else { - syslog(LOG_ERR, "Couldn't initialize networking. Exiting.\n"); - return 1; - } - } - - - DHT *dht = new_DHT(net); - - if (dht == NULL) { - syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); - return 1; - } - - Onion *onion = new_onion(dht); - Onion_Announce *onion_a = new_onion_announce(dht); - - if (!(onion && onion_a)) { - syslog(LOG_ERR, "Couldn't initialize Tox Onion. Exiting.\n"); - return 1; - } - - if (enable_motd) { - if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) { - syslog(LOG_INFO, "Set MOTD successfully.\n"); - } else { - syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); - return 1; - } - - free(motd); - } - - if (manage_keys(dht, keys_file_path)) { - syslog(LOG_INFO, "Keys are managed successfully.\n"); - } else { - syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); - return 1; - } - - TCP_Server *tcp_server = NULL; - - if (enable_tcp_relay) { - if (tcp_relay_port_count == 0) { - syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n"); - return 1; - } - - tcp_server = new_TCP_server(enable_ipv6, tcp_relay_port_count, tcp_relay_ports, dht->self_secret_key, onion); - - // tcp_relay_port_count != 0 at this point - free(tcp_relay_ports); - - if (tcp_server != NULL) { - syslog(LOG_INFO, "Initialized Tox TCP server successfully.\n"); - } else { - syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); - return 1; - } - } - - if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { - syslog(LOG_INFO, "List of bootstrap nodes read successfully.\n"); - } else { - syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); - return 1; - } - - print_public_key(dht->self_public_key); - - // Write the PID file - FILE *pidf = fopen(pid_file_path, "a+"); - - if (pidf == NULL) { - syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); - return 1; - } - - free(pid_file_path); - free(keys_file_path); - - // Fork off from the parent process - const pid_t pid = fork(); - - if (pid > 0) { - fprintf(pidf, "%d", pid); - fclose(pidf); - syslog(LOG_INFO, "Forked successfully: PID: %d.\n", pid); - return 0; - } else { - fclose(pidf); - } - - if (pid < 0) { - syslog(LOG_ERR, "Forking failed. Exiting.\n"); - return 1; - } - - // Change the file mode mask - umask(0); - - // Create a new SID for the child process - if (setsid() < 0) { - syslog(LOG_ERR, "SID creation failure. Exiting.\n"); - return 1; - } - - // Change the current working directory - if ((chdir("/")) < 0) { - syslog(LOG_ERR, "Couldn't change working directory to '/'. Exiting.\n"); - return 1; - } - - // Go quiet - close(STDOUT_FILENO); - close(STDIN_FILENO); - close(STDERR_FILENO); - - uint64_t last_LANdiscovery = 0; - const uint16_t htons_port = htons(port); - - int waiting_for_dht_connection = 1; - - if (enable_lan_discovery) { - LANdiscovery_init(dht); - syslog(LOG_INFO, "Initialized LAN discovery.\n"); - } - - while (1) { - do_DHT(dht); - - if (enable_lan_discovery && is_timeout(last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) { - send_LANdiscovery(htons_port, dht); - last_LANdiscovery = unix_time(); - } - - if (enable_tcp_relay) { - do_TCP_server(tcp_server); - } - - networking_poll(dht->net); - - if (waiting_for_dht_connection && DHT_isconnected(dht)) { - syslog(LOG_INFO, "Connected to other bootstrap node successfully.\n"); - waiting_for_dht_connection = 0; - } - - sleep; - } - - return 1; -} -- cgit v1.2.3 From c50781a2b7d0ab56acb31b8f79df2e69f9f74b8b Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 01:24:31 -0500 Subject: Make logger a global object instead of an instance Passing Logger object into every function isn't fun. See for yourself: something as simple as a public key printing function turns from >void print_public_key(const uint8_t *public_key) to >void print_public_key(Logger *logger, const uint8_t *public_key) --- other/bootstrap_daemon/src/log.c | 115 ++++++++++++++++++++++++++++++++++++ other/bootstrap_daemon/src/log.h | 61 +++++++++++++++++++ other/bootstrap_daemon/src/logger.c | 112 ----------------------------------- other/bootstrap_daemon/src/logger.h | 63 -------------------- 4 files changed, 176 insertions(+), 175 deletions(-) create mode 100644 other/bootstrap_daemon/src/log.c create mode 100644 other/bootstrap_daemon/src/log.h delete mode 100644 other/bootstrap_daemon/src/logger.c delete mode 100644 other/bootstrap_daemon/src/logger.h diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c new file mode 100644 index 00000000..dff2dbad --- /dev/null +++ b/other/bootstrap_daemon/src/log.c @@ -0,0 +1,115 @@ +/* logger.c + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "log.h" + +#include "global.h" + +#include + +#include +#include + +LOGGER_BACKEND current_backend = -1; + +bool open_log(LOGGER_BACKEND backend) +{ + if (current_backend != -1) { + return false; + } + + if (backend == LOGGER_BACKEND_SYSLOG) { + openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); + } + + current_backend = backend; + + return true; +} + +bool close_log() +{ + if (current_backend == -1) { + return false; + } + + if (current_backend == LOGGER_BACKEND_SYSLOG) { + closelog(); + } + + current_backend = -1; + + return true; +} + +int level_syslog(LOG_LEVEL level) +{ + switch (level) { + case LOG_LEVEL_INFO: + return LOG_INFO; + case LOG_LEVEL_WARNING: + return LOG_WARNING; + case LOG_LEVEL_ERROR: + return LOG_ERR; + } +} + +void log_syslog(LOG_LEVEL level, const char *format, va_list args) +{ + vsyslog(level_syslog(level), format, args); +} + +FILE* level_stdout(LOG_LEVEL level) +{ + switch (level) { + case LOG_LEVEL_INFO: + return stdout; + case LOG_LEVEL_WARNING: // intentional fallthrough + case LOG_LEVEL_ERROR: + return stderr; + } +} + +void log_stdout(LOG_LEVEL level, const char *format, va_list args) +{ + vfprintf(level_stdout(level), format, args); +} + +bool log(LOG_LEVEL level, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (current_backend) { + case LOGGER_BACKEND_SYSLOG: + log_syslog(level, format, args); + break; + case LOGGER_BACKEND_STDOUT: + log_stdout(level, format, args); + break; + } + + va_end(args); + + return current_backend != -1; +} diff --git a/other/bootstrap_daemon/src/log.h b/other/bootstrap_daemon/src/log.h new file mode 100644 index 00000000..7e5dce99 --- /dev/null +++ b/other/bootstrap_daemon/src/log.h @@ -0,0 +1,61 @@ +/* log.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef LOG_H +#define LOG_H + +typedef enum LOGGER_BACKEND { + LOGGER_BACKEND_SYSLOG, + LOGGER_BACKEND_STDOUT +} LOGGER_BACKEND; + +typedef enum LOG_LEVEL { + LOG_LEVEL_INFO, + LOG_LEVEL_WARNING, + LOG_LEVEL_ERROR +} LOG_LEVEL; + +/** + * Initializes logger. + * @param backend Specifies which backend to use. + * @return true on success, flase if log is already opened. + */ +bool open_log(LOGGER_BACKEND backend); + +/** + * Releases all used resources by the logger. + * @return true on success, flase if log is already closed. + */ +bool close_log(); + +/** + * Logs a message. + * @param level Log level to use. + * @param format printf-like format string. + * @param ... Zero or more arguments, similar to printf function. + * @return true on success, flase if log is closed. + */ +bool log(LOG_LEVEL level, const char *format, ...); + + +#endif // LOG_H diff --git a/other/bootstrap_daemon/src/logger.c b/other/bootstrap_daemon/src/logger.c deleted file mode 100644 index 3cf18fd6..00000000 --- a/other/bootstrap_daemon/src/logger.c +++ /dev/null @@ -1,112 +0,0 @@ -/* logger.c - * - * Tox DHT bootstrap daemon. - * - * Copyright (C) 2015 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#include "logger.h" - -#include "global.h" - -#include - -#include -#include - -typedef struct Logger { - LOGGER_BACKEND backend; -} Logger; - -Logger* new_logger(LOGGER_BACKEND backend) -{ - if (backend == LOGGER_BACKEND_SYSLOG) { - openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); - } - - Logger* logger = malloc(sizeof(Logger)); - - if (logger == NULL) { - return NULL; - } - - logger->backend = backend; - - return logger; -} - -void kill_logger(Logger* logger) -{ - if (backend == LOGGER_BACKEND_SYSLOG) { - closelog(); - } - - free(logger); -} - -int level_syslog(LOG_LEVEL level) -{ - switch (level) { - case LOG_LEVEL_INFO: - return LOG_INFO; - case LOG_LEVEL_WARNING: - return LOG_WARNING; - case LOG_LEVEL_ERROR: - return LOG_ERR; - } -} - -void log_syslog(LOG_LEVEL level, const char *format, va_list args) -{ - vsyslog(level_syslog(level), format, args); -} - -FILE* level_stdout(LOG_LEVEL level) -{ - switch (level) { - case LOG_LEVEL_INFO: - return stdout; - case LOG_LEVEL_WARNING: // intentional fallthrough - case LOG_LEVEL_ERROR: - return stderr; - - } -} - -void log_stdout(LOG_LEVEL level, const char *format, va_list args) -{ - vfprintf(level_stdout(level), format, args); -} - -void log(Logger* logger, LOG_LEVEL level, const char *format, ...) -{ - va_list args; - va_start(args, format); - - switch (logger->backend) { - case LOGGER_BACKEND_SYSLOG: - log_syslog(level, format, args); - break; - case LOGGER_BACKEND_STDOUT: - log_stdout(level, format, args); - break; - } - - va_end(args); -} diff --git a/other/bootstrap_daemon/src/logger.h b/other/bootstrap_daemon/src/logger.h deleted file mode 100644 index 174d3445..00000000 --- a/other/bootstrap_daemon/src/logger.h +++ /dev/null @@ -1,63 +0,0 @@ -/* logger.h - * - * Tox DHT bootstrap daemon. - * - * Copyright (C) 2015 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifndef LOGGER_H -#define LOGGER_H - -typedef enum LOGGER_BACKEND { - LOGGER_BACKEND_SYSLOG, - LOGGER_BACKEND_STDOUT -} LOGGER_BACKEND; - -typedef enum LOG_LEVEL { - LOG_LEVEL_INFO, - LOG_LEVEL_WARNING, - LOG_LEVEL_ERROR -} LOG_LEVEL; - -typedef struct Logger Logger; - -/** - * Creates new logger. - * @param backend Specifies which backend the logger should use. - * @return Logger object on success, NULL on failure. - */ -Logger* new_logger(LOGGER_BACKEND backend); - -/** - * Destroys a logger object, releasing all used resources. - * @param logger Logger object to destroy. - */ -void kill_logger(Logger* logger); - -/** - * Logs a message. - * @param logger Logger object to use. - * @param level Log level to use. - * @param format printf-like format string. - * @param ... Zero or more arguments, similar to printf function. - */ -void log(Logger* logger, LOG_LEVEL level, const char *format, ...); - - -#endif // LOGGER_H -- cgit v1.2.3 From 8c812f534175d43d93e022af49f0441cfca0ea0d Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 02:44:44 -0500 Subject: Make daemon use the new log code "log" is a reserved name (log from math.h), so it got changed into write_log. --- other/bootstrap_daemon/Makefile.inc | 4 +- other/bootstrap_daemon/src/log.c | 2 +- other/bootstrap_daemon/src/log.h | 6 +- other/bootstrap_daemon/src/tox-bootstrapd.c | 164 ++++++++++++++-------------- 4 files changed, 90 insertions(+), 86 deletions(-) diff --git a/other/bootstrap_daemon/Makefile.inc b/other/bootstrap_daemon/Makefile.inc index f274aba0..eb94f0e7 100644 --- a/other/bootstrap_daemon/Makefile.inc +++ b/other/bootstrap_daemon/Makefile.inc @@ -3,7 +3,9 @@ if BUILD_DHT_BOOTSTRAP_DAEMON bin_PROGRAMS += tox-bootstrapd tox_bootstrapd_SOURCES = \ - ../other/bootstrap_daemon/tox-bootstrapd.c + ../other/bootstrap_daemon/src/tox-bootstrapd.c \ + ../other/bootstrap_daemon/src/log.c \ + ../other/bootstrap_daemon/src/log.h tox_bootstrapd_CFLAGS = \ -I$(top_srcdir)/other/bootstrap_daemon \ diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c index dff2dbad..b5f838fb 100644 --- a/other/bootstrap_daemon/src/log.c +++ b/other/bootstrap_daemon/src/log.c @@ -95,7 +95,7 @@ void log_stdout(LOG_LEVEL level, const char *format, va_list args) vfprintf(level_stdout(level), format, args); } -bool log(LOG_LEVEL level, const char *format, ...) +bool write_log(LOG_LEVEL level, const char *format, ...) { va_list args; va_start(args, format); diff --git a/other/bootstrap_daemon/src/log.h b/other/bootstrap_daemon/src/log.h index 7e5dce99..b97d3733 100644 --- a/other/bootstrap_daemon/src/log.h +++ b/other/bootstrap_daemon/src/log.h @@ -24,6 +24,8 @@ #ifndef LOG_H #define LOG_H +#include + typedef enum LOGGER_BACKEND { LOGGER_BACKEND_SYSLOG, LOGGER_BACKEND_STDOUT @@ -49,13 +51,13 @@ bool open_log(LOGGER_BACKEND backend); bool close_log(); /** - * Logs a message. + * Writes a message to the log. * @param level Log level to use. * @param format printf-like format string. * @param ... Zero or more arguments, similar to printf function. * @return true on success, flase if log is closed. */ -bool log(LOG_LEVEL level, const char *format, ...); +bool write_log(LOG_LEVEL level, const char *format, ...); #endif // LOG_H diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 71b1386d..9a4ccf9f 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -51,9 +51,9 @@ #include "../bootstrap_node_packets.c" #include "../../testing/misc_tools.c" +#include "global.h" +#include "log.h" -#define DAEMON_NAME "tox-bootstrapd" -#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day #define SLEEP_TIME_MILLISECONDS 30 #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) @@ -136,15 +136,15 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); if (ports_array == NULL) { - syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); - syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); + write_log(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; int i; for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - syslog(LOG_INFO, "Port #%d: %u\n", i, default_ports[i]); + write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, default_ports[i]); } // similar procedure to the one of reading config file below @@ -156,7 +156,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); continue; } @@ -176,7 +176,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } if (config_setting_is_array(ports_array) == CONFIG_FALSE) { - syslog(LOG_ERR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", + write_log(LOG_LEVEL_ERROR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", NAME_TCP_RELAY_PORTS); return; } @@ -184,7 +184,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int int config_port_count = config_setting_length(ports_array); if (config_port_count == 0) { - syslog(LOG_ERR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); + write_log(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); return; } @@ -197,12 +197,12 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int if (elem == NULL) { // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be - syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); + write_log(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); break; } if (config_setting_is_number(elem) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i); + write_log(LOG_LEVEL_WARNING, "Port #%d: Not a number. Skipping.\n", i); continue; } @@ -210,7 +210,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); continue; } @@ -257,15 +257,15 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k // Read the file. If there is an error, report it and exit. if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); return 0; } // Get port if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); - syslog(LOG_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); *port = DEFAULT_PORT; } @@ -273,8 +273,8 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k const char *tmp_pid_file; if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); tmp_pid_file = DEFAULT_PID_FILE_PATH; } @@ -285,8 +285,8 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k const char *tmp_keys_file; if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); tmp_keys_file = DEFAULT_KEYS_FILE_PATH; } @@ -295,31 +295,31 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k // Get IPv6 option if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); *enable_ipv6 = DEFAULT_ENABLE_IPV6; } // Get IPv4 fallback option if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false"); *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK; } // Get LAN discovery option if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false"); *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; } // Get TCP relay option if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; } @@ -332,8 +332,8 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k // Get MOTD option if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, DEFAULT_ENABLE_MOTD ? "true" : "false"); *enable_motd = DEFAULT_ENABLE_MOTD; } @@ -343,8 +343,8 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k const char *tmp_motd; if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { - syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); - syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); tmp_motd = DEFAULT_MOTD; } @@ -357,34 +357,34 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k config_destroy(&cfg); - syslog(LOG_INFO, "Successfully read:\n"); - syslog(LOG_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); - syslog(LOG_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); - syslog(LOG_INFO, "'%s': %d\n", NAME_PORT, *port); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "Successfully read:\n"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); + write_log(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); // show info about tcp ports only if tcp relay is enabled if (*enable_tcp_relay) { if (*tcp_relay_port_count == 0) { - syslog(LOG_ERR, "No TCP ports could be read.\n"); + write_log(LOG_LEVEL_ERROR, "No TCP ports could be read.\n"); } else { - syslog(LOG_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); + write_log(LOG_LEVEL_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); int i; for (i = 0; i < *tcp_relay_port_count; i ++) { - syslog(LOG_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); + write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); } } } - syslog(LOG_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); if (*enable_motd) { - syslog(LOG_INFO, "'%s': %s\n", NAME_MOTD, *motd); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd); } return 1; @@ -408,7 +408,7 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) config_init(&cfg); if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - syslog(LOG_ERR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); return 0; } @@ -416,13 +416,13 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); if (node_list == NULL) { - syslog(LOG_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); + write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); config_destroy(&cfg); return 1; } if (config_setting_length(node_list) == 0) { - syslog(LOG_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); + write_log(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); config_destroy(&cfg); return 1; } @@ -446,29 +446,29 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) // Check that all settings are present if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); goto next; } if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); goto next; } if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) { - syslog(LOG_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); goto next; } // Process settings if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, bs_public_key); goto next; } if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); goto next; } @@ -479,11 +479,11 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) free(bs_public_key_bin); if (!address_resolved) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); goto next; } - syslog(LOG_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); + write_log(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); next: // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly @@ -511,19 +511,19 @@ void print_public_key(const uint8_t *public_key) index += sprintf(buffer + index, "%02hhX", public_key[i]); } - syslog(LOG_INFO, "Public Key: %s\n", buffer); + write_log(LOG_LEVEL_INFO, "Public Key: %s\n", buffer); return; } int main(int argc, char *argv[]) { - openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); + open_log(LOGGER_BACKEND_SYSLOG); - syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); + write_log(LOG_LEVEL_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); if (argc < 2) { - syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); return 1; } @@ -541,14 +541,14 @@ int main(int argc, char *argv[]) if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_ipv4_fallback, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { - syslog(LOG_INFO, "General config read successfully\n"); + write_log(LOG_LEVEL_INFO, "General config read successfully\n"); } else { - syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); + write_log(LOG_LEVEL_ERROR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); return 1; } if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) { - syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + write_log(LOG_LEVEL_ERROR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); return 1; } @@ -556,7 +556,7 @@ int main(int argc, char *argv[]) FILE *pid_file; if ((pid_file = fopen(pid_file_path, "r"))) { - syslog(LOG_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); + write_log(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); fclose(pid_file); } @@ -567,17 +567,17 @@ int main(int argc, char *argv[]) if (net == NULL) { if (enable_ipv6 && enable_ipv4_fallback) { - syslog(LOG_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); + write_log(LOG_LEVEL_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); enable_ipv6 = 0; ip_init(&ip, enable_ipv6); net = new_networking(ip, port); if (net == NULL) { - syslog(LOG_ERR, "Couldn't fallback to IPv4. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't fallback to IPv4. Exiting.\n"); return 1; } } else { - syslog(LOG_ERR, "Couldn't initialize networking. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't initialize networking. Exiting.\n"); return 1; } } @@ -586,7 +586,7 @@ int main(int argc, char *argv[]) DHT *dht = new_DHT(net); if (dht == NULL) { - syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n"); return 1; } @@ -594,15 +594,15 @@ int main(int argc, char *argv[]) Onion_Announce *onion_a = new_onion_announce(dht); if (!(onion && onion_a)) { - syslog(LOG_ERR, "Couldn't initialize Tox Onion. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n"); return 1; } if (enable_motd) { if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) { - syslog(LOG_INFO, "Set MOTD successfully.\n"); + write_log(LOG_LEVEL_INFO, "Set MOTD successfully.\n"); } else { - syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); + write_log(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd); return 1; } @@ -610,9 +610,9 @@ int main(int argc, char *argv[]) } if (manage_keys(dht, keys_file_path)) { - syslog(LOG_INFO, "Keys are managed successfully.\n"); + write_log(LOG_LEVEL_INFO, "Keys are managed successfully.\n"); } else { - syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); + write_log(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); return 1; } @@ -620,7 +620,7 @@ int main(int argc, char *argv[]) if (enable_tcp_relay) { if (tcp_relay_port_count == 0) { - syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n"); return 1; } @@ -630,17 +630,17 @@ int main(int argc, char *argv[]) free(tcp_relay_ports); if (tcp_server != NULL) { - syslog(LOG_INFO, "Initialized Tox TCP server successfully.\n"); + write_log(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n"); } else { - syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n"); return 1; } } if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { - syslog(LOG_INFO, "List of bootstrap nodes read successfully.\n"); + write_log(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n"); } else { - syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); + write_log(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); return 1; } @@ -650,7 +650,7 @@ int main(int argc, char *argv[]) FILE *pidf = fopen(pid_file_path, "a+"); if (pidf == NULL) { - syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); + write_log(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); return 1; } @@ -663,14 +663,14 @@ int main(int argc, char *argv[]) if (pid > 0) { fprintf(pidf, "%d", pid); fclose(pidf); - syslog(LOG_INFO, "Forked successfully: PID: %d.\n", pid); + write_log(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); return 0; } else { fclose(pidf); } if (pid < 0) { - syslog(LOG_ERR, "Forking failed. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); return 1; } @@ -679,13 +679,13 @@ int main(int argc, char *argv[]) // Create a new SID for the child process if (setsid() < 0) { - syslog(LOG_ERR, "SID creation failure. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); return 1; } // Change the current working directory if ((chdir("/")) < 0) { - syslog(LOG_ERR, "Couldn't change working directory to '/'. Exiting.\n"); + write_log(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); return 1; } @@ -701,7 +701,7 @@ int main(int argc, char *argv[]) if (enable_lan_discovery) { LANdiscovery_init(dht); - syslog(LOG_INFO, "Initialized LAN discovery.\n"); + write_log(LOG_LEVEL_INFO, "Initialized LAN discovery.\n"); } while (1) { @@ -719,7 +719,7 @@ int main(int argc, char *argv[]) networking_poll(dht->net); if (waiting_for_dht_connection && DHT_isconnected(dht)) { - syslog(LOG_INFO, "Connected to other bootstrap node successfully.\n"); + write_log(LOG_LEVEL_INFO, "Connected to other bootstrap node successfully.\n"); waiting_for_dht_connection = 0; } -- cgit v1.2.3 From a40fd1bb6c4769683c11b3e308279c17a0acbc5a Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 18:48:44 -0500 Subject: Add ability to specify multiple command line arguments Needed in order to specify which log backend to use. Init scripts need to be updated to contain --config before the path to the config file. --- other/bootstrap_daemon/src/tox-bootstrapd.c | 128 ++++++++++++++++++++++++-- other/bootstrap_daemon/tox-bootstrapd.service | 2 +- other/bootstrap_daemon/tox-bootstrapd.sh | 2 +- 3 files changed, 121 insertions(+), 11 deletions(-) diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 9a4ccf9f..e2bf7ade 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -23,6 +23,7 @@ // system provided #include +#include #include #include #include @@ -516,18 +517,125 @@ void print_public_key(const uint8_t *public_key) return; } -int main(int argc, char *argv[]) +// Prints --help message + +bool print_help() { - open_log(LOGGER_BACKEND_SYSLOG); + // 2 space ident + // make sure all lines fit into 80 columns + write_log(LOG_LEVEL_INFO, + "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" + "\n" + "Options:\n" + " --config=FILE_PATH Specify path to the config file.\n" + " This is a required option.\n" + " Set FILE_PATH to a path to an empty file in order to\n" + " use default settings.\n" + " --help Print this help message.\n" + " --log-backend=BACKEND Specify which logging backend to use.\n" + " Valid BACKEND values (case sensetive):\n" + " syslog Writes log messages to syslog.\n" + " Default option when no --log-backend is\n" + " specified.\n" + " stdout Writes log messages to stdout/stderr.\n" + " --version Print version information.\n"); +} - write_log(LOG_LEVEL_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); +// Handels command line arguments, setting cfg_file_path and log_backend. +// Terminates the application if incorrect arguments are specified. +void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOGGER_BACKEND *log_backend) +{ if (argc < 2) { - write_log(LOG_LEVEL_ERROR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); - return 1; + write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); + print_help(); + exit(1); + } + + opterr = 0; + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"config", required_argument, 0, 'c'}, // required option + {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog + {"version", no_argument, 0, 'v'}, + {0, 0, 0, 0 } + }; + + bool cfg_file_path_set = false; + bool log_backend_set = false; + + int opt; + + while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { + + switch (opt) { + case 'h': + print_help(); + exit(0); + + case 'c': + *cfg_file_path = optarg; + cfg_file_path_set = true; + break; + + case 'l': + if (strcmp(optarg, "syslog") == 0) { + *log_backend = LOGGER_BACKEND_SYSLOG; + log_backend_set = true; + } else if (strcmp(optarg, "stdout") == 0) { + *log_backend = LOGGER_BACKEND_STDOUT; + log_backend_set = true; + } else { + write_log(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg); + print_help(); + exit(1); + } + break; + + case 'v': + write_log(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER); + exit(0); + + case '?': + write_log(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind-1]); + print_help(); + exit(1); + + case ':': + write_log(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind-1]); + print_help(); + exit(1); + } + } + + if (!log_backend_set) { + *log_backend = LOGGER_BACKEND_SYSLOG; } - const char *cfg_file_path = argv[1]; + if (!cfg_file_path_set) { + write_log(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n"); + print_help(); + exit(1); + } +} + +int main(int argc, char *argv[]) +{ + char *cfg_file_path; + LOGGER_BACKEND log_backend; + + // choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal + log_backend = isatty(STDOUT_FILENO) ? LOGGER_BACKEND_STDOUT : LOGGER_BACKEND_SYSLOG; + + open_log(log_backend); + handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend); + close_log(); + + open_log(log_backend); + + write_log(LOG_LEVEL_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); + char *pid_file_path, *keys_file_path; int port; int enable_ipv6; @@ -690,9 +798,11 @@ int main(int argc, char *argv[]) } // Go quiet - close(STDOUT_FILENO); - close(STDIN_FILENO); - close(STDERR_FILENO); + if (log_backend != LOGGER_BACKEND_STDOUT) { + close(STDOUT_FILENO); + close(STDIN_FILENO); + close(STDERR_FILENO); + } uint64_t last_LANdiscovery = 0; const uint16_t htons_port = htons(port); diff --git a/other/bootstrap_daemon/tox-bootstrapd.service b/other/bootstrap_daemon/tox-bootstrapd.service index db54cc41..20f698d2 100644 --- a/other/bootstrap_daemon/tox-bootstrapd.service +++ b/other/bootstrap_daemon/tox-bootstrapd.service @@ -8,7 +8,7 @@ RuntimeDirectory=tox-bootstrapd RuntimeDirectoryMode=750 PIDFile=/var/run/tox-bootstrapd/tox-bootstrapd.pid WorkingDirectory=/var/lib/tox-bootstrapd -ExecStart=/usr/local/bin/tox-bootstrapd /etc/tox-bootstrapd.conf +ExecStart=/usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf User=tox-bootstrapd Group=tox-bootstrapd #CapabilityBoundingSet=CAP_NET_BIND_SERVICE diff --git a/other/bootstrap_daemon/tox-bootstrapd.sh b/other/bootstrap_daemon/tox-bootstrapd.sh index 1431bde0..d33c38da 100644 --- a/other/bootstrap_daemon/tox-bootstrapd.sh +++ b/other/bootstrap_daemon/tox-bootstrapd.sh @@ -15,7 +15,7 @@ DESC="Tox DHT bootstrap daemon" NAME=tox-bootstrapd DAEMON=/usr/local/bin/$NAME CFGFILE=/etc/$NAME.conf -DAEMON_ARGS="$CFGFILE" +DAEMON_ARGS="--config $CFGFILE" PIDDIR=/var/run/$NAME PIDFILE=$PIDDIR/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME -- cgit v1.2.3 From ffa927fa361c366d8d1d2fefdeb58d0977ab91ae Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 20:01:24 -0500 Subject: Rename LOGGER_BACKEND to LOG_BACKEND --- other/bootstrap_daemon/src/log.c | 12 ++++++------ other/bootstrap_daemon/src/log.h | 10 +++++----- other/bootstrap_daemon/src/tox-bootstrapd.c | 14 +++++++------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c index b5f838fb..f41b8420 100644 --- a/other/bootstrap_daemon/src/log.c +++ b/other/bootstrap_daemon/src/log.c @@ -30,15 +30,15 @@ #include #include -LOGGER_BACKEND current_backend = -1; +LOG_BACKEND current_backend = -1; -bool open_log(LOGGER_BACKEND backend) +bool open_log(LOG_BACKEND backend) { if (current_backend != -1) { return false; } - if (backend == LOGGER_BACKEND_SYSLOG) { + if (backend == LOG_BACKEND_SYSLOG) { openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); } @@ -53,7 +53,7 @@ bool close_log() return false; } - if (current_backend == LOGGER_BACKEND_SYSLOG) { + if (current_backend == LOG_BACKEND_SYSLOG) { closelog(); } @@ -101,10 +101,10 @@ bool write_log(LOG_LEVEL level, const char *format, ...) va_start(args, format); switch (current_backend) { - case LOGGER_BACKEND_SYSLOG: + case LOG_BACKEND_SYSLOG: log_syslog(level, format, args); break; - case LOGGER_BACKEND_STDOUT: + case LOG_BACKEND_STDOUT: log_stdout(level, format, args); break; } diff --git a/other/bootstrap_daemon/src/log.h b/other/bootstrap_daemon/src/log.h index b97d3733..b7712368 100644 --- a/other/bootstrap_daemon/src/log.h +++ b/other/bootstrap_daemon/src/log.h @@ -26,10 +26,10 @@ #include -typedef enum LOGGER_BACKEND { - LOGGER_BACKEND_SYSLOG, - LOGGER_BACKEND_STDOUT -} LOGGER_BACKEND; +typedef enum LOG_BACKEND { + LOG_BACKEND_SYSLOG, + LOG_BACKEND_STDOUT +} LOG_BACKEND; typedef enum LOG_LEVEL { LOG_LEVEL_INFO, @@ -42,7 +42,7 @@ typedef enum LOG_LEVEL { * @param backend Specifies which backend to use. * @return true on success, flase if log is already opened. */ -bool open_log(LOGGER_BACKEND backend); +bool open_log(LOG_BACKEND backend); /** * Releases all used resources by the logger. diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index e2bf7ade..3bbddf98 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -544,7 +544,7 @@ bool print_help() // Handels command line arguments, setting cfg_file_path and log_backend. // Terminates the application if incorrect arguments are specified. -void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOGGER_BACKEND *log_backend) +void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend) { if (argc < 2) { write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); @@ -581,10 +581,10 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, case 'l': if (strcmp(optarg, "syslog") == 0) { - *log_backend = LOGGER_BACKEND_SYSLOG; + *log_backend = LOG_BACKEND_SYSLOG; log_backend_set = true; } else if (strcmp(optarg, "stdout") == 0) { - *log_backend = LOGGER_BACKEND_STDOUT; + *log_backend = LOG_BACKEND_STDOUT; log_backend_set = true; } else { write_log(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg); @@ -610,7 +610,7 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, } if (!log_backend_set) { - *log_backend = LOGGER_BACKEND_SYSLOG; + *log_backend = LOG_BACKEND_SYSLOG; } if (!cfg_file_path_set) { @@ -623,10 +623,10 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, int main(int argc, char *argv[]) { char *cfg_file_path; - LOGGER_BACKEND log_backend; + LOG_BACKEND log_backend; // choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal - log_backend = isatty(STDOUT_FILENO) ? LOGGER_BACKEND_STDOUT : LOGGER_BACKEND_SYSLOG; + log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; open_log(log_backend); handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend); @@ -798,7 +798,7 @@ int main(int argc, char *argv[]) } // Go quiet - if (log_backend != LOGGER_BACKEND_STDOUT) { + if (log_backend != LOG_BACKEND_STDOUT) { close(STDOUT_FILENO); close(STDIN_FILENO); close(STDERR_FILENO); -- cgit v1.2.3 From 2ef1ce9421bbddb8a2ad89f81ca85ca6500fe3fc Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 20:06:37 -0500 Subject: Fix wrong filename mentioned above license --- other/bootstrap_daemon/src/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c index f41b8420..ec68050e 100644 --- a/other/bootstrap_daemon/src/log.c +++ b/other/bootstrap_daemon/src/log.c @@ -1,4 +1,4 @@ -/* logger.c +/* log.c * * Tox DHT bootstrap daemon. * -- cgit v1.2.3 From e1fc8c1d3cca7e915a73cfe44462f71d2938ecba Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Thu, 31 Dec 2015 23:18:39 -0500 Subject: Add ability to run the daemon in foreground Useful for things like a Docker container or just running it in the terminal. Complements the stdout logging option. This is actually why the stdout logging was added in the first place -- to be used in the foreground mode, though nothing stops one from using stdout in the background mode, which one could redirect to a file. --- other/bootstrap_daemon/src/tox-bootstrapd.c | 142 ++++++++++++++++------------ 1 file changed, 81 insertions(+), 61 deletions(-) diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 3bbddf98..a8098e41 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -523,6 +523,7 @@ bool print_help() { // 2 space ident // make sure all lines fit into 80 columns + // make sure options are listed in alphabetical order write_log(LOG_LEVEL_INFO, "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" "\n" @@ -531,6 +532,8 @@ bool print_help() " This is a required option.\n" " Set FILE_PATH to a path to an empty file in order to\n" " use default settings.\n" + " --foreground Run the daemon in foreground. The daemon won't fork\n" + " (detach from the terminal) and won't use the PID file.\n" " --help Print this help message.\n" " --log-backend=BACKEND Specify which logging backend to use.\n" " Valid BACKEND values (case sensetive):\n" @@ -544,7 +547,7 @@ bool print_help() // Handels command line arguments, setting cfg_file_path and log_backend. // Terminates the application if incorrect arguments are specified. -void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend) +void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground) { if (argc < 2) { write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); @@ -557,6 +560,7 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"config", required_argument, 0, 'c'}, // required option + {"foreground", no_argument, 0, 'f'}, {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog {"version", no_argument, 0, 'v'}, {0, 0, 0, 0 } @@ -565,6 +569,8 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, bool cfg_file_path_set = false; bool log_backend_set = false; + *run_in_foreground = false; + int opt; while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { @@ -579,6 +585,10 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, cfg_file_path_set = true; break; + case 'f': + *run_in_foreground = true; + break; + case 'l': if (strcmp(optarg, "syslog") == 0) { *log_backend = LOG_BACKEND_SYSLOG; @@ -620,16 +630,77 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, } } +// Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend +// Terminates the application if the daemonization fails. + +void daemonize(LOG_BACKEND log_backend, char *pid_file_path) +{ + // Check if the PID file exists + FILE *pid_file; + + if ((pid_file = fopen(pid_file_path, "r"))) { + write_log(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); + fclose(pid_file); + } + + // Open the PID file for writing + pid_file = fopen(pid_file_path, "a+"); + if (pid_file == NULL) { + write_log(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); + exit(1); + } + + // Fork off from the parent process + const pid_t pid = fork(); + + if (pid > 0) { + fprintf(pid_file, "%d", pid); + fclose(pid_file); + write_log(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); + exit(0); + } else { + fclose(pid_file); + } + + if (pid < 0) { + write_log(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); + exit(1); + } + + // Create a new SID for the child process + if (setsid() < 0) { + write_log(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); + exit(1); + } + + // Change the file mode mask + umask(0); + + // Change the current working directory + if ((chdir("/")) < 0) { + write_log(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); + exit(1); + } + + // Go quiet + if (log_backend != LOG_BACKEND_STDOUT) { + close(STDOUT_FILENO); + close(STDIN_FILENO); + close(STDERR_FILENO); + } +} + int main(int argc, char *argv[]) { char *cfg_file_path; LOG_BACKEND log_backend; + bool run_in_foreground; // choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; open_log(log_backend); - handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend); + handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground); close_log(); open_log(log_backend); @@ -660,14 +731,12 @@ int main(int argc, char *argv[]) return 1; } - // Check if the PID file exists - FILE *pid_file; - - if ((pid_file = fopen(pid_file_path, "r"))) { - write_log(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); - fclose(pid_file); + if (!run_in_foreground) { + daemonize(log_backend, pid_file_path); } + free(pid_file_path); + IP ip; ip_init(&ip, enable_ipv6); @@ -690,7 +759,6 @@ int main(int argc, char *argv[]) } } - DHT *dht = new_DHT(net); if (dht == NULL) { @@ -724,6 +792,8 @@ int main(int argc, char *argv[]) return 1; } + free(keys_file_path); + TCP_Server *tcp_server = NULL; if (enable_tcp_relay) { @@ -754,56 +824,6 @@ int main(int argc, char *argv[]) print_public_key(dht->self_public_key); - // Write the PID file - FILE *pidf = fopen(pid_file_path, "a+"); - - if (pidf == NULL) { - write_log(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); - return 1; - } - - free(pid_file_path); - free(keys_file_path); - - // Fork off from the parent process - const pid_t pid = fork(); - - if (pid > 0) { - fprintf(pidf, "%d", pid); - fclose(pidf); - write_log(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid); - return 0; - } else { - fclose(pidf); - } - - if (pid < 0) { - write_log(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n"); - return 1; - } - - // Change the file mode mask - umask(0); - - // Create a new SID for the child process - if (setsid() < 0) { - write_log(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n"); - return 1; - } - - // Change the current working directory - if ((chdir("/")) < 0) { - write_log(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); - return 1; - } - - // Go quiet - if (log_backend != LOG_BACKEND_STDOUT) { - close(STDOUT_FILENO); - close(STDIN_FILENO); - close(STDERR_FILENO); - } - uint64_t last_LANdiscovery = 0; const uint16_t htons_port = htons(port); @@ -811,7 +831,7 @@ int main(int argc, char *argv[]) if (enable_lan_discovery) { LANdiscovery_init(dht); - write_log(LOG_LEVEL_INFO, "Initialized LAN discovery.\n"); + write_log(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n"); } while (1) { @@ -829,7 +849,7 @@ int main(int argc, char *argv[]) networking_poll(dht->net); if (waiting_for_dht_connection && DHT_isconnected(dht)) { - write_log(LOG_LEVEL_INFO, "Connected to other bootstrap node successfully.\n"); + write_log(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n"); waiting_for_dht_connection = 0; } -- cgit v1.2.3 From 6b40a581b1ce036e744c51452bbd6be6c690508f Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 00:19:35 -0500 Subject: Put config-related functions in a separate file bootstrap_node_packets.c was giving an error as it was being included twice and there were no include guards, so part of it was split into bootstrap_node_packets.h. --- other/DHT_bootstrap.c | 2 +- other/Makefile.inc | 4 +- other/bootstrap_daemon/Makefile.inc | 7 +- other/bootstrap_daemon/src/config.c | 400 +++++++++++++++++++++++++++ other/bootstrap_daemon/src/config.h | 49 ++++ other/bootstrap_daemon/src/config_defaults.h | 41 +++ other/bootstrap_daemon/src/global.h | 3 + other/bootstrap_daemon/src/tox-bootstrapd.c | 399 +------------------------- other/bootstrap_node_packets.c | 2 +- other/bootstrap_node_packets.h | 35 +++ 10 files changed, 541 insertions(+), 401 deletions(-) create mode 100644 other/bootstrap_daemon/src/config.c create mode 100644 other/bootstrap_daemon/src/config.h create mode 100644 other/bootstrap_daemon/src/config_defaults.h create mode 100644 other/bootstrap_node_packets.h diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 52e84315..16dc87b9 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -40,7 +40,7 @@ #include "../testing/misc_tools.c" #ifdef DHT_NODE_EXTRA_PACKETS -#include "./bootstrap_node_packets.c" +#include "./bootstrap_node_packets.h" #define DHT_VERSION_NUMBER 1 #define DHT_MOTD "This is a test motd" diff --git a/other/Makefile.inc b/other/Makefile.inc index 368a32f2..c86b7922 100644 --- a/other/Makefile.inc +++ b/other/Makefile.inc @@ -2,7 +2,9 @@ bin_PROGRAMS += DHT_bootstrap DHT_bootstrap_SOURCES = ../other/DHT_bootstrap.c \ ../toxcore/DHT.h \ - ../toxcore/friend_requests.h + ../toxcore/friend_requests.h \ + ../other/bootstrap_node_packets.h \ + ../other/bootstrap_node_packets.c DHT_bootstrap_CFLAGS = -I$(top_srcdir)/other \ $(LIBSODIUM_CFLAGS) \ diff --git a/other/bootstrap_daemon/Makefile.inc b/other/bootstrap_daemon/Makefile.inc index eb94f0e7..5dce910e 100644 --- a/other/bootstrap_daemon/Makefile.inc +++ b/other/bootstrap_daemon/Makefile.inc @@ -5,7 +5,12 @@ bin_PROGRAMS += tox-bootstrapd tox_bootstrapd_SOURCES = \ ../other/bootstrap_daemon/src/tox-bootstrapd.c \ ../other/bootstrap_daemon/src/log.c \ - ../other/bootstrap_daemon/src/log.h + ../other/bootstrap_daemon/src/log.h \ + ../other/bootstrap_daemon/src/config.h \ + ../other/bootstrap_daemon/src/config.c \ + ../other/bootstrap_daemon/src/config_defaults.h \ + ../other/bootstrap_node_packets.h \ + ../other/bootstrap_node_packets.c tox_bootstrapd_CFLAGS = \ -I$(top_srcdir)/other/bootstrap_daemon \ diff --git a/other/bootstrap_daemon/src/config.c b/other/bootstrap_daemon/src/config.c new file mode 100644 index 00000000..270d399f --- /dev/null +++ b/other/bootstrap_daemon/src/config.c @@ -0,0 +1,400 @@ +/* config.c + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "config.h" + +#include "config_defaults.h" +#include "log.h" + +// C +//#include +#include + +// 3rd party +#include + +// toxcore +#include "../../bootstrap_node_packets.h" +//#include "../../testing/misc_tools.c" + +// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array +// +// Supposed to be called from get_general_config only +// +// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` + +void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) +{ + const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; + + *tcp_relay_port_count = 0; + + config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); + + if (ports_array == NULL) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); + write_log(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); + + uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; + + int i; + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, default_ports[i]); + } + + // similar procedure to the one of reading config file below + *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + + (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; + + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT + || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + if ((*tcp_relay_port_count) > 0) { + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); + } else { + free(*tcp_relay_ports); + *tcp_relay_ports = NULL; + } + + return; + } + + if (config_setting_is_array(ports_array) == CONFIG_FALSE) { + write_log(LOG_LEVEL_ERROR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", + NAME_TCP_RELAY_PORTS); + return; + } + + int config_port_count = config_setting_length(ports_array); + + if (config_port_count == 0) { + write_log(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); + return; + } + + *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); + + int i; + + for (i = 0; i < config_port_count; i ++) { + config_setting_t *elem = config_setting_get_elem(ports_array, i); + + if (elem == NULL) { + // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be + write_log(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); + break; + } + + if (config_setting_is_number(elem) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "Port #%d: Not a number. Skipping.\n", i); + continue; + } + + (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); + + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT + || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, + (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + if ((*tcp_relay_port_count) > 0) { + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); + } else { + free(*tcp_relay_ports); + *tcp_relay_ports = NULL; + } +} + +int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, + int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, + int *tcp_relay_port_count, int *enable_motd, char **motd) +{ + config_t cfg; + + const char *NAME_PORT = "port"; + const char *NAME_PID_FILE_PATH = "pid_file_path"; + const char *NAME_KEYS_FILE_PATH = "keys_file_path"; + const char *NAME_ENABLE_IPV6 = "enable_ipv6"; + const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback"; + const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; + const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; + const char *NAME_ENABLE_MOTD = "enable_motd"; + const char *NAME_MOTD = "motd"; + + config_init(&cfg); + + // Read the file. If there is an error, report it and exit. + if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { + write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return 0; + } + + // Get port + if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); + *port = DEFAULT_PORT; + } + + // Get PID file location + const char *tmp_pid_file; + + if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); + tmp_pid_file = DEFAULT_PID_FILE_PATH; + } + + *pid_file_path = malloc(strlen(tmp_pid_file) + 1); + strcpy(*pid_file_path, tmp_pid_file); + + // Get keys file location + const char *tmp_keys_file; + + if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); + tmp_keys_file = DEFAULT_KEYS_FILE_PATH; + } + + *keys_file_path = malloc(strlen(tmp_keys_file) + 1); + strcpy(*keys_file_path, tmp_keys_file); + + // Get IPv6 option + if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); + *enable_ipv6 = DEFAULT_ENABLE_IPV6; + } + + // Get IPv4 fallback option + if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, + DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false"); + *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK; + } + + // Get LAN discovery option + if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, + DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false"); + *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; + } + + // Get TCP relay option + if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, + DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); + *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; + } + + if (*enable_tcp_relay) { + parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); + } else { + *tcp_relay_port_count = 0; + } + + // Get MOTD option + if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, + DEFAULT_ENABLE_MOTD ? "true" : "false"); + *enable_motd = DEFAULT_ENABLE_MOTD; + } + + if (*enable_motd) { + // Get MOTD + const char *tmp_motd; + + if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); + write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); + tmp_motd = DEFAULT_MOTD; + } + + size_t tmp_motd_length = strlen(tmp_motd) + 1; + size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; + *motd = malloc(motd_length); + strncpy(*motd, tmp_motd, motd_length); + (*motd)[motd_length - 1] = '\0'; + } + + config_destroy(&cfg); + + write_log(LOG_LEVEL_INFO, "Successfully read:\n"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); + write_log(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); + + // show info about tcp ports only if tcp relay is enabled + if (*enable_tcp_relay) { + if (*tcp_relay_port_count == 0) { + write_log(LOG_LEVEL_ERROR, "No TCP ports could be read.\n"); + } else { + write_log(LOG_LEVEL_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); + int i; + + for (i = 0; i < *tcp_relay_port_count; i ++) { + write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); + } + } + } + + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); + + if (*enable_motd) { + write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd); + } + + return 1; +} + +int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) +{ + const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; + + const char *NAME_PUBLIC_KEY = "public_key"; + const char *NAME_PORT = "port"; + const char *NAME_ADDRESS = "address"; + + config_t cfg; + + config_init(&cfg); + + if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { + write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + return 0; + } + + config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); + + if (node_list == NULL) { + write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); + config_destroy(&cfg); + return 1; + } + + if (config_setting_length(node_list) == 0) { + write_log(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); + config_destroy(&cfg); + return 1; + } + + int bs_port; + const char *bs_address; + const char *bs_public_key; + + config_setting_t *node; + + int i = 0; + + while (config_setting_length(node_list)) { + + node = config_setting_get_elem(node_list, 0); + + if (node == NULL) { + config_destroy(&cfg); + return 0; + } + + // Check that all settings are present + if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); + goto next; + } + + if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); + goto next; + } + + if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); + goto next; + } + + // Process settings + if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, + bs_public_key); + goto next; + } + + if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, + bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + goto next; + } + + uint8_t *bs_public_key_bin = hex_string_to_bin((char *)bs_public_key); + const int address_resolved = DHT_bootstrap_from_address(dht, bs_address, enable_ipv6, htons(bs_port), + bs_public_key_bin); + free(bs_public_key_bin); + + if (!address_resolved) { + write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); + goto next; + } + + write_log(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); + +next: + // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly + // though it's freed when the element is removed, so we free it right away in order to keep memory + // consumption minimal + config_setting_remove_elem(node_list, 0); + i++; + } + + config_destroy(&cfg); + + return 1; +} diff --git a/other/bootstrap_daemon/src/config.h b/other/bootstrap_daemon/src/config.h new file mode 100644 index 00000000..73bc6e0b --- /dev/null +++ b/other/bootstrap_daemon/src/config.h @@ -0,0 +1,49 @@ +/* config.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "../../../toxcore/DHT.h" + +// Gets general config options +// +// Important: you are responsible for freeing `pid_file_path` and `keys_file_path` +// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` +// and also `motd` iff `enable_motd` is set +// +// returns 1 on success +// 0 on failure, doesn't modify any data pointed by arguments + +int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, + int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, + int *tcp_relay_port_count, int *enable_motd, char **motd); + +// Bootstraps nodes listed in the config file +// +// returns 1 on success, some or no bootstrap nodes were added +// 0 on failure, a error accured while parsing config file + +int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6); + +#endif // CONFIG_H diff --git a/other/bootstrap_daemon/src/config_defaults.h b/other/bootstrap_daemon/src/config_defaults.h new file mode 100644 index 00000000..34d715e7 --- /dev/null +++ b/other/bootstrap_daemon/src/config_defaults.h @@ -0,0 +1,41 @@ +/* config_defaults.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef CONFIG_DEFAULTS_H +#define CONFIG_DEFAULTS_H + +#include "global.h" + +#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid" +#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys" +#define DEFAULT_PORT 33445 +#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false +#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly +#define DEFAULT_TCP_RELAY_PORTS_COUNT 3 +#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false +#define DEFAULT_MOTD DAEMON_NAME + +#endif // CONFIG_DEFAULTS_H diff --git a/other/bootstrap_daemon/src/global.h b/other/bootstrap_daemon/src/global.h index 7aa42780..71f24635 100644 --- a/other/bootstrap_daemon/src/global.h +++ b/other/bootstrap_daemon/src/global.h @@ -27,4 +27,7 @@ #define DAEMON_NAME "tox-bootstrapd" #define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day +#define MIN_ALLOWED_PORT 1 +#define MAX_ALLOWED_PORT 65535 + #endif // GLOBAL_H diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index a8098e41..d4191e80 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -34,9 +34,6 @@ #include #include -// 3rd party -#include - // ./configure #ifdef HAVE_CONFIG_H #include "config.h" @@ -49,9 +46,10 @@ #include "../../toxcore/util.h" // misc -#include "../bootstrap_node_packets.c" +#include "../bootstrap_node_packets.h" #include "../../testing/misc_tools.c" +#include "config.h" #include "global.h" #include "log.h" @@ -59,22 +57,6 @@ #define SLEEP_TIME_MILLISECONDS 30 #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) -#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid" -#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys" -#define DEFAULT_PORT 33445 -#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false -#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly -#define DEFAULT_TCP_RELAY_PORTS_COUNT 3 -#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false -#define DEFAULT_MOTD DAEMON_NAME - -#define MIN_ALLOWED_PORT 1 -#define MAX_ALLOWED_PORT 65535 - - // Uses the already existing key or creates one if it didn't exist // // retirns 1 on success @@ -122,383 +104,6 @@ int manage_keys(DHT *dht, char *keys_file_path) return 1; } -// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array -// -// Supposed to be called from get_general_config only -// -// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` - -void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) -{ - const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; - - *tcp_relay_port_count = 0; - - config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); - - if (ports_array == NULL) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); - write_log(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); - - uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; - - int i; - - for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, default_ports[i]); - } - - // similar procedure to the one of reading config file below - *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); - - for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { - - (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; - - if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT - || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, - (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - continue; - } - - (*tcp_relay_port_count) ++; - } - - // the loop above skips invalid ports, so we adjust the allocated memory size - if ((*tcp_relay_port_count) > 0) { - *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); - } else { - free(*tcp_relay_ports); - *tcp_relay_ports = NULL; - } - - return; - } - - if (config_setting_is_array(ports_array) == CONFIG_FALSE) { - write_log(LOG_LEVEL_ERROR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", - NAME_TCP_RELAY_PORTS); - return; - } - - int config_port_count = config_setting_length(ports_array); - - if (config_port_count == 0) { - write_log(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); - return; - } - - *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); - - int i; - - for (i = 0; i < config_port_count; i ++) { - config_setting_t *elem = config_setting_get_elem(ports_array, i); - - if (elem == NULL) { - // it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be - write_log(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); - break; - } - - if (config_setting_is_number(elem) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "Port #%d: Not a number. Skipping.\n", i); - continue; - } - - (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); - - if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT - || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { - write_log(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, - (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - continue; - } - - (*tcp_relay_port_count) ++; - } - - // the loop above skips invalid ports, so we adjust the allocated memory size - if ((*tcp_relay_port_count) > 0) { - *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); - } else { - free(*tcp_relay_ports); - *tcp_relay_ports = NULL; - } -} - -// Gets general config options -// -// Important: you are responsible for freeing `pid_file_path` and `keys_file_path` -// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` -// and also `motd` iff `enable_motd` is set -// -// returns 1 on success -// 0 on failure, doesn't modify any data pointed by arguments - -int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, - int *enable_ipv6, - int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, - int *tcp_relay_port_count, int *enable_motd, char **motd) -{ - config_t cfg; - - const char *NAME_PORT = "port"; - const char *NAME_PID_FILE_PATH = "pid_file_path"; - const char *NAME_KEYS_FILE_PATH = "keys_file_path"; - const char *NAME_ENABLE_IPV6 = "enable_ipv6"; - const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback"; - const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; - const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; - const char *NAME_ENABLE_MOTD = "enable_motd"; - const char *NAME_MOTD = "motd"; - - config_init(&cfg); - - // Read the file. If there is an error, report it and exit. - if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return 0; - } - - // Get port - if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT); - *port = DEFAULT_PORT; - } - - // Get PID file location - const char *tmp_pid_file; - - if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH); - tmp_pid_file = DEFAULT_PID_FILE_PATH; - } - - *pid_file_path = malloc(strlen(tmp_pid_file) + 1); - strcpy(*pid_file_path, tmp_pid_file); - - // Get keys file location - const char *tmp_keys_file; - - if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH); - tmp_keys_file = DEFAULT_KEYS_FILE_PATH; - } - - *keys_file_path = malloc(strlen(tmp_keys_file) + 1); - strcpy(*keys_file_path, tmp_keys_file); - - // Get IPv6 option - if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false"); - *enable_ipv6 = DEFAULT_ENABLE_IPV6; - } - - // Get IPv4 fallback option - if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, - DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false"); - *enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK; - } - - // Get LAN discovery option - if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, - DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false"); - *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; - } - - // Get TCP relay option - if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, - DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); - *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; - } - - if (*enable_tcp_relay) { - parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); - } else { - *tcp_relay_port_count = 0; - } - - // Get MOTD option - if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, - DEFAULT_ENABLE_MOTD ? "true" : "false"); - *enable_motd = DEFAULT_ENABLE_MOTD; - } - - if (*enable_motd) { - // Get MOTD - const char *tmp_motd; - - if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); - write_log(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); - tmp_motd = DEFAULT_MOTD; - } - - size_t tmp_motd_length = strlen(tmp_motd) + 1; - size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; - *motd = malloc(motd_length); - strncpy(*motd, tmp_motd, motd_length); - (*motd)[motd_length - 1] = '\0'; - } - - config_destroy(&cfg); - - write_log(LOG_LEVEL_INFO, "Successfully read:\n"); - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); - write_log(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port); - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); - - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); - - // show info about tcp ports only if tcp relay is enabled - if (*enable_tcp_relay) { - if (*tcp_relay_port_count == 0) { - write_log(LOG_LEVEL_ERROR, "No TCP ports could be read.\n"); - } else { - write_log(LOG_LEVEL_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count); - int i; - - for (i = 0; i < *tcp_relay_port_count; i ++) { - write_log(LOG_LEVEL_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); - } - } - } - - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); - - if (*enable_motd) { - write_log(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd); - } - - return 1; -} - -// Bootstraps nodes listed in the config file -// -// returns 1 on success, some or no bootstrap nodes were added -// 0 on failure, a error accured while parsing config file - -int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) -{ - const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; - - const char *NAME_PUBLIC_KEY = "public_key"; - const char *NAME_PORT = "port"; - const char *NAME_ADDRESS = "address"; - - config_t cfg; - - config_init(&cfg); - - if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { - write_log(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); - config_destroy(&cfg); - return 0; - } - - config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); - - if (node_list == NULL) { - write_log(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", NAME_BOOTSTRAP_NODES); - config_destroy(&cfg); - return 1; - } - - if (config_setting_length(node_list) == 0) { - write_log(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); - config_destroy(&cfg); - return 1; - } - - int bs_port; - const char *bs_address; - const char *bs_public_key; - - config_setting_t *node; - - int i = 0; - - while (config_setting_length(node_list)) { - - node = config_setting_get_elem(node_list, 0); - - if (node == NULL) { - config_destroy(&cfg); - return 0; - } - - // Check that all settings are present - if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PUBLIC_KEY); - goto next; - } - - if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT); - goto next; - } - - if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS); - goto next; - } - - // Process settings - if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES * 2) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, - bs_public_key); - goto next; - } - - if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, - bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); - goto next; - } - - uint8_t *bs_public_key_bin = hex_string_to_bin((char *)bs_public_key); - const int address_resolved = DHT_bootstrap_from_address(dht, bs_address, enable_ipv6, htons(bs_port), - bs_public_key_bin); - free(bs_public_key_bin); - - if (!address_resolved) { - write_log(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address); - goto next; - } - - write_log(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); - -next: - // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly - // though it's freed when the element is removed, so we free it right away in order to keep memory - // consumption minimal - config_setting_remove_elem(node_list, 0); - i++; - } - - config_destroy(&cfg); - - return 1; -} - // Prints public key void print_public_key(const uint8_t *public_key) diff --git a/other/bootstrap_node_packets.c b/other/bootstrap_node_packets.c index 0bf9b9b0..21bb2894 100644 --- a/other/bootstrap_node_packets.c +++ b/other/bootstrap_node_packets.c @@ -23,7 +23,7 @@ * */ -#define MAX_MOTD_LENGTH 256 /* I recommend you use a maximum of 96 bytes. The hard maximum is this though. */ +#include "bootstrap_node_packets.h" #define INFO_REQUEST_PACKET_LENGTH 78 diff --git a/other/bootstrap_node_packets.h b/other/bootstrap_node_packets.h new file mode 100644 index 00000000..43356e7b --- /dev/null +++ b/other/bootstrap_node_packets.h @@ -0,0 +1,35 @@ +/* bootstrap_node_packets.h + * + * Special bootstrap node only packets. + * + * Include it in your bootstrap node and use: bootstrap_set_callbacks() to enable. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef BOOTSTRAP_NODE_PACKETS_H +#define BOOTSTRAP_NODE_PACKETS_H + +#include "../toxcore/network.h" + +#define MAX_MOTD_LENGTH 256 /* I recommend you use a maximum of 96 bytes. The hard maximum is this though. */ + +int bootstrap_set_callbacks(Networking_Core *net, uint32_t version, uint8_t *motd, uint16_t motd_length); + +#endif // BOOTSTRAP_NODE_PACKETS_H -- cgit v1.2.3 From 7d86caf51fd2f127a7f12c90293981650f6aae3c Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 00:36:57 -0500 Subject: Put command-line arguments related functions in a separate file --- other/bootstrap_daemon/Makefile.inc | 4 +- .../bootstrap_daemon/src/command_line_arguments.c | 141 +++++++++++++++++++++ .../bootstrap_daemon/src/command_line_arguments.h | 34 +++++ other/bootstrap_daemon/src/tox-bootstrapd.c | 114 +---------------- 4 files changed, 179 insertions(+), 114 deletions(-) create mode 100644 other/bootstrap_daemon/src/command_line_arguments.c create mode 100644 other/bootstrap_daemon/src/command_line_arguments.h diff --git a/other/bootstrap_daemon/Makefile.inc b/other/bootstrap_daemon/Makefile.inc index 5dce910e..b278e3f0 100644 --- a/other/bootstrap_daemon/Makefile.inc +++ b/other/bootstrap_daemon/Makefile.inc @@ -10,7 +10,9 @@ tox_bootstrapd_SOURCES = \ ../other/bootstrap_daemon/src/config.c \ ../other/bootstrap_daemon/src/config_defaults.h \ ../other/bootstrap_node_packets.h \ - ../other/bootstrap_node_packets.c + ../other/bootstrap_node_packets.c \ + ../other/bootstrap_daemon/src/command_line_arguments.h \ + ../other/bootstrap_daemon/src/command_line_arguments.c tox_bootstrapd_CFLAGS = \ -I$(top_srcdir)/other/bootstrap_daemon \ diff --git a/other/bootstrap_daemon/src/command_line_arguments.c b/other/bootstrap_daemon/src/command_line_arguments.c new file mode 100644 index 00000000..9b3b2e8c --- /dev/null +++ b/other/bootstrap_daemon/src/command_line_arguments.c @@ -0,0 +1,141 @@ +/* command_line_arguments.c + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "command_line_arguments.h" + +#include "global.h" + +#include + +#include +#include + +// Prints --help message + +void print_help() +{ + // 2 space ident + // make sure all lines fit into 80 columns + // make sure options are listed in alphabetical order + write_log(LOG_LEVEL_INFO, + "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" + "\n" + "Options:\n" + " --config=FILE_PATH Specify path to the config file.\n" + " This is a required option.\n" + " Set FILE_PATH to a path to an empty file in order to\n" + " use default settings.\n" + " --foreground Run the daemon in foreground. The daemon won't fork\n" + " (detach from the terminal) and won't use the PID file.\n" + " --help Print this help message.\n" + " --log-backend=BACKEND Specify which logging backend to use.\n" + " Valid BACKEND values (case sensetive):\n" + " syslog Writes log messages to syslog.\n" + " Default option when no --log-backend is\n" + " specified.\n" + " stdout Writes log messages to stdout/stderr.\n" + " --version Print version information.\n"); +} + +void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground) +{ + if (argc < 2) { + write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); + print_help(); + exit(1); + } + + opterr = 0; + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"config", required_argument, 0, 'c'}, // required option + {"foreground", no_argument, 0, 'f'}, + {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog + {"version", no_argument, 0, 'v'}, + {0, 0, 0, 0 } + }; + + bool cfg_file_path_set = false; + bool log_backend_set = false; + + *run_in_foreground = false; + + int opt; + + while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { + + switch (opt) { + case 'h': + print_help(); + exit(0); + + case 'c': + *cfg_file_path = optarg; + cfg_file_path_set = true; + break; + + case 'f': + *run_in_foreground = true; + break; + + case 'l': + if (strcmp(optarg, "syslog") == 0) { + *log_backend = LOG_BACKEND_SYSLOG; + log_backend_set = true; + } else if (strcmp(optarg, "stdout") == 0) { + *log_backend = LOG_BACKEND_STDOUT; + log_backend_set = true; + } else { + write_log(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg); + print_help(); + exit(1); + } + break; + + case 'v': + write_log(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER); + exit(0); + + case '?': + write_log(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind-1]); + print_help(); + exit(1); + + case ':': + write_log(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind-1]); + print_help(); + exit(1); + } + } + + if (!log_backend_set) { + *log_backend = LOG_BACKEND_SYSLOG; + } + + if (!cfg_file_path_set) { + write_log(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n"); + print_help(); + exit(1); + } +} diff --git a/other/bootstrap_daemon/src/command_line_arguments.h b/other/bootstrap_daemon/src/command_line_arguments.h new file mode 100644 index 00000000..1581278f --- /dev/null +++ b/other/bootstrap_daemon/src/command_line_arguments.h @@ -0,0 +1,34 @@ +/* command_line_arguments.h + * + * Tox DHT bootstrap daemon. + * + * Copyright (C) 2015 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef COMMAND_LINE_ARGUMENTS_H +#define COMMAND_LINE_ARGUMENTS_H + +#include "log.h" + +// Handles command line arguments, setting cfg_file_path and log_backend. +// Terminates the application if incorrect arguments are specified. + +void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground); + +#endif // COMMAND_LINE_ARGUMENTS_H diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index d4191e80..8ffef009 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -49,6 +49,7 @@ #include "../bootstrap_node_packets.h" #include "../../testing/misc_tools.c" +#include "command_line_arguments.h" #include "config.h" #include "global.h" #include "log.h" @@ -122,119 +123,6 @@ void print_public_key(const uint8_t *public_key) return; } -// Prints --help message - -bool print_help() -{ - // 2 space ident - // make sure all lines fit into 80 columns - // make sure options are listed in alphabetical order - write_log(LOG_LEVEL_INFO, - "Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n" - "\n" - "Options:\n" - " --config=FILE_PATH Specify path to the config file.\n" - " This is a required option.\n" - " Set FILE_PATH to a path to an empty file in order to\n" - " use default settings.\n" - " --foreground Run the daemon in foreground. The daemon won't fork\n" - " (detach from the terminal) and won't use the PID file.\n" - " --help Print this help message.\n" - " --log-backend=BACKEND Specify which logging backend to use.\n" - " Valid BACKEND values (case sensetive):\n" - " syslog Writes log messages to syslog.\n" - " Default option when no --log-backend is\n" - " specified.\n" - " stdout Writes log messages to stdout/stderr.\n" - " --version Print version information.\n"); -} - -// Handels command line arguments, setting cfg_file_path and log_backend. -// Terminates the application if incorrect arguments are specified. - -void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground) -{ - if (argc < 2) { - write_log(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n"); - print_help(); - exit(1); - } - - opterr = 0; - - static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"config", required_argument, 0, 'c'}, // required option - {"foreground", no_argument, 0, 'f'}, - {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0 } - }; - - bool cfg_file_path_set = false; - bool log_backend_set = false; - - *run_in_foreground = false; - - int opt; - - while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { - - switch (opt) { - case 'h': - print_help(); - exit(0); - - case 'c': - *cfg_file_path = optarg; - cfg_file_path_set = true; - break; - - case 'f': - *run_in_foreground = true; - break; - - case 'l': - if (strcmp(optarg, "syslog") == 0) { - *log_backend = LOG_BACKEND_SYSLOG; - log_backend_set = true; - } else if (strcmp(optarg, "stdout") == 0) { - *log_backend = LOG_BACKEND_STDOUT; - log_backend_set = true; - } else { - write_log(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg); - print_help(); - exit(1); - } - break; - - case 'v': - write_log(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER); - exit(0); - - case '?': - write_log(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind-1]); - print_help(); - exit(1); - - case ':': - write_log(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind-1]); - print_help(); - exit(1); - } - } - - if (!log_backend_set) { - *log_backend = LOG_BACKEND_SYSLOG; - } - - if (!cfg_file_path_set) { - write_log(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n"); - print_help(); - exit(1); - } -} - // Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend // Terminates the application if the daemonization fails. -- cgit v1.2.3 From da76da6c95fedf6014b69ed475cce074ad0afda9 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 00:55:09 -0500 Subject: Remove dependency on files from testing directory Also remove unneeded includes and refactor sleep define. --- other/bootstrap_daemon/src/config.c | 32 ++++++++++++++++++++++++----- other/bootstrap_daemon/src/tox-bootstrapd.c | 17 ++------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/other/bootstrap_daemon/src/config.c b/other/bootstrap_daemon/src/config.c index 270d399f..ee9fbdd2 100644 --- a/other/bootstrap_daemon/src/config.c +++ b/other/bootstrap_daemon/src/config.c @@ -26,16 +26,13 @@ #include "config_defaults.h" #include "log.h" -// C -//#include +#include +#include #include -// 3rd party #include -// toxcore #include "../../bootstrap_node_packets.h" -//#include "../../testing/misc_tools.c" // Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array // @@ -296,6 +293,31 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k return 1; } +// Converts a hex string with even number of characters into binary +// +// You are responsible for freeing the return value! +// +// Returns binary on success, +// NULL on failure + +uint8_t *hex_string_to_bin(char *hex_string) +{ + if (strlen(hex_string) % 2 != 0) { + return NULL; + } + + size_t len = strlen(hex_string) / 2; + uint8_t *ret = malloc(len); + + char *pos = hex_string; + size_t i; + for (i = 0; i < len; ++i, pos += 2) { + sscanf(pos, "%2hhx", &ret[i]); + } + + return ret; +} + int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) { const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 8ffef009..45b7add0 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -22,11 +22,6 @@ */ // system provided -#include -#include -#include -#include -#include #include // C @@ -34,11 +29,6 @@ #include #include -// ./configure -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - // toxcore #include "../../toxcore/LAN_discovery.h" #include "../../toxcore/onion_announce.h" @@ -47,16 +37,13 @@ // misc #include "../bootstrap_node_packets.h" -#include "../../testing/misc_tools.c" #include "command_line_arguments.h" #include "config.h" #include "global.h" #include "log.h" - -#define SLEEP_TIME_MILLISECONDS 30 -#define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) +#define SLEEP_MILLISECONDS(MS) usleep(1000*MS) // Uses the already existing key or creates one if it didn't exist // @@ -346,7 +333,7 @@ int main(int argc, char *argv[]) waiting_for_dht_connection = 0; } - sleep; + SLEEP_MILLISECONDS(30); } return 1; -- cgit v1.2.3 From d89fdb230b9160ea7b09cb29f2e7789025a32ee6 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 01:17:19 -0500 Subject: Fix include paths They are relative to the Makefile instead of the source file itself, which is unintuitive and is messing with my IDE. --- build/Makefile.am | 2 +- other/bootstrap_daemon/Makefile.inc | 36 --------------------------- other/bootstrap_daemon/src/Makefile.inc | 38 +++++++++++++++++++++++++++++ other/bootstrap_daemon/src/tox-bootstrapd.c | 12 +++++---- 4 files changed, 46 insertions(+), 42 deletions(-) delete mode 100644 other/bootstrap_daemon/Makefile.inc create mode 100644 other/bootstrap_daemon/src/Makefile.inc diff --git a/build/Makefile.am b/build/Makefile.am index c0e59645..ea844b3f 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -10,5 +10,5 @@ include ../toxencryptsave/Makefile.inc include ../toxav/Makefile.inc include ../other/Makefile.inc include ../testing/Makefile.inc -include ../other/bootstrap_daemon/Makefile.inc +include ../other/bootstrap_daemon/src/Makefile.inc include ../auto_tests/Makefile.inc diff --git a/other/bootstrap_daemon/Makefile.inc b/other/bootstrap_daemon/Makefile.inc deleted file mode 100644 index b278e3f0..00000000 --- a/other/bootstrap_daemon/Makefile.inc +++ /dev/null @@ -1,36 +0,0 @@ -if BUILD_DHT_BOOTSTRAP_DAEMON - -bin_PROGRAMS += tox-bootstrapd - -tox_bootstrapd_SOURCES = \ - ../other/bootstrap_daemon/src/tox-bootstrapd.c \ - ../other/bootstrap_daemon/src/log.c \ - ../other/bootstrap_daemon/src/log.h \ - ../other/bootstrap_daemon/src/config.h \ - ../other/bootstrap_daemon/src/config.c \ - ../other/bootstrap_daemon/src/config_defaults.h \ - ../other/bootstrap_node_packets.h \ - ../other/bootstrap_node_packets.c \ - ../other/bootstrap_daemon/src/command_line_arguments.h \ - ../other/bootstrap_daemon/src/command_line_arguments.c - -tox_bootstrapd_CFLAGS = \ - -I$(top_srcdir)/other/bootstrap_daemon \ - $(LIBSODIUM_CFLAGS) \ - $(NACL_CFLAGS) \ - $(LIBCONFIG_CFLAGS) - -tox_bootstrapd_LDADD = \ - $(LIBSODIUM_LDFLAGS) \ - $(NACL_LDFLAGS) \ - libtoxcore.la \ - $(LIBCONFIG_LIBS) \ - $(LIBSODIUM_LIBS) \ - $(NACL_LIBS) - -endif - -EXTRA_DIST += \ - $(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.conf \ - $(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.sh - diff --git a/other/bootstrap_daemon/src/Makefile.inc b/other/bootstrap_daemon/src/Makefile.inc new file mode 100644 index 00000000..a0d75fa0 --- /dev/null +++ b/other/bootstrap_daemon/src/Makefile.inc @@ -0,0 +1,38 @@ +if BUILD_DHT_BOOTSTRAP_DAEMON + +bin_PROGRAMS += tox-bootstrapd + +tox_bootstrapd_SOURCES = \ + ../other/bootstrap_daemon/src/command_line_arguments.c \ + ../other/bootstrap_daemon/src/command_line_arguments.h \ + ../other/bootstrap_daemon/src/config.c \ + ../other/bootstrap_daemon/src/config_defaults.h \ + ../other/bootstrap_daemon/src/config.h \ + ../other/bootstrap_daemon/src/log.c \ + ../other/bootstrap_daemon/src/log.h \ + ../other/bootstrap_daemon/src/tox-bootstrapd.c \ + ../other/bootstrap_node_packets.c \ + ../other/bootstrap_node_packets.h + + +tox_bootstrapd_CFLAGS = \ + -I$(top_srcdir)/other/bootstrap_daemon \ + $(LIBSODIUM_CFLAGS) \ + $(NACL_CFLAGS) \ + $(LIBCONFIG_CFLAGS) + +tox_bootstrapd_LDADD = \ + $(LIBSODIUM_LDFLAGS) \ + $(NACL_LDFLAGS) \ + libtoxcore.la \ + $(LIBCONFIG_LIBS) \ + $(LIBSODIUM_LIBS) \ + $(NACL_LIBS) + +endif + +EXTRA_DIST += \ + $(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.conf \ + $(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.service \ + $(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.sh + diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 45b7add0..4883f885 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -30,19 +30,21 @@ #include // toxcore -#include "../../toxcore/LAN_discovery.h" -#include "../../toxcore/onion_announce.h" -#include "../../toxcore/TCP_server.h" -#include "../../toxcore/util.h" +#include "../../../toxcore/LAN_discovery.h" +#include "../../../toxcore/onion_announce.h" +#include "../../../toxcore/TCP_server.h" +#include "../../../toxcore/util.h" + // misc -#include "../bootstrap_node_packets.h" +#include "../../bootstrap_node_packets.h" #include "command_line_arguments.h" #include "config.h" #include "global.h" #include "log.h" + #define SLEEP_MILLISECONDS(MS) usleep(1000*MS) // Uses the already existing key or creates one if it didn't exist -- cgit v1.2.3 From 232488816eb68d2306f95bf30f003d9a044a7863 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 01:26:00 -0500 Subject: Fix license headers and file descriptions --- other/bootstrap_daemon/src/command_line_arguments.c | 3 ++- other/bootstrap_daemon/src/command_line_arguments.h | 3 ++- other/bootstrap_daemon/src/config.c | 3 ++- other/bootstrap_daemon/src/config.h | 3 ++- other/bootstrap_daemon/src/config_defaults.h | 3 ++- other/bootstrap_daemon/src/global.h | 3 ++- other/bootstrap_daemon/src/log.c | 3 ++- other/bootstrap_daemon/src/log.h | 3 ++- other/bootstrap_daemon/src/tox-bootstrapd.c | 4 ++-- 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/other/bootstrap_daemon/src/command_line_arguments.c b/other/bootstrap_daemon/src/command_line_arguments.c index 9b3b2e8c..d364d329 100644 --- a/other/bootstrap_daemon/src/command_line_arguments.c +++ b/other/bootstrap_daemon/src/command_line_arguments.c @@ -1,8 +1,9 @@ /* command_line_arguments.c * * Tox DHT bootstrap daemon. + * Command line argument handling. * - * Copyright (C) 2015 Tox project All Rights Reserved. + * Copyright (C) 2015-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/command_line_arguments.h b/other/bootstrap_daemon/src/command_line_arguments.h index 1581278f..c96e8eaa 100644 --- a/other/bootstrap_daemon/src/command_line_arguments.h +++ b/other/bootstrap_daemon/src/command_line_arguments.h @@ -1,8 +1,9 @@ /* command_line_arguments.h * * Tox DHT bootstrap daemon. + * Command line argument handling. * - * Copyright (C) 2015 Tox project All Rights Reserved. + * Copyright (C) 2015-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/config.c b/other/bootstrap_daemon/src/config.c index ee9fbdd2..84e18a69 100644 --- a/other/bootstrap_daemon/src/config.c +++ b/other/bootstrap_daemon/src/config.c @@ -1,8 +1,9 @@ /* config.c * * Tox DHT bootstrap daemon. + * Functionality related to dealing with the config file. * - * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * Copyright (C) 2014-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/config.h b/other/bootstrap_daemon/src/config.h index 73bc6e0b..91f9c43f 100644 --- a/other/bootstrap_daemon/src/config.h +++ b/other/bootstrap_daemon/src/config.h @@ -1,8 +1,9 @@ /* config.h * * Tox DHT bootstrap daemon. + * Functionality related to dealing with the config file. * - * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * Copyright (C) 2014-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/config_defaults.h b/other/bootstrap_daemon/src/config_defaults.h index 34d715e7..17bffd3a 100644 --- a/other/bootstrap_daemon/src/config_defaults.h +++ b/other/bootstrap_daemon/src/config_defaults.h @@ -1,8 +1,9 @@ /* config_defaults.h * * Tox DHT bootstrap daemon. + * Default config options for when they are missing in the config file. * - * Copyright (C) 2014-2015 Tox project All Rights Reserved. + * Copyright (C) 2014-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/global.h b/other/bootstrap_daemon/src/global.h index 71f24635..a18afee3 100644 --- a/other/bootstrap_daemon/src/global.h +++ b/other/bootstrap_daemon/src/global.h @@ -1,8 +1,9 @@ /* global.h * * Tox DHT bootstrap daemon. + * Globally used defines. * - * Copyright (C) 2015 Tox project All Rights Reserved. + * Copyright (C) 2014-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c index ec68050e..b3aec180 100644 --- a/other/bootstrap_daemon/src/log.c +++ b/other/bootstrap_daemon/src/log.c @@ -1,8 +1,9 @@ /* log.c * * Tox DHT bootstrap daemon. + * Logging utility with support of multipel logging backends. * - * Copyright (C) 2015 Tox project All Rights Reserved. + * Copyright (C) 2015-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/log.h b/other/bootstrap_daemon/src/log.h index b7712368..61cb2ee3 100644 --- a/other/bootstrap_daemon/src/log.h +++ b/other/bootstrap_daemon/src/log.h @@ -1,8 +1,9 @@ /* log.h * * Tox DHT bootstrap daemon. + * Logging utility with support of multipel logging backends. * - * Copyright (C) 2015 Tox project All Rights Reserved. + * Copyright (C) 2015-2016 Tox project All Rights Reserved. * * This file is part of Tox. * diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 4883f885..e252a37d 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -1,8 +1,9 @@ /* tox-bootstrapd.c * * Tox DHT bootstrap daemon. + * Main file. * - * Copyright (C) 2014 Tox project All Rights Reserved. + * Copyright (C) 2014-2016 Tox project All Rights Reserved. * * This file is part of Tox. * @@ -35,7 +36,6 @@ #include "../../../toxcore/TCP_server.h" #include "../../../toxcore/util.h" - // misc #include "../../bootstrap_node_packets.h" -- cgit v1.2.3 From 5d9e40bbd3c5b278a93ac55ebcdda1f793c8bcdd Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 01:45:23 -0500 Subject: Unify function comment style Use doxygen java-style function comments already used in log.[c|h]. --- .../bootstrap_daemon/src/command_line_arguments.c | 4 ++- .../bootstrap_daemon/src/command_line_arguments.h | 13 +++++++--- other/bootstrap_daemon/src/config.c | 29 +++++++++++---------- other/bootstrap_daemon/src/config.h | 30 ++++++++++++---------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/other/bootstrap_daemon/src/command_line_arguments.c b/other/bootstrap_daemon/src/command_line_arguments.c index d364d329..d5f301ee 100644 --- a/other/bootstrap_daemon/src/command_line_arguments.c +++ b/other/bootstrap_daemon/src/command_line_arguments.c @@ -31,8 +31,10 @@ #include #include -// Prints --help message +/** + * Prints --help message + */ void print_help() { // 2 space ident diff --git a/other/bootstrap_daemon/src/command_line_arguments.h b/other/bootstrap_daemon/src/command_line_arguments.h index c96e8eaa..c73cd15e 100644 --- a/other/bootstrap_daemon/src/command_line_arguments.h +++ b/other/bootstrap_daemon/src/command_line_arguments.h @@ -27,9 +27,16 @@ #include "log.h" -// Handles command line arguments, setting cfg_file_path and log_backend. -// Terminates the application if incorrect arguments are specified. - +/** + * Handles command line arguments, setting cfg_file_path and log_backend. + * Terminates the application if incorrect arguments are specified. + * + * @param argc Argc passed into main(). + * @param argv Argv passed into main(). + * @param cfg_file_path Sets to the provided by the user config file path. + * @param log_backend Sets to the provided by the user log backend option. + * @param run_in_foreground Sets to the provided by the user foreground option. + */ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend, bool *run_in_foreground); #endif // COMMAND_LINE_ARGUMENTS_H diff --git a/other/bootstrap_daemon/src/config.c b/other/bootstrap_daemon/src/config.c index 84e18a69..861a3803 100644 --- a/other/bootstrap_daemon/src/config.c +++ b/other/bootstrap_daemon/src/config.c @@ -35,12 +35,13 @@ #include "../../bootstrap_node_packets.h" -// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array -// -// Supposed to be called from get_general_config only -// -// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` - +/** + * Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array. + * + * Supposed to be called from get_general_config only. + * + * Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports`. + */ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) { const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; @@ -294,13 +295,15 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k return 1; } -// Converts a hex string with even number of characters into binary -// -// You are responsible for freeing the return value! -// -// Returns binary on success, -// NULL on failure - +/** + * + * Converts a hex string with even number of characters into binary. + * + * Important: You are responsible for freeing the return value. + * + * @return binary on success, + * NULL on failure. + */ uint8_t *hex_string_to_bin(char *hex_string) { if (strlen(hex_string) % 2 != 0) { diff --git a/other/bootstrap_daemon/src/config.h b/other/bootstrap_daemon/src/config.h index 91f9c43f..13cf929a 100644 --- a/other/bootstrap_daemon/src/config.h +++ b/other/bootstrap_daemon/src/config.h @@ -27,24 +27,26 @@ #include "../../../toxcore/DHT.h" -// Gets general config options -// -// Important: you are responsible for freeing `pid_file_path` and `keys_file_path` -// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` -// and also `motd` iff `enable_motd` is set -// -// returns 1 on success -// 0 on failure, doesn't modify any data pointed by arguments - +/** + * Gets general config options from the config file. + * + * Important: You are responsible for freeing `pid_file_path` and `keys_file_path` + * also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` + * and also `motd` iff `enable_motd` is set. + * + * @return 1 on success, + * 0 on failure, doesn't modify any data pointed by arguments. + */ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd); -// Bootstraps nodes listed in the config file -// -// returns 1 on success, some or no bootstrap nodes were added -// 0 on failure, a error accured while parsing config file - +/** + * Bootstraps off nodes listed in the config file. + * + * @return 1 on success, some or no bootstrap nodes were added + * 0 on failure, a error accured while parsing config file. + */ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6); #endif // CONFIG_H -- cgit v1.2.3 From c22c06adbe2351bcfbbd60326fc3b600206e701e Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 02:46:14 -0500 Subject: Flush stdout output Apparently when no tty is attached, which is the case for Docker, the buffer size for stdout increases to the point that only half of the entire log might be written. --- other/bootstrap_daemon/src/log.c | 1 + 1 file changed, 1 insertion(+) diff --git a/other/bootstrap_daemon/src/log.c b/other/bootstrap_daemon/src/log.c index b3aec180..d441b98e 100644 --- a/other/bootstrap_daemon/src/log.c +++ b/other/bootstrap_daemon/src/log.c @@ -94,6 +94,7 @@ FILE* level_stdout(LOG_LEVEL level) void log_stdout(LOG_LEVEL level, const char *format, va_list args) { vfprintf(level_stdout(level), format, args); + fflush(level_stdout(level)); } bool write_log(LOG_LEVEL level, const char *format, ...) -- cgit v1.2.3 From 1b721ea1ec1b0bca82750e07bd475662f8cc8df0 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 17:18:37 -0500 Subject: Add Dockerfile for the daemon --- other/bootstrap_daemon/README.md | 51 +++++++++++++++++++++++++- other/bootstrap_daemon/docker/Dockerfile | 59 ++++++++++++++++++++++++++++++ other/bootstrap_daemon/docker/get-nodes.py | 49 +++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 other/bootstrap_daemon/docker/Dockerfile create mode 100644 other/bootstrap_daemon/docker/get-nodes.py diff --git a/other/bootstrap_daemon/README.md b/other/bootstrap_daemon/README.md index e77e3ae0..2d9e5615 100644 --- a/other/bootstrap_daemon/README.md +++ b/other/bootstrap_daemon/README.md @@ -5,7 +5,9 @@
- [For `init.d` users](#initd) - [Troubleshooting](#initd-troubleshooting) - +
+- [For `Docker` users](#docker) + - [Troubleshooting](#docker-troubleshooting) These instructions are primarily tested on Debian Linux, Wheezy for init.d and Jessie for systemd, but they should work on other POSIX-compliant systems too. @@ -146,3 +148,50 @@ sudo grep "tox-bootstrapd" /var/log/syslog - Make sure tox-bootstrapd has read permission for the config file. - Make sure tox-bootstrapd location matches its path in the `/etc/init.d/tox-bootstrapd` init script. + + + +##For `Docker` users: + +If you are familiar with Docker and would rather run the daemon in a Docker container, run the following from this directory: + +```sh +sudo docker build -t tox-bootstrapd docker/ + +sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd +sudo chmod 700 /var/lib/tox-bootstrapd + +sudo docker run -d --name tox-bootstrapd --restart always -v /var/lib/tox-bootstrapd/:/var/lib/tox-bootstrapd/ -p 443:443 -p 3389:3389 -p 33445:33445 -p 33445:33445/udp tox-bootstrapd +``` + +We create a new user and protect its home directory in order to mount it in the Docker image, so that the kyepair the daemon uses would be shared with the host system, which makes it less likely that you would loose the keypair while playing with the Docker container. + +You can check logs for your public key or any errors: +```sh +sudo docker logs tox-bootstrapd +``` + +If you are an experienced Docker user and have a version of Docker that supports `docker cp` both host->container and container->host directions, you might want to skip the directory mounting part and just do: + +```sh +sudo docker build -t tox-bootstrapd docker/ +sudo docker run -d --name tox-bootstrapd --restart always -p 443:443 -p 3389:3389 -p 33445:33445 -p 33445:33445/udp tox-bootstrapd +sudo docker logs tox-bootstrapd +``` + +The keypair is stored in `/var/lib/tox-bootstrapd/keys` file, so if you skipped the directory mounting part and want a new Docker container to retain the same public key that from an old one, just copy/overwrite it from the old container. + +Note that the Docker container runs a script which pulls a list of bootstrap nodes off https://nodes.tox.chat/ and adds them in the config file. + + +###Troubleshooting: + +- Check if the container is running: +```sh +sudo docker ps -a +``` + +- Check the log for errors: +```sh +sudo docker logs tox-bootstrapd +``` diff --git a/other/bootstrap_daemon/docker/Dockerfile b/other/bootstrap_daemon/docker/Dockerfile new file mode 100644 index 00000000..ef9d525c --- /dev/null +++ b/other/bootstrap_daemon/docker/Dockerfile @@ -0,0 +1,59 @@ +FROM debian:jessie + +# get all deps +RUN apt-get update && apt-get install -y \ + build-essential \ + libtool \ + autotools-dev \ + automake \ + checkinstall \ + check \ + git \ + yasm \ + libsodium-dev \ + libconfig-dev \ + python3 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# install toxcore and daemon +WORKDIR /root/ +RUN git clone https://github.com/irungentoo/toxcore +WORKDIR /root/toxcore/ +RUN ./autogen.sh +RUN ./configure --enable-daemon +RUN make -j`nproc` +RUN make install -j`nproc` +RUN ldconfig + +WORKDIR /root/toxcore/other/bootstrap_daemon/ + +# add new user +RUN useradd --home-dir /var/lib/tox-bootstrapd --create-home \ + --system --shell /sbin/nologin \ + --comment "Account to run Tox's DHT bootstrap daemon" \ + --user-group tox-bootstrapd +RUN chmod 700 /var/lib/tox-bootstrapd + +RUN cp tox-bootstrapd.conf /etc/tox-bootstrapd.conf + +# remove all the example bootstrap nodes from the config file +RUN N=-1 && \ + while grep -q "bootstrap_nodes =" /etc/tox-bootstrapd.conf; \ + do \ + head -n $N tox-bootstrapd.conf > /etc/tox-bootstrapd.conf; \ + N=$((N-1)); \ + done + +# add bootstrap nodes from https://nodes.tox.chat/ +RUN python3 docker/get-nodes.py >> /etc/tox-bootstrapd.conf + +USER tox-bootstrapd + +ENTRYPOINT /usr/local/bin/tox-bootstrapd \ + --config /etc/tox-bootstrapd.conf \ + --log-backend stdout \ + --foreground + +EXPOSE 443 3389 33445 +EXPOSE 33445/udp diff --git a/other/bootstrap_daemon/docker/get-nodes.py b/other/bootstrap_daemon/docker/get-nodes.py new file mode 100644 index 00000000..9a284748 --- /dev/null +++ b/other/bootstrap_daemon/docker/get-nodes.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +""" +Copyright (c) 2016 by nurupo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + +# Gets a list of nodes from https://nodes.tox.chat/json and prints them out +# in the format of tox-bootstrapd config file. + +import urllib.request +import json + +response = urllib.request.urlopen('https://nodes.tox.chat/json') +raw_json = response.read().decode('ascii', 'ignore') +nodes = json.loads(raw_json)['nodes'] + +output = 'bootstrap_nodes = (' + +for node in nodes: + node_output = ' { // ' + node['maintainer'] + '\n' + node_output += ' public_key = "' + node['public_key'] + '"\n' + node_output += ' port = ' + str(node['port']) + '\n' + node_output += ' address = "' + if len(node['ipv4']) > 4: + output += node_output + node['ipv4'] + '"\n },\n' + if len(node['ipv6']) > 4: + output += node_output + node['ipv6'] + '"\n },\n' + +# remove last comma +output = output[:-2] + '\n)\n' + +print(output) -- cgit v1.2.3 From f74d7c5ae6a35265d6b92ed974758028da774583 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 20:03:55 -0500 Subject: Version bump --- other/bootstrap_daemon/src/global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/bootstrap_daemon/src/global.h b/other/bootstrap_daemon/src/global.h index a18afee3..9ae3ec45 100644 --- a/other/bootstrap_daemon/src/global.h +++ b/other/bootstrap_daemon/src/global.h @@ -26,7 +26,7 @@ #define GLOBAL_H #define DAEMON_NAME "tox-bootstrapd" -#define DAEMON_VERSION_NUMBER 2014101200UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day +#define DAEMON_VERSION_NUMBER 2016010100UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day #define MIN_ALLOWED_PORT 1 #define MAX_ALLOWED_PORT 65535 -- cgit v1.2.3 From 6c104b5fe3ce6e6d7d6d091b3a4af25146ecfb17 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Fri, 1 Jan 2016 21:10:20 -0500 Subject: Keep it in alphabetical order --- other/bootstrap_daemon/src/command_line_arguments.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/other/bootstrap_daemon/src/command_line_arguments.c b/other/bootstrap_daemon/src/command_line_arguments.c index d5f301ee..187fa786 100644 --- a/other/bootstrap_daemon/src/command_line_arguments.c +++ b/other/bootstrap_daemon/src/command_line_arguments.c @@ -71,9 +71,9 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, opterr = 0; static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, {"config", required_argument, 0, 'c'}, // required option {"foreground", no_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, {"log-backend", required_argument, 0, 'l'}, // optional, defaults to syslog {"version", no_argument, 0, 'v'}, {0, 0, 0, 0 } @@ -89,9 +89,6 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, while ((opt = getopt_long(argc, argv, ":", long_options, NULL)) != -1) { switch (opt) { - case 'h': - print_help(); - exit(0); case 'c': *cfg_file_path = optarg; @@ -102,6 +99,10 @@ void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, *run_in_foreground = true; break; + case 'h': + print_help(); + exit(0); + case 'l': if (strcmp(optarg, "syslog") == 0) { *log_backend = LOG_BACKEND_SYSLOG; -- cgit v1.2.3 From 516d5ac09d77248ee44232c3c7ecf414e1b9bda6 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 2 Jan 2016 18:46:52 -0500 Subject: Add information on how to update the bootstrap daemon --- other/bootstrap_daemon/README.md | 92 +++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/other/bootstrap_daemon/README.md b/other/bootstrap_daemon/README.md index 2d9e5615..b2d9118e 100644 --- a/other/bootstrap_daemon/README.md +++ b/other/bootstrap_daemon/README.md @@ -1,19 +1,29 @@ #Instructions - [For `systemd` users](#systemd) + - [Setting up](#systemd-setting-up) + - [Updating](#systemd-updating) - [Troubleshooting](#systemd-troubleshooting)
- [For `init.d` users](#initd) + - [Setting up](#initd-setting-up) + - [Updating](#initd-updating) - [Troubleshooting](#initd-troubleshooting)
- [For `Docker` users](#docker) + - [Setting up](#docker-setting-up) + - [Updating](#docker-updating) - [Troubleshooting](#docker-troubleshooting) + These instructions are primarily tested on Debian Linux, Wheezy for init.d and Jessie for systemd, but they should work on other POSIX-compliant systems too.
-##For `systemd` users: +##For `systemd` users + + +###Setting up For security reasons we run the daemon under its own user. @@ -58,8 +68,31 @@ Get your public key and check that the daemon initialized correctly: sudo grep "tox-bootstrapd" /var/log/syslog ``` + +###Updating + +You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month. + +To update the daemon first stop it: + +```sh +sudo systemctl stop tox-bootstrapd.service +``` + +Then update your toxcore git repository, rebuild the toxcore and the daemon and make sure to install them. + +Check if `tox-bootstrapd.service` in toxcore git repository was modified since the last time you copied it, as you might need to update it too. + +After all of this is done, simply start the daemon back again: + +```sh +sudo systemctl start tox-bootstrapd.service +``` + +Note that `tox-bootstrapd.service` file might + -###Troubleshooting: +###Troubleshooting - Check daemon's status: ```sh @@ -85,6 +118,9 @@ sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrapd.service ##For `init.d` users + +###Setting up + For security reasons we run the daemon under its own user. Create a new user by executing the following: @@ -128,8 +164,29 @@ Get your public key and check that the daemon initialized correctly: sudo grep "tox-bootstrapd" /var/log/syslog ``` + +###Updating + +You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month. + +To update the daemon first stop it: + +```sh +sudo service tox-bootstrapd stop +``` + +Then update your toxcore git repository, rebuild the toxcore and the daemon and make sure to install them. + +Check if `tox-bootstrapd.sh` in toxcore git repository was modified since the last time you copied it, as you might need to update it too. + +After all of this is done, simply start the daemon back again: + +```sh +sudo service tox-bootstrapd start +``` + -###Troubleshooting: +###Troubleshooting - Check daemon's status: ```sh @@ -153,6 +210,9 @@ sudo grep "tox-bootstrapd" /var/log/syslog ##For `Docker` users: + +###Setting up + If you are familiar with Docker and would rather run the daemon in a Docker container, run the following from this directory: ```sh @@ -164,27 +224,37 @@ sudo chmod 700 /var/lib/tox-bootstrapd sudo docker run -d --name tox-bootstrapd --restart always -v /var/lib/tox-bootstrapd/:/var/lib/tox-bootstrapd/ -p 443:443 -p 3389:3389 -p 33445:33445 -p 33445:33445/udp tox-bootstrapd ``` -We create a new user and protect its home directory in order to mount it in the Docker image, so that the kyepair the daemon uses would be shared with the host system, which makes it less likely that you would loose the keypair while playing with the Docker container. +We create a new user and protect its home directory in order to mount it in the Docker image, so that the kyepair the daemon uses would be stored on the host system, which makes it less likely that you would loose the keypair while playing with or updating the Docker container. You can check logs for your public key or any errors: ```sh sudo docker logs tox-bootstrapd ``` -If you are an experienced Docker user and have a version of Docker that supports `docker cp` both host->container and container->host directions, you might want to skip the directory mounting part and just do: +Note that the Docker container runs a script which pulls a list of bootstrap nodes off https://nodes.tox.chat/ and adds them in the config file. + + +###Updating + +You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month. + +To update the daemon, all you need is to erase current container with its image: ```sh -sudo docker build -t tox-bootstrapd docker/ -sudo docker run -d --name tox-bootstrapd --restart always -p 443:443 -p 3389:3389 -p 33445:33445 -p 33445:33445/udp tox-bootstrapd -sudo docker logs tox-bootstrapd +sudo docker stop tox-bootstrapd +sudo docker rm tox-bootstrapd +sudo docker rmi tox-bootstrapd ``` -The keypair is stored in `/var/lib/tox-bootstrapd/keys` file, so if you skipped the directory mounting part and want a new Docker container to retain the same public key that from an old one, just copy/overwrite it from the old container. +Then rebuild and run the image again: -Note that the Docker container runs a script which pulls a list of bootstrap nodes off https://nodes.tox.chat/ and adds them in the config file. +```sh +sudo docker build -t tox-bootstrapd docker/ +sudo docker run -d --name tox-bootstrapd --restart always -v /var/lib/tox-bootstrapd/:/var/lib/tox-bootstrapd/ -p 443:443 -p 3389:3389 -p 33445:33445 -p 33445:33445/udp tox-bootstrapd +``` -###Troubleshooting: +###Troubleshooting - Check if the container is running: ```sh -- cgit v1.2.3 From 9d1efd594914629204d4cd1a84678daf67eb8068 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 2 Jan 2016 18:55:53 -0500 Subject: Change init.d to SysVinit --- other/bootstrap_daemon/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/other/bootstrap_daemon/README.md b/other/bootstrap_daemon/README.md index b2d9118e..93e390ef 100644 --- a/other/bootstrap_daemon/README.md +++ b/other/bootstrap_daemon/README.md @@ -5,10 +5,10 @@ - [Updating](#systemd-updating) - [Troubleshooting](#systemd-troubleshooting)
-- [For `init.d` users](#initd) - - [Setting up](#initd-setting-up) - - [Updating](#initd-updating) - - [Troubleshooting](#initd-troubleshooting) +- [For `SysVinit` users](#sysvinit) + - [Setting up](#sysvinit-setting-up) + - [Updating](#sysvinit-updating) + - [Troubleshooting](#sysvinit-troubleshooting)
- [For `Docker` users](#docker) - [Setting up](#docker-setting-up) @@ -16,7 +16,7 @@ - [Troubleshooting](#docker-troubleshooting) -These instructions are primarily tested on Debian Linux, Wheezy for init.d and Jessie for systemd, but they should work on other POSIX-compliant systems too. +These instructions are primarily tested on Debian Linux, Wheezy for SysVinit and Jessie for systemd, but they should work on other POSIX-compliant systems too.
@@ -115,10 +115,10 @@ sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrapd.service - Make sure tox-bootstrapd location matches its path in tox-bootstrapd.service file. - -##For `init.d` users + +##For `SysVinit` users - + ###Setting up For security reasons we run the daemon under its own user. @@ -164,7 +164,7 @@ Get your public key and check that the daemon initialized correctly: sudo grep "tox-bootstrapd" /var/log/syslog ``` - + ###Updating You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month. @@ -185,7 +185,7 @@ After all of this is done, simply start the daemon back again: sudo service tox-bootstrapd start ``` - + ###Troubleshooting - Check daemon's status: -- cgit v1.2.3