File main.c changed (mode: 100644) (index 2d09e2e..661f5dd) |
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 |
1 |
#include "main.h" |
#include "main.h" |
15 |
2 |
#include "tox_bootstrap.h" |
#include "tox_bootstrap.h" |
16 |
3 |
|
|
|
... |
... |
static Tox_Options tox_options; |
18 |
5 |
static Tox *tox; |
static Tox *tox; |
19 |
6 |
int client_socket = 0; |
int client_socket = 0; |
20 |
7 |
|
|
|
8 |
|
/** CONFIGURATION OPTIONS **/ |
|
9 |
|
/* Whether we're a client */ |
|
10 |
|
int client_mode = 0; |
|
11 |
|
/* Just send a ping and exit */ |
|
12 |
|
int ping_mode = 0; |
|
13 |
|
/* Remote Tox ID in client mode */ |
|
14 |
|
char *remote_tox_id = NULL; |
|
15 |
|
/* Ports and hostname for port forwarding */ |
|
16 |
|
int remote_port = 0; |
|
17 |
|
char *remote_host = NULL; |
|
18 |
|
int local_port = 0; |
|
19 |
|
|
|
20 |
|
/* The state machine */ |
|
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 |
|
|
|
29 |
|
/* We keep two hash tables: one indexed by sockfd and another by "connection id" */ |
|
30 |
|
tunnel *by_id = NULL; |
|
31 |
|
tunnel *by_fd = NULL; |
|
32 |
|
|
|
33 |
|
/* Generate an unique tunnel ID. To be used in a server. */ |
|
34 |
|
uint16_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. */ |
|
55 |
|
static 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 |
|
|
|
75 |
|
static void tunnel_delete(tunnel *t) |
|
76 |
|
{ |
|
77 |
|
HASH_DEL( by_id, t ); |
|
78 |
|
HASH_DEL( by_fd, t ); |
|
79 |
|
free(t); |
|
80 |
|
} |
|
81 |
|
|
21 |
82 |
static void writechecksum(uint8_t *address) |
static void writechecksum(uint8_t *address) |
22 |
83 |
{ |
{ |
23 |
84 |
uint8_t *checksum = address + 36; |
uint8_t *checksum = address + 36; |
|
... |
... |
static void writechecksum(uint8_t *address) |
30 |
91 |
/* From utox/util.c */ |
/* From utox/util.c */ |
31 |
92 |
static void to_hex(char_t *a, const char_t *p, int size) |
static 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 |
97 |
while(p != end) { |
while(p != end) { |
36 |
98 |
b = *p++; |
b = *p++; |
|
... |
... |
void id_to_string(char_t *dest, const char_t *src) |
58 |
120 |
to_hex(dest, src, TOX_FRIEND_ADDRESS_SIZE); |
to_hex(dest, src, TOX_FRIEND_ADDRESS_SIZE); |
59 |
121 |
} |
} |
60 |
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 |
|
|
61 |
159 |
/* bootstrap to dht with bootstrap_nodes */ |
/* bootstrap to dht with bootstrap_nodes */ |
62 |
160 |
/* From uTox/tox.c */ |
/* From uTox/tox.c */ |
63 |
161 |
static void do_bootstrap(Tox *tox) |
static void do_bootstrap(Tox *tox) |
|
... |
... |
void set_tox_username(Tox *tox) |
107 |
205 |
|
|
108 |
206 |
// freeaddrinfo(info); |
// freeaddrinfo(info); |
109 |
207 |
} |
} |
110 |
|
|
|
111 |
|
void 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 |
|
|
|
121 |
|
void 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 |
208 |
// get sockaddr, IPv4 or IPv6: |
// get sockaddr, IPv4 or IPv6: |
133 |
209 |
/* From Beej */ |
/* From Beej */ |
134 |
210 |
void *get_in_addr(struct sockaddr *sa) |
void *get_in_addr(struct sockaddr *sa) |
|
... |
... |
void *get_in_addr(struct sockaddr *sa) |
141 |
217 |
} |
} |
142 |
218 |
|
|
143 |
219 |
/* From Beej */ |
/* From Beej */ |
144 |
|
int get_client_socket() |
|
|
220 |
|
int get_client_socket(char *hostname, int port) |
145 |
221 |
{ |
{ |
146 |
222 |
int sockfd, numbytes; |
int sockfd, numbytes; |
147 |
223 |
char buf[READ_BUFFER_SIZE]; |
char buf[READ_BUFFER_SIZE]; |
148 |
224 |
struct addrinfo hints, *servinfo, *p; |
struct addrinfo hints, *servinfo, *p; |
149 |
225 |
int rv; |
int rv; |
150 |
226 |
char s[INET6_ADDRSTRLEN]; |
char s[INET6_ADDRSTRLEN]; |
151 |
|
int port = 22; |
|
152 |
|
char hostname[4096] = "127.0.0.1"; |
|
153 |
227 |
char port_str[6]; |
char port_str[6]; |
154 |
228 |
|
|
155 |
229 |
snprintf(port_str, 6, "%d", port); |
snprintf(port_str, 6, "%d", port); |
|
... |
... |
int get_client_socket() |
160 |
234 |
|
|
161 |
235 |
if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { |
if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { |
162 |
236 |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); |
163 |
|
exit(1); |
|
|
237 |
|
return -1; |
164 |
238 |
} |
} |
165 |
239 |
|
|
166 |
240 |
// loop through all the results and connect to the first we can |
// loop through all the results and connect to the first we can |
|
... |
... |
int get_client_socket() |
196 |
270 |
return sockfd; |
return sockfd; |
197 |
271 |
} |
} |
198 |
272 |
|
|
199 |
|
unsigned 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 |
|
*/ |
|
279 |
|
int 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 |
|
|
|
307 |
|
int handle_ping_frame(protocol_frame *rcvd_frame) |
200 |
308 |
{ |
{ |
201 |
|
// assert data_len < 65536 |
|
202 |
|
dst[0] = 0xa2; |
|
203 |
|
dst[1] = 0x6a; |
|
204 |
|
dst[2] = sockfd >> 8; |
|
205 |
|
dst[3] = sockfd & 0xff; |
|
206 |
|
dst[4] = (data_len >> 8) & 0xff; |
|
207 |
|
dst[5] = data_len & 0xff; |
|
208 |
|
memcpy(dst+PROTOCOL_BUFFER_OFFSET, data, data_len); |
|
209 |
|
return data_len + PROTOCOL_BUFFER_OFFSET; |
|
|
309 |
|
uint8_t data[TOX_MAX_CUSTOM_PACKET_SIZE]; |
|
310 |
|
protocol_frame frame_s; |
|
311 |
|
protocol_frame *frame = &frame_s; |
|
312 |
|
|
|
313 |
|
frame->data = data + PROTOCOL_BUFFER_OFFSET; |
|
314 |
|
memcpy(frame->data, rcvd_frame->data, rcvd_frame->data_length); |
|
315 |
|
|
|
316 |
|
frame->friendnumber = rcvd_frame->friendnumber; |
|
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 |
|
|
212 |
|
int do_loop() |
|
|
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) |
|
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 */ |
|
395 |
|
int 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 |
|
*/ |
|
425 |
|
int 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 |
|
|
|
472 |
|
int 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 |
|
|
|
503 |
|
void 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 |
|
|
|
529 |
|
void 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 |
|
|
|
541 |
|
int do_server_loop() |
213 |
542 |
{ |
{ |
214 |
543 |
struct timeval tv; |
struct timeval tv; |
215 |
544 |
fd_set fds; |
fd_set fds; |
|
... |
... |
int do_loop() |
221 |
550 |
tv.tv_usec = 20000; |
tv.tv_usec = 20000; |
222 |
551 |
|
|
223 |
552 |
FD_ZERO(&fds); |
FD_ZERO(&fds); |
224 |
|
FD_SET(client_socket, &fds); |
|
|
553 |
|
// FD_SET(client_socket, &fds); |
225 |
554 |
|
|
226 |
555 |
master = fds; |
master = fds; |
227 |
556 |
|
|
|
... |
... |
int do_loop() |
245 |
574 |
{ |
{ |
246 |
575 |
unsigned int tox_packet_length = 0; |
unsigned int tox_packet_length = 0; |
247 |
576 |
read_buf[nbytes] = '\0'; |
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 |
577 |
printf("READ: %s\n", read_buf); |
printf("READ: %s\n", read_buf); |
251 |
578 |
} |
} |
252 |
579 |
} |
} |
|
... |
... |
int do_loop() |
255 |
582 |
} |
} |
256 |
583 |
} |
} |
257 |
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 |
|
|
|
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 |
|
|
|
697 |
|
void 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 |
|
|
258 |
706 |
int main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
259 |
707 |
{ |
{ |
260 |
708 |
unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE]; |
unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE]; |
261 |
709 |
unsigned char tox_printable_id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1]; |
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 |
737 |
on_exit(cleanup, NULL); |
on_exit(cleanup, NULL); |
264 |
738 |
|
|
|
... |
... |
int main(int argc, char *argv[]) |
269 |
743 |
|
|
270 |
744 |
tox = tox_new(&tox_options); |
tox = tox_new(&tox_options); |
271 |
745 |
|
|
272 |
|
tox_callback_friend_request(tox, accept_friend_request, NULL); |
|
273 |
|
|
|
274 |
746 |
set_tox_username(tox); |
set_tox_username(tox); |
275 |
747 |
|
|
276 |
748 |
tox_get_address(tox, tox_id); |
tox_get_address(tox, tox_id); |
|
... |
... |
int main(int argc, char *argv[]) |
280 |
752 |
|
|
281 |
753 |
do_bootstrap(tox); |
do_bootstrap(tox); |
282 |
754 |
|
|
283 |
|
/* Connect to the forwarded service */ |
|
284 |
|
client_socket = get_client_socket(); |
|
|
755 |
|
/* TODO use proper argparse */ |
|
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 |
769 |
return 0; |
return 0; |
289 |
770 |
} |
} |