diff options
author | GDR! <gdr@go2.pl> | 2014-11-25 23:09:45 +0100 |
---|---|---|
committer | GDR! <gdr@go2.pl> | 2014-11-25 23:09:45 +0100 |
commit | 16add85eb81629b07dd7bdb04fbe30be1410cc83 (patch) | |
tree | f2cc52d65a2deb0e8c1014f28d9926612c7cf074 | |
parent | c311fb3bdd2c26c347c2dd734f97003ac0538037 (diff) |
Multi-connection support client-side.
Dealing with congestion control, too
-rw-r--r-- | client.c | 221 | ||||
-rw-r--r-- | client.h | 1 | ||||
-rw-r--r-- | main.c | 78 | ||||
-rw-r--r-- | main.h | 8 |
4 files changed, 213 insertions, 95 deletions
@@ -10,6 +10,9 @@ struct timespec ping_sent_time; | |||
10 | /* Client mode tunnel */ | 10 | /* Client mode tunnel */ |
11 | tunnel client_tunnel; | 11 | tunnel client_tunnel; |
12 | 12 | ||
13 | /* Sock representing the local port - call accept() on it */ | ||
14 | int bind_sockfd; | ||
15 | |||
13 | fd_set client_master_fdset; | 16 | fd_set client_master_fdset; |
14 | 17 | ||
15 | int handle_pong_frame(protocol_frame *rcvd_frame) | 18 | int handle_pong_frame(protocol_frame *rcvd_frame) |
@@ -31,17 +34,12 @@ int handle_pong_frame(protocol_frame *rcvd_frame) | |||
31 | } | 34 | } |
32 | } | 35 | } |
33 | 36 | ||
34 | int local_bind(tunnel *tun) | 37 | int local_bind() |
35 | { | 38 | { |
36 | struct addrinfo hints, *res; | 39 | struct addrinfo hints, *res; |
37 | int sockfd; | ||
38 | char port[6]; | 40 | char port[6]; |
39 | int yes = 1; | 41 | int yes = 1; |
40 | 42 | int flags; | |
41 | /* accept() variables - TODO they should not be there */ | ||
42 | int newfd; | ||
43 | struct sockaddr_storage remoteaddr; // client address | ||
44 | socklen_t addrlen; | ||
45 | 43 | ||
46 | snprintf(port, 6, "%d", local_port); | 44 | snprintf(port, 6, "%d", local_port); |
47 | 45 | ||
@@ -52,69 +50,66 @@ int local_bind(tunnel *tun) | |||
52 | 50 | ||
53 | getaddrinfo(NULL, port, &hints, &res); | 51 | getaddrinfo(NULL, port, &hints, &res); |
54 | 52 | ||
55 | sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | 53 | bind_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
56 | if(sockfd < 0) | 54 | if(bind_sockfd < 0) |
57 | { | 55 | { |
58 | fprintf(stderr, "Could not create a socket for local listening\n"); | 56 | fprintf(stderr, "Could not create a socket for local listening: %s\n", strerror(errno)); |
59 | exit(1); | 57 | exit(1); |
60 | } | 58 | } |
61 | 59 | ||
62 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); | 60 | setsockopt(bind_sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); |
63 | 61 | ||
64 | if(bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) | 62 | /* Set O_NONBLOCK to make accept() non-blocking */ |
63 | if (-1 == (flags = fcntl(bind_sockfd, F_GETFL, 0))) | ||
65 | { | 64 | { |
66 | fprintf(stderr, "Bind to port %d failed: %s", local_port, strerror(errno)); | 65 | flags = 0; |
67 | close(sockfd); | ||
68 | exit(1); | ||
69 | } | 66 | } |
67 | fcntl(bind_sockfd, F_SETFL, flags | O_NONBLOCK); | ||
70 | 68 | ||
71 | if(listen(sockfd, 1) < 0) | 69 | if(bind(bind_sockfd, res->ai_addr, res->ai_addrlen) < 0) |
72 | { | 70 | { |
73 | fprintf(stderr, "Listening on port %d failed: %s", local_port, strerror(errno)); | 71 | fprintf(stderr, "Bind to port %d failed: %s\n", local_port, strerror(errno)); |
74 | close(sockfd); | 72 | close(bind_sockfd); |
75 | exit(1); | 73 | exit(1); |
76 | } | 74 | } |
77 | 75 | ||
78 | // TODO return sockfd | 76 | if(listen(bind_sockfd, 1) < 0) |
79 | |||
80 | /* TODO: make a proper accept loop and track tunnels, to handle more than 1 connection */ | ||
81 | addrlen = sizeof(remoteaddr); | ||
82 | newfd = accept(sockfd, | ||
83 | (struct sockaddr *)&remoteaddr, | ||
84 | &addrlen); | ||
85 | |||
86 | if(newfd < 0) | ||
87 | { | 77 | { |
88 | fprintf(stderr, "Error when accepting a local connection: %s\n", strerror(errno)); | 78 | fprintf(stderr, "Listening on port %d failed: %s\n", local_port, strerror(errno)); |
89 | close(sockfd); | 79 | close(bind_sockfd); |
90 | exit(0); | 80 | exit(1); |
91 | } | 81 | } |
92 | 82 | ||
93 | // TODO close(sockfd); | 83 | fprintf(stderr, "Bound to local port %d\n", local_port); |
94 | |||
95 | return newfd; | ||
96 | } | 84 | } |
97 | 85 | ||
86 | /* Bind the client.sockfd to a tunnel */ | ||
98 | int handle_acktunnel_frame(protocol_frame *rcvd_frame) | 87 | int handle_acktunnel_frame(protocol_frame *rcvd_frame) |
99 | { | 88 | { |
89 | tunnel *tun; | ||
90 | |||
100 | if(!client_mode) | 91 | if(!client_mode) |
101 | { | 92 | { |
102 | fprintf(stderr, "Got ACK tunnel frame when not in client mode!?\n"); | 93 | fprintf(stderr, "Got ACK tunnel frame when not in client mode!?\n"); |
103 | return -1; | 94 | return -1; |
104 | } | 95 | } |
105 | 96 | ||
106 | client_tunnel.connid = rcvd_frame->connid; | 97 | tun = tunnel_create( |
107 | client_tunnel.friendnumber = rcvd_frame->friendnumber; | 98 | client_tunnel.sockfd, |
108 | // TODO open local port and fill client_tunnel.sockfd | 99 | rcvd_frame->connid, |
109 | printf("New tunnel ID: %d\n", client_tunnel.connid); | 100 | rcvd_frame->friendnumber |
101 | ); | ||
102 | |||
103 | /* Mark that we can accept() another connection */ | ||
104 | client_tunnel.sockfd = -1; | ||
105 | |||
106 | printf("New tunnel ID: %d\n", tun->connid); | ||
110 | 107 | ||
111 | if(client_local_port_mode) | 108 | if(client_local_port_mode) |
112 | { | 109 | { |
113 | client_tunnel.sockfd = local_bind(&client_tunnel); | 110 | update_select_nfds(tun->sockfd); |
114 | update_select_nfds(client_tunnel.sockfd); | 111 | FD_SET(tun->sockfd, &client_master_fdset); |
115 | FD_SET(client_tunnel.sockfd, &client_master_fdset); | 112 | fprintf(stderr, "Accepted a new connection on port %d\n", local_port); |
116 | fprintf(stderr, "Accepting connections on port %d\n", local_port); | ||
117 | state = CLIENT_STATE_FORWARDING; | ||
118 | } | 113 | } |
119 | else | 114 | else |
120 | { | 115 | { |
@@ -126,9 +121,17 @@ int handle_acktunnel_frame(protocol_frame *rcvd_frame) | |||
126 | /* Handle a TCP frame received from server */ | 121 | /* Handle a TCP frame received from server */ |
127 | int handle_server_tcp_frame(protocol_frame *rcvd_frame) | 122 | int handle_server_tcp_frame(protocol_frame *rcvd_frame) |
128 | { | 123 | { |
129 | /* TODO find tunnel basing on ID */ | ||
130 | int offset = 0; | 124 | int offset = 0; |
131 | tunnel *tun = &client_tunnel; | 125 | tunnel *tun = NULL; |
126 | int tun_id = rcvd_frame->connid; | ||
127 | |||
128 | HASH_FIND_INT(by_id, &tun_id, tun); | ||
129 | |||
130 | if(!tun) | ||
131 | { | ||
132 | fprintf(stderr, "Got TCP frame with unknown tunnel ID %d\n", rcvd_frame->connid); | ||
133 | return -1; | ||
134 | } | ||
132 | 135 | ||
133 | while(offset < rcvd_frame->data_length) | 136 | while(offset < rcvd_frame->data_length) |
134 | { | 137 | { |
@@ -143,13 +146,27 @@ int handle_server_tcp_frame(protocol_frame *rcvd_frame) | |||
143 | 146 | ||
144 | if(sent_bytes < 0) | 147 | if(sent_bytes < 0) |
145 | { | 148 | { |
149 | char data[PROTOCOL_BUFFER_OFFSET]; | ||
150 | protocol_frame frame_st, *frame; | ||
151 | |||
146 | fprintf(stderr, "Could not write to socket %d: %s\n", tun->sockfd, strerror(errno)); | 152 | fprintf(stderr, "Could not write to socket %d: %s\n", tun->sockfd, strerror(errno)); |
153 | |||
154 | frame = &frame_st; | ||
155 | memset(frame, 0, sizeof(protocol_frame)); | ||
156 | frame->friendnumber = tun->friendnumber; | ||
157 | frame->packet_type = PACKET_TYPE_TCP_FIN; | ||
158 | frame->connid = tun->connid; | ||
159 | frame->data_length = 0; | ||
160 | send_frame(frame, data); | ||
161 | tunnel_delete(tun); | ||
162 | |||
147 | return -1; | 163 | return -1; |
148 | } | 164 | } |
149 | 165 | ||
150 | offset += sent_bytes; | 166 | offset += sent_bytes; |
151 | } | 167 | } |
152 | 168 | ||
169 | printf("Got %d bytes from server - wrote to fd %d\n", rcvd_frame->data_length, tun->sockfd); | ||
153 | 170 | ||
154 | return 0; | 171 | return 0; |
155 | } | 172 | } |
@@ -172,6 +189,12 @@ int do_client_loop(char *tox_id_str) | |||
172 | exit(1); | 189 | exit(1); |
173 | } | 190 | } |
174 | 191 | ||
192 | if(!ping_mode) /* TODO handle pipe mode */ | ||
193 | { | ||
194 | local_bind(); | ||
195 | signal(SIGPIPE, SIG_IGN); | ||
196 | } | ||
197 | |||
175 | fprintf(stderr, "Connecting to Tox...\n"); | 198 | fprintf(stderr, "Connecting to Tox...\n"); |
176 | 199 | ||
177 | while(1) | 200 | while(1) |
@@ -232,7 +255,7 @@ int do_client_loop(char *tox_id_str) | |||
232 | } | 255 | } |
233 | else | 256 | else |
234 | { | 257 | { |
235 | state = CLIENT_STATE_REQUEST_TUNNEL; | 258 | state = CLIENT_STATE_BIND_PORT; |
236 | } | 259 | } |
237 | break; | 260 | break; |
238 | case CLIENT_STATE_SEND_PING: | 261 | case CLIENT_STATE_SEND_PING: |
@@ -256,9 +279,21 @@ int do_client_loop(char *tox_id_str) | |||
256 | case CLIENT_STATE_PING_SENT: | 279 | case CLIENT_STATE_PING_SENT: |
257 | /* Just sit there and wait for pong */ | 280 | /* Just sit there and wait for pong */ |
258 | break; | 281 | break; |
282 | |||
283 | case CLIENT_STATE_BIND_PORT: | ||
284 | if(bind_sockfd < 0) | ||
285 | { | ||
286 | fprintf(stderr, "Shutting down - could not bind to listening port\n"); | ||
287 | state = CLIENT_STATE_SHUTDOWN; | ||
288 | } | ||
289 | else | ||
290 | { | ||
291 | state = CLIENT_STATE_FORWARDING; | ||
292 | } | ||
293 | break; | ||
259 | case CLIENT_STATE_REQUEST_TUNNEL: | 294 | case CLIENT_STATE_REQUEST_TUNNEL: |
260 | send_tunnel_request_packet( | 295 | send_tunnel_request_packet( |
261 | "127.0.0.1", | 296 | remote_host, |
262 | remote_port, | 297 | remote_port, |
263 | friendnumber | 298 | friendnumber |
264 | ); | 299 | ); |
@@ -268,49 +303,73 @@ int do_client_loop(char *tox_id_str) | |||
268 | break; | 303 | break; |
269 | case CLIENT_STATE_FORWARDING: | 304 | case CLIENT_STATE_FORWARDING: |
270 | { | 305 | { |
306 | int accept_fd = 0; | ||
307 | tunnel *tmp = NULL; | ||
308 | tunnel *tun = NULL; | ||
309 | |||
271 | tv.tv_sec = 0; | 310 | tv.tv_sec = 0; |
272 | tv.tv_usec = 20000; | 311 | tv.tv_usec = 20000; |
273 | fds = client_master_fdset; | 312 | fds = client_master_fdset; |
274 | |||
275 | select(select_nfds, &fds, NULL, NULL, &tv); | ||
276 | 313 | ||
277 | if(FD_ISSET(client_tunnel.sockfd, &fds)) | 314 | /* Handle accepting new connections */ |
315 | if(client_tunnel.sockfd <= 0) /* Don't accept if we're already waiting to establish a tunnel */ | ||
278 | { | 316 | { |
279 | int nbytes = recv(client_tunnel.sockfd, | 317 | accept_fd = accept(bind_sockfd, NULL, NULL); |
280 | tox_packet_buf + PROTOCOL_BUFFER_OFFSET, | 318 | if(accept_fd != -1) |
281 | READ_BUFFER_SIZE, 0); | ||
282 | |||
283 | /* Check if connection closed */ | ||
284 | if(nbytes == 0) | ||
285 | { | 319 | { |
286 | char data[PROTOCOL_BUFFER_OFFSET]; | 320 | fprintf(stderr, "Accepting a new connection - requesting tunnel...\n"); |
287 | protocol_frame frame_st, *frame; | 321 | |
288 | 322 | /* Open a new tunnel for this FD */ | |
289 | fprintf(stderr, "Connection closed\n"); | 323 | client_tunnel.sockfd = accept_fd; |
290 | 324 | send_tunnel_request_packet( | |
291 | frame = &frame_st; | 325 | remote_host, |
292 | memset(frame, 0, sizeof(protocol_frame)); | 326 | remote_port, |
293 | frame->friendnumber = client_tunnel.friendnumber; | 327 | friendnumber |
294 | frame->packet_type = PACKET_TYPE_TCP_FIN; | 328 | ); |
295 | frame->connid = client_tunnel.connid; | ||
296 | frame->data_length = 0; | ||
297 | send_frame(frame, data); | ||
298 | |||
299 | state = CLIENT_STATE_SHUTDOWN; | ||
300 | |||
301 | // exit(1); // TODO handle it in a smarter way (accept() again?) | ||
302 | } | 329 | } |
303 | else | 330 | } |
331 | |||
332 | /* Handle reading from sockets */ | ||
333 | select(select_nfds, &fds, NULL, NULL, &tv); | ||
334 | HASH_ITER(hh, by_id, tun, tmp) | ||
335 | { | ||
336 | if(FD_ISSET(tun->sockfd, &fds)) | ||
304 | { | 337 | { |
305 | protocol_frame frame_st, *frame; | 338 | int nbytes = recv(tun->sockfd, |
306 | 339 | tox_packet_buf + PROTOCOL_BUFFER_OFFSET, | |
307 | frame = &frame_st; | 340 | READ_BUFFER_SIZE, 0); |
308 | memset(frame, 0, sizeof(protocol_frame)); | 341 | |
309 | frame->friendnumber = client_tunnel.friendnumber; | 342 | /* Check if connection closed */ |
310 | frame->packet_type = PACKET_TYPE_TCP; | 343 | if(nbytes == 0) |
311 | frame->connid = client_tunnel.connid; | 344 | { |
312 | frame->data_length = nbytes; | 345 | char data[PROTOCOL_BUFFER_OFFSET]; |
313 | send_frame(frame, tox_packet_buf); | 346 | protocol_frame frame_st, *frame; |
347 | |||
348 | fprintf(stderr, "Connection closed\n"); | ||
349 | |||
350 | frame = &frame_st; | ||
351 | memset(frame, 0, sizeof(protocol_frame)); | ||
352 | frame->friendnumber = tun->friendnumber; | ||
353 | frame->packet_type = PACKET_TYPE_TCP_FIN; | ||
354 | frame->connid = tun->connid; | ||
355 | frame->data_length = 0; | ||
356 | send_frame(frame, data); | ||
357 | tunnel_delete(tun); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | protocol_frame frame_st, *frame; | ||
362 | |||
363 | frame = &frame_st; | ||
364 | memset(frame, 0, sizeof(protocol_frame)); | ||
365 | frame->friendnumber = tun->friendnumber; | ||
366 | frame->packet_type = PACKET_TYPE_TCP; | ||
367 | frame->connid = tun->connid; | ||
368 | frame->data_length = nbytes; | ||
369 | send_frame(frame, tox_packet_buf); | ||
370 | |||
371 | printf("Wrote %d bytes from sock %d to tunnel %d\n", nbytes, tun->sockfd, tun->connid); | ||
372 | } | ||
314 | } | 373 | } |
315 | } | 374 | } |
316 | 375 | ||
@@ -11,6 +11,7 @@ | |||
11 | #define CLIENT_STATE_WAIT_FOR_ACKTUNNEL 9 | 11 | #define CLIENT_STATE_WAIT_FOR_ACKTUNNEL 9 |
12 | #define CLIENT_STATE_FORWARDING 10 | 12 | #define CLIENT_STATE_FORWARDING 10 |
13 | #define CLIENT_STATE_SHUTDOWN 11 | 13 | #define CLIENT_STATE_SHUTDOWN 11 |
14 | #define CLIENT_STATE_BIND_PORT 12 | ||
14 | 15 | ||
15 | int handle_pong_frame(protocol_frame *rcvd_frame); | 16 | int handle_pong_frame(protocol_frame *rcvd_frame); |
16 | int handle_acktunnel_frame(protocol_frame *rcvd_frame); | 17 | int handle_acktunnel_frame(protocol_frame *rcvd_frame); |
@@ -9,14 +9,19 @@ int client_socket = 0; | |||
9 | /** CONFIGURATION OPTIONS **/ | 9 | /** CONFIGURATION OPTIONS **/ |
10 | /* Whether we're a client */ | 10 | /* Whether we're a client */ |
11 | int client_mode = 0; | 11 | int client_mode = 0; |
12 | |||
12 | /* Just send a ping and exit */ | 13 | /* Just send a ping and exit */ |
13 | int ping_mode = 0; | 14 | int ping_mode = 0; |
15 | |||
14 | /* Open a local port and forward it */ | 16 | /* Open a local port and forward it */ |
15 | int client_local_port_mode = 0; | 17 | int client_local_port_mode = 0; |
18 | |||
16 | /* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ | 19 | /* Forward stdin/stdout to remote machine - SSH ProxyCommand mode */ |
17 | int client_pipe_mode = 0; | 20 | int client_pipe_mode = 0; |
21 | |||
18 | /* Remote Tox ID in client mode */ | 22 | /* Remote Tox ID in client mode */ |
19 | char *remote_tox_id = NULL; | 23 | char *remote_tox_id = NULL; |
24 | |||
20 | /* Ports and hostname for port forwarding */ | 25 | /* Ports and hostname for port forwarding */ |
21 | int remote_port = 0; | 26 | int remote_port = 0; |
22 | char *remote_host = NULL; | 27 | char *remote_host = NULL; |
@@ -26,7 +31,6 @@ fd_set master_server_fds; | |||
26 | 31 | ||
27 | /* We keep two hash tables: one indexed by sockfd and another by "connection id" */ | 32 | /* We keep two hash tables: one indexed by sockfd and another by "connection id" */ |
28 | tunnel *by_id = NULL; | 33 | tunnel *by_id = NULL; |
29 | tunnel *by_fd = NULL; | ||
30 | 34 | ||
31 | /* Highest used fd + 1 for select() */ | 35 | /* Highest used fd + 1 for select() */ |
32 | int select_nfds = 4; | 36 | int select_nfds = 4; |
@@ -62,7 +66,7 @@ void update_select_nfds(int fd) | |||
62 | } | 66 | } |
63 | 67 | ||
64 | /* Constructor. Returns NULL on failure. */ | 68 | /* Constructor. Returns NULL on failure. */ |
65 | static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) | 69 | tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) |
66 | { | 70 | { |
67 | tunnel *t = NULL; | 71 | tunnel *t = NULL; |
68 | 72 | ||
@@ -76,6 +80,8 @@ static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) | |||
76 | t->connid = connid; | 80 | t->connid = connid; |
77 | t->friendnumber = friendnumber; | 81 | t->friendnumber = friendnumber; |
78 | 82 | ||
83 | fprintf(stderr, "Created a new tunnel object connid=%d sockfd=%d\n", connid, sockfd); | ||
84 | |||
79 | update_select_nfds(t->sockfd); | 85 | update_select_nfds(t->sockfd); |
80 | 86 | ||
81 | HASH_ADD_INT( by_id, connid, t ); | 87 | HASH_ADD_INT( by_id, connid, t ); |
@@ -83,7 +89,7 @@ static tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber) | |||
83 | return t; | 89 | return t; |
84 | } | 90 | } |
85 | 91 | ||
86 | static void tunnel_delete(tunnel *t) | 92 | void tunnel_delete(tunnel *t) |
87 | { | 93 | { |
88 | printf("Deleting tunnel #%d\n", t->connid); | 94 | printf("Deleting tunnel #%d\n", t->connid); |
89 | if(t->sockfd) | 95 | if(t->sockfd) |
@@ -167,7 +173,7 @@ int get_client_socket(char *hostname, int port) | |||
167 | snprintf(port_str, 6, "%d", port); | 173 | snprintf(port_str, 6, "%d", port); |
168 | 174 | ||
169 | memset(&hints, 0, sizeof hints); | 175 | memset(&hints, 0, sizeof hints); |
170 | hints.ai_family = AF_UNSPEC; | 176 | hints.ai_family = AF_INET; |
171 | hints.ai_socktype = SOCK_STREAM; | 177 | hints.ai_socktype = SOCK_STREAM; |
172 | 178 | ||
173 | if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { | 179 | if ((rv = getaddrinfo(hostname, port_str, &hints, &servinfo)) != 0) { |
@@ -177,6 +183,9 @@ int get_client_socket(char *hostname, int port) | |||
177 | 183 | ||
178 | // loop through all the results and connect to the first we can | 184 | // loop through all the results and connect to the first we can |
179 | for(p = servinfo; p != NULL; p = p->ai_next) { | 185 | for(p = servinfo; p != NULL; p = p->ai_next) { |
186 | if (p->ai_family != AF_INET && p->ai_family != AF_INET6) | ||
187 | continue; | ||
188 | |||
180 | if ((sockfd = socket(p->ai_family, p->ai_socktype, | 189 | if ((sockfd = socket(p->ai_family, p->ai_socktype, |
181 | p->ai_protocol)) == -1) { | 190 | p->ai_protocol)) == -1) { |
182 | perror("client: socket"); | 191 | perror("client: socket"); |
@@ -216,7 +225,8 @@ int get_client_socket(char *hostname, int port) | |||
216 | */ | 225 | */ |
217 | int send_frame(protocol_frame *frame, uint8_t *data) | 226 | int send_frame(protocol_frame *frame, uint8_t *data) |
218 | { | 227 | { |
219 | int rv; | 228 | int rv = -1; |
229 | int i; | ||
220 | 230 | ||
221 | data[0] = PROTOCOL_MAGIC_HIGH; | 231 | data[0] = PROTOCOL_MAGIC_HIGH; |
222 | data[1] = PROTOCOL_MAGIC_LOW; | 232 | data[1] = PROTOCOL_MAGIC_LOW; |
@@ -227,16 +237,40 @@ int send_frame(protocol_frame *frame, uint8_t *data) | |||
227 | data[6] = BYTE2(frame->data_length); | 237 | data[6] = BYTE2(frame->data_length); |
228 | data[7] = BYTE1(frame->data_length); | 238 | data[7] = BYTE1(frame->data_length); |
229 | 239 | ||
230 | rv = tox_send_lossless_packet( | 240 | for(i = 0; i < 17;) |
231 | tox, | 241 | { |
232 | frame->friendnumber, | 242 | int j; |
233 | data, | 243 | |
234 | frame->data_length + PROTOCOL_BUFFER_OFFSET | 244 | rv = tox_send_lossless_packet( |
235 | ); | 245 | tox, |
246 | frame->friendnumber, | ||
247 | data, | ||
248 | frame->data_length + PROTOCOL_BUFFER_OFFSET | ||
249 | ); | ||
236 | 250 | ||
237 | if(rv < 0) | 251 | if(rv < 0) |
252 | { | ||
253 | /* If this branch is ran, most likely we've hit congestion control. */ | ||
254 | fprintf(stderr, "[%d] Failed to send packet to friend %d\n", i, frame->friendnumber); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | if(i == 0) i = 2; | ||
262 | else i = i * 2; | ||
263 | |||
264 | for(j = 0; j < i; j++) | ||
265 | { | ||
266 | tox_do(tox); | ||
267 | usleep(j * 10000); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | if(i > 0 && rv >= 0) | ||
238 | { | 272 | { |
239 | fprintf(stderr, "Failed to send packet to friend %d\n", frame->friendnumber); | 273 | fprintf(stderr, "Packet succeeded at try %d", i+1); |
240 | } | 274 | } |
241 | 275 | ||
242 | return rv; | 276 | return rv; |
@@ -570,6 +604,7 @@ int do_server_loop() | |||
570 | unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; | 604 | unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; |
571 | tunnel *tun = NULL; | 605 | tunnel *tun = NULL; |
572 | tunnel *tmp = NULL; | 606 | tunnel *tmp = NULL; |
607 | int connected = 0; | ||
573 | 608 | ||
574 | tv.tv_sec = 0; | 609 | tv.tv_sec = 0; |
575 | tv.tv_usec = 20000; | 610 | tv.tv_usec = 20000; |
@@ -578,9 +613,26 @@ int do_server_loop() | |||
578 | 613 | ||
579 | while(1) | 614 | while(1) |
580 | { | 615 | { |
616 | int tmp_isconnected = 0; | ||
617 | |||
581 | /* Let tox do its stuff */ | 618 | /* Let tox do its stuff */ |
582 | tox_do(tox); | 619 | tox_do(tox); |
583 | 620 | ||
621 | /* Check change in connection state */ | ||
622 | tmp_isconnected = tox_isconnected(tox); | ||
623 | if(tmp_isconnected != connected) | ||
624 | { | ||
625 | connected = tmp_isconnected; | ||
626 | if(connected) | ||
627 | { | ||
628 | fprintf(stderr, "Connected to Tox network\n"); | ||
629 | } | ||
630 | else | ||
631 | { | ||
632 | fprintf(stderr, "Disconnected from Tox network\n"); | ||
633 | } | ||
634 | } | ||
635 | |||
584 | fds = master_server_fds; | 636 | fds = master_server_fds; |
585 | 637 | ||
586 | /* Poll for data from our client connection */ | 638 | /* Poll for data from our client connection */ |
@@ -3,8 +3,10 @@ | |||
3 | 3 | ||
4 | #include <arpa/inet.h> | 4 | #include <arpa/inet.h> |
5 | #include <errno.h> | 5 | #include <errno.h> |
6 | #include <fcntl.h> | ||
6 | #include <netdb.h> | 7 | #include <netdb.h> |
7 | #include <netinet/in.h> | 8 | #include <netinet/in.h> |
9 | #include <signal.h> | ||
8 | #include <stdio.h> | 10 | #include <stdio.h> |
9 | #include <stdlib.h> | 11 | #include <stdlib.h> |
10 | #include <string.h> | 12 | #include <string.h> |
@@ -18,7 +20,6 @@ | |||
18 | #include "util.h" | 20 | #include "util.h" |
19 | #include "uthash.h" | 21 | #include "uthash.h" |
20 | 22 | ||
21 | #define READ_BUFFER_SIZE 1024 | ||
22 | 23 | ||
23 | #define PROTOCOL_MAGIC_V1 0xa26a | 24 | #define PROTOCOL_MAGIC_V1 0xa26a |
24 | #define PROTOCOL_MAGIC PROTOCOL_MAGIC_V1 | 25 | #define PROTOCOL_MAGIC PROTOCOL_MAGIC_V1 |
@@ -37,8 +38,10 @@ | |||
37 | 38 | ||
38 | /* Offset of the data buffer in the packet */ | 39 | /* Offset of the data buffer in the packet */ |
39 | #define PROTOCOL_BUFFER_OFFSET 8 | 40 | #define PROTOCOL_BUFFER_OFFSET 8 |
41 | #define READ_BUFFER_SIZE TOX_MAX_CUSTOM_PACKET_SIZE - PROTOCOL_BUFFER_OFFSET | ||
40 | #define PROTOCOL_MAX_PACKET_SIZE (READ_BUFFER_SIZE + PROTOCOL_BUFFER_OFFSET) | 42 | #define PROTOCOL_MAX_PACKET_SIZE (READ_BUFFER_SIZE + PROTOCOL_BUFFER_OFFSET) |
41 | 43 | ||
44 | |||
42 | typedef struct tunnel_t { | 45 | typedef struct tunnel_t { |
43 | /* The forwarded socket fd */ | 46 | /* The forwarded socket fd */ |
44 | int sockfd; | 47 | int sockfd; |
@@ -80,6 +83,9 @@ extern char *remote_host; | |||
80 | extern int local_port; | 83 | extern int local_port; |
81 | 84 | ||
82 | extern int select_nfds; | 85 | extern int select_nfds; |
86 | extern tunnel *by_id; | ||
83 | 87 | ||
84 | int parse_lossless_packet(void *sender_uc, const uint8_t *data, uint32_t len); | 88 | int parse_lossless_packet(void *sender_uc, const uint8_t *data, uint32_t len); |
89 | tunnel *tunnel_create(int sockfd, int connid, uint32_t friendnumber); | ||
90 | void tunnel_delete(tunnel *t); | ||
85 | #endif | 91 | #endif |