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

Switch to using json DHT nodes file

Parsing json manually like this is ugly, but this allows us to use the json formatted nodeslist file
at nodes.tox.chat instead of having to update the list by hand. We could also potentially
use curl to fetch the list and update it automatically.
This commit is contained in:
Jfreegman 2016-09-17 21:38:32 -04:00
parent 1f02bb2be5
commit 5e20e6b279
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
5 changed files with 109 additions and 88 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
/* bootstrap.c /* bootstrap.c
* *
* *
* Copyright (C) 2014 Toxic All Rights Reserved. * Copyright (C) 2016 Toxic All Rights Reserved.
* *
* This file is part of Toxic. * This file is part of Toxic.
* *
@ -37,11 +37,23 @@ extern struct arg_opts arg_opts;
/* Time to wait between bootstrap attempts */ /* Time to wait between bootstrap attempts */
#define TRY_BOOTSTRAP_INTERVAL 5 #define TRY_BOOTSTRAP_INTERVAL 5
#define IPv4_MAX_SIZE 64
#define PORT_MAX_SIZE 5
#define IPV4_JSON_VALUE "\"ipv4\":\""
#define IPV4_JSON_VALUE_LEN (sizeof(IPV4_JSON_VALUE) - 1)
#define PORT_JSON_VALUE "\"port\":"
#define PORT_JSON_VALUE_LEN (sizeof(PORT_JSON_VALUE) - 1)
#define KEY_JSON_VALUE "\"public_key\":\""
#define KEY_JSON_VALUE_LEN (sizeof(KEY_JSON_VALUE) - 1)
#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.chat = 8) */ #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 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) #define NODELEN (MAX_NODE_LINE - TOX_PUBLIC_KEY_SIZE - 7)
#define MAX_NODELIST_SIZE (1024 * MAXNODES)
static struct toxNodes { static struct toxNodes {
size_t lines; size_t lines;
@ -50,67 +62,104 @@ static struct toxNodes {
char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE]; char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE];
} toxNodes; } toxNodes;
/* Load the DHT nodelist to memory. /* Load the DHT nodelist to memory from json formatted nodes file obtained at https://nodes.tox.chat/json.
* *
* Return 0 on success. * Return 0 on success.
* Return -1 if nodelist file cannot be opened. * Return -1 if nodelist file cannot be opened.
* Return -2 if nodelist file does not contain any valid node entries. * Return -2 if nodelist file cannot be parsed.
* Return -3 if nodelist file does not contain any valid node entries.
*/ */
int load_DHT_nodelist(void) int load_DHT_nodelist(void)
{ {
const char *filename = !arg_opts.nodes_path[0] ? PACKAGE_DATADIR "/DHTnodes" : arg_opts.nodes_path; const char *filename = !arg_opts.nodes_path[0] ? PACKAGE_DATADIR "/DHTnodes" : arg_opts.nodes_path;
FILE *fp = fopen(filename, "r"); FILE *fp = fopen(filename, "r");
if (fp == NULL) if (fp == NULL)
return -1; return -1;
char line[MAX_NODE_LINE]; char line[MAX_NODELIST_SIZE];
while (fgets(line, sizeof(line), fp) && toxNodes.lines < MAXNODES) { if (fgets(line, sizeof(line), fp) == NULL) {
size_t line_len = strlen(line); return -2;
}
if (line_len >= MIN_NODE_LINE && line_len <= MAX_NODE_LINE) { const char *line_start = 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) while ((line_start = strstr(line_start + 1, IPV4_JSON_VALUE)) && toxNodes.lines < MAXNODES) {
/* Extract IPv4 address */
const char *ip_start = strstr(line_start, IPV4_JSON_VALUE);
// TODO: These strlen() calls are very inefficient. Should probably keep track of length manually.
if (ip_start == NULL || strlen(ip_start) < IPV4_JSON_VALUE_LEN) {
continue; continue;
}
long int port = strtol(port_str, NULL, 10); ip_start += IPV4_JSON_VALUE_LEN;
int ip_len = char_find(0, ip_start, '"');
if (ip_len == 0 || ip_len > IPv4_MAX_SIZE) {
continue;
}
char ipv4_string[ip_len + 1];
memcpy(ipv4_string, ip_start, ip_len);
ipv4_string[ip_len] = 0;
/* Extract port */
const char *port_start = strstr(ip_start, PORT_JSON_VALUE);
if (!port_start || strlen(port_start) < PORT_JSON_VALUE_LEN) {
continue;
}
port_start += PORT_JSON_VALUE_LEN;
int port_len = char_find(0, port_start, ',');
if (port_len == 0 || port_len > PORT_MAX_SIZE) {
continue;
}
char port_string[port_len + 1];
memcpy(port_string, port_start, port_len);
port_string[port_len] = 0;
long int port = strtol(port_string, NULL, 10);
if (port <= 0 || port > MAX_PORT_RANGE) if (port <= 0 || port > MAX_PORT_RANGE)
continue; continue;
size_t key_len = strlen(key_ascii); /* Extract key */
size_t name_len = strlen(name); const char *key_start = strstr(port_start, KEY_JSON_VALUE);
if (key_len < TOX_PUBLIC_KEY_SIZE * 2 || name_len >= NODELEN) if (!key_start || strlen(key_start) < KEY_JSON_VALUE_LEN) {
continue; continue;
}
snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", name); key_start += KEY_JSON_VALUE_LEN;
toxNodes.nodes[toxNodes.lines][NODELEN - 1] = 0; int key_len = char_find(0, key_start, '"');
if (key_len != TOX_PUBLIC_KEY_SIZE * 2) {
continue;
}
char key_string[TOX_PUBLIC_KEY_SIZE * 2 + 1];
memcpy(key_string, key_start, TOX_PUBLIC_KEY_SIZE * 2);
key_string[TOX_PUBLIC_KEY_SIZE * 2] = 0;
/* Add IP-Port-Key to nodes list */
snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", ipv4_string);
toxNodes.ports[toxNodes.lines] = port; toxNodes.ports[toxNodes.lines] = port;
/* remove possible trailing newline from key string */ if (hex_string_to_bin(key_string, key_len, toxNodes.keys[toxNodes.lines], TOX_PUBLIC_KEY_SIZE) == -1)
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; continue;
toxNodes.lines++; toxNodes.lines++;
} }
}
fclose(fp); fclose(fp);
if (toxNodes.lines == 0) if (toxNodes.lines == 0)
return -2; return -3;
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
/* bootstrap.h /* bootstrap.h
* *
* *
* Copyright (C) 2014 Toxic All Rights Reserved. * Copyright (C) 2016 Toxic All Rights Reserved.
* *
* This file is part of Toxic. * This file is part of Toxic.
* *
@ -23,10 +23,11 @@
/* Manages connection to the Tox DHT network. */ /* Manages connection to the Tox DHT network. */
void do_tox_connection(Tox *m); void do_tox_connection(Tox *m);
/* Load the DHT nodelist to memory. /* Load the DHT nodelist to memory from json formatted nodes file obtained attempts https://nodes.tox.chat/json.
* *
* Return 0 on success. * Return 0 on success.
* Return -1 if nodelist file cannot be opened. * Return -1 if nodelist file cannot be opened.
* Return -2 if nodelist file does not contain any valid node entries. * Return -2 if nodelist file cannot be parsed.
* Return -3 if nodelist file does not contain any valid node entries.
*/ */
int load_DHT_nodelist(void); int load_DHT_nodelist(void);

View File

@ -367,9 +367,13 @@ size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
} }
/* returns index of the first instance of ch in s starting at idx. /* returns index of the first instance of ch in s starting at idx.
returns length of s if char not found */ returns length of s if char not found or 0 if s is NULL. */
int char_find(int idx, const char *s, char ch) int char_find(int idx, const char *s, char ch)
{ {
if (!s) {
return 0;
}
int i = idx; int i = idx;
for (i = idx; s[i]; ++i) { for (i = idx; s[i]; ++i) {
@ -381,9 +385,13 @@ int char_find(int idx, const char *s, char ch)
} }
/* returns index of the last instance of ch in s starting at len. /* returns index of the last instance of ch in s starting at len.
returns 0 if char not found (skips 0th index). */ returns 0 if char not found or s is NULL (skips 0th index). */
int char_rfind(const char *s, char ch, int len) int char_rfind(const char *s, char ch, int len)
{ {
if (!s) {
return 0;
}
int i = 0; int i = 0;
for (i = len; i > 0; --i) { for (i = len; i > 0; --i) {

View File

@ -136,11 +136,11 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length); size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
/* returns index of the first instance of ch in s starting at idx. /* returns index of the first instance of ch in s starting at idx.
returns length of s if char not found */ returns length of s if char not found or 0 if s is NULL. */
int char_find(int idx, const char *s, char ch); int char_find(int idx, const char *s, char ch);
/* returns index of the last instance of ch in s /* returns index of the last instance of ch in s starting at len.
returns 0 if char not found */ returns 0 if char not found or s is NULL (skips 0th index). */
int char_rfind(const char *s, char ch, int len); int char_rfind(const char *s, char ch, int len);
/* Converts bytes to appropriate unit and puts in buf as a string */ /* Converts bytes to appropriate unit and puts in buf as a string */