1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-26 13:13:27 +01:00

Ignore offline bootstrap nodes, small refactor of Nodes struct

This commit is contained in:
Jfreegman 2016-09-21 12:51:57 -04:00
parent 221d761ff4
commit 703d5419a3
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
4 changed files with 75 additions and 44 deletions

View File

@ -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;

View File

@ -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);
} }
} }
} }

View File

@ -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);

View File

@ -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