summaryrefslogtreecommitdiff
path: root/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
diff options
context:
space:
mode:
authorTom Bartelt <tom@ataullah.(none)>2013-07-23 06:28:47 -0400
committerTom Bartelt <tom@ataullah.(none)>2013-07-23 06:28:47 -0400
commit9f6f3117bb1b3131038dd5a890063b7625858177 (patch)
tree15cbd966a7c4dc4b5f08a5656c8bf839b0928186 /other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
parent413c5810e1ac8909e06f4dea2716c5bdded0e2c1 (diff)
Update daemon to use config files
Diffstat (limited to 'other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c')
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c395
1 files changed, 331 insertions, 64 deletions
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 4d79c48b..667e5237 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -1,50 +1,306 @@
1/* DHT boostrap 1/* DHT boostrap
2* 2 *
3* A simple DHT boostrap server for tox (daemon edition) 3 * A simple DHT boostrap server for tox - daemon edition.
4*/ 4 */
5 5
6#include <sys/types.h> /* pid_t */ 6#include <sys/types.h> /* pid_t */
7#include <sys/stat.h> /* umask */ 7#include <sys/stat.h> /* umask */
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h> /* POSIX things */ 8#include <unistd.h> /* POSIX things */
11#include <errno.h> 9#include <errno.h>
12 10#include <err.h>
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <libconfig.h>
15#include <arpa/inet.h> /* htons() */
16#include <string.h> /* strcpy() */
17
13#include "../../core/DHT.h" 18#include "../../core/DHT.h"
14#include "../../core/friend_requests.h" 19#include "../../core/friend_requests.h"
15 20
16 21#define DEFAULT_PORT 33445
17/* Sleep function (x = milliseconds) */ 22#define DEFAULT_PID_FILE "bootstrap_server.pid"
18#ifdef WIN32 23#define DEFAULT_KEYS_FILE "bootstrap_server.keys"
19#define c_sleep(x) Sleep(1*x) 24
20#else 25/* Server info struct */
21#include <unistd.h> 26struct server_info_s {
22#define c_sleep(x) usleep(1000*x) 27 int valid;
23#endif 28 IP_Port conn;
24 29 uint8_t bs_pk[32];
25#define PORT 33445 30};
26#define USERNAME getenv("USER") 31
27#define PIDFILE "/home/%s/.bootstrap_server.pid" /* %s represents the unser's name */ 32/* This is the struct configure_server() uses to return its data to */
28 33struct server_conf_s {
34 int err;
35 int port;
36 char pid_file[512];
37 char keys_file[512];
38 struct server_info_s info[32];
39};
40
41int b16_to_key(char b16_string[], uint8_t *bs_pubkey) {
42
43 int i;
44 unsigned int num1 = 0, num2 = 0;
45
46 for(i = 0; i < 32; ++i)
47 {
48 sscanf(&b16_string[i*2], "%1X", &num1);
49 sscanf(&b16_string[i*2+1], "%1X", &num2);
50 num1 = num1 << 4;
51 bs_pubkey[i] = bs_pubkey[i] | num1;
52 bs_pubkey[i] = bs_pubkey[i] | num2;
53 }
54 return 0;
55}
56
57/* This unction connects to all specified servers
58and connect to them.
59returns 1 if the connection to the DHT is up
60returns -1 if all attempts failed
61*/
62int connect_to_servers(struct server_info_s *info)
63{
64 int i;
65 int c;
66
67 IP_Port ip_port;
68 uint8_t data[MAX_UDP_PACKET_SIZE];
69 uint32_t length;
70
71 for(i = 0; i < 32; ++i) {
72 if(info[i].valid) {
73 /* Actual bootstrapping code goes here */
74 //puts("Calling DHT_bootstrap");
75 DHT_bootstrap(info[i].conn, info[i].bs_pk);
76 }
77 }
78
79 /* Check if we're connected to the DHT */
80 for(c = 0; c != 100; ++c) {
81 usleep(10000);
82 if(DHT_isconnected()) {
83 //puts("Connected");
84 return 1;
85 break;
86 }
87 if(DHT_isconnected() == 0 && c == 99) {
88 //puts("Not connected");
89 return -1;
90 break;
91 }
92
93 doDHT();
94
95 while(receivepacket(&ip_port, data, &length) != -1)
96 {
97 DHT_handlepacket(data, length, ip_port);
98 }
99 }
100
101 /* This probably never happens */
102 return 0;
103}
104
105void manage_keys(char *keys_file)
106{
107 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
108 uint8_t keys[KEYS_SIZE];
109
110 /* TODO: stat the file before trying to open it. We aren't cave people! */
111 FILE *keysf = fopen(keys_file, "r");
112 if (keysf != NULL) {
113 /* if file was opened successfully -- load keys */
114 size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keysf);
115 if (read_size != KEYS_SIZE) {
116 printf("Error while reading the key file\nExiting.\n");
117 exit(1);
118 } else {
119 printf("Keys loaded successfully\n");
120 }
121 load_keys(keys);
122
123 } else {
124 /* otherwise save new keys */
125 /* Silly work-around to ignore any errors coming from new_keys() */
126 new_keys();
127 save_keys(keys);
128 keysf = fopen(keys_file, "w");
129 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) {
130 printf("Error while writing the key file.\nExiting.\n");
131 exit(1);
132 } else {
133 printf("Keys saved successfully\n");
134 }
135 }
136
137 fclose(keysf);
138}
139
140/* This reads the configuration file, and returns a struct server_conf_s with:
141 *an error number:
142 *-1 = file wasn't read, for whatever reason
143 *-2 = no bootstrap servers found
144 *the port
145 *the location of the keys file
146 *the location of the PID file
147 *the list of bootstrap servers
148*/
149struct server_conf_s configure_server(char *cfg_file)
150{
151 config_t cfg;
152 config_setting_t *server_list;
153
154 /* This one will be strcpy'd into the pid_file array in server_conf */
155 const char *pid_file_tmp;
156 const char *keys_file_tmp;
157
158 /* Remote bootstrap server variables */
159 int bs_port;
160 const char *bs_ip;
161 const char *bs_pk;
162
163 /* The big struct */
164 static struct server_conf_s server_conf;
165
166 /* Set both to their default values. If there's an error
167 with opening/reading the config file, we return right away */
168 server_conf.port = DEFAULT_PORT;
169 strcpy(server_conf.pid_file, DEFAULT_PID_FILE);
170 strcpy(server_conf.keys_file, DEFAULT_KEYS_FILE);
171
172 config_init(&cfg);
173
174 /* Read the file. If there is an error, report it and exit. */
175 if(! config_read_file(&cfg, cfg_file))
176 {
177 fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
178 config_error_line(&cfg), config_error_text(&cfg));
179 config_destroy(&cfg);
180 server_conf.err = -1;
181 return server_conf;
182 }
183
184 /* Get the port to listen on */
185 if(config_lookup_int(&cfg, "port", &server_conf.port)) {
186 //printf("Port: %d\n", port);
187 } else {
188 fprintf(stderr, "No 'port' setting in configuration file.\n");
189 }
190
191 /* Get PID file location */
192 if(config_lookup_string(&cfg, "pid_file", &pid_file_tmp)) {
193 //printf("PID file: %s\n", pid_file_tmp);
194 strcpy(server_conf.pid_file, pid_file_tmp);
195 } else {
196 fprintf(stderr, "No 'pid_file' setting in configuration file.\n");
197 }
198
199 /* Get keys file location */
200 if(config_lookup_string(&cfg, "keys_file", &keys_file_tmp)) {
201 //printf("Keys file: %s\n", keys_file_tmp);
202 strcpy(server_conf.keys_file, keys_file_tmp);
203 } else {
204 fprintf(stderr, "No 'keys_file' setting in configuration file.\n");
205 }
206
207 /* Get all the servers in the list */
208 server_list = config_lookup(&cfg, "bootstrap_servers");
209 if(server_list != NULL) {
210 int count = config_setting_length(server_list);
211 int i;
212
213 char tmp_ip[30]; /* IP */
214 char tmp_pk[64]; /* bs_pk */
215 for(i = 0; i < count; ++i) {
216 config_setting_t *server = config_setting_get_elem(server_list, i);
217 /* Get a pointer on the key aray */
218 uint8_t *bs_pk_p = server_conf.info[i].bs_pk;
219
220 /* Only output the record if all of the expected fields are present. */
221 if(!(config_setting_lookup_string(server, "ip", &bs_ip)
222 && config_setting_lookup_int(server, "port", &bs_port)
223 && config_setting_lookup_string(server, "bs_pk", &bs_pk)))
224 continue;
225
226 /* Converting all that stuff into usable formats and storing
227 it away in the server_info struct */
228 server_conf.info[i].valid = 1;
229
230 if(resolve_addr(strcpy(tmp_ip, bs_ip)) == -1) {
231 server_conf.info[i].valid = 0;
232 printf("bootstrap_server %d: Invalid IP\n", i);
233 }
234
235 if(strlen(bs_pk) != 64) {
236 server_conf.info[i].valid = 0;
237 printf("bootstrap_server %d: Invalid public key\n", i);
238 }
239
240 if(!bs_port) {
241 server_conf.info[i].valid = 0;
242 printf("bootstrap_server %d: Invalid port\n", i);
243 }
244
245 server_conf.info[i].conn.ip.i = inet_addr(strcpy(tmp_ip, bs_ip));
246 server_conf.info[i].conn.port = htons(bs_port);
247 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
248 }
249
250 /* Check if at least one server entry is valid */
251 for(i = 0; i < 32; ++i) {
252 if(server_conf.info[i].valid)
253 break;
254 else
255 server_conf.err = -2;
256 }
257
258 } else {
259 server_conf.err = -2;
260 }
261
262 config_destroy(&cfg);
263 return server_conf;
264}
265
29int main(int argc, char *argv[]) { 266int main(int argc, char *argv[]) {
30 267
31 char pidfloc[512]; /* Location of the soon-to-be PID file */
32 pid_t pid, sid; /* Process- and Session-ID */ 268 pid_t pid, sid; /* Process- and Session-ID */
33 269 struct server_conf_s server_conf;
270
34 FILE *pidf; /* The PID file */ 271 FILE *pidf; /* The PID file */
35 272
36 /* Assemble PID file location an try to open the file */ 273 if(argc < 2) {
37 sprintf(pidfloc, PIDFILE, USERNAME); 274 printf("Please specify a configuration file.\n");
38 pidf = fopen(pidfloc, "w"); 275 exit(EXIT_FAILURE);
39 276 }
40 /* Generate new keypair */ 277
41 new_keys(); 278 /* Read the config file */
42 279 server_conf = configure_server(argv[1]);
280
281 printf("PID file: %s\n", server_conf.pid_file);
282 printf("Key file: %s\n", server_conf.keys_file);
283
284 if(server_conf.err == -1)
285 printf("Config file not read.\n");
286
287 if(server_conf.err == -2)
288 printf("No valid servers in list.\n");
289
290 /* Open PID file for writing - if an error happens,
291 it will be caught down the line */
292 pidf = fopen(server_conf.pid_file, "w");
293
294 /* Manage the keys */
295 /* for now, just ignore any errors after this call. */
296 int tmperr = errno;
297 manage_keys(server_conf.keys_file);
298 errno = tmperr;
299
43 /* Public key */ 300 /* Public key */
44 uint32_t i; 301 int i;
45
46 printf("\nPublic Key: "); 302 printf("\nPublic Key: ");
47 for(i = 0; i < 32; i++) 303 for(i = 0; i < 32; ++i)
48 { 304 {
49 uint8_t ln, hn; 305 uint8_t ln, hn;
50 ln = 0x0F & self_public_key[i]; 306 ln = 0x0F & self_public_key[i];
@@ -53,84 +309,95 @@ int main(int argc, char *argv[]) {
53 printf("%X%X", hn, ln); 309 printf("%X%X", hn, ln);
54 } 310 }
55 printf("\n"); 311 printf("\n");
56 312
57 /* initialize networking 313 /* initialize networking
58 bind to ip 0.0.0.0:PORT */ 314 bind to ip 0.0.0.0:PORT */
59 IP ip; 315 IP ip;
60 ip.i = 0; 316 ip.i = 0;
61 init_networking(ip, PORT); 317 init_networking(ip, server_conf.port);
62 318
319 /* Bootstrap the DHT
320 This one throws odd errors, too. Ignore. I assume they come
321 from somewhere in the core. */
322 tmperr = errno;
323 connect_to_servers(server_conf.info);
324 errno = tmperr;
325
326 if(!DHT_isconnected()) {
327 puts("Could not establish DHT connection. Check server settings.\n");
328 exit(EXIT_FAILURE);
329 } else {
330 printf("Connected to DHT successfully.\n");
331 }
332
63 /* If there's been an error, exit before forking off */ 333 /* If there's been an error, exit before forking off */
64 if (errno != 0) { 334 if (errno != 0) {
65 perror("Error"); 335 perror("Error");
66 printf("Error(s) occured during start-up. Exiting.\n"); 336 printf("Error(s) occured during start-up. Exiting.\n");
67 exit(EXIT_FAILURE); 337 exit(EXIT_FAILURE);
68 } 338 }
69 339
70// /* Assemble the location of the PID file */ 340 /* Things that make the daemon work come past here.
71// sprintf(pidfloc, PIDFILE, USERNAME); 341 There should be nothing here but the daemon code and
72// pidf = fopen(pidfloc, "w"); 342 the main loop. */
73// /* Check if we can actually open the file */ 343
74// if(pidf == NULL) { 344 /* Fork off from the parent process */
75// printf("Couldn't open PID-File %s for writing.\n", pidfloc);
76// exit(EXIT_FAILURE);
77// }
78
79 /* Fork off the parent process */
80 pid = fork(); 345 pid = fork();
81 if (pid < 0) { 346 if (pid < 0) {
82 printf("Forking failed.\n"); 347 printf("Forking failed.\n");
83 exit(EXIT_FAILURE); 348 exit(EXIT_FAILURE);
84 } 349 }
85 350
86 /* If we got a good PID, then 351 /* If we got a good PID, then
87 we can exit the parent process. */ 352 we can exit the parent process. */
88 if (pid > 0) { 353 if (pid > 0) {
89 printf("Forked successfully: %d\n", pid); 354 printf("Forked successfully: %d\n", pid);
90 355
91 /* Write the PID file */ 356 /* Write the PID file */
92 fprintf(pidf, "%d\n", pid); 357 fprintf(pidf, "%d\n", pid);
93 fclose(pidf); 358 fclose(pidf);
94 359
95 /* Exit parent */ 360 /* Exit parent */
96 exit(EXIT_SUCCESS); 361 exit(EXIT_SUCCESS);
97 } 362 }
98 363
99 /* Change the file mode mask */ 364 /* Change the file mode mask */
100 umask(0); 365 umask(0);
101 366
102 /* Create a new SID for the child process */ 367 /* Create a new SID for the child process */
103 sid = setsid(); 368 sid = setsid();
104 if (sid < 0) { 369 if (sid < 0) {
105 printf("SID creation failure.\n"); 370 printf("SID creation failure.\n");
106 exit(EXIT_FAILURE); 371 exit(EXIT_FAILURE);
107 } 372 }
108 373
109 /* Change the current working directory */ 374 /* Change the current working directory */
110 if ((chdir("/")) < 0) { 375 if ((chdir("/")) < 0) {
111 exit(EXIT_FAILURE); 376 exit(EXIT_FAILURE);
112 } 377 }
113 378
114 /* Go quiet */ 379 /* Go quiet */
115 close(STDIN_FILENO);
116 close(STDOUT_FILENO); 380 close(STDOUT_FILENO);
381 close(STDIN_FILENO);
117 close(STDERR_FILENO); 382 close(STDERR_FILENO);
118 383
384 /* Main loop */
119 IP_Port ip_port; 385 IP_Port ip_port;
120 uint8_t data[MAX_UDP_PACKET_SIZE]; 386 uint8_t data[MAX_UDP_PACKET_SIZE];
121 uint32_t length; 387 uint32_t length;
122 388
123 /* Main loop */ 389 while(1)
124 while(1) { 390 {
125 doDHT(); 391 doDHT();
126 while(receivepacket(&ip_port, data, &length) != -1) { 392
393 while(receivepacket(&ip_port, data, &length) != -1)
394 {
127 DHT_handlepacket(data, length, ip_port); 395 DHT_handlepacket(data, length, ip_port);
128 friendreq_handlepacket(data, length, ip_port); 396 friendreq_handlepacket(data, length, ip_port);
129 } 397 }
130 c_sleep(1); 398 usleep(10000);
131 } 399 }
132 400
133 shutdown_networking(); 401 shutdown_networking();
134 exit(EXIT_SUCCESS); 402 exit(EXIT_SUCCESS);
135} 403}
136