mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-22 20:13:04 +01:00
Ignore offline bootstrap nodes, small refactor of Nodes struct
This commit is contained in:
parent
221d761ff4
commit
703d5419a3
@ -45,7 +45,7 @@ ui = {
|
|||||||
show_connection_msg=true;
|
show_connection_msg=true;
|
||||||
|
|
||||||
// How often in days to update the DHT nodes list. (0 to disable updates)
|
// How often in days to update the DHT nodes list. (0 to disable updates)
|
||||||
nodeslist_update_freq=30;
|
nodeslist_update_freq=7;
|
||||||
|
|
||||||
// maximum lines for chat window history
|
// maximum lines for chat window history
|
||||||
history_size=700;
|
history_size=700;
|
||||||
|
113
src/bootstrap.c
113
src/bootstrap.c
@ -49,34 +49,51 @@ extern struct user_settings *user_settings;
|
|||||||
/* Number of nodes to bootstrap to per try */
|
/* Number of nodes to bootstrap to per try */
|
||||||
#define NUM_BOOTSTRAP_NODES 5
|
#define NUM_BOOTSTRAP_NODES 5
|
||||||
|
|
||||||
#define IPv4_MAX_SIZE 64
|
/* Number of seconds since last successful ping before we consider a node offline */
|
||||||
|
#define NODE_OFFLINE_TIMOUT (60*60*24*2)
|
||||||
|
|
||||||
|
#define IP_MAX_SIZE 45
|
||||||
#define PORT_MAX_SIZE 5
|
#define PORT_MAX_SIZE 5
|
||||||
|
|
||||||
#define LAST_SCAN_JSON_VALUE "\"last_scan\":"
|
#define LAST_SCAN_JSON_KEY "\"last_scan\":"
|
||||||
#define LAST_SCAN_JSON_VALUE_LEN (sizeof(LAST_SCAN_JSON_VALUE) - 1)
|
#define LAST_SCAN_JSON_KEY_LEN (sizeof(LAST_SCAN_JSON_KEY) - 1)
|
||||||
|
|
||||||
#define IPV4_JSON_VALUE "\"ipv4\":\""
|
#define IPV4_JSON_KEY "\"ipv4\":\""
|
||||||
#define IPV4_JSON_VALUE_LEN (sizeof(IPV4_JSON_VALUE) - 1)
|
#define IPV4_JSON_KEY_LEN (sizeof(IPV4_JSON_KEY) - 1)
|
||||||
|
|
||||||
#define PORT_JSON_VALUE "\"port\":"
|
#define PORT_JSON_KEY "\"port\":"
|
||||||
#define PORT_JSON_VALUE_LEN (sizeof(PORT_JSON_VALUE) - 1)
|
#define PORT_JSON_KEY_LEN (sizeof(PORT_JSON_KEY) - 1)
|
||||||
|
|
||||||
#define KEY_JSON_VALUE "\"public_key\":\""
|
#define PK_JSON_KEY "\"public_key\":\""
|
||||||
#define KEY_JSON_VALUE_LEN (sizeof(KEY_JSON_VALUE) - 1)
|
#define PK_JSON_KEY_LEN (sizeof(PK_JSON_KEY) - 1)
|
||||||
|
|
||||||
|
#define LAST_PING_JSON_KEY "\"last_ping\":"
|
||||||
|
#define LAST_PING_JSON_KEY_LEN (sizeof(LAST_PING_JSON_KEY) - 1)
|
||||||
|
|
||||||
|
/* Maximum allowable size of the nodes list */
|
||||||
|
#define MAX_NODELIST_SIZE (MAX_RECV_CURL_DATA_SIZE)
|
||||||
|
|
||||||
#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.chat = 8) */
|
|
||||||
#define MAX_NODE_LINE 300 /* Max number of chars in a sever line (name + port + key) */
|
|
||||||
#define MAXNODES 50
|
#define MAXNODES 50
|
||||||
#define NODELEN (MAX_NODE_LINE - TOX_PUBLIC_KEY_SIZE - 7)
|
struct Node {
|
||||||
#define MAX_NODELIST_SIZE (1024 * MAXNODES)
|
char ip4[IP_MAX_SIZE + 1];
|
||||||
|
char ip6[IP_MAX_SIZE + 1];
|
||||||
|
char key[TOX_PUBLIC_KEY_SIZE];
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
|
||||||
static struct DHT_Nodes {
|
static struct DHT_Nodes {
|
||||||
size_t lines;
|
struct Node list[MAXNODES];
|
||||||
char nodes[MAXNODES][NODELEN];
|
size_t count;
|
||||||
uint16_t ports[MAXNODES];
|
uint64_t last_updated;
|
||||||
char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE];
|
|
||||||
} Nodes;
|
} Nodes;
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine if a node is offline by comparing the age of the nodeslist
|
||||||
|
* to the last time the node was successfully pinged.
|
||||||
|
*/
|
||||||
|
#define NODE_IS_OFFLINE(last_scan, last_ping) ((last_ping + NODE_OFFLINE_TIMOUT) <= (last_ping))
|
||||||
|
|
||||||
|
|
||||||
/* Return true if nodeslist pointed to by fp needs to be updated.
|
/* Return true if nodeslist pointed to by fp needs to be updated.
|
||||||
* This will be the case if the file is empty, has an invalid format,
|
* This will be the case if the file is empty, has an invalid format,
|
||||||
* or if the file is older than the given timeout.
|
* or if the file is older than the given timeout.
|
||||||
@ -94,7 +111,7 @@ static bool nodeslist_needs_update(const char *nodes_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* last_scan value should be at beginning of file */
|
/* last_scan value should be at beginning of file */
|
||||||
char line[LAST_SCAN_JSON_VALUE_LEN + 32];
|
char line[LAST_SCAN_JSON_KEY_LEN + 32];
|
||||||
|
|
||||||
if (fgets(line, sizeof(line), fp) == NULL) {
|
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -103,14 +120,15 @@ static bool nodeslist_needs_update(const char *nodes_path)
|
|||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
const char *last_scan_val = strstr(line, LAST_SCAN_JSON_VALUE);
|
const char *last_scan_val = strstr(line, LAST_SCAN_JSON_KEY);
|
||||||
|
|
||||||
if (last_scan_val == NULL) {
|
if (last_scan_val == NULL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_scan_val += LAST_SCAN_JSON_VALUE_LEN;
|
last_scan_val += LAST_SCAN_JSON_KEY_LEN;
|
||||||
long long int last_scan = strtoll(last_scan_val, NULL, 10);
|
long long int last_scan = strtoll(last_scan_val, NULL, 10);
|
||||||
|
Nodes.last_updated = last_scan;
|
||||||
|
|
||||||
if (timed_out(last_scan, user_settings->nodeslist_update_freq * 24 * 60 * 60)) {
|
if (timed_out(last_scan, user_settings->nodeslist_update_freq * 24 * 60 * 60)) {
|
||||||
return true;
|
return true;
|
||||||
@ -268,7 +286,7 @@ int load_DHT_nodeslist(void)
|
|||||||
fprintf(stderr, "update_DHT_nodeslist() failed with error %d\n", update_err);
|
fprintf(stderr, "update_DHT_nodeslist() failed with error %d\n", update_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
char line[MAX_NODELIST_SIZE];
|
char line[MAX_NODELIST_SIZE + 1];
|
||||||
|
|
||||||
if (fgets(line, sizeof(line), fp) == NULL) {
|
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -277,18 +295,18 @@ int load_DHT_nodeslist(void)
|
|||||||
|
|
||||||
const char *line_start = line;
|
const char *line_start = line;
|
||||||
|
|
||||||
while ((line_start = strstr(line_start + 1, IPV4_JSON_VALUE)) && Nodes.lines < MAXNODES) {
|
while ((line_start = strstr(line_start + 1, IPV4_JSON_KEY)) && Nodes.count < MAXNODES) {
|
||||||
/* Extract IPv4 address */
|
/* Extract IPv4 address */
|
||||||
const char *ip_start = strstr(line_start, IPV4_JSON_VALUE);
|
const char *ip_start = strstr(line_start, IPV4_JSON_KEY);
|
||||||
|
|
||||||
if (ip_start == NULL) {
|
if (ip_start == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip_start += IPV4_JSON_VALUE_LEN;
|
ip_start += IPV4_JSON_KEY_LEN;
|
||||||
int ip_len = char_find(0, ip_start, '"');
|
int ip_len = char_find(0, ip_start, '"');
|
||||||
|
|
||||||
if (ip_len == 0 || ip_len > IPv4_MAX_SIZE) {
|
if (ip_len == 0 || ip_len > IP_MAX_SIZE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,13 +320,13 @@ int load_DHT_nodeslist(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extract port */
|
/* Extract port */
|
||||||
const char *port_start = strstr(ip_start, PORT_JSON_VALUE);
|
const char *port_start = strstr(ip_start, PORT_JSON_KEY);
|
||||||
|
|
||||||
if (!port_start) {
|
if (!port_start) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
port_start += PORT_JSON_VALUE_LEN;
|
port_start += PORT_JSON_KEY_LEN;
|
||||||
int port_len = char_find(0, port_start, ',');
|
int port_len = char_find(0, port_start, ',');
|
||||||
|
|
||||||
if (port_len == 0 || port_len > PORT_MAX_SIZE) {
|
if (port_len == 0 || port_len > PORT_MAX_SIZE) {
|
||||||
@ -326,13 +344,13 @@ int load_DHT_nodeslist(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Extract key */
|
/* Extract key */
|
||||||
const char *key_start = strstr(port_start, KEY_JSON_VALUE);
|
const char *key_start = strstr(port_start, PK_JSON_KEY);
|
||||||
|
|
||||||
if (!key_start) {
|
if (!key_start) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_start += KEY_JSON_VALUE_LEN;
|
key_start += PK_JSON_KEY_LEN;
|
||||||
int key_len = char_find(0, key_start, '"');
|
int key_len = char_find(0, key_start, '"');
|
||||||
|
|
||||||
if (key_len != TOX_PUBLIC_KEY_SIZE * 2) {
|
if (key_len != TOX_PUBLIC_KEY_SIZE * 2) {
|
||||||
@ -343,20 +361,33 @@ int load_DHT_nodeslist(void)
|
|||||||
memcpy(key_string, key_start, TOX_PUBLIC_KEY_SIZE * 2);
|
memcpy(key_string, key_start, TOX_PUBLIC_KEY_SIZE * 2);
|
||||||
key_string[TOX_PUBLIC_KEY_SIZE * 2] = 0;
|
key_string[TOX_PUBLIC_KEY_SIZE * 2] = 0;
|
||||||
|
|
||||||
/* Add entry to nodes list */
|
/* Check last pinged value and ignore nodes that appear offline */
|
||||||
snprintf(Nodes.nodes[Nodes.lines], sizeof(Nodes.nodes[Nodes.lines]), "%s", ipv4_string);
|
const char *last_pinged_str = strstr(key_start, LAST_PING_JSON_KEY);
|
||||||
Nodes.ports[Nodes.lines] = port;
|
|
||||||
|
|
||||||
if (hex_string_to_bin(key_string, key_len, Nodes.keys[Nodes.lines], TOX_PUBLIC_KEY_SIZE) == -1)
|
if (!last_pinged_str) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Nodes.lines++;
|
last_pinged_str += LAST_PING_JSON_KEY_LEN;
|
||||||
|
long long int last_pinged = strtoll(last_pinged_str, NULL, 10);
|
||||||
|
|
||||||
|
if (last_pinged <= 0 || NODE_IS_OFFLINE(Nodes.last_scan, last_pinged)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add entry to nodes list */
|
||||||
|
size_t idx = Nodes.count++;
|
||||||
|
snprintf(Nodes.list[idx].ip4, sizeof(Nodes.list[idx].ip4), "%s", ipv4_string);
|
||||||
|
Nodes.list[idx].port = port;
|
||||||
|
|
||||||
|
if (hex_string_to_bin(key_string, key_len, Nodes.list[idx].key, TOX_PUBLIC_KEY_SIZE) == -1)
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If nodeslist does not contain any valid entries we set the last_scan value
|
/* If nodeslist does not contain any valid entries we set the last_scan value
|
||||||
* to 0 so that it will fetch a new list the next time this function is called.
|
* to 0 so that it will fetch a new list the next time this function is called.
|
||||||
*/
|
*/
|
||||||
if (Nodes.lines == 0) {
|
if (Nodes.count == 0) {
|
||||||
const char *s = "{\"last_scan\":0}";
|
const char *s = "{\"last_scan\":0}";
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
|
fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
|
||||||
@ -371,26 +402,26 @@ int load_DHT_nodeslist(void)
|
|||||||
/* Connects to NUM_BOOTSTRAP_NODES random DHT nodes listed in the DHTnodes file. */
|
/* Connects to NUM_BOOTSTRAP_NODES random DHT nodes listed in the DHTnodes file. */
|
||||||
static void DHT_bootstrap(Tox *m)
|
static void DHT_bootstrap(Tox *m)
|
||||||
{
|
{
|
||||||
if (Nodes.lines == 0) {
|
if (Nodes.count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < NUM_BOOTSTRAP_NODES; ++i) {
|
for (i = 0; i < NUM_BOOTSTRAP_NODES; ++i) {
|
||||||
size_t node = rand() % Nodes.lines;
|
size_t node = rand() % Nodes.count;
|
||||||
|
|
||||||
TOX_ERR_BOOTSTRAP err;
|
TOX_ERR_BOOTSTRAP err;
|
||||||
tox_bootstrap(m, Nodes.nodes[node], Nodes.ports[node], (uint8_t *) Nodes.keys[node], &err);
|
tox_bootstrap(m, Nodes.list[node].ip4, Nodes.list[node].port, (uint8_t *) Nodes.list[node].key, &err);
|
||||||
|
|
||||||
if (err != TOX_ERR_BOOTSTRAP_OK) {
|
if (err != TOX_ERR_BOOTSTRAP_OK) {
|
||||||
fprintf(stderr, "Failed to bootstrap %s:%d\n", Nodes.nodes[node], Nodes.ports[node]);
|
fprintf(stderr, "Failed to bootstrap %s:%d\n", Nodes.list[node].ip4, Nodes.list[node].port);
|
||||||
}
|
}
|
||||||
|
|
||||||
tox_add_tcp_relay(m, Nodes.nodes[node], Nodes.ports[node], (uint8_t *) Nodes.keys[node], &err);
|
tox_add_tcp_relay(m, Nodes.list[node].ip4, Nodes.list[node].port, (uint8_t *) Nodes.list[node].key, &err);
|
||||||
|
|
||||||
if (err != TOX_ERR_BOOTSTRAP_OK) {
|
if (err != TOX_ERR_BOOTSTRAP_OK) {
|
||||||
fprintf(stderr, "Failed to add TCP relay %s:%d\n", Nodes.nodes[node], Nodes.ports[node]);
|
fprintf(stderr, "Failed to add TCP relay %s:%d\n", Nodes.list[node].ip4, Nodes.list[node].port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ static void ui_defaults(struct user_settings* settings)
|
|||||||
settings->show_typing_other = SHOW_TYPING_ON;
|
settings->show_typing_other = SHOW_TYPING_ON;
|
||||||
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
|
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
|
||||||
settings->show_connection_msg = SHOW_CONNECTION_MSG_ON;
|
settings->show_connection_msg = SHOW_CONNECTION_MSG_ON;
|
||||||
settings->nodeslist_update_freq = 30;
|
settings->nodeslist_update_freq = 7;
|
||||||
|
|
||||||
snprintf(settings->line_join, LINE_HINT_MAX + 1, "%s", LINE_JOIN);
|
snprintf(settings->line_join, LINE_HINT_MAX + 1, "%s", LINE_JOIN);
|
||||||
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
|
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
|
||||||
|
@ -1143,7 +1143,7 @@ int main(int argc, char **argv)
|
|||||||
int nodeslist_ret = load_DHT_nodeslist();
|
int nodeslist_ret = load_DHT_nodeslist();
|
||||||
|
|
||||||
if (nodeslist_ret != 0) {
|
if (nodeslist_ret != 0) {
|
||||||
queue_init_message("DHT nodeslist failed to load (error %d)\n", nodeslist_ret);
|
queue_init_message("DHT nodeslist failed to load (error %d)", nodeslist_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef X11
|
#ifdef X11
|
||||||
|
Loading…
Reference in New Issue
Block a user