summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorGDR! <gdr@go2.pl>2014-11-15 20:14:53 +0100
committerGDR! <gdr@go2.pl>2014-11-15 20:14:53 +0100
commit9b523f2b826dea54613f2eac78f754c9772841b6 (patch)
treecf566f5bbabb5a5e29e81d40c6df447d76b6a7bd /main.c
parent3b42ed1ca1be6d1c8f14606befee8b8deae64ac8 (diff)
creating tunnels half-made
Diffstat (limited to 'main.c')
-rw-r--r--main.c599
1 files changed, 540 insertions, 59 deletions
diff --git a/main.c b/main.c
index 2d09e2e..661f5dd 100644
--- a/main.c
+++ b/main.c
@@ -1,16 +1,3 @@
1#include <arpa/inet.h>
2#include <errno.h>
3#include <netdb.h>
4#include <netinet/in.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/socket.h>
9#include <sys/time.h>
10#include <sys/types.h>
11#include <tox/tox.h>
12#include <unistd.h>
13
14#include "main.h" 1#include "main.h"
15#include "tox_bootstrap.h" 2#include "tox_bootstrap.h"
16 3
@@ -18,6 +5,80 @@ static Tox_Options tox_options;
18static Tox *tox; 5static Tox *tox;
19int client_socket = 0; 6int client_socket = 0;
20 7
8/** CONFIGURATION OPTIONS **/
9/* Whether we're a client */
10int client_mode = 0;
11/* Just send a ping and exit */
12int ping_mode = 0;
13/* Remote Tox ID in client mode */
14char *remote_tox_id = NULL;
15/* Ports and hostname for port forwarding */
16int remote_port = 0;
17char *remote_host = NULL;
18int local_port = 0;
19
20/* The state machine */
21int state = CLIENT_STATE_INITIAL;
22
23/* Used in ping mode */
24struct timespec ping_sent_time;
25
26/* Client mode tunnel */
27tunnel client_tunnel;
28
29/* We keep two hash tables: one indexed by sockfd and another by "connection id" */
30tunnel *by_id = NULL;
31tunnel *by_fd = NULL;
32
33/* Generate an unique tunnel ID. To be used in a server. */
34uint16_t get_random_tunnel_id()
35{
36 while(1)
37 {
38 int key;
39 uint16_t tunnel_id;
40 tunnel *tun;
41
42 tunnel_id = (uint16_t)rand();
43 key = tunnel_id;
44
45 HASH_FIND_INT(by_id, &key, tun);
46 if(!tun)
47 {
48 return tunnel_id;
49 }
50 fprintf(stderr, "[i] Found duplicated tunnel ID %d\n", key);
51 }
52}
53
54/* Constructor. Returns NULL on failure. */
55static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber)
56{
57 tunnel *t = NULL;
58
59 t = calloc(1, sizeof(tunnel));
60 if(!t)
61 {
62 return NULL;
63 }
64
65 t->sockfd = sockfd;
66 t->connid = connid;
67 t->friendnumber = friendnumber;
68
69 HASH_ADD_INT( by_id, connid, t );
70 HASH_ADD_INT( by_fd, sockfd, t );
71
72 return t;
73}
74
75static void tunnel_delete(tunnel *t)
76{
77 HASH_DEL( by_id, t );
78 HASH_DEL( by_fd, t );
79 free(t);
80}
81
21static void writechecksum(uint8_t *address) 82static void writechecksum(uint8_t *address)
22{ 83{
23 uint8_t *checksum = address + 36; 84 uint8_t *checksum = address + 36;
@@ -30,7 +91,8 @@ static void writechecksum(uint8_t *address)
30/* From utox/util.c */ 91/* From utox/util.c */
31static void to_hex(char_t *a, const char_t *p, int size) 92static void to_hex(char_t *a, const char_t *p, int size)
32{ 93{
33 char_t b, c, *end = p + size; 94 char_t b, c;
95 const char_t *end = p + size;
34 96
35 while(p != end) { 97 while(p != end) {
36 b = *p++; 98 b = *p++;
@@ -58,6 +120,42 @@ void id_to_string(char_t *dest, const char_t *src)
58 to_hex(dest, src, TOX_FRIEND_ADDRESS_SIZE); 120 to_hex(dest, src, TOX_FRIEND_ADDRESS_SIZE);
59} 121}
60 122
123/* From utox/util.c */
124int string_to_id(char_t *w, char_t *a)
125{
126 char_t *end = w + TOX_FRIEND_ADDRESS_SIZE;
127 while(w != end) {
128 char_t c, v;
129
130 c = *a++;
131 if(c >= '0' && c <= '9') {
132 v = (c - '0') << 4;
133 } else if(c >= 'A' && c <= 'F') {
134 v = (c - 'A' + 10) << 4;
135 } else if(c >= 'a' && c <= 'f') {
136 v = (c - 'a' + 10) << 4;
137 } else {
138 return 0;
139 }
140
141 c = *a++;
142 if(c >= '0' && c <= '9') {
143 v |= (c - '0');
144 } else if(c >= 'A' && c <= 'F') {
145 v |= (c - 'A' + 10);
146 } else if(c >= 'a' && c <= 'f') {
147 v |= (c - 'a' + 10);
148 } else {
149 return 0;
150 }
151
152 *w++ = v;
153 }
154
155 return 1;
156}
157
158
61/* bootstrap to dht with bootstrap_nodes */ 159/* bootstrap to dht with bootstrap_nodes */
62/* From uTox/tox.c */ 160/* From uTox/tox.c */
63static void do_bootstrap(Tox *tox) 161static void do_bootstrap(Tox *tox)
@@ -107,28 +205,6 @@ void set_tox_username(Tox *tox)
107 205
108// freeaddrinfo(info); 206// freeaddrinfo(info);
109} 207}
110
111void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
112{
113 unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1];
114
115 printf("Got friend request\n");
116 tox_add_friend_norequest(tox, public_key);
117 id_to_string(tox_printable_id, public_key);
118 printf("Accepted friend request from %s\n", tox_printable_id);
119}
120
121void cleanup(int status, void *tmp)
122{
123 printf("kthxbye\n");
124 fflush(stdout);
125 tox_kill(tox);
126 if(client_socket)
127 {
128 close(client_socket);
129 }
130}
131
132// get sockaddr, IPv4 or IPv6: 208// get sockaddr, IPv4 or IPv6:
133/* From Beej */ 209/* From Beej */
134void *get_in_addr(struct sockaddr *sa) 210void *get_in_addr(struct sockaddr *sa)
@@ -141,15 +217,13 @@ void *get_in_addr(struct sockaddr *sa)
141} 217}
142 218
143/* From Beej */ 219/* From Beej */
144int get_client_socket() 220int get_client_socket(char *hostname, int port)
145{ 221{
146 int sockfd, numbytes; 222 int sockfd, numbytes;
147 char buf[READ_BUFFER_SIZE]; 223 char buf[READ_BUFFER_SIZE];
148 struct addrinfo hints, *servinfo, *p; 224 struct addrinfo hints, *servinfo, *p;
149 int rv; 225 int rv;
150 char s[INET6_ADDRSTRLEN]; 226 char s[INET6_ADDRSTRLEN];
151 int port = 22;
152 char hostname[4096] = "127.0.0.1";
153 char port_str[6]; 227 char port_str[6];
154 228
155 snprintf(port_str, 6, "%d", port); 229 snprintf(port_str, 6, "%d", port);
@@ -160,7 +234,7 @@ int get_client_socket()
160 234
161 if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { 235 if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) {
162 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 236 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
163 exit(1); 237 return -1;
164 } 238 }
165 239
166 // loop through all the results and connect to the first we can 240 // loop through all the results and connect to the first we can
@@ -196,20 +270,275 @@ int get_client_socket()
196 return sockfd; 270 return sockfd;
197} 271}
198 272
199unsigned int create_packet(unsigned char *dst, unsigned char *data, int data_len, int sockfd) 273/* Proto - our protocol handling */
274
275/*
276 * send_frame: (almost) zero-copy. Overwrites first PROTOCOL_BUFFER_OFFSET bytes of data
277 * so actual data should start at position PROTOCOL_BUFFER_OFFSET
278 */
279int send_frame(protocol_frame *frame, uint8_t *data)
280{
281 int rv;
282
283 data[0] = PROTOCOL_MAGIC_HIGH;
284 data[1] = PROTOCOL_MAGIC_LOW;
285 data[2] = BYTE2(frame->packet_type);
286 data[3] = BYTE1(frame->packet_type);
287 data[4] = BYTE2(frame->connid);
288 data[5] = BYTE1(frame->connid);
289 data[6] = BYTE2(frame->data_length);
290 data[7] = BYTE1(frame->data_length);
291
292 rv = tox_send_lossless_packet(
293 tox,
294 frame->friendnumber,
295 data,
296 frame->data_length + PROTOCOL_BUFFER_OFFSET
297 );
298
299 if(rv < 0)
300 {
301 fprintf(stderr, "Failed to send packet to friend %d\n", frame->friendnumber);
302 }
303
304 return rv;
305}
306
307int handle_ping_frame(protocol_frame *rcvd_frame)
200{ 308{
201// assert data_len < 65536 309 uint8_t data[TOX_MAX_CUSTOM_PACKET_SIZE];
202 dst[0] = 0xa2; 310 protocol_frame frame_s;
203 dst[1] = 0x6a; 311 protocol_frame *frame = &frame_s;
204 dst[2] = sockfd >> 8; 312
205 dst[3] = sockfd & 0xff; 313 frame->data = data + PROTOCOL_BUFFER_OFFSET;
206 dst[4] = (data_len >> 8) & 0xff; 314 memcpy(frame->data, rcvd_frame->data, rcvd_frame->data_length);
207 dst[5] = data_len & 0xff; 315
208 memcpy(dst+PROTOCOL_BUFFER_OFFSET, data, data_len); 316 frame->friendnumber = rcvd_frame->friendnumber;
209 return data_len + PROTOCOL_BUFFER_OFFSET; 317 frame->packet_type = PACKET_TYPE_PONG;
318 frame->data_length = rcvd_frame->data_length;
319
320 send_frame(frame, data);
210} 321}
211 322
212int do_loop() 323int handle_pong_frame(protocol_frame *rcvd_frame)
324{
325 struct timespec pong_rcvd_time;
326 double secs1, secs2;
327
328 clock_gettime(CLOCK_MONOTONIC, &pong_rcvd_time);
329
330 secs1 = (1.0 * ping_sent_time.tv_sec) + (1e-9 * ping_sent_time.tv_nsec);
331 secs2 = (1.0 * pong_rcvd_time.tv_sec) + (1e-9 * pong_rcvd_time.tv_nsec);
332
333 printf("GOT PONG! Time = %.3fs\n", secs2-secs1);
334
335 if(ping_mode)
336 {
337// state = CLIENT_STATE_PONG_RECEIVED;
338 state = CLIENT_STATE_SEND_PING;
339 }
340}
341
342int handle_request_tunnel_frame(protocol_frame *rcvd_frame)
343{
344 char *hostname = NULL;
345 tunnel *tun;
346 int port = -1;
347 int sockfd = 0;
348 uint16_t tunnel_id;
349
350 if(client_mode)
351 {
352 fprintf(stderr, "Got tunnel request frame from friend #%d when in client mode\n", rcvd_frame->friendnumber);
353 return -1;
354 }
355
356 port = rcvd_frame->connid;
357 hostname = calloc(1, rcvd_frame->data_length + 1);
358 if(!hostname)
359 {
360 fprintf(stderr, "Could not allocate memory for tunnel request hostname\n");
361 return -1;
362 }
363
364 strncpy(hostname, rcvd_frame->data, rcvd_frame->data_length);
365 hostname[rcvd_frame->data_length] = '\0';
366
367 printf("Got a request to forward data from %s:%d\n", hostname, port);
368
369 tunnel_id = get_random_tunnel_id();
370 printf("Tunnel ID: %d\n", tunnel_id);
371 /* TODO make connection */
372 sockfd = get_client_socket(hostname, port);
373 if(sockfd > 0)
374 {
375 tun = tunnel_create(sockfd, tunnel_id, rcvd_frame->friendnumber);
376 if(tun)
377 {
378 fprintf(stderr, "Created tunnel, yay!\n");
379 /* TODO send ack */
380 }
381 else
382 {
383 fprintf(stderr, "Couldn't allocate memory for tunnel\n");
384 }
385 }
386 else
387 {
388 fprintf(stderr, "Could not connect to %s:%d\n", hostname, port);
389 /* TODO send reject */
390 }
391
392}
393
394/* This is a dispatcher for our encapsulated protocol */
395int handle_frame(protocol_frame *frame)
396{
397 switch(frame->packet_type)
398 {
399 case PACKET_TYPE_PING:
400 return handle_ping_frame(frame);
401 break;
402 case PACKET_TYPE_PONG:
403 return handle_pong_frame(frame);
404 break;
405 case PACKET_TYPE_TCP:
406 break;
407 case PACKET_TYPE_REQUESTTUNNEL:
408 handle_request_tunnel_frame(frame);
409 break;
410 default:
411 fprintf(stderr, "Got unknown packet type 0x%x from friend %d\n",
412 frame->packet_type,
413 frame->friendnumber
414 );
415 }
416
417 return 0;
418}
419
420/*
421 * This is a callback which gets a packet from Tox core.
422 * It checks for basic inconsistiencies and allocates the
423 * protocol_frame structure.
424 */
425int parse_lossless_packet(void *sender_uc, const uint8_t *data, uint32_t len)
426{
427 protocol_frame *frame = NULL;
428
429 if(len < PROTOCOL_BUFFER_OFFSET)
430 {
431 fprintf(stderr, "Received too short data frame - only %d bytes, at least %d expected\n", len, PROTOCOL_BUFFER_OFFSET);
432 return -1;
433 }
434
435 if(data[0] != PROTOCOL_MAGIC_HIGH || data[1] != PROTOCOL_MAGIC_LOW)
436 {
437 fprintf(stderr, "Received data frame with invalid protocol magic number 0x%x%x\n", data[0], data[1]);
438 return -1;
439 }
440
441 frame = calloc(1, sizeof(protocol_frame));
442 if(!frame)
443 {
444 fprintf(stderr, "Could not allocate memory for protocol_frame_t\n");
445 return -1;
446 }
447
448 /* TODO check if friendnumber is the same in sender and connid tunnel*/
449 frame->magic = INT16_AT(data, 0);
450 frame->packet_type = INT16_AT(data, 2);
451 frame->connid = INT16_AT(data, 4);
452 frame->data_length = INT16_AT(data, 6);
453 frame->data = data + PROTOCOL_BUFFER_OFFSET;
454 frame->friendnumber = *((uint32_t*)sender_uc);
455 printf("Got protocol frame magic 0x%x type 0x%x from friend %d\n", frame->magic, frame->packet_type, frame->friendnumber);
456
457 if(len < frame->data_length + PROTOCOL_BUFFER_OFFSET)
458 {
459 fprintf(stderr, "Received frame too small (attempted buffer overflow?): %d bytes, excepted at least %d bytes\n", len, frame->data_length + PROTOCOL_BUFFER_OFFSET);
460 return -1;
461 }
462
463 if(frame->data_length > (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET))
464 {
465 fprintf(stderr, "Declared data length too big (attempted buffer overflow?): %d bytes, excepted at most %d bytes\n", frame->data_length, (TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET));
466 return -1;
467 }
468
469 handle_frame(frame);
470}
471
472int send_tunnel_request_packet(char *remote_host, int remote_port, int friend_number)
473{
474 int packet_length = 0;
475 protocol_frame frame_i, *frame;
476 char *data = NULL;
477
478 fprintf(stderr, "Sending packet to friend #%d to forward %s:%d\n", friend_number, remote_host, remote_port);
479 packet_length = PROTOCOL_BUFFER_OFFSET + strlen(remote_host);
480 frame = &frame_i;
481
482 data = calloc(1, packet_length);
483 if(!data)
484 {
485 fprintf(stderr, "Could not allocate memory for tunnel request packet\n");
486 exit(1);
487 }
488 strcpy(data+PROTOCOL_BUFFER_OFFSET, remote_host);
489
490 frame->friendnumber = friend_number;
491 frame->packet_type = PACKET_TYPE_REQUESTTUNNEL;
492 frame->connid = remote_port;
493 frame->data_length = strlen(remote_host);
494
495 send_frame(frame, data);
496
497 free(data);
498 return 0;
499}
500
501/* End proto */
502
503void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
504{
505 unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1];
506 int32_t friendnumber;
507 int32_t *friendnumber_ptr = NULL;
508
509 printf("Got friend request\n");
510
511 friendnumber = tox_add_friend_norequest(tox, public_key);
512
513 id_to_string(tox_printable_id, public_key);
514 printf("Accepted friend request from %s as %d\n", tox_printable_id, friendnumber);
515
516 /* TODO: this is not freed right now, we're leaking 4 bytes per contact (OMG!) */
517 friendnumber_ptr = malloc(sizeof(int32_t));
518 if(!friendnumber_ptr)
519 {
520 fprintf(stderr, "Could not allocate memory for friendnumber_ptr\n");
521 return;
522 }
523
524 *friendnumber_ptr = friendnumber;
525
526 tox_lossless_packet_registerhandler(tox, friendnumber, (PROTOCOL_MAGIC_V1)>>8, parse_lossless_packet, (void*)friendnumber_ptr);
527}
528
529void cleanup(int status, void *tmp)
530{
531 printf("kthxbye\n");
532 fflush(stdout);
533 tox_kill(tox);
534 if(client_socket)
535 {
536 close(client_socket);
537 }
538}
539
540
541int do_server_loop()
213{ 542{
214 struct timeval tv; 543 struct timeval tv;
215 fd_set fds; 544 fd_set fds;
@@ -221,7 +550,7 @@ int do_loop()
221 tv.tv_usec = 20000; 550 tv.tv_usec = 20000;
222 551
223 FD_ZERO(&fds); 552 FD_ZERO(&fds);
224 FD_SET(client_socket, &fds); 553// FD_SET(client_socket, &fds);
225 554
226 master = fds; 555 master = fds;
227 556
@@ -245,8 +574,6 @@ int do_loop()
245 { 574 {
246 unsigned int tox_packet_length = 0; 575 unsigned int tox_packet_length = 0;
247 read_buf[nbytes] = '\0'; 576 read_buf[nbytes] = '\0';
248 tox_packet_length = create_packet(tox_packet_buf, read_buf, nbytes, client_socket);
249 tox_send_lossless_packet(tox, 0, tox_packet_buf, tox_packet_length);
250 printf("READ: %s\n", read_buf); 577 printf("READ: %s\n", read_buf);
251 } 578 }
252 } 579 }
@@ -255,10 +582,157 @@ int do_loop()
255 } 582 }
256} 583}
257 584
585int do_client_loop(char *tox_id_str)
586{
587 unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE];
588 unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE];
589 uint32_t friendnumber;
590
591 if(!string_to_id(tox_id, tox_id_str))
592 {
593 fprintf(stderr, "Invalid Tox ID");
594 exit(1);
595 }
596
597 fprintf(stderr, "Connecting to Tox...\n");
598
599 while(1)
600 {
601 /* Let tox do its stuff */
602 tox_do(tox);
603
604 switch(state)
605 {
606 /*
607 * Send friend request
608 */
609 case CLIENT_STATE_INITIAL:
610 if(tox_isconnected(tox))
611 {
612 state = CLIENT_STATE_CONNECTED;
613 }
614 break;
615 case CLIENT_STATE_CONNECTED:
616 {
617 uint8_t data[] = "Hi, fellow tuntox instance!";
618 uint16_t length = sizeof(data);
619
620 fprintf(stderr, "Connected. Sending friend request.\n");
621
622 friendnumber = tox_add_friend(
623 tox,
624 tox_id,
625 data,
626 length
627 );
628
629 if(friendnumber < 0)
630 {
631 fprintf(stderr, "Error %d adding friend %s\n", friendnumber, tox_id);
632 exit(-1);
633 }
634
635 tox_lossless_packet_registerhandler(tox, friendnumber, (PROTOCOL_MAGIC_V1)>>8, parse_lossless_packet, (void*)&friendnumber);
636 state = CLIENT_STATE_SENTREQUEST;
637 fprintf(stderr, "Waiting for friend to accept us...\n");
638 }
639 break;
640 case CLIENT_STATE_SENTREQUEST:
641 if(tox_get_friend_connection_status(tox, friendnumber) == 1)
642 {
643 fprintf(stderr, "Friend request accepted!\n");
644 state = CLIENT_STATE_REQUEST_ACCEPTED;
645 }
646 else
647 {
648 }
649 break;
650 case CLIENT_STATE_REQUEST_ACCEPTED:
651 if(ping_mode)
652 {
653 state = CLIENT_STATE_SEND_PING;
654 }
655 else
656 {
657 state = CLIENT_STATE_REQUEST_TUNNEL;
658 }
659 break;
660 case CLIENT_STATE_SEND_PING:
661 /* Send the ping packet */
662 {
663 uint8_t data[] = {
664 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05,
665 0x48, 0x65, 0x6c, 0x6c, 0x6f
666 };
667
668 clock_gettime(CLOCK_MONOTONIC, &ping_sent_time);
669 tox_send_lossless_packet(
670 tox,
671 friendnumber,
672 data,
673 sizeof(data)
674 );
675 }
676 state = CLIENT_STATE_PING_SENT;
677 break;
678 case CLIENT_STATE_PING_SENT:
679 /* Just sit there and wait for pong */
680 break;
681 case CLIENT_STATE_REQUEST_TUNNEL:
682 send_tunnel_request_packet(
683 "127.0.0.1",
684 remote_port,
685 friendnumber
686 );
687 state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL;
688 break;
689 case CLIENT_STATE_WAIT_FOR_ACKTUNNEL:
690 break;
691 }
692
693 usleep(tox_do_interval(tox) * 1000);
694 }
695}
696
697void help()
698{
699 fprintf(stderr, "tuntox - Forward ports over the Tox protocol\n");
700 fprintf(stderr, "USAGE:\n\n");
701 fprintf(stderr, "-i <toxid> - remote point Tox ID\n");
702 fprintf(stderr, "-L <localport>:<remotehostname>:<remoteport> - forward <remotehostname>:<remoteport> to 127.0.0.1:<localport>\n");
703 fprintf(stderr, "-p - ping the server from -i and exit\n");
704}
705
258int main(int argc, char *argv[]) 706int main(int argc, char *argv[])
259{ 707{
260 unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE]; 708 unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE];
261 unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1]; 709 unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1];
710 int oc;
711
712 while ((oc = getopt(argc, argv, "L:pi:")) != -1)
713 {
714 switch(oc)
715 {
716 case 'L':
717 /* Local port forwarding */
718 client_mode = 1;
719 remote_port = atoi(optarg);
720 fprintf(stderr, "Forwarding remote port %d\n", remote_port);
721 break;
722 case 'p':
723 /* Ping */
724 client_mode = 1;
725 ping_mode = 1;
726 break;
727 case 'i':
728 remote_tox_id = optarg;
729 break;
730 case '?':
731 default:
732 help();
733 exit(1);
734 }
735 }
262 736
263 on_exit(cleanup, NULL); 737 on_exit(cleanup, NULL);
264 738
@@ -269,8 +743,6 @@ int main(int argc, char *argv[])
269 743
270 tox = tox_new(&tox_options); 744 tox = tox_new(&tox_options);
271 745
272 tox_callback_friend_request(tox, accept_friend_request, NULL);
273
274 set_tox_username(tox); 746 set_tox_username(tox);
275 747
276 tox_get_address(tox, tox_id); 748 tox_get_address(tox, tox_id);
@@ -280,10 +752,19 @@ int main(int argc, char *argv[])
280 752
281 do_bootstrap(tox); 753 do_bootstrap(tox);
282 754
283 /* Connect to the forwarded service */ 755 /* TODO use proper argparse */
284 client_socket = get_client_socket(); 756 if(client_mode)
757 {
758 do_client_loop(remote_tox_id);
759 }
760 else
761 {
762 /* Connect to the forwarded service */
763// client_socket = get_client_socket();
285 764
286 do_loop(); 765 tox_callback_friend_request(tox, accept_friend_request, NULL);
766 do_server_loop();
767 }
287 768
288 return 0; 769 return 0;
289} 770}