diff options
author | GDR! <gdr@go2.pl> | 2014-11-16 03:54:56 +0100 |
---|---|---|
committer | GDR! <gdr@go2.pl> | 2014-11-16 03:54:56 +0100 |
commit | c311fb3bdd2c26c347c2dd734f97003ac0538037 (patch) | |
tree | 09ec99c8722049f77b08db307e8a5388aa7cb029 /main.c | |
parent | 9b523f2b826dea54613f2eac78f754c9772841b6 (diff) |
TCP works, yay
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 431 |
1 files changed, 193 insertions, 238 deletions
@@ -1,8 +1,9 @@ | |||
1 | #include "main.h" | 1 | #include "main.h" |
2 | #include "client.h" | ||
2 | #include "tox_bootstrap.h" | 3 | #include "tox_bootstrap.h" |
3 | 4 | ||
4 | static Tox_Options tox_options; | 5 | static Tox_Options tox_options; |
5 | static Tox *tox; | 6 | Tox *tox; |
6 | int client_socket = 0; | 7 | int client_socket = 0; |
7 | 8 | ||
8 | /** CONFIGURATION OPTIONS **/ | 9 | /** CONFIGURATION OPTIONS **/ |
@@ -10,6 +11,10 @@ int client_socket = 0; | |||
10 | int client_mode = 0; | 11 | int client_mode = 0; |
11 | /* Just send a ping and exit */ | 12 | /* Just send a ping and exit */ |
12 | int ping_mode = 0; | 13 | int ping_mode = 0; |
14 | /* Open a local port and forward it */ | ||
15 | int client_local_port_mode = 0; | ||
16 | /* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ | ||
17 | int client_pipe_mode = 0; | ||
13 | /* Remote Tox ID in client mode */ | 18 | /* Remote Tox ID in client mode */ |
14 | char *remote_tox_id = NULL; | 19 | char *remote_tox_id = NULL; |
15 | /* Ports and hostname for port forwarding */ | 20 | /* Ports and hostname for port forwarding */ |
@@ -17,19 +22,15 @@ int remote_port = 0; | |||
17 | char *remote_host = NULL; | 22 | char *remote_host = NULL; |
18 | int local_port = 0; | 23 | int local_port = 0; |
19 | 24 | ||
20 | /* The state machine */ | 25 | fd_set master_server_fds; |
21 | int state = CLIENT_STATE_INITIAL; | ||
22 | |||
23 | /* Used in ping mode */ | ||
24 | struct timespec ping_sent_time; | ||
25 | |||
26 | /* Client mode tunnel */ | ||
27 | tunnel client_tunnel; | ||
28 | 26 | ||
29 | /* We keep two hash tables: one indexed by sockfd and another by "connection id" */ | 27 | /* We keep two hash tables: one indexed by sockfd and another by "connection id" */ |
30 | tunnel *by_id = NULL; | 28 | tunnel *by_id = NULL; |
31 | tunnel *by_fd = NULL; | 29 | tunnel *by_fd = NULL; |
32 | 30 | ||
31 | /* Highest used fd + 1 for select() */ | ||
32 | int select_nfds = 4; | ||
33 | |||
33 | /* Generate an unique tunnel ID. To be used in a server. */ | 34 | /* Generate an unique tunnel ID. To be used in a server. */ |
34 | uint16_t get_random_tunnel_id() | 35 | uint16_t get_random_tunnel_id() |
35 | { | 36 | { |
@@ -51,6 +52,15 @@ uint16_t get_random_tunnel_id() | |||
51 | } | 52 | } |
52 | } | 53 | } |
53 | 54 | ||
55 | void update_select_nfds(int fd) | ||
56 | { | ||
57 | /* TODO maybe replace with a scan every time to make select() more efficient in the long run? */ | ||
58 | if(fd + 1 > select_nfds) | ||
59 | { | ||
60 | select_nfds = fd + 1; | ||
61 | } | ||
62 | } | ||
63 | |||
54 | /* Constructor. Returns NULL on failure. */ | 64 | /* Constructor. Returns NULL on failure. */ |
55 | static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) | 65 | static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) |
56 | { | 66 | { |
@@ -66,96 +76,24 @@ static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) | |||
66 | t->connid = connid; | 76 | t->connid = connid; |
67 | t->friendnumber = friendnumber; | 77 | t->friendnumber = friendnumber; |
68 | 78 | ||
79 | update_select_nfds(t->sockfd); | ||
80 | |||
69 | HASH_ADD_INT( by_id, connid, t ); | 81 | HASH_ADD_INT( by_id, connid, t ); |
70 | HASH_ADD_INT( by_fd, sockfd, t ); | ||
71 | 82 | ||
72 | return t; | 83 | return t; |
73 | } | 84 | } |
74 | 85 | ||
75 | static void tunnel_delete(tunnel *t) | 86 | static void tunnel_delete(tunnel *t) |
76 | { | 87 | { |
88 | printf("Deleting tunnel #%d\n", t->connid); | ||
89 | if(t->sockfd) | ||
90 | { | ||
91 | close(t->sockfd); | ||
92 | } | ||
77 | HASH_DEL( by_id, t ); | 93 | HASH_DEL( by_id, t ); |
78 | HASH_DEL( by_fd, t ); | ||
79 | free(t); | 94 | free(t); |
80 | } | 95 | } |
81 | 96 | ||
82 | static void writechecksum(uint8_t *address) | ||
83 | { | ||
84 | uint8_t *checksum = address + 36; | ||
85 | uint32_t i; | ||
86 | |||
87 | for (i = 0; i < 36; ++i) | ||
88 | checksum[i % 2] ^= address[i]; | ||
89 | } | ||
90 | |||
91 | /* From utox/util.c */ | ||
92 | static void to_hex(char_t *a, const char_t *p, int size) | ||
93 | { | ||
94 | char_t b, c; | ||
95 | const char_t *end = p + size; | ||
96 | |||
97 | while(p != end) { | ||
98 | b = *p++; | ||
99 | |||
100 | c = (b & 0xF); | ||
101 | b = (b >> 4); | ||
102 | |||
103 | if(b < 10) { | ||
104 | *a++ = b + '0'; | ||
105 | } else { | ||
106 | *a++ = b - 10 + 'A'; | ||
107 | } | ||
108 | |||
109 | if(c < 10) { | ||
110 | *a++ = c + '0'; | ||
111 | } else { | ||
112 | *a++ = c - 10 + 'A'; | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* From utox/util.c */ | ||
118 | void id_to_string(char_t *dest, const char_t *src) | ||
119 | { | ||
120 | to_hex(dest, src, TOX_FRIEND_ADDRESS_SIZE); | ||
121 | } | ||
122 | |||
123 | /* From utox/util.c */ | ||
124 | int 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 | |||
159 | /* bootstrap to dht with bootstrap_nodes */ | 97 | /* bootstrap to dht with bootstrap_nodes */ |
160 | /* From uTox/tox.c */ | 98 | /* From uTox/tox.c */ |
161 | static void do_bootstrap(Tox *tox) | 99 | static void do_bootstrap(Tox *tox) |
@@ -304,6 +242,23 @@ int send_frame(protocol_frame *frame, uint8_t *data) | |||
304 | return rv; | 242 | return rv; |
305 | } | 243 | } |
306 | 244 | ||
245 | int send_tunnel_ack_frame(tunnel *tun) | ||
246 | { | ||
247 | protocol_frame frame_st; | ||
248 | protocol_frame *frame; | ||
249 | char data[PROTOCOL_BUFFER_OFFSET]; | ||
250 | |||
251 | frame = &frame_st; | ||
252 | memset(frame, 0, sizeof(protocol_frame)); | ||
253 | |||
254 | frame->packet_type = PACKET_TYPE_ACKTUNNEL; | ||
255 | frame->connid = tun->connid; | ||
256 | frame->data_length = 0; | ||
257 | frame->friendnumber = tun->friendnumber; | ||
258 | |||
259 | return send_frame(frame, data); | ||
260 | } | ||
261 | |||
307 | int handle_ping_frame(protocol_frame *rcvd_frame) | 262 | int handle_ping_frame(protocol_frame *rcvd_frame) |
308 | { | 263 | { |
309 | uint8_t data[TOX_MAX_CUSTOM_PACKET_SIZE]; | 264 | uint8_t data[TOX_MAX_CUSTOM_PACKET_SIZE]; |
@@ -320,25 +275,6 @@ int handle_ping_frame(protocol_frame *rcvd_frame) | |||
320 | send_frame(frame, data); | 275 | send_frame(frame, data); |
321 | } | 276 | } |
322 | 277 | ||
323 | int 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 | |||
342 | int handle_request_tunnel_frame(protocol_frame *rcvd_frame) | 278 | int handle_request_tunnel_frame(protocol_frame *rcvd_frame) |
343 | { | 279 | { |
344 | char *hostname = NULL; | 280 | char *hostname = NULL; |
@@ -375,8 +311,10 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) | |||
375 | tun = tunnel_create(sockfd, tunnel_id, rcvd_frame->friendnumber); | 311 | tun = tunnel_create(sockfd, tunnel_id, rcvd_frame->friendnumber); |
376 | if(tun) | 312 | if(tun) |
377 | { | 313 | { |
314 | FD_SET(sockfd, &master_server_fds); | ||
315 | update_select_nfds(sockfd); | ||
378 | fprintf(stderr, "Created tunnel, yay!\n"); | 316 | fprintf(stderr, "Created tunnel, yay!\n"); |
379 | /* TODO send ack */ | 317 | send_tunnel_ack_frame(tun); |
380 | } | 318 | } |
381 | else | 319 | else |
382 | { | 320 | { |
@@ -388,7 +326,73 @@ int handle_request_tunnel_frame(protocol_frame *rcvd_frame) | |||
388 | fprintf(stderr, "Could not connect to %s:%d\n", hostname, port); | 326 | fprintf(stderr, "Could not connect to %s:%d\n", hostname, port); |
389 | /* TODO send reject */ | 327 | /* TODO send reject */ |
390 | } | 328 | } |
329 | } | ||
330 | |||
331 | /* Handle a TCP frame received from client */ | ||
332 | int handle_client_tcp_frame(protocol_frame *rcvd_frame) | ||
333 | { | ||
334 | tunnel *tun=NULL; | ||
335 | int offset = 0; | ||
336 | int connid = rcvd_frame->connid; | ||
337 | |||
338 | HASH_FIND_INT(by_id, &connid, tun); | ||
339 | |||
340 | if(!tun) | ||
341 | { | ||
342 | fprintf(stderr, "Got TCP frame with unknown tunnel ID %d\n", rcvd_frame->connid); | ||
343 | return -1; | ||
344 | } | ||
345 | |||
346 | while(offset < rcvd_frame->data_length) | ||
347 | { | ||
348 | int sent_bytes; | ||
349 | |||
350 | sent_bytes = send( | ||
351 | tun->sockfd, | ||
352 | rcvd_frame->data + offset, | ||
353 | rcvd_frame->data_length - offset, | ||
354 | 0 | ||
355 | ); | ||
356 | |||
357 | if(sent_bytes < 0) | ||
358 | { | ||
359 | fprintf(stderr, "Could not write to socket %d: %s\n", tun->sockfd, strerror(errno)); | ||
360 | return -1; | ||
361 | } | ||
362 | |||
363 | offset += sent_bytes; | ||
364 | } | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | int handle_server_tcp_fin_frame(protocol_frame *rcvd_frame) | ||
370 | { | ||
371 | |||
372 | } | ||
391 | 373 | ||
374 | /* Handle close-tunnel frame received from the client */ | ||
375 | int handle_client_tcp_fin_frame(protocol_frame *rcvd_frame) | ||
376 | { | ||
377 | tunnel *tun=NULL; | ||
378 | int offset = 0; | ||
379 | int connid = rcvd_frame->connid; | ||
380 | |||
381 | HASH_FIND_INT(by_id, &connid, tun); | ||
382 | |||
383 | if(!tun) | ||
384 | { | ||
385 | fprintf(stderr, "Got TCP FIN frame with unknown tunnel ID %d\n", rcvd_frame->connid); | ||
386 | return -1; | ||
387 | } | ||
388 | |||
389 | if(tun->friendnumber != rcvd_frame->friendnumber) | ||
390 | { | ||
391 | fprintf(stderr, "Friend #%d tried to close tunnel which belongs to #%d\n", rcvd_frame->friendnumber, tun->friendnumber); | ||
392 | return -1; | ||
393 | } | ||
394 | |||
395 | tunnel_delete(tun); | ||
392 | } | 396 | } |
393 | 397 | ||
394 | /* This is a dispatcher for our encapsulated protocol */ | 398 | /* This is a dispatcher for our encapsulated protocol */ |
@@ -403,10 +407,31 @@ int handle_frame(protocol_frame *frame) | |||
403 | return handle_pong_frame(frame); | 407 | return handle_pong_frame(frame); |
404 | break; | 408 | break; |
405 | case PACKET_TYPE_TCP: | 409 | case PACKET_TYPE_TCP: |
410 | if(client_mode) | ||
411 | { | ||
412 | return handle_server_tcp_frame(frame); | ||
413 | } | ||
414 | else | ||
415 | { | ||
416 | return handle_client_tcp_frame(frame); | ||
417 | } | ||
406 | break; | 418 | break; |
407 | case PACKET_TYPE_REQUESTTUNNEL: | 419 | case PACKET_TYPE_REQUESTTUNNEL: |
408 | handle_request_tunnel_frame(frame); | 420 | handle_request_tunnel_frame(frame); |
409 | break; | 421 | break; |
422 | case PACKET_TYPE_ACKTUNNEL: | ||
423 | handle_acktunnel_frame(frame); | ||
424 | break; | ||
425 | case PACKET_TYPE_TCP_FIN: | ||
426 | if(client_mode) | ||
427 | { | ||
428 | return handle_server_tcp_fin_frame(frame); | ||
429 | } | ||
430 | else | ||
431 | { | ||
432 | return handle_client_tcp_fin_frame(frame); | ||
433 | } | ||
434 | break; | ||
410 | default: | 435 | default: |
411 | fprintf(stderr, "Got unknown packet type 0x%x from friend %d\n", | 436 | fprintf(stderr, "Got unknown packet type 0x%x from friend %d\n", |
412 | frame->packet_type, | 437 | frame->packet_type, |
@@ -542,155 +567,67 @@ int do_server_loop() | |||
542 | { | 567 | { |
543 | struct timeval tv; | 568 | struct timeval tv; |
544 | fd_set fds; | 569 | fd_set fds; |
545 | fd_set master; | ||
546 | unsigned char read_buf[READ_BUFFER_SIZE+1]; | ||
547 | unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; | 570 | unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; |
571 | tunnel *tun = NULL; | ||
572 | tunnel *tmp = NULL; | ||
548 | 573 | ||
549 | tv.tv_sec = 0; | 574 | tv.tv_sec = 0; |
550 | tv.tv_usec = 20000; | 575 | tv.tv_usec = 20000; |
551 | 576 | ||
552 | FD_ZERO(&fds); | 577 | FD_ZERO(&master_server_fds); |
553 | // FD_SET(client_socket, &fds); | ||
554 | |||
555 | master = fds; | ||
556 | 578 | ||
557 | while(1) | 579 | while(1) |
558 | { | 580 | { |
559 | /* Let tox do its stuff */ | 581 | /* Let tox do its stuff */ |
560 | tox_do(tox); | 582 | tox_do(tox); |
561 | 583 | ||
562 | /* Poll for data from our client connection */ | 584 | fds = master_server_fds; |
563 | select(client_socket+1, &fds, NULL, NULL, &tv); | ||
564 | if(FD_ISSET(client_socket, &fds)) | ||
565 | { | ||
566 | int nbytes = recv(client_socket, read_buf, READ_BUFFER_SIZE, 0); | ||
567 | |||
568 | /* Check if connection closed */ | ||
569 | if(nbytes == 0) | ||
570 | { | ||
571 | printf("conn closed!\n"); | ||
572 | } | ||
573 | else | ||
574 | { | ||
575 | unsigned int tox_packet_length = 0; | ||
576 | read_buf[nbytes] = '\0'; | ||
577 | printf("READ: %s\n", read_buf); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | fds = master; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | int 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 | 585 | ||
597 | fprintf(stderr, "Connecting to Tox...\n"); | 586 | /* Poll for data from our client connection */ |
598 | 587 | select(select_nfds, &fds, NULL, NULL, &tv); | |
599 | while(1) | 588 | HASH_ITER(hh, by_id, tun, tmp) |
600 | { | ||
601 | /* Let tox do its stuff */ | ||
602 | tox_do(tox); | ||
603 | |||
604 | switch(state) | ||
605 | { | 589 | { |
606 | /* | 590 | if(FD_ISSET(tun->sockfd, &fds)) |
607 | * Send friend request | 591 | { |
608 | */ | 592 | int nbytes = recv(tun->sockfd, |
609 | case CLIENT_STATE_INITIAL: | 593 | tox_packet_buf+PROTOCOL_BUFFER_OFFSET, |
610 | if(tox_isconnected(tox)) | 594 | READ_BUFFER_SIZE, 0); |
595 | |||
596 | /* Check if connection closed */ | ||
597 | if(nbytes == 0) | ||
611 | { | 598 | { |
612 | state = CLIENT_STATE_CONNECTED; | 599 | char data[PROTOCOL_BUFFER_OFFSET]; |
613 | } | 600 | protocol_frame frame_st, *frame; |
614 | break; | 601 | |
615 | case CLIENT_STATE_CONNECTED: | 602 | printf("conn closed!\n"); |
616 | { | 603 | |
617 | uint8_t data[] = "Hi, fellow tuntox instance!"; | 604 | frame = &frame_st; |
618 | uint16_t length = sizeof(data); | 605 | memset(frame, 0, sizeof(protocol_frame)); |
619 | 606 | frame->friendnumber = tun->friendnumber; | |
620 | fprintf(stderr, "Connected. Sending friend request.\n"); | 607 | frame->packet_type = PACKET_TYPE_TCP_FIN; |
621 | 608 | frame->connid = tun->connid; | |
622 | friendnumber = tox_add_friend( | 609 | frame->data_length = 0; |
623 | tox, | 610 | send_frame(frame, data); |
624 | tox_id, | 611 | |
625 | data, | 612 | tunnel_delete(tun); |
626 | length | 613 | |
627 | ); | 614 | /* TODO remove tunnel? resume connection? */ |
628 | 615 | continue; | |
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 | } | 616 | } |
646 | else | 617 | else |
647 | { | 618 | { |
619 | protocol_frame frame_st, *frame; | ||
620 | |||
621 | frame = &frame_st; | ||
622 | memset(frame, 0, sizeof(protocol_frame)); | ||
623 | frame->friendnumber = tun->friendnumber; | ||
624 | frame->packet_type = PACKET_TYPE_TCP; | ||
625 | frame->connid = tun->connid; | ||
626 | frame->data_length = nbytes; | ||
627 | send_frame(frame, tox_packet_buf); | ||
648 | } | 628 | } |
649 | break; | 629 | } |
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 | } | 630 | } |
692 | |||
693 | usleep(tox_do_interval(tox) * 1000); | ||
694 | } | 631 | } |
695 | } | 632 | } |
696 | 633 | ||
@@ -700,6 +637,7 @@ void help() | |||
700 | fprintf(stderr, "USAGE:\n\n"); | 637 | fprintf(stderr, "USAGE:\n\n"); |
701 | fprintf(stderr, "-i <toxid> - remote point Tox ID\n"); | 638 | 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"); | 639 | fprintf(stderr, "-L <localport>:<remotehostname>:<remoteport> - forward <remotehostname>:<remoteport> to 127.0.0.1:<localport>\n"); |
640 | fprintf(stderr, "-P <remotehostname>:<remoteport> - forward <remotehostname>:<remoteport> to stdin/stdout (SSH ProxyCommand mode)\n"); | ||
703 | fprintf(stderr, "-p - ping the server from -i and exit\n"); | 641 | fprintf(stderr, "-p - ping the server from -i and exit\n"); |
704 | } | 642 | } |
705 | 643 | ||
@@ -716,6 +654,18 @@ int main(int argc, char *argv[]) | |||
716 | case 'L': | 654 | case 'L': |
717 | /* Local port forwarding */ | 655 | /* Local port forwarding */ |
718 | client_mode = 1; | 656 | client_mode = 1; |
657 | client_local_port_mode = 1; | ||
658 | if(parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port) < 0) | ||
659 | { | ||
660 | fprintf(stderr, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); | ||
661 | exit(1); | ||
662 | } | ||
663 | fprintf(stderr, "Forwarding remote port %d to local port %d\n", remote_port, local_port); | ||
664 | break; | ||
665 | case 'P': | ||
666 | /* Pipe forwarding */ | ||
667 | client_mode = 1; | ||
668 | client_pipe_mode = 1; | ||
719 | remote_port = atoi(optarg); | 669 | remote_port = atoi(optarg); |
720 | fprintf(stderr, "Forwarding remote port %d\n", remote_port); | 670 | fprintf(stderr, "Forwarding remote port %d\n", remote_port); |
721 | break; | 671 | break; |
@@ -755,6 +705,11 @@ int main(int argc, char *argv[]) | |||
755 | /* TODO use proper argparse */ | 705 | /* TODO use proper argparse */ |
756 | if(client_mode) | 706 | if(client_mode) |
757 | { | 707 | { |
708 | if(!remote_tox_id) | ||
709 | { | ||
710 | fprintf(stderr, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); | ||
711 | exit(1); | ||
712 | } | ||
758 | do_client_loop(remote_tox_id); | 713 | do_client_loop(remote_tox_id); |
759 | } | 714 | } |
760 | else | 715 | else |