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