summaryrefslogtreecommitdiff
path: root/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c')
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c460
1 files changed, 0 insertions, 460 deletions
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
deleted file mode 100644
index dc519448..00000000
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ /dev/null
@@ -1,460 +0,0 @@
1/* DHT boostrap
2 *
3 * A simple DHT boostrap server for tox - daemon edition.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h> /* pid_t */
25#include <sys/stat.h> /* umask */
26#include <unistd.h> /* POSIX things */
27#include <errno.h>
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <libconfig.h>
32#include <arpa/inet.h> /* htons() */
33#include <string.h> /* strcpy() */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include "../../toxcore/DHT.h"
40#include "../../toxcore/friend_requests.h"
41
42#define DEFAULT_PORT 33445
43#define DEFAULT_PID_FILE "bootstrap_server.pid"
44#define DEFAULT_KEYS_FILE "bootstrap_server.keys"
45
46/* Server info struct */
47struct server_info_s {
48 int valid;
49 IP_Port conn;
50 uint8_t bs_pk[32];
51};
52
53/* This is the struct configure_server() uses to return its data to */
54struct server_conf_s {
55 int err;
56 int port;
57 char pid_file[512];
58 char keys_file[512];
59 struct server_info_s info[32];
60};
61
62int b16_to_key(char b16_string[], uint8_t *bs_pubkey)
63{
64
65 int i;
66 unsigned int num1 = 0, num2 = 0;
67
68 for (i = 0; i < 32; ++i) {
69 sscanf(&b16_string[i * 2], "%1X", &num1);
70 sscanf(&b16_string[i * 2 + 1], "%1X", &num2);
71 num1 = num1 << 4;
72 bs_pubkey[i] = bs_pubkey[i] | num1;
73 bs_pubkey[i] = bs_pubkey[i] | num2;
74 }
75
76 return 0;
77}
78
79/*
80 resolve_addr():
81 address should represent IPv4 or a hostname with a record
82
83 returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
84 returns 0 on failure
85
86 TODO: Fix ipv6 support
87*/
88
89uint32_t resolve_addr(const char *address)
90{
91 struct addrinfo *server = NULL;
92 struct addrinfo hints;
93 int rc;
94 uint32_t addr;
95
96 memset(&hints, 0, sizeof(hints));
97 hints.ai_family = AF_INET; // IPv4 only right now.
98 hints.ai_socktype = SOCK_DGRAM; // Type of socket Tox uses.
99
100 rc = getaddrinfo(address, "echo", &hints, &server);
101
102 // Lookup failed.
103 if (rc != 0) {
104 return 0;
105 }
106
107 // IPv4 records only..
108 if (server->ai_family != AF_INET) {
109 freeaddrinfo(server);
110 return 0;
111 }
112
113
114 addr = ((struct sockaddr_in *)server->ai_addr)->sin_addr.s_addr;
115
116 freeaddrinfo(server);
117 return addr;
118}
119
120/* This function connects to all specified servers
121and connect to them.
122returns 1 if the connection to the DHT is up
123returns -1 if all attempts failed
124*/
125int connect_to_servers(DHT *dht, struct server_info_s *info)
126{
127 int i;
128 int c;
129
130 for (i = 0; i < 32; ++i) {
131 if (info[i].valid) {
132 /* Actual bootstrapping code goes here */
133 //puts("Calling DHT_bootstrap");
134 DHT_bootstrap(dht, info[i].conn, info[i].bs_pk);
135 }
136 }
137
138 /* Check if we're connected to the DHT */
139 for (c = 0; c != 100; ++c) {
140 usleep(10000);
141
142 if (DHT_isconnected(dht)) {
143 //puts("Connected");
144 return 1;
145 break;
146 }
147
148 if (DHT_isconnected(dht) == 0 && c == 99) {
149 //puts("Not connected");
150 return -1;
151 break;
152 }
153
154 do_DHT(dht);
155
156 networking_poll(dht->c->lossless_udp->net);
157 }
158
159 /* This probably never happens */
160 return 0;
161}
162
163void manage_keys(DHT *dht, char *keys_file)
164{
165 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
166 uint8_t keys[KEYS_SIZE];
167 struct stat existence;
168 FILE *keysf;
169
170 /* Check if file exits, proceed to open and load keys */
171 if (stat(keys_file, &existence) >= 0) {
172 keysf = fopen(keys_file, "r");
173 size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf);
174
175 if (read_size != KEYS_SIZE) {
176 printf("Error while reading the key file\nExiting.\n");
177 exit(1);
178 } else {
179 printf("Keys loaded successfully\n");
180 }
181
182 load_keys(dht->c, keys);
183
184 } else {
185 /* Otherwise save new keys */
186 /* Silly work-around to ignore any errors coming from new_keys() */
187 new_keys(dht->c);
188 save_keys(dht->c, keys);
189 keysf = fopen(keys_file, "w");
190
191 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) {
192 printf("Error while writing the key file.\nExiting.\n");
193 exit(1);
194 } else {
195 printf("Keys saved successfully\n");
196 }
197 }
198
199 fclose(keysf);
200}
201
202/* This reads the configuration file, and returns a struct server_conf_s with:
203 *an error number:
204 *-1 = file wasn't read, for whatever reason
205 *-2 = no bootstrap servers found
206 *the port
207 *the location of the keys file
208 *the location of the PID file
209 *the list of bootstrap servers
210*/
211struct server_conf_s configure_server(char *cfg_file)
212{
213 config_t cfg;
214 config_setting_t *server_list;
215
216 /* This one will be strcpy'd into the pid_file array in server_conf */
217 const char *pid_file_tmp;
218 const char *keys_file_tmp;
219
220 /* Remote bootstrap server variables */
221 int bs_port;
222 const char *bs_ip;
223 const char *bs_pk;
224
225 /* The big struct */
226 static struct server_conf_s server_conf;
227
228 /* Set both to their default values. If there's an error
229 with opening/reading the config file, we return right away */
230 server_conf.port = DEFAULT_PORT;
231 strcpy(server_conf.pid_file, DEFAULT_PID_FILE);
232 strcpy(server_conf.keys_file, DEFAULT_KEYS_FILE);
233
234 config_init(&cfg);
235
236 /* Read the file. If there is an error, report it and exit. */
237 if (! config_read_file(&cfg, cfg_file)) {
238 fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
239 config_error_line(&cfg), config_error_text(&cfg));
240 config_destroy(&cfg);
241 server_conf.err = -1;
242 return server_conf;
243 }
244
245 /* Get the port to listen on */
246 if (config_lookup_int(&cfg, "port", &server_conf.port)) {
247 //printf("Port: %d\n", port);
248 } else {
249 fprintf(stderr, "No 'port' setting in configuration file.\n");
250 }
251
252 /* Get PID file location */
253 if (config_lookup_string(&cfg, "pid_file", &pid_file_tmp)) {
254 //printf("PID file: %s\n", pid_file_tmp);
255 strcpy(server_conf.pid_file, pid_file_tmp);
256 } else {
257 fprintf(stderr, "No 'pid_file' setting in configuration file.\n");
258 }
259
260 /* Get keys file location */
261 if (config_lookup_string(&cfg, "keys_file", &keys_file_tmp)) {
262 //printf("Keys file: %s\n", keys_file_tmp);
263 strcpy(server_conf.keys_file, keys_file_tmp);
264 } else {
265 fprintf(stderr, "No 'keys_file' setting in configuration file.\n");
266 }
267
268 /* Get all the servers in the list */
269 server_list = config_lookup(&cfg, "bootstrap_servers");
270
271 if (server_list != NULL) {
272 int count = config_setting_length(server_list);
273 int i;
274
275 char tmp_ip[30]; /* IP */
276 char tmp_pk[64]; /* bs_pk */
277
278 for (i = 0; i < count; ++i) {
279 config_setting_t *server = config_setting_get_elem(server_list, i);
280 /* Get a pointer on the key array */
281 uint8_t *bs_pk_p = server_conf.info[i].bs_pk;
282
283 /* Only output the record if all of the expected fields are present. */
284 if (!(config_setting_lookup_string(server, "ip", &bs_ip)
285 && config_setting_lookup_int(server, "port", &bs_port)
286 && config_setting_lookup_string(server, "bs_pk", &bs_pk)))
287 continue;
288
289 /* Converting all that stuff into usable formats and storing
290 it away in the server_info struct */
291 server_conf.info[i].valid = 1;
292
293 if (resolve_addr(strcpy(tmp_ip, bs_ip)) == 0) {
294 server_conf.info[i].valid = 0;
295 printf("bootstrap_server %d: Invalid IP.\n", i);
296 }
297
298 if (strlen(bs_pk) != 64) {
299 server_conf.info[i].valid = 0;
300 printf("bootstrap_server %d: Invalid public key.\n", i);
301 }
302
303 if (!bs_port) {
304 server_conf.info[i].valid = 0;
305 printf("bootstrap_server %d: Invalid port.\n", i);
306 }
307
308 server_conf.info[i].conn.ip.family = AF_INET;
309 server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
310 server_conf.info[i].conn.port = htons(bs_port);
311 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
312 }
313
314 /* Check if at least one server entry is valid */
315 for (i = 0; i < 32; ++i) {
316 if (server_conf.info[i].valid)
317 break;
318 else
319 server_conf.err = -2;
320 }
321
322 } else {
323 server_conf.err = -2;
324 }
325
326 config_destroy(&cfg);
327 return server_conf;
328}
329
330int main(int argc, char *argv[])
331{
332
333 pid_t pid, sid; /* Process- and Session-ID */
334 struct server_conf_s server_conf;
335
336 FILE *pidf; /* The PID file */
337
338 if (argc < 2) {
339 printf("Please specify a configuration file.\n");
340 exit(EXIT_FAILURE);
341 }
342
343 server_conf = configure_server(argv[1]);
344
345 /* Initialize networking
346 bind to ip 0.0.0.0:PORT */
347 IP ip;
348 ip_init(&ip, 0);
349 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port)));
350 /* Read the config file */
351 printf("PID file: %s\n", server_conf.pid_file);
352 printf("Key file: %s\n", server_conf.keys_file);
353
354 if (server_conf.err == -1)
355 printf("Config file not read.\n");
356
357 if (server_conf.err == -2)
358 printf("No valid servers in list.\n");
359
360 /* Open PID file for writing - if an error happens,
361 it will be caught down the line */
362 pidf = fopen(server_conf.pid_file, "w");
363
364 /* Manage the keys */
365 /* for now, just ignore any errors after this call. */
366 int tmperr = errno;
367 manage_keys(dht, server_conf.keys_file);
368 errno = tmperr;
369
370 /* Public key */
371 int i;
372 printf("\nPublic Key: ");
373
374 for (i = 0; i < 32; ++i) {
375 uint8_t ln, hn;
376 ln = 0x0F & dht->c->self_public_key[i];
377 hn = 0xF0 & dht->c->self_public_key[i];
378 hn = hn >> 4;
379 printf("%X%X", hn, ln);
380 }
381
382 printf("\n");
383
384 /* Bootstrap the DHT
385 This one throws odd errors, too. Ignore. I assume they come
386 from somewhere in the core. */
387 tmperr = errno;
388 connect_to_servers(dht, server_conf.info);
389 errno = tmperr;
390
391 if (!DHT_isconnected(dht)) {
392 puts("Could not establish DHT connection. Check server settings.\n");
393 exit(EXIT_FAILURE);
394 } else {
395 printf("Connected to DHT successfully.\n");
396 }
397
398 /* If there's been an error, exit before forking off */
399 if (errno != 0) {
400 perror("Error");
401 printf("Error(s) occured during start-up. Exiting.\n");
402 exit(EXIT_FAILURE);
403 }
404
405 /* Things that make the daemon work come past here.
406 There should be nothing here but the daemon code and
407 the main loop. */
408
409 /* Fork off from the parent process */
410 pid = fork();
411
412 if (pid < 0) {
413 printf("Forking failed.\n");
414 exit(EXIT_FAILURE);
415 }
416
417 /* If we got a good PID, then
418 we can exit the parent process. */
419 if (pid > 0) {
420 printf("Forked successfully: %d.\n", pid);
421
422 /* Write the PID file */
423 fprintf(pidf, "%d\n", pid);
424 fclose(pidf);
425
426 /* Exit parent */
427 exit(EXIT_SUCCESS);
428 }
429
430 /* Change the file mode mask */
431 umask(0);
432
433 /* Create a new SID for the child process */
434 sid = setsid();
435
436 if (sid < 0) {
437 printf("SID creation failure.\n");
438 exit(EXIT_FAILURE);
439 }
440
441 /* Change the current working directory */
442 if ((chdir("/")) < 0) {
443 exit(EXIT_FAILURE);
444 }
445
446 /* Go quiet */
447 close(STDOUT_FILENO);
448 close(STDIN_FILENO);
449 close(STDERR_FILENO);
450
451 while (1) {
452 do_DHT(dht);
453
454 networking_poll(dht->c->lossless_udp->net);
455 usleep(10000);
456 }
457
458 //shutdown_networking();
459 exit(EXIT_SUCCESS);
460}