1 /*
2  * Project: udptunnel
3  * File: client.c
4  *
5  * Copyright (C) 2009 Daniel Meekins
6  * Contact: dmeekins - gmail
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #ifndef WIN32
26 #include <sys/time.h>
27 #endif /*WIN32*/
28 
29 #include "common.h"
30 #include "client.h"
31 #include "socket.h"
32 
33 extern int debug_level;
34 
35 /*
36  * Allocates and initializes a new client object.
37  * id - ID number for the client to have
38  * tcp_sock/udp_sock - sockets attributed to the client. this function copies
39  *   the structure, so the calling function can free the sockets passed to
40  *   here.
41  * connected - whether the TCP socket is connected or not.
42  * Returns a pointer to the new structure. Call client_free() when done with
43  * it.
44  */
client_create(uint16_t id,socket_t * tcp_sock,socket_t * udp_sock,int connected)45 client_t *client_create(uint16_t id, socket_t *tcp_sock, socket_t *udp_sock,
46                         int connected)
47 {
48     client_t *c = NULL;
49 
50     c = calloc(1, sizeof(client_t));
51     if(!c)
52         goto error;
53 
54     c->id = id;
55     c->tcp_sock = sock_copy(tcp_sock);
56     c->udp_sock = sock_copy(udp_sock);
57     c->udp2tcp_state = CLIENT_WAIT_HELLO;
58     c->tcp2udp_state = CLIENT_WAIT_DATA0;
59     c->connected = connected;
60 
61     timerclear(&c->keepalive);
62     timerclear(&c->tcp2udp_timeout);
63     c->resend_count = 0;
64 
65     return c;
66 
67   error:
68     if(c)
69     {
70         if(c->tcp_sock)
71             sock_free(c->tcp_sock);
72         if(c->udp_sock)
73             sock_free(c->udp_sock);
74         free(c);
75     }
76 
77     return NULL;
78 }
79 
80 /*
81  * Performs a deep copy of the client structure.
82  */
client_copy(client_t * dst,client_t * src,size_t len)83 client_t *client_copy(client_t *dst, client_t *src, size_t len)
84 {
85     if(!dst || !src)
86         return NULL;
87 
88     memcpy(dst, src, sizeof(*src));
89 
90     dst->tcp_sock = sock_copy(src->tcp_sock);
91     if(!dst->tcp_sock)
92         return NULL;
93 
94     dst->udp_sock = sock_copy(src->udp_sock);
95     if(!dst->udp_sock)
96         return NULL;
97 
98     return dst;
99 }
100 
101 /*
102  * Compares the ID of the two clients.
103  */
client_cmp(client_t * c1,client_t * c2,size_t len)104 int client_cmp(client_t *c1, client_t *c2, size_t len)
105 {
106     return c1->id - c2->id;
107 }
108 
109 /*
110  * Connects the TCP socket of the client (wrapper for sock_connect()). Returns
111  * 0 on success or -1 on error.
112  */
client_connect_tcp(client_t * c,char * port)113 int client_connect_tcp(client_t *c, char *port)
114 {
115     if(!c->connected)
116     {
117         if(sock_connect(c->tcp_sock, 0, port) == 0)
118         {
119             c->connected = 1;
120             return 0;
121         }
122     }
123 
124     return -1;
125 }
126 
127 /*
128  * Closes the TCP socket for the client (wrapper for sock_close()).
129  */
client_disconnect_tcp(client_t * c)130 void client_disconnect_tcp(client_t *c)
131 {
132     if(c->connected)
133     {
134         sock_close(c->tcp_sock);
135         c->connected = 0;
136     }
137 }
138 
139 /*
140  * Closes the UDP socket for the client (wrapper for sock_close()).
141  */
client_disconnect_udp(client_t * c)142 void client_disconnect_udp(client_t *c)
143 {
144     sock_close(c->udp_sock);
145 }
146 
147 /*
148  * Releases the memory used by the client.
149  */
client_free(client_t * c)150 void client_free(client_t *c)
151 {
152     if(c)
153     {
154         sock_free(c->tcp_sock);
155         sock_free(c->udp_sock);
156         free(c);
157     }
158 }
159 
160 /*
161  * Receives a message from the UDP tunnel for the client. Only used in
162  * udpclient program because each client has their own UDP socket. Returns 0
163  * for success or -1 on error. The data is written to memory pointed to by
164  * data, and the id, msg_type, and len are set from the message header.
165  */
client_recv_udp_msg(client_t * client,char * data,int data_len,uint16_t * id,uint8_t * msg_type,uint16_t * len)166 int client_recv_udp_msg(client_t *client, char *data, int data_len,
167                         uint16_t *id, uint8_t *msg_type, uint16_t *len)
168 {
169     int ret;
170     socket_t from;
171 
172     ret = msg_recv_msg(client->udp_sock, &from, data, data_len,
173                        id, msg_type, len);
174     if(ret < 0)
175         return ret;
176 
177     if(!sock_addr_equal(client->udp_sock, &from))
178         return -1;
179 
180     return 0;
181 }
182 
183 /*
184  * Copy data to the internal buffer for sending to tcp connection and send ACK
185  * back to tunnel. Returns 0 on success, 1 if this was "resending" data, -1
186  * on error, or -2 if need to disconnect.
187  */
client_got_udp_data(client_t * client,char * data,int data_len,uint8_t msg_type)188 int client_got_udp_data(client_t *client, char *data, int data_len,
189                         uint8_t msg_type)
190 {
191     int ret;
192     int is_resend = 0;
193 
194     if(data_len > MSG_MAX_LEN)
195         return -1;
196 
197     /* Check if got new data, which is when got the data type (DATA0 or DATA1)
198        that it was waiting for, and write that new data to the buffer. */
199     if((msg_type == MSG_TYPE_DATA0 &&
200         client->udp2tcp_state == CLIENT_WAIT_DATA0)
201        || (msg_type == MSG_TYPE_DATA1 &&
202            client->udp2tcp_state == CLIENT_WAIT_DATA1))
203     {
204         memcpy(client->udp2tcp, data, data_len);
205         client->udp2tcp_len = data_len;
206     }
207     else
208         is_resend = 1; /* Otherwise, the other host resent the data */
209 
210     msg_type = (msg_type == MSG_TYPE_DATA0) ? MSG_TYPE_ACK0 : MSG_TYPE_ACK1;
211 
212     /* Send the ACK for the data */
213     ret = msg_send_msg(client->udp_sock, client->id, msg_type, NULL, 0);
214     if(ret < 0)
215         return ret;
216 
217     if(is_resend)
218         return 1;
219 
220     /* Set the state to wait for the next type of data */
221     client->udp2tcp_state = client->udp2tcp_state == CLIENT_WAIT_DATA0 ?
222         CLIENT_WAIT_DATA1 : CLIENT_WAIT_DATA0;
223 
224     return 0;
225 }
226 
227 /*
228  * Send data received from UDP tunnel to TCP connection. Need to call
229  * client_got_udp_data() first. Returns -1 on general error, -2 if need to
230  * disconnect, and 0 on success.
231  */
client_send_tcp_data(client_t * client)232 int client_send_tcp_data(client_t *client)
233 {
234     int ret;
235 
236     ret = sock_send(client->tcp_sock, client->udp2tcp, client->udp2tcp_len);
237 
238     if(ret < 0)
239         return -1;
240     else if(ret == 0)
241         return -2;
242     else
243         return 0;
244 }
245 
246 /*
247  * Reads data that is ready on the TCP socket and stores it in the internal
248  * buffer. The routine client_send_udp_data() send that data to the tunnel.
249  */
client_recv_tcp_data(client_t * client)250 int client_recv_tcp_data(client_t *client)
251 {
252     int ret;
253 
254     /* Don't read the tcp data yet if waiting for an ack or the hello */
255     if(client->tcp2udp_state == CLIENT_WAIT_ACK0 ||
256        client->tcp2udp_state == CLIENT_WAIT_ACK1 ||
257        client->udp2tcp_state == CLIENT_WAIT_HELLO)
258         return 1;
259 
260     ret = sock_recv(client->tcp_sock, NULL, client->tcp2udp,
261                     sizeof(client->tcp2udp));
262     if(ret < 0)
263         return -1;
264     if(ret == 0)
265         return -2;
266 
267     client->tcp2udp_len = ret;
268 
269     return 0;
270 }
271 
272 /*
273  * Sends the data in the tcp2udp buffer to the UDP tunnel. Returns 0 for
274  * success, -1 on error, and -2 if needs to disconnect.
275  */
client_send_udp_data(client_t * client)276 int client_send_udp_data(client_t *client)
277 {
278     uint8_t msg_type;
279     int ret;
280 
281     if(client->resend_count >= CLIENT_MAX_RESEND)
282         return -2;
283 
284     /* Set the message type it is sending. If the client is in the WAIT_ACK
285        state, then it will send the same type of data again (since this would
286        have been called b/c of a timeout. */
287     switch(client->tcp2udp_state)
288     {
289         case CLIENT_WAIT_DATA0:
290         case CLIENT_WAIT_ACK0:
291             msg_type = MSG_TYPE_DATA0;
292             break;
293 
294         case CLIENT_WAIT_DATA1:
295         case CLIENT_WAIT_ACK1:
296             msg_type = MSG_TYPE_DATA1;
297             break;
298 
299         default:
300             return -1;
301     }
302 
303     ret = msg_send_msg(client->udp_sock, client->id, msg_type,
304                        client->tcp2udp, client->tcp2udp_len);
305     if(ret < 0)
306         return ret;
307 
308     /* Set the state to wait for an ACK and set the timeout to some time in
309        the future */
310     client->tcp2udp_state = (msg_type == MSG_TYPE_DATA0) ?
311         CLIENT_WAIT_ACK0 : CLIENT_WAIT_ACK1;
312     gettimeofday(&client->tcp2udp_timeout, NULL);
313     client->tcp2udp_timeout.tv_sec += (client->resend_count+1)*CLIENT_TIMEOUT;
314 
315     return 0;
316 }
317 
318 /*
319  * Notifies the client that it got an ACK to change the internal state to
320  * wait for data. Returns 0 if ok or -1 if something weird happened.
321  */
client_got_ack(client_t * client,uint8_t ack_type)322 int client_got_ack(client_t *client, uint8_t ack_type)
323 {
324     if(ack_type == MSG_TYPE_ACK0 && client->tcp2udp_state == CLIENT_WAIT_ACK0)
325     {
326         client->tcp2udp_state = CLIENT_WAIT_DATA1;
327         client->resend_count = 0;
328         return 0;
329     }
330 
331     if(ack_type == MSG_TYPE_ACK1 && client->tcp2udp_state == CLIENT_WAIT_ACK1)
332     {
333         client->tcp2udp_state = CLIENT_WAIT_DATA0;
334         client->resend_count = 0;
335         return 0;
336     }
337 
338     return -1;
339 }
340 
341 /*
342  * Sends a HELLO type message to the udpserver (proxy) to tell it to make a
343  * TCP connection to the specified host:port.
344  */
client_send_hello(client_t * client,char * host,char * port,uint16_t req_id)345 int client_send_hello(client_t *client, char *host, char *port,
346                       uint16_t req_id)
347 {
348     return msg_send_hello(client->udp_sock, host, port, req_id);
349 }
350 
351 /*
352  * Sends a Hello ACK to the UDP tunnel.
353  */
client_send_helloack(client_t * client,uint16_t req_id)354 int client_send_helloack(client_t *client, uint16_t req_id)
355 {
356     req_id = htons(req_id);
357 
358     return msg_send_msg(client->udp_sock, client->id, MSG_TYPE_HELLOACK,
359                         (char *)&req_id, sizeof(req_id));
360 }
361 
362 /*
363  * Notify the client that it got a Hello ACK.
364  */
client_got_helloack(client_t * client)365 int client_got_helloack(client_t *client)
366 {
367     if(client->udp2tcp_state == CLIENT_WAIT_HELLO)
368         client->udp2tcp_state = CLIENT_WAIT_DATA0;
369 
370     return 0;
371 }
372 
373 /*
374  * Sends a goodbye message to the UDP server.
375  */
client_send_goodbye(client_t * client)376 int client_send_goodbye(client_t *client)
377 {
378     return msg_send_msg(client->udp_sock, client->id, MSG_TYPE_GOODBYE,
379                         NULL, 0);
380 }
381 
382 /*
383  * Checks the timeout state of the client and resend the data if the timeout
384  * is up.
385  */
client_check_and_resend(client_t * client,struct timeval curr_tv)386 int client_check_and_resend(client_t *client, struct timeval curr_tv)
387 {
388     if((client->tcp2udp_state == CLIENT_WAIT_ACK0 ||
389         client->tcp2udp_state == CLIENT_WAIT_ACK1)
390        && timercmp(&curr_tv, &client->tcp2udp_timeout, >))
391     {
392         client->resend_count++;
393         if(debug_level >= DEBUG_LEVEL2)
394             printf("client(%d): resending data, count %d\n",
395                    CLIENT_ID(client), client->resend_count);
396 
397         return client_send_udp_data(client);
398     }
399 
400     return 0;
401 }
402 
403 /*
404  * Sends a keepalive message to the UDP server.
405  */
client_check_and_send_keepalive(client_t * client,struct timeval curr_tv)406 int client_check_and_send_keepalive(client_t *client, struct timeval curr_tv)
407 {
408     if(client_timed_out(client, curr_tv))
409     {
410         curr_tv.tv_sec += KEEP_ALIVE_SECS;
411         memcpy(&client->keepalive, &curr_tv, sizeof(struct timeval));
412 
413         return msg_send_msg(client->udp_sock, client->id, MSG_TYPE_KEEPALIVE,
414                             NULL, 0);
415     }
416 
417     return 0;
418 }
419 
420 /*
421  * Sets the client's keepalive timeout to be the current time plus the timeout
422  * period.
423  */
client_reset_keepalive(client_t * client)424 void client_reset_keepalive(client_t *client)
425 {
426     struct timeval curr;
427 
428     gettimeofday(&curr, NULL);
429     curr.tv_sec += KEEP_ALIVE_TIMEOUT_SECS;
430     memcpy(&client->keepalive, &curr, sizeof(struct timeval));
431 }
432 
433 /*
434  * Returns 1 if the client timed out (didn't get any data or keep alive
435  * messages in the period), or 0 if it hasn't yet.
436  */
client_timed_out(client_t * client,struct timeval curr_tv)437 int client_timed_out(client_t *client, struct timeval curr_tv)
438 {
439     if(timercmp(&curr_tv, &client->keepalive, >))
440         return 1;
441     else
442         return 0;
443 }
444