/* bootstrap.c
*
*
* Copyright (C) 2014 Toxic All Rights Reserved.
*
* This file is part of Toxic.
*
* Toxic 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.
*
* Toxic 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 Toxic. If not, see .
*
*/
#include
#include
#include
#include
#include "line_info.h"
#include "windows.h"
#include "misc_tools.h"
extern struct arg_opts arg_opts;
/* Time to wait between bootstrap attempts */
#define TRY_BOOTSTRAP_INTERVAL 5
#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.chat = 8) */
#define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */
#define MAXNODES 50
#define NODELEN (MAX_NODE_LINE - TOX_PUBLIC_KEY_SIZE - 7)
static struct toxNodes {
size_t lines;
char nodes[MAXNODES][NODELEN];
uint16_t ports[MAXNODES];
char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE];
} toxNodes;
/* Load the DHT nodelist to memory.
*
* Return 0 on success.
* Return -1 if nodelist file cannot be opened.
* Return -2 if nodelist file does not contain any valid node entries.
*/
int load_DHT_nodelist(void)
{
const char *filename = !arg_opts.nodes_path[0] ? PACKAGE_DATADIR "/DHTnodes" : arg_opts.nodes_path;
FILE *fp = fopen(filename, "r");
if (fp == NULL)
return -1;
char line[MAX_NODE_LINE];
while (fgets(line, sizeof(line), fp) && toxNodes.lines < MAXNODES) {
size_t line_len = strlen(line);
if (line_len >= MIN_NODE_LINE && line_len <= MAX_NODE_LINE) {
const char *name = strtok(line, " ");
const char *port_str = strtok(NULL, " ");
const char *key_ascii = strtok(NULL, " ");
if (name == NULL || port_str == NULL || key_ascii == NULL)
continue;
long int port = strtol(port_str, NULL, 10);
if (port <= 0 || port > MAX_PORT_RANGE)
continue;
size_t key_len = strlen(key_ascii);
size_t name_len = strlen(name);
if (key_len < TOX_PUBLIC_KEY_SIZE * 2 || name_len >= NODELEN)
continue;
snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", name);
toxNodes.nodes[toxNodes.lines][NODELEN - 1] = 0;
toxNodes.ports[toxNodes.lines] = port;
/* remove possible trailing newline from key string */
char real_ascii_key[TOX_PUBLIC_KEY_SIZE * 2 + 1];
memcpy(real_ascii_key, key_ascii, TOX_PUBLIC_KEY_SIZE * 2);
key_len = TOX_PUBLIC_KEY_SIZE * 2;
real_ascii_key[key_len] = '\0';
if (hex_string_to_bin(real_ascii_key, key_len, toxNodes.keys[toxNodes.lines], TOX_PUBLIC_KEY_SIZE) == -1)
continue;
toxNodes.lines++;
}
}
fclose(fp);
if (toxNodes.lines == 0)
return -2;
return 0;
}
/* Connects to a random DHT node listed in the DHTnodes file. */
static void DHT_bootstrap(Tox *m)
{
if (toxNodes.lines == 0) {
return;
}
size_t node = rand() % toxNodes.lines;
TOX_ERR_BOOTSTRAP err;
tox_bootstrap(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
if (err != TOX_ERR_BOOTSTRAP_OK) {
fprintf(stderr, "Failed to bootstrap %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
}
tox_add_tcp_relay(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err);
if (err != TOX_ERR_BOOTSTRAP_OK) {
fprintf(stderr, "Failed to add TCP relay %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]);
}
}
/* Manages connection to the Tox DHT network. */
void do_tox_connection(Tox *m)
{
static uint64_t last_bootstrap_time = 0;
bool connected = tox_self_get_connection_status(m) != TOX_CONNECTION_NONE;
if (!connected && timed_out(last_bootstrap_time, TRY_BOOTSTRAP_INTERVAL)) {
DHT_bootstrap(m);
last_bootstrap_time = get_unix_time();
}
}