diff options
Diffstat (limited to 'client.c')
-rw-r--r-- | client.c | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/client.c b/client.c new file mode 100644 index 0000000..190c7e5 --- /dev/null +++ b/client.c | |||
@@ -0,0 +1,328 @@ | |||
1 | #include "main.h" | ||
2 | #include "client.h" | ||
3 | |||
4 | /* The state machine */ | ||
5 | int state = CLIENT_STATE_INITIAL; | ||
6 | |||
7 | /* Used in ping mode */ | ||
8 | struct timespec ping_sent_time; | ||
9 | |||
10 | /* Client mode tunnel */ | ||
11 | tunnel client_tunnel; | ||
12 | |||
13 | fd_set client_master_fdset; | ||
14 | |||
15 | int handle_pong_frame(protocol_frame *rcvd_frame) | ||
16 | { | ||
17 | struct timespec pong_rcvd_time; | ||
18 | double secs1, secs2; | ||
19 | |||
20 | clock_gettime(CLOCK_MONOTONIC, &pong_rcvd_time); | ||
21 | |||
22 | secs1 = (1.0 * ping_sent_time.tv_sec) + (1e-9 * ping_sent_time.tv_nsec); | ||
23 | secs2 = (1.0 * pong_rcvd_time.tv_sec) + (1e-9 * pong_rcvd_time.tv_nsec); | ||
24 | |||
25 | printf("GOT PONG! Time = %.3fs\n", secs2-secs1); | ||
26 | |||
27 | if(ping_mode) | ||
28 | { | ||
29 | // state = CLIENT_STATE_PONG_RECEIVED; | ||
30 | state = CLIENT_STATE_SEND_PING; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | int local_bind(tunnel *tun) | ||
35 | { | ||
36 | struct addrinfo hints, *res; | ||
37 | int sockfd; | ||
38 | char port[6]; | ||
39 | int yes = 1; | ||
40 | |||
41 | /* accept() variables - TODO they should not be there */ | ||
42 | int newfd; | ||
43 | struct sockaddr_storage remoteaddr; // client address | ||
44 | socklen_t addrlen; | ||
45 | |||
46 | snprintf(port, 6, "%d", local_port); | ||
47 | |||
48 | memset(&hints, 0, sizeof hints); | ||
49 | hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever | ||
50 | hints.ai_socktype = SOCK_STREAM; | ||
51 | hints.ai_flags = AI_PASSIVE; // fill in my IP for me | ||
52 | |||
53 | getaddrinfo(NULL, port, &hints, &res); | ||
54 | |||
55 | sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
56 | if(sockfd < 0) | ||
57 | { | ||
58 | fprintf(stderr, "Could not create a socket for local listening\n"); | ||
59 | exit(1); | ||
60 | } | ||
61 | |||
62 | setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); | ||
63 | |||
64 | if(bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) | ||
65 | { | ||
66 | fprintf(stderr, "Bind to port %d failed: %s", local_port, strerror(errno)); | ||
67 | close(sockfd); | ||
68 | exit(1); | ||
69 | } | ||
70 | |||
71 | if(listen(sockfd, 1) < 0) | ||
72 | { | ||
73 | fprintf(stderr, "Listening on port %d failed: %s", local_port, strerror(errno)); | ||
74 | close(sockfd); | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | // TODO return sockfd | ||
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 | { | ||
88 | fprintf(stderr, "Error when accepting a local connection: %s\n", strerror(errno)); | ||
89 | close(sockfd); | ||
90 | exit(0); | ||
91 | } | ||
92 | |||
93 | // TODO close(sockfd); | ||
94 | |||
95 | return newfd; | ||
96 | } | ||
97 | |||
98 | int handle_acktunnel_frame(protocol_frame *rcvd_frame) | ||
99 | { | ||
100 | if(!client_mode) | ||
101 | { | ||
102 | fprintf(stderr, "Got ACK tunnel frame when not in client mode!?\n"); | ||
103 | return -1; | ||
104 | } | ||
105 | |||
106 | client_tunnel.connid = rcvd_frame->connid; | ||
107 | client_tunnel.friendnumber = rcvd_frame->friendnumber; | ||
108 | // TODO open local port and fill client_tunnel.sockfd | ||
109 | printf("New tunnel ID: %d\n", client_tunnel.connid); | ||
110 | |||
111 | if(client_local_port_mode) | ||
112 | { | ||
113 | client_tunnel.sockfd = local_bind(&client_tunnel); | ||
114 | update_select_nfds(client_tunnel.sockfd); | ||
115 | FD_SET(client_tunnel.sockfd, &client_master_fdset); | ||
116 | fprintf(stderr, "Accepting connections on port %d\n", local_port); | ||
117 | state = CLIENT_STATE_FORWARDING; | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | fprintf(stderr, "This tunnel mode is not supported yet"); | ||
122 | exit(1); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /* Handle a TCP frame received from server */ | ||
127 | int handle_server_tcp_frame(protocol_frame *rcvd_frame) | ||
128 | { | ||
129 | /* TODO find tunnel basing on ID */ | ||
130 | int offset = 0; | ||
131 | tunnel *tun = &client_tunnel; | ||
132 | |||
133 | while(offset < rcvd_frame->data_length) | ||
134 | { | ||
135 | int sent_bytes; | ||
136 | |||
137 | sent_bytes = send( | ||
138 | tun->sockfd, | ||
139 | rcvd_frame->data + offset, | ||
140 | rcvd_frame->data_length - offset, | ||
141 | 0 | ||
142 | ); | ||
143 | |||
144 | if(sent_bytes < 0) | ||
145 | { | ||
146 | fprintf(stderr, "Could not write to socket %d: %s\n", tun->sockfd, strerror(errno)); | ||
147 | return -1; | ||
148 | } | ||
149 | |||
150 | offset += sent_bytes; | ||
151 | } | ||
152 | |||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* Main loop for the client */ | ||
158 | int do_client_loop(char *tox_id_str) | ||
159 | { | ||
160 | unsigned char tox_packet_buf[PROTOCOL_MAX_PACKET_SIZE]; | ||
161 | unsigned char tox_id[TOX_FRIEND_ADDRESS_SIZE]; | ||
162 | uint32_t friendnumber; | ||
163 | struct timeval tv; | ||
164 | fd_set fds; | ||
165 | |||
166 | client_tunnel.sockfd = 0; | ||
167 | FD_ZERO(&client_master_fdset); | ||
168 | |||
169 | if(!string_to_id(tox_id, tox_id_str)) | ||
170 | { | ||
171 | fprintf(stderr, "Invalid Tox ID"); | ||
172 | exit(1); | ||
173 | } | ||
174 | |||
175 | fprintf(stderr, "Connecting to Tox...\n"); | ||
176 | |||
177 | while(1) | ||
178 | { | ||
179 | /* Let tox do its stuff */ | ||
180 | tox_do(tox); | ||
181 | |||
182 | switch(state) | ||
183 | { | ||
184 | /* | ||
185 | * Send friend request | ||
186 | */ | ||
187 | case CLIENT_STATE_INITIAL: | ||
188 | if(tox_isconnected(tox)) | ||
189 | { | ||
190 | state = CLIENT_STATE_CONNECTED; | ||
191 | } | ||
192 | break; | ||
193 | case CLIENT_STATE_CONNECTED: | ||
194 | { | ||
195 | uint8_t data[] = "Hi, fellow tuntox instance!"; | ||
196 | uint16_t length = sizeof(data); | ||
197 | |||
198 | fprintf(stderr, "Connected. Sending friend request.\n"); | ||
199 | |||
200 | friendnumber = tox_add_friend( | ||
201 | tox, | ||
202 | tox_id, | ||
203 | data, | ||
204 | length | ||
205 | ); | ||
206 | |||
207 | if(friendnumber < 0) | ||
208 | { | ||
209 | fprintf(stderr, "Error %d adding friend %s\n", friendnumber, tox_id); | ||
210 | exit(-1); | ||
211 | } | ||
212 | |||
213 | tox_lossless_packet_registerhandler(tox, friendnumber, (PROTOCOL_MAGIC_V1)>>8, parse_lossless_packet, (void*)&friendnumber); | ||
214 | state = CLIENT_STATE_SENTREQUEST; | ||
215 | fprintf(stderr, "Waiting for friend to accept us...\n"); | ||
216 | } | ||
217 | break; | ||
218 | case CLIENT_STATE_SENTREQUEST: | ||
219 | if(tox_get_friend_connection_status(tox, friendnumber) == 1) | ||
220 | { | ||
221 | fprintf(stderr, "Friend request accepted!\n"); | ||
222 | state = CLIENT_STATE_REQUEST_ACCEPTED; | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | } | ||
227 | break; | ||
228 | case CLIENT_STATE_REQUEST_ACCEPTED: | ||
229 | if(ping_mode) | ||
230 | { | ||
231 | state = CLIENT_STATE_SEND_PING; | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | state = CLIENT_STATE_REQUEST_TUNNEL; | ||
236 | } | ||
237 | break; | ||
238 | case CLIENT_STATE_SEND_PING: | ||
239 | /* Send the ping packet */ | ||
240 | { | ||
241 | uint8_t data[] = { | ||
242 | 0xa2, 0x6a, 0x01, 0x08, 0x00, 0x00, 0x00, 0x05, | ||
243 | 0x48, 0x65, 0x6c, 0x6c, 0x6f | ||
244 | }; | ||
245 | |||
246 | clock_gettime(CLOCK_MONOTONIC, &ping_sent_time); | ||
247 | tox_send_lossless_packet( | ||
248 | tox, | ||
249 | friendnumber, | ||
250 | data, | ||
251 | sizeof(data) | ||
252 | ); | ||
253 | } | ||
254 | state = CLIENT_STATE_PING_SENT; | ||
255 | break; | ||
256 | case CLIENT_STATE_PING_SENT: | ||
257 | /* Just sit there and wait for pong */ | ||
258 | break; | ||
259 | case CLIENT_STATE_REQUEST_TUNNEL: | ||
260 | send_tunnel_request_packet( | ||
261 | "127.0.0.1", | ||
262 | remote_port, | ||
263 | friendnumber | ||
264 | ); | ||
265 | state = CLIENT_STATE_WAIT_FOR_ACKTUNNEL; | ||
266 | break; | ||
267 | case CLIENT_STATE_WAIT_FOR_ACKTUNNEL: | ||
268 | break; | ||
269 | case CLIENT_STATE_FORWARDING: | ||
270 | { | ||
271 | tv.tv_sec = 0; | ||
272 | tv.tv_usec = 20000; | ||
273 | fds = client_master_fdset; | ||
274 | |||
275 | select(select_nfds, &fds, NULL, NULL, &tv); | ||
276 | |||
277 | if(FD_ISSET(client_tunnel.sockfd, &fds)) | ||
278 | { | ||
279 | int nbytes = recv(client_tunnel.sockfd, | ||
280 | tox_packet_buf + PROTOCOL_BUFFER_OFFSET, | ||
281 | READ_BUFFER_SIZE, 0); | ||
282 | |||
283 | /* Check if connection closed */ | ||
284 | if(nbytes == 0) | ||
285 | { | ||
286 | char data[PROTOCOL_BUFFER_OFFSET]; | ||
287 | protocol_frame frame_st, *frame; | ||
288 | |||
289 | fprintf(stderr, "Connection closed\n"); | ||
290 | |||
291 | frame = &frame_st; | ||
292 | memset(frame, 0, sizeof(protocol_frame)); | ||
293 | frame->friendnumber = client_tunnel.friendnumber; | ||
294 | frame->packet_type = PACKET_TYPE_TCP_FIN; | ||
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 | } | ||
303 | else | ||
304 | { | ||
305 | protocol_frame frame_st, *frame; | ||
306 | |||
307 | frame = &frame_st; | ||
308 | memset(frame, 0, sizeof(protocol_frame)); | ||
309 | frame->friendnumber = client_tunnel.friendnumber; | ||
310 | frame->packet_type = PACKET_TYPE_TCP; | ||
311 | frame->connid = client_tunnel.connid; | ||
312 | frame->data_length = nbytes; | ||
313 | send_frame(frame, tox_packet_buf); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | fds = client_master_fdset; | ||
318 | } | ||
319 | break; | ||
320 | case CLIENT_STATE_SHUTDOWN: | ||
321 | exit(0); | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | usleep(tox_do_interval(tox) * 1000); | ||
326 | } | ||
327 | } | ||
328 | |||