Squashed 'external/toxcore/c-toxcore/' content from commit 67badf69
git-subtree-dir: external/toxcore/c-toxcore git-subtree-split: 67badf69416a74e74f6d7eb51dd96f37282b8455
This commit is contained in:
47
other/bootstrap_daemon/src/Makefile.inc
Normal file
47
other/bootstrap_daemon/src/Makefile.inc
Normal file
@ -0,0 +1,47 @@
|
||||
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.h \
|
||||
../other/bootstrap_daemon/src/config_defaults.h \
|
||||
../other/bootstrap_daemon/src/global.h \
|
||||
../other/bootstrap_daemon/src/log.c \
|
||||
../other/bootstrap_daemon/src/log.h \
|
||||
../other/bootstrap_daemon/src/log_backend_stdout.c \
|
||||
../other/bootstrap_daemon/src/log_backend_stdout.h \
|
||||
../other/bootstrap_daemon/src/log_backend_syslog.c \
|
||||
../other/bootstrap_daemon/src/log_backend_syslog.h \
|
||||
../other/bootstrap_daemon/src/tox-bootstrapd.c \
|
||||
../other/bootstrap_daemon/src/global.h \
|
||||
../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_OBJECTS) \
|
||||
$(NACL_LIBS)
|
||||
|
||||
bashcompdir = $(datarootdir)/bash-completion/completions
|
||||
dist_bashcomp_DATA = $(top_builddir)/other/bootstrap_daemon/bash-completion/completions/tox-bootstrapd
|
||||
|
||||
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
|
||||
|
||||
endif
|
134
other/bootstrap_daemon/src/command_line_arguments.c
Normal file
134
other/bootstrap_daemon/src/command_line_arguments.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Command line argument handling.
|
||||
*/
|
||||
#include "command_line_arguments.h"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Prints --help message
|
||||
*/
|
||||
static void print_help(void)
|
||||
{
|
||||
// 2 space ident
|
||||
// make sure all lines fit into 80 columns
|
||||
// make sure options are listed in alphabetical order
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n");
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opterr = 0;
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"config", required_argument, nullptr, 'c'}, // required option
|
||||
{"foreground", no_argument, nullptr, 'f'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"log-backend", required_argument, nullptr, 'l'}, // optional, defaults to syslog
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{nullptr, 0, nullptr, 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, nullptr)) != -1) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'c':
|
||||
*cfg_file_path = optarg;
|
||||
cfg_file_path_set = true;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*run_in_foreground = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
|
||||
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 {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg);
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
log_write(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER);
|
||||
exit(0);
|
||||
|
||||
case '?':
|
||||
log_write(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind - 1]);
|
||||
print_help();
|
||||
exit(1);
|
||||
|
||||
case ':':
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n");
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
28
other/bootstrap_daemon/src/command_line_arguments.h
Normal file
28
other/bootstrap_daemon/src/command_line_arguments.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Command line argument handling.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_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.
|
||||
*
|
||||
* @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 // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H
|
414
other/bootstrap_daemon/src/config.c
Normal file
414
other/bootstrap_daemon/src/config.c
Normal file
@ -0,0 +1,414 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Functionality related to dealing with the config file.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "config_defaults.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libconfig.h>
|
||||
|
||||
#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`.
|
||||
*/
|
||||
static 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 == nullptr) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS);
|
||||
|
||||
uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS};
|
||||
|
||||
for (int i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; ++i) {
|
||||
log_write(LOG_LEVEL_INFO, "Port #%d: %u\n", i, default_ports[i]);
|
||||
}
|
||||
|
||||
// similar procedure to the one of reading config file below
|
||||
*tcp_relay_ports = (uint16_t *)malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t));
|
||||
|
||||
for (int 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) {
|
||||
log_write(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 = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
|
||||
} else {
|
||||
free(*tcp_relay_ports);
|
||||
*tcp_relay_ports = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (config_setting_is_array(ports_array) == CONFIG_FALSE) {
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS);
|
||||
return;
|
||||
}
|
||||
|
||||
*tcp_relay_ports = (uint16_t *)malloc(config_port_count * sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i < config_port_count; ++i) {
|
||||
config_setting_t *elem = config_setting_get_elem(ports_array, i);
|
||||
|
||||
if (elem == nullptr) {
|
||||
// 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
|
||||
log_write(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) {
|
||||
log_write(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) {
|
||||
log_write(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 = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
|
||||
} else {
|
||||
free(*tcp_relay_ports);
|
||||
*tcp_relay_ports = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH);
|
||||
tmp_pid_file = DEFAULT_PID_FILE_PATH;
|
||||
}
|
||||
|
||||
const size_t pid_file_path_len = strlen(tmp_pid_file) + 1;
|
||||
*pid_file_path = (char *)malloc(pid_file_path_len);
|
||||
memcpy(*pid_file_path, tmp_pid_file, pid_file_path_len);
|
||||
|
||||
// Get keys file location
|
||||
const char *tmp_keys_file;
|
||||
|
||||
if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH);
|
||||
tmp_keys_file = DEFAULT_KEYS_FILE_PATH;
|
||||
}
|
||||
|
||||
const size_t keys_file_path_len = strlen(tmp_keys_file) + 1;
|
||||
*keys_file_path = (char *)malloc(keys_file_path_len);
|
||||
memcpy(*keys_file_path, tmp_keys_file, keys_file_path_len);
|
||||
|
||||
// Get IPv6 option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD);
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD);
|
||||
log_write(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 = (char *)malloc(motd_length);
|
||||
snprintf(*motd, motd_length, "%s", tmp_motd);
|
||||
}
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Successfully read:\n");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false");
|
||||
|
||||
log_write(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) {
|
||||
log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count);
|
||||
|
||||
for (int i = 0; i < *tcp_relay_port_count; ++i) {
|
||||
log_write(LOG_LEVEL_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false");
|
||||
|
||||
if (*enable_motd) {
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
static uint8_t *bootstrap_hex_string_to_bin(const char *hex_string)
|
||||
{
|
||||
if (strlen(hex_string) % 2 != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t len = strlen(hex_string) / 2;
|
||||
uint8_t *ret = (uint8_t *)malloc(len);
|
||||
|
||||
const char *pos = hex_string;
|
||||
|
||||
for (size_t i = 0; i < len; ++i, pos += 2) {
|
||||
unsigned int val;
|
||||
sscanf(pos, "%02x", &val);
|
||||
ret[i] = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
log_write(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 == nullptr) {
|
||||
log_write(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) {
|
||||
log_write(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)) {
|
||||
int address_resolved;
|
||||
uint8_t *bs_public_key_bin;
|
||||
|
||||
node = config_setting_get_elem(node_list, 0);
|
||||
|
||||
if (node == nullptr) {
|
||||
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) {
|
||||
log_write(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) {
|
||||
log_write(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) {
|
||||
log_write(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_PUBLIC_KEY_SIZE * 2) {
|
||||
log_write(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) {
|
||||
log_write(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;
|
||||
}
|
||||
|
||||
bs_public_key_bin = bootstrap_hex_string_to_bin(bs_public_key);
|
||||
address_resolved = dht_bootstrap_from_address(dht, bs_address, enable_ipv6, net_htons(bs_port),
|
||||
bs_public_key_bin);
|
||||
free(bs_public_key_bin);
|
||||
|
||||
if (!address_resolved) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address);
|
||||
goto next;
|
||||
}
|
||||
|
||||
log_write(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;
|
||||
}
|
37
other/bootstrap_daemon/src/config.h
Normal file
37
other/bootstrap_daemon/src/config.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Functionality related to dealing with the config file.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
||||
|
||||
#include "../../../toxcore/DHT.h"
|
||||
|
||||
/**
|
||||
* 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 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 // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
27
other/bootstrap_daemon/src/config_defaults.h
Normal file
27
other/bootstrap_daemon/src/config_defaults.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Default config options for when they are missing in the config file.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_DEFAULTS_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_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 // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_DEFAULTS_H
|
44
other/bootstrap_daemon/src/global.h
Normal file
44
other/bootstrap_daemon/src/global.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Globally used defines.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
||||
|
||||
#include "../../../toxcore/tox.h"
|
||||
|
||||
#define DAEMON_NAME "tox-bootstrapd"
|
||||
|
||||
#define DAEMON_VERSION_MAJOR TOX_VERSION_MAJOR
|
||||
#define DAEMON_VERSION_MINOR TOX_VERSION_MINOR
|
||||
#define DAEMON_VERSION_PATCH TOX_VERSION_PATCH
|
||||
|
||||
// Make sure versions are within the limit
|
||||
#define VERSION_IS_OK(NUM) ( NUM >= 0 && NUM <= 999 )
|
||||
#if !VERSION_IS_OK(DAEMON_VERSION_MAJOR) || !VERSION_IS_OK(DAEMON_VERSION_MINOR) || !VERSION_IS_OK(DAEMON_VERSION_PATCH)
|
||||
#error "At least one of major, minor or patch parts of the version is out of bounds of [0, 999]. Current version: " DAEMON_VERSION_MAJOR "." DAEMON_VERSION_MINOR "." DAEMON_VERSION_PATCH
|
||||
#endif
|
||||
#undef VERSION_IS_OK
|
||||
|
||||
// New version scheme of 1AAABBBCCC, where A B and C are major, minor and patch
|
||||
// versions of toxcore. The leading 1 is there just to keep the leading zeros,
|
||||
// so that it would be easier to read the version when printed as a number.
|
||||
// The version is in a visual decimal format rather than in any other format,
|
||||
// because the original version was using a similar format, it was using
|
||||
// YYYYMMDDVV date-based format for the version, with VV being an incremental
|
||||
// counter in case more than one version was released at that day. Due to this
|
||||
// some tools started showing the version to users as a plain number, rather
|
||||
// than some binary format that needs to be parsed before being shown to users
|
||||
// so we decided to keep this display format compatibility and adopted this
|
||||
// weird scheme with a leading 1.
|
||||
#define DAEMON_VERSION_NUMBER (1000000000UL + DAEMON_VERSION_MAJOR*1000000UL + DAEMON_VERSION_MINOR*1000UL + DAEMON_VERSION_PATCH*1UL)
|
||||
|
||||
#define MIN_ALLOWED_PORT 1
|
||||
#define MAX_ALLOWED_PORT 65535
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
82
other/bootstrap_daemon/src/log.c
Normal file
82
other/bootstrap_daemon/src/log.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Logging utility with support of multiple logging backends.
|
||||
*/
|
||||
#include "log.h"
|
||||
#include "log_backend_stdout.h"
|
||||
#include "log_backend_syslog.h"
|
||||
|
||||
#define INVALID_BACKEND ((LOG_BACKEND)-1u)
|
||||
static LOG_BACKEND current_backend = INVALID_BACKEND;
|
||||
|
||||
bool log_open(LOG_BACKEND backend)
|
||||
{
|
||||
if (current_backend != INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_backend = backend;
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
// nothing to do here
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_open();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool log_close(void)
|
||||
{
|
||||
if (current_backend == INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
// nothing to do here
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_close();
|
||||
break;
|
||||
}
|
||||
|
||||
current_backend = INVALID_BACKEND;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool log_write(LOG_LEVEL level, const char *format, ...)
|
||||
{
|
||||
if (current_backend == INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
log_backend_stdout_write(level, format, args);
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_write(level, format, args);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return true;
|
||||
}
|
51
other/bootstrap_daemon/src/log.h
Normal file
51
other/bootstrap_daemon/src/log.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Logging utility with support of multiple logging backends.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
typedef enum LOG_BACKEND {
|
||||
LOG_BACKEND_STDOUT,
|
||||
LOG_BACKEND_SYSLOG
|
||||
} LOG_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, false if log is already opened.
|
||||
*/
|
||||
bool log_open(LOG_BACKEND backend);
|
||||
|
||||
/**
|
||||
* Releases all used resources by the logger.
|
||||
* @return true on success, false if log is already closed.
|
||||
*/
|
||||
bool log_close(void);
|
||||
|
||||
/**
|
||||
* 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, false if log is closed.
|
||||
*/
|
||||
bool log_write(LOG_LEVEL level, const char *format, ...) GNU_PRINTF(2, 3);
|
||||
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
32
other/bootstrap_daemon/src/log_backend_stdout.c
Normal file
32
other/bootstrap_daemon/src/log_backend_stdout.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Stdout logging backend.
|
||||
*/
|
||||
#include "log_backend_stdout.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static FILE *log_backend_stdout_level(LOG_LEVEL level)
|
||||
{
|
||||
switch (level) {
|
||||
case LOG_LEVEL_INFO:
|
||||
return stdout;
|
||||
|
||||
case LOG_LEVEL_WARNING: // intentional fallthrough
|
||||
case LOG_LEVEL_ERROR:
|
||||
return stderr;
|
||||
}
|
||||
|
||||
return stdout;
|
||||
}
|
||||
|
||||
void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args)
|
||||
{
|
||||
vfprintf(log_backend_stdout_level(level), format, args);
|
||||
fflush(log_backend_stdout_level(level));
|
||||
}
|
19
other/bootstrap_daemon/src/log_backend_stdout.h
Normal file
19
other/bootstrap_daemon/src/log_backend_stdout.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Stdout logging backend.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
66
other/bootstrap_daemon/src/log_backend_syslog.c
Normal file
66
other/bootstrap_daemon/src/log_backend_syslog.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Syslog logging backend.
|
||||
*/
|
||||
#include "log_backend_syslog.h"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
void log_backend_syslog_open(void)
|
||||
{
|
||||
openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
void log_backend_syslog_close(void)
|
||||
{
|
||||
closelog();
|
||||
}
|
||||
|
||||
static int log_backend_syslog_level(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;
|
||||
}
|
||||
|
||||
return LOG_INFO;
|
||||
}
|
||||
|
||||
void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args)
|
||||
{
|
||||
va_list args2;
|
||||
|
||||
va_copy(args2, args);
|
||||
int size = vsnprintf(nullptr, 0, format, args2);
|
||||
va_end(args2);
|
||||
|
||||
assert(size >= 0);
|
||||
|
||||
if (size < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf = (char *)malloc(size + 1);
|
||||
vsnprintf(buf, size + 1, format, args);
|
||||
|
||||
syslog(log_backend_syslog_level(level), "%s", buf);
|
||||
free(buf);
|
||||
}
|
21
other/bootstrap_daemon/src/log_backend_syslog.h
Normal file
21
other/bootstrap_daemon/src/log_backend_syslog.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Syslog logging backend.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void log_backend_syslog_open(void);
|
||||
void log_backend_syslog_close(void);
|
||||
void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
624
other/bootstrap_daemon/src/tox-bootstrapd.c
Normal file
624
other/bootstrap_daemon/src/tox-bootstrapd.c
Normal file
@ -0,0 +1,624 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Main file.
|
||||
*/
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
// system provided
|
||||
#include <signal.h> // system header, rather than C, because we need it for POSIX sigaction(2)
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// C
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// toxcore
|
||||
#include "../../../toxcore/tox.h"
|
||||
#include "../../../toxcore/LAN_discovery.h"
|
||||
#include "../../../toxcore/TCP_server.h"
|
||||
#include "../../../toxcore/announce.h"
|
||||
#include "../../../toxcore/group_onion_announce.h"
|
||||
#include "../../../toxcore/logger.h"
|
||||
#include "../../../toxcore/mono_time.h"
|
||||
#include "../../../toxcore/onion_announce.h"
|
||||
#include "../../../toxcore/util.h"
|
||||
|
||||
// misc
|
||||
#include "../../bootstrap_node_packets.h"
|
||||
|
||||
#include "command_line_arguments.h"
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
static void sleep_milliseconds(uint32_t ms)
|
||||
{
|
||||
struct timespec req;
|
||||
req.tv_sec = ms / 1000;
|
||||
req.tv_nsec = (long)ms % 1000 * 1000 * 1000;
|
||||
nanosleep(&req, nullptr);
|
||||
}
|
||||
|
||||
// Uses the already existing key or creates one if it didn't exist
|
||||
//
|
||||
// returns 1 on success
|
||||
// 0 on failure - no keys were read or stored
|
||||
|
||||
static int manage_keys(DHT *dht, char *keys_file_path)
|
||||
{
|
||||
enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
|
||||
uint8_t keys[KEYS_SIZE];
|
||||
FILE *keys_file;
|
||||
|
||||
// Check if file exits, proceed to open and load keys
|
||||
keys_file = fopen(keys_file_path, "rb");
|
||||
|
||||
if (keys_file != nullptr) {
|
||||
const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
|
||||
|
||||
if (read_size != KEYS_SIZE) {
|
||||
fclose(keys_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dht_set_self_public_key(dht, keys);
|
||||
dht_set_self_secret_key(dht, keys + CRYPTO_PUBLIC_KEY_SIZE);
|
||||
} else {
|
||||
// Otherwise save new keys
|
||||
memcpy(keys, dht_get_self_public_key(dht), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, dht_get_self_secret_key(dht), CRYPTO_SECRET_KEY_SIZE);
|
||||
|
||||
keys_file = fopen(keys_file_path, "wb");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Prints public key
|
||||
|
||||
static void print_public_key(const uint8_t *public_key)
|
||||
{
|
||||
char buffer[2 * CRYPTO_PUBLIC_KEY_SIZE + 1];
|
||||
int index = 0;
|
||||
|
||||
for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
|
||||
index += snprintf(buffer + index, sizeof(buffer) - index, "%02X", public_key[i]);
|
||||
}
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Public Key: %s\n", buffer);
|
||||
}
|
||||
|
||||
// Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend
|
||||
// Terminates the application if the daemonization fails.
|
||||
|
||||
static 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"))) {
|
||||
log_write(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 == nullptr) {
|
||||
log_write(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);
|
||||
log_write(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid);
|
||||
exit(0);
|
||||
} else {
|
||||
fclose(pid_file);
|
||||
}
|
||||
|
||||
if (pid < 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Create a new SID for the child process
|
||||
if (setsid() < 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Change the current working directory
|
||||
if ((chdir("/")) < 0) {
|
||||
log_write(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);
|
||||
}
|
||||
}
|
||||
|
||||
// Logs toxcore logger message using our logger facility
|
||||
|
||||
static void toxcore_logger_callback(void *context, Logger_Level level, const char *file, int line,
|
||||
const char *func, const char *message, void *userdata)
|
||||
{
|
||||
LOG_LEVEL log_level;
|
||||
|
||||
switch (level) {
|
||||
case LOGGER_LEVEL_TRACE:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_DEBUG:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_INFO:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_WARNING:
|
||||
log_level = LOG_LEVEL_WARNING;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_ERROR:
|
||||
log_level = LOG_LEVEL_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
log_write(log_level, "%s:%d(%s) %s\n", file, line, func, message);
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t caught_signal = 0;
|
||||
|
||||
static void handle_signal(int signum)
|
||||
{
|
||||
caught_signal = signum;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
umask(077);
|
||||
char *cfg_file_path = nullptr;
|
||||
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;
|
||||
|
||||
log_open(log_backend);
|
||||
handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground);
|
||||
log_close();
|
||||
|
||||
log_open(log_backend);
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER);
|
||||
|
||||
char *pid_file_path = nullptr;
|
||||
char *keys_file_path = nullptr;
|
||||
int start_port;
|
||||
int enable_ipv6;
|
||||
int enable_ipv4_fallback;
|
||||
int enable_lan_discovery;
|
||||
int enable_tcp_relay;
|
||||
uint16_t *tcp_relay_ports = nullptr;
|
||||
int tcp_relay_port_count;
|
||||
int enable_motd;
|
||||
char *motd = nullptr;
|
||||
|
||||
if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &start_port, &enable_ipv6, &enable_ipv4_fallback,
|
||||
&enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) {
|
||||
log_write(LOG_LEVEL_INFO, "General config read successfully\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (start_port < MIN_ALLOWED_PORT || start_port > MAX_ALLOWED_PORT) {
|
||||
log_write(LOG_LEVEL_ERROR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", start_port, MIN_ALLOWED_PORT,
|
||||
MAX_ALLOWED_PORT);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
free(pid_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!run_in_foreground) {
|
||||
daemonize(log_backend, pid_file_path);
|
||||
}
|
||||
|
||||
free(pid_file_path);
|
||||
|
||||
IP ip;
|
||||
ip_init(&ip, enable_ipv6);
|
||||
|
||||
Logger *logger = logger_new();
|
||||
|
||||
if (MIN_LOGGER_LEVEL == LOGGER_LEVEL_TRACE || MIN_LOGGER_LEVEL == LOGGER_LEVEL_DEBUG) {
|
||||
logger_callback_log(logger, toxcore_logger_callback, nullptr, nullptr);
|
||||
}
|
||||
|
||||
const uint16_t end_port = start_port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM);
|
||||
const Network *ns = system_network();
|
||||
Networking_Core *net = new_networking_ex(logger, ns, &ip, start_port, end_port, nullptr);
|
||||
|
||||
if (net == nullptr) {
|
||||
if (enable_ipv6 && enable_ipv4_fallback) {
|
||||
log_write(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_ex(logger, ns, &ip, start_port, end_port, nullptr);
|
||||
|
||||
if (net == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't fallback to IPv4. Exiting.\n");
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize networking. Exiting.\n");
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Mono_Time *const mono_time = mono_time_new(nullptr, nullptr);
|
||||
|
||||
if (mono_time == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize monotonic timer. Exiting.\n");
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_time_update(mono_time);
|
||||
|
||||
const Random *rng = system_random();
|
||||
DHT *const dht = new_dht(logger, rng, ns, mono_time, net, true, enable_lan_discovery);
|
||||
|
||||
if (dht == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n");
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Forwarding *forwarding = new_forwarding(logger, rng, mono_time, dht);
|
||||
|
||||
if (forwarding == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize forwarding. Exiting.\n");
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Announcements *announce = new_announcements(logger, rng, mono_time, forwarding);
|
||||
|
||||
if (announce == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize DHT announcements. Exiting.\n");
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
GC_Announces_List *group_announce = new_gca_list();
|
||||
|
||||
if (group_announce == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize group announces. Exiting.\n");
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Onion *onion = new_onion(logger, mono_time, rng, dht);
|
||||
|
||||
if (!onion) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n");
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Onion_Announce *onion_a = new_onion_announce(logger, rng, mono_time, dht);
|
||||
|
||||
if (!onion_a) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion Announce. Exiting.\n");
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gca_onion_init(group_announce, onion_a);
|
||||
|
||||
if (enable_motd) {
|
||||
if (bootstrap_set_callbacks(dht_get_net(dht), DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) {
|
||||
log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n");
|
||||
free(motd);
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (manage_keys(dht, keys_file_path)) {
|
||||
log_write(LOG_LEVEL_INFO, "Keys are managed successfully.\n");
|
||||
free(keys_file_path);
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
TCP_Server *tcp_server = nullptr;
|
||||
|
||||
if (enable_tcp_relay) {
|
||||
if (tcp_relay_port_count == 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n");
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_onion(onion);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(tcp_relay_ports);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcp_server = new_TCP_server(logger, rng, ns, enable_ipv6, tcp_relay_port_count, tcp_relay_ports,
|
||||
dht_get_self_secret_key(dht), onion, forwarding);
|
||||
|
||||
free(tcp_relay_ports);
|
||||
|
||||
if (tcp_server != nullptr) {
|
||||
log_write(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n");
|
||||
|
||||
struct rlimit limit;
|
||||
|
||||
const rlim_t rlim_suggested = 32768;
|
||||
const rlim_t rlim_min = 4096;
|
||||
|
||||
assert(rlim_suggested >= rlim_min);
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &limit)) {
|
||||
if (limit.rlim_cur < limit.rlim_max) {
|
||||
// Some systems have a hard limit of over 1000000 open file descriptors, so let's cap it at something reasonable
|
||||
// so that we don't set it to an unreasonably high number.
|
||||
limit.rlim_cur = limit.rlim_max > rlim_suggested ? rlim_suggested : limit.rlim_max;
|
||||
setrlimit(RLIMIT_NOFILE, &limit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &limit) && limit.rlim_cur < rlim_min) {
|
||||
log_write(LOG_LEVEL_WARNING,
|
||||
"Current limit on the number of files this process can open (%ju) is rather low for the proper functioning of the TCP server. "
|
||||
"Consider raising the limit to at least %ju or the recommended %ju. "
|
||||
"Continuing using the current limit (%ju).\n",
|
||||
(uintmax_t)limit.rlim_cur, (uintmax_t)rlim_min, (uintmax_t)rlim_suggested, (uintmax_t)limit.rlim_cur);
|
||||
}
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n");
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) {
|
||||
log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path);
|
||||
kill_TCP_server(tcp_server);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_public_key(dht_get_self_public_key(dht));
|
||||
|
||||
uint64_t last_LANdiscovery = 0;
|
||||
const uint16_t net_htons_port = net_htons(start_port);
|
||||
|
||||
int waiting_for_dht_connection = 1;
|
||||
|
||||
Broadcast_Info *broadcast = nullptr;
|
||||
|
||||
if (enable_lan_discovery) {
|
||||
broadcast = lan_discovery_init(ns);
|
||||
log_write(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n");
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_handler = handle_signal;
|
||||
|
||||
// Try to restart interrupted system calls if they are restartable
|
||||
sa.sa_flags = SA_RESTART;
|
||||
|
||||
// Prevent the signal handler from being called again before it returns
|
||||
sigfillset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(SIGINT, &sa, nullptr)) {
|
||||
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGINT. Continuing without the signal handler set.\n");
|
||||
}
|
||||
|
||||
if (sigaction(SIGTERM, &sa, nullptr)) {
|
||||
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGTERM. Continuing without the signal handler set.\n");
|
||||
}
|
||||
|
||||
while (!caught_signal) {
|
||||
mono_time_update(mono_time);
|
||||
|
||||
do_dht(dht);
|
||||
|
||||
if (enable_lan_discovery && mono_time_is_timeout(mono_time, last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) {
|
||||
lan_discovery_send(dht_get_net(dht), broadcast, dht_get_self_public_key(dht), net_htons_port);
|
||||
last_LANdiscovery = mono_time_get(mono_time);
|
||||
}
|
||||
|
||||
if (enable_tcp_relay) {
|
||||
do_TCP_server(tcp_server, mono_time);
|
||||
}
|
||||
|
||||
networking_poll(dht_get_net(dht), nullptr);
|
||||
|
||||
if (waiting_for_dht_connection && dht_isconnected(dht)) {
|
||||
log_write(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n");
|
||||
waiting_for_dht_connection = 0;
|
||||
}
|
||||
|
||||
sleep_milliseconds(30);
|
||||
}
|
||||
|
||||
switch (caught_signal) {
|
||||
case SIGINT:
|
||||
log_write(LOG_LEVEL_INFO, "Received SIGINT (%d) signal. Exiting.\n", SIGINT);
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
log_write(LOG_LEVEL_INFO, "Received SIGTERM (%d) signal. Exiting.\n", SIGTERM);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_write(LOG_LEVEL_INFO, "Received (%d) signal. Exiting.\n", caught_signal);
|
||||
}
|
||||
|
||||
lan_discovery_kill(broadcast);
|
||||
kill_TCP_server(tcp_server);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user