ffi-tox 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/ProjectTox-Core/AUTHORS +0 -0
  3. data/ProjectTox-Core/ChangeLog +0 -0
  4. data/ProjectTox-Core/INSTALL +370 -0
  5. data/ProjectTox-Core/INSTALL.md +455 -56
  6. data/ProjectTox-Core/Makefile.am +35 -0
  7. data/ProjectTox-Core/NEWS +0 -0
  8. data/ProjectTox-Core/README +43 -0
  9. data/ProjectTox-Core/README.md +34 -44
  10. data/ProjectTox-Core/auto_tests/Makefile.inc +110 -0
  11. data/ProjectTox-Core/auto_tests/TCP_test.c +519 -0
  12. data/ProjectTox-Core/auto_tests/assoc_test.c +160 -0
  13. data/ProjectTox-Core/auto_tests/crypto_test.c +302 -0
  14. data/ProjectTox-Core/auto_tests/dht_test.c +362 -0
  15. data/ProjectTox-Core/auto_tests/encryptsave_test.c +104 -0
  16. data/ProjectTox-Core/auto_tests/friends_test.c +238 -0
  17. data/ProjectTox-Core/auto_tests/helpers.h +15 -0
  18. data/ProjectTox-Core/auto_tests/messenger_test.c +365 -0
  19. data/ProjectTox-Core/auto_tests/network_test.c +171 -0
  20. data/ProjectTox-Core/auto_tests/onion_test.c +363 -0
  21. data/ProjectTox-Core/auto_tests/skeleton_test.c +49 -0
  22. data/ProjectTox-Core/auto_tests/tox_test.c +454 -0
  23. data/ProjectTox-Core/auto_tests/toxav_basic_test.c +597 -0
  24. data/ProjectTox-Core/auto_tests/toxav_many_test.c +402 -0
  25. data/ProjectTox-Core/autogen.sh +6 -0
  26. data/ProjectTox-Core/build/Makefile.am +14 -0
  27. data/ProjectTox-Core/configure.ac +694 -0
  28. data/ProjectTox-Core/dist-build/android-arm.sh +3 -0
  29. data/ProjectTox-Core/dist-build/android-armv7.sh +3 -0
  30. data/ProjectTox-Core/dist-build/android-build.sh +59 -0
  31. data/ProjectTox-Core/dist-build/android-mips.sh +3 -0
  32. data/ProjectTox-Core/dist-build/android-x86.sh +3 -0
  33. data/ProjectTox-Core/docs/Group-Chats.md +71 -0
  34. data/ProjectTox-Core/docs/Hardening.txt +60 -0
  35. data/ProjectTox-Core/docs/Hardening_docs.txt +30 -0
  36. data/ProjectTox-Core/docs/Prevent_Tracking.txt +160 -0
  37. data/ProjectTox-Core/docs/TCP_Network.txt +154 -0
  38. data/ProjectTox-Core/docs/TODO +62 -0
  39. data/ProjectTox-Core/docs/Tox_middle_level_network_protocol.txt +120 -0
  40. data/ProjectTox-Core/docs/av_api.md +194 -0
  41. data/ProjectTox-Core/libtoxav.pc.in +11 -0
  42. data/ProjectTox-Core/libtoxcore.pc.in +11 -0
  43. data/ProjectTox-Core/m4/ax_have_epoll.m4 +104 -0
  44. data/ProjectTox-Core/m4/ax_pthread.m4 +317 -0
  45. data/ProjectTox-Core/m4/pkg.m4 +199 -0
  46. data/ProjectTox-Core/other/DHT_bootstrap.c +121 -58
  47. data/ProjectTox-Core/other/DHTnodes +3 -0
  48. data/ProjectTox-Core/other/Makefile.inc +20 -0
  49. data/ProjectTox-Core/other/bootstrap_node_packets.c +65 -0
  50. data/ProjectTox-Core/other/tox.png +0 -0
  51. data/ProjectTox-Core/testing/DHT_test.c +170 -98
  52. data/ProjectTox-Core/testing/Makefile.inc +112 -0
  53. data/ProjectTox-Core/testing/Messenger_test.c +133 -69
  54. data/ProjectTox-Core/testing/dns3_test.c +115 -0
  55. data/ProjectTox-Core/testing/misc_tools.c +59 -13
  56. data/ProjectTox-Core/testing/nTox.c +1127 -264
  57. data/ProjectTox-Core/testing/nTox.h +10 -19
  58. data/ProjectTox-Core/testing/tox_shell.c +159 -0
  59. data/ProjectTox-Core/testing/tox_sync.c +299 -0
  60. data/ProjectTox-Core/tools/README +11 -0
  61. data/ProjectTox-Core/tools/astylerc +11 -0
  62. data/ProjectTox-Core/tools/pre-commit +17 -0
  63. data/ProjectTox-Core/toxav/Makefile.inc +36 -0
  64. data/ProjectTox-Core/toxav/codec.c +357 -0
  65. data/ProjectTox-Core/toxav/codec.h +116 -0
  66. data/ProjectTox-Core/toxav/msi.c +1949 -0
  67. data/ProjectTox-Core/toxav/msi.h +267 -0
  68. data/ProjectTox-Core/toxav/rtp.c +600 -0
  69. data/ProjectTox-Core/toxav/rtp.h +196 -0
  70. data/ProjectTox-Core/toxav/toxav.c +1148 -0
  71. data/ProjectTox-Core/toxav/toxav.h +389 -0
  72. data/ProjectTox-Core/toxcore/DHT.c +2521 -0
  73. data/ProjectTox-Core/toxcore/DHT.h +412 -0
  74. data/ProjectTox-Core/toxcore/LAN_discovery.c +322 -0
  75. data/ProjectTox-Core/{core → toxcore}/LAN_discovery.h +17 -12
  76. data/ProjectTox-Core/toxcore/Makefile.inc +67 -0
  77. data/ProjectTox-Core/toxcore/Messenger.c +3006 -0
  78. data/ProjectTox-Core/toxcore/Messenger.h +818 -0
  79. data/ProjectTox-Core/toxcore/TCP_client.c +858 -0
  80. data/ProjectTox-Core/toxcore/TCP_client.h +156 -0
  81. data/ProjectTox-Core/toxcore/TCP_server.c +1332 -0
  82. data/ProjectTox-Core/toxcore/TCP_server.h +181 -0
  83. data/ProjectTox-Core/toxcore/assoc.c +1033 -0
  84. data/ProjectTox-Core/toxcore/assoc.h +104 -0
  85. data/ProjectTox-Core/toxcore/crypto_core.c +278 -0
  86. data/ProjectTox-Core/toxcore/crypto_core.h +151 -0
  87. data/ProjectTox-Core/toxcore/friend_requests.c +175 -0
  88. data/ProjectTox-Core/toxcore/friend_requests.h +83 -0
  89. data/ProjectTox-Core/toxcore/group_chats.c +837 -0
  90. data/ProjectTox-Core/toxcore/group_chats.h +199 -0
  91. data/ProjectTox-Core/toxcore/list.c +256 -0
  92. data/ProjectTox-Core/toxcore/list.h +85 -0
  93. data/ProjectTox-Core/toxcore/logger.c +153 -0
  94. data/ProjectTox-Core/toxcore/logger.h +84 -0
  95. data/ProjectTox-Core/toxcore/misc_tools.h +70 -0
  96. data/ProjectTox-Core/toxcore/net_crypto.c +2753 -0
  97. data/ProjectTox-Core/toxcore/net_crypto.h +410 -0
  98. data/ProjectTox-Core/toxcore/network.c +979 -0
  99. data/ProjectTox-Core/toxcore/network.h +367 -0
  100. data/ProjectTox-Core/toxcore/onion.c +540 -0
  101. data/ProjectTox-Core/toxcore/onion.h +150 -0
  102. data/ProjectTox-Core/toxcore/onion_announce.c +433 -0
  103. data/ProjectTox-Core/toxcore/onion_announce.h +139 -0
  104. data/ProjectTox-Core/toxcore/onion_client.c +1347 -0
  105. data/ProjectTox-Core/toxcore/onion_client.h +253 -0
  106. data/ProjectTox-Core/toxcore/ping.c +346 -0
  107. data/ProjectTox-Core/toxcore/ping.h +47 -0
  108. data/ProjectTox-Core/toxcore/ping_array.c +162 -0
  109. data/ProjectTox-Core/toxcore/ping_array.h +75 -0
  110. data/ProjectTox-Core/toxcore/tox.c +940 -0
  111. data/ProjectTox-Core/toxcore/tox.h +734 -0
  112. data/ProjectTox-Core/toxcore/util.c +193 -0
  113. data/ProjectTox-Core/toxcore/util.h +63 -0
  114. data/ProjectTox-Core/toxdns/Makefile.inc +29 -0
  115. data/ProjectTox-Core/toxdns/toxdns.c +238 -0
  116. data/ProjectTox-Core/toxdns/toxdns.h +88 -0
  117. data/ProjectTox-Core/toxencryptsave/Makefile.inc +45 -0
  118. data/ProjectTox-Core/toxencryptsave/toxencryptsave.c +179 -0
  119. data/ProjectTox-Core/toxencryptsave/toxencryptsave.h +74 -0
  120. data/interfaces/libtox.i +2 -6
  121. data/lib/ffi-tox/libtox.rb +406 -28
  122. metadata +124 -46
  123. data/ProjectTox-Core/CMakeLists.txt +0 -50
  124. data/ProjectTox-Core/cmake/FindLIBCONFIG.cmake +0 -15
  125. data/ProjectTox-Core/cmake/FindNaCl.cmake +0 -17
  126. data/ProjectTox-Core/cmake/FindSODIUM.cmake +0 -15
  127. data/ProjectTox-Core/core/CMakeLists.txt +0 -19
  128. data/ProjectTox-Core/core/DHT.c +0 -1104
  129. data/ProjectTox-Core/core/DHT.h +0 -111
  130. data/ProjectTox-Core/core/LAN_discovery.c +0 -79
  131. data/ProjectTox-Core/core/Lossless_UDP.c +0 -755
  132. data/ProjectTox-Core/core/Lossless_UDP.h +0 -106
  133. data/ProjectTox-Core/core/Messenger.c +0 -596
  134. data/ProjectTox-Core/core/Messenger.h +0 -165
  135. data/ProjectTox-Core/core/friend_requests.c +0 -131
  136. data/ProjectTox-Core/core/friend_requests.h +0 -51
  137. data/ProjectTox-Core/core/net_crypto.c +0 -575
  138. data/ProjectTox-Core/core/net_crypto.h +0 -134
  139. data/ProjectTox-Core/core/network.c +0 -205
  140. data/ProjectTox-Core/core/network.h +0 -134
  141. data/ProjectTox-Core/docs/commands.md +0 -25
  142. data/ProjectTox-Core/docs/start_guide.de.md +0 -40
  143. data/ProjectTox-Core/docs/start_guide.md +0 -38
  144. data/ProjectTox-Core/other/CMakeLists.txt +0 -9
  145. data/ProjectTox-Core/testing/CMakeLists.txt +0 -18
  146. data/ProjectTox-Core/testing/DHT_cryptosendfiletest.c +0 -228
  147. data/ProjectTox-Core/testing/DHT_sendfiletest.c +0 -176
  148. data/ProjectTox-Core/testing/Lossless_UDP_testclient.c +0 -214
  149. data/ProjectTox-Core/testing/Lossless_UDP_testserver.c +0 -201
  150. data/ProjectTox-Core/testing/misc_tools.h +0 -29
  151. data/ProjectTox-Core/testing/nTox_win32.c +0 -387
  152. data/ProjectTox-Core/testing/nTox_win32.h +0 -40
  153. data/ProjectTox-Core/testing/rect.py +0 -45
@@ -0,0 +1,858 @@
1
+ /*
2
+ * TCP_client.c -- Implementation of the TCP relay client part of Tox.
3
+ *
4
+ * Copyright (C) 2014 Tox project All Rights Reserved.
5
+ *
6
+ * This file is part of Tox.
7
+ *
8
+ * Tox 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
+ * Tox 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 Tox. If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+ #ifdef HAVE_CONFIG_H
24
+ #include "config.h"
25
+ #endif
26
+
27
+ #include "TCP_client.h"
28
+
29
+ #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
30
+ #include <sys/ioctl.h>
31
+ #endif
32
+
33
+ #include "util.h"
34
+
35
+ /* return 1 on success
36
+ * return 0 on failure
37
+ */
38
+ static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
39
+ {
40
+ if (proxy_info)
41
+ ip_port = proxy_info->ip_port;
42
+
43
+ struct sockaddr_storage addr = {0};
44
+ size_t addrsize;
45
+
46
+ if (ip_port.ip.family == AF_INET) {
47
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
48
+
49
+ addrsize = sizeof(struct sockaddr_in);
50
+ addr4->sin_family = AF_INET;
51
+ addr4->sin_addr = ip_port.ip.ip4.in_addr;
52
+ addr4->sin_port = ip_port.port;
53
+ } else if (ip_port.ip.family == AF_INET6) {
54
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
55
+
56
+ addrsize = sizeof(struct sockaddr_in6);
57
+ addr6->sin6_family = AF_INET6;
58
+ addr6->sin6_addr = ip_port.ip.ip6.in6_addr;
59
+ addr6->sin6_port = ip_port.port;
60
+ } else {
61
+ return 0;
62
+ }
63
+
64
+ /* nonblocking socket, connect will never return success */
65
+ connect(sock, (struct sockaddr *)&addr, addrsize);
66
+ return 1;
67
+ }
68
+
69
+
70
+ static void socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
71
+ {
72
+ TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
73
+ TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */
74
+ TCP_conn->last_packet[2] = 0; /* No authentication */
75
+
76
+ TCP_conn->last_packet_length = 3;
77
+ TCP_conn->last_packet_sent = 0;
78
+ }
79
+
80
+ /* return 1 on success.
81
+ * return 0 if no data received.
82
+ * return -1 on failure (connection refused).
83
+ */
84
+ static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
85
+ {
86
+ uint8_t data[2];
87
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
88
+
89
+ if (ret == -1)
90
+ return 0;
91
+
92
+ if (data[0] == 5 && data[1] == 0)
93
+ return 1;
94
+
95
+ return -1;
96
+ }
97
+
98
+ static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
99
+ {
100
+ TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
101
+ TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
102
+ TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */
103
+ uint16_t length = 3;
104
+
105
+ if (TCP_conn->ip_port.ip.family == AF_INET) {
106
+ TCP_conn->last_packet[3] = 1; /* IPv4 address */
107
+ ++length;
108
+ memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip4.uint8, sizeof(IP4));
109
+ length += sizeof(IP4);
110
+ } else {
111
+ TCP_conn->last_packet[3] = 4; /* IPv6 address */
112
+ ++length;
113
+ memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip6.uint8, sizeof(IP6));
114
+ length += sizeof(IP6);
115
+ }
116
+
117
+ memcpy(TCP_conn->last_packet + length, &TCP_conn->ip_port.port, sizeof(uint16_t));
118
+ length += sizeof(uint16_t);
119
+
120
+ TCP_conn->last_packet_length = length;
121
+ TCP_conn->last_packet_sent = 0;
122
+ }
123
+
124
+ /* return 1 on success.
125
+ * return 0 if no data received.
126
+ * return -1 on failure (connection refused).
127
+ */
128
+ static int socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
129
+ {
130
+ if (TCP_conn->ip_port.ip.family == AF_INET) {
131
+ uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
132
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
133
+
134
+ if (ret == -1)
135
+ return 0;
136
+
137
+ if (data[0] == 5 && data[1] == 0)
138
+ return 1;
139
+
140
+ } else {
141
+ uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
142
+ int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
143
+
144
+ if (ret == -1)
145
+ return 0;
146
+
147
+ if (data[0] == 5 && data[1] == 0)
148
+ return 1;
149
+ }
150
+
151
+ return -1;
152
+ }
153
+
154
+ /* return 0 on success.
155
+ * return -1 on failure.
156
+ */
157
+ static int generate_handshake(TCP_Client_Connection *TCP_conn)
158
+ {
159
+ uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
160
+ crypto_box_keypair(plain, TCP_conn->temp_secret_key);
161
+ random_nonce(TCP_conn->sent_nonce);
162
+ memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES);
163
+ memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, crypto_box_PUBLICKEYBYTES);
164
+ new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES);
165
+ int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain,
166
+ sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
167
+
168
+ if (len != sizeof(plain) + crypto_box_MACBYTES)
169
+ return -1;
170
+
171
+ TCP_conn->last_packet_length = crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(plain) + crypto_box_MACBYTES;
172
+ TCP_conn->last_packet_sent = 0;
173
+ return 0;
174
+ }
175
+
176
+ /* data must be of length TCP_SERVER_HANDSHAKE_SIZE
177
+ *
178
+ * return 0 on success.
179
+ * return -1 on failure.
180
+ */
181
+ static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
182
+ {
183
+ uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
184
+ int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES,
185
+ TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain);
186
+
187
+ if (len != sizeof(plain))
188
+ return -1;
189
+
190
+ memcpy(TCP_conn->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
191
+ encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
192
+ memset(TCP_conn->temp_secret_key, 0, crypto_box_SECRETKEYBYTES);
193
+ return 0;
194
+ }
195
+
196
+ /* return 0 if pending data was sent completely
197
+ * return -1 if it wasn't
198
+ */
199
+ static int send_pending_data_nonpriority(TCP_Client_Connection *con)
200
+ {
201
+ if (con->last_packet_length == 0) {
202
+ return 0;
203
+ }
204
+
205
+ uint16_t left = con->last_packet_length - con->last_packet_sent;
206
+ int len = send(con->sock, con->last_packet + con->last_packet_sent, left, MSG_NOSIGNAL);
207
+
208
+ if (len <= 0)
209
+ return -1;
210
+
211
+ if (len == left) {
212
+ con->last_packet_length = 0;
213
+ con->last_packet_sent = 0;
214
+ return 0;
215
+ }
216
+
217
+ con->last_packet_sent += len;
218
+ return -1;
219
+ }
220
+
221
+ /* return 0 if pending data was sent completely
222
+ * return -1 if it wasn't
223
+ */
224
+ static int send_pending_data(TCP_Client_Connection *con)
225
+ {
226
+ /* finish sending current non-priority packet */
227
+ if (send_pending_data_nonpriority(con) == -1) {
228
+ return -1;
229
+ }
230
+
231
+ TCP_Priority_List *p = con->priority_queue_start;
232
+
233
+ while (p) {
234
+ uint16_t left = p->size - p->sent;
235
+ int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL);
236
+
237
+ if (len != left) {
238
+ if (len > 0) {
239
+ p->sent += len;
240
+ }
241
+
242
+ break;
243
+ }
244
+
245
+ TCP_Priority_List *pp = p;
246
+ p = p->next;
247
+ free(pp);
248
+ }
249
+
250
+ con->priority_queue_start = p;
251
+
252
+ if (!p) {
253
+ con->priority_queue_end = NULL;
254
+ return 0;
255
+ }
256
+
257
+ return -1;
258
+ }
259
+
260
+ /* return 0 on failure (only if malloc fails)
261
+ * return 1 on success
262
+ */
263
+ static _Bool add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
264
+ {
265
+ TCP_Priority_List *p = con->priority_queue_end, *new;
266
+ new = malloc(sizeof(TCP_Priority_List) + size);
267
+
268
+ if (!new) {
269
+ return 0;
270
+ }
271
+
272
+ new->next = NULL;
273
+ new->size = size;
274
+ new->sent = sent;
275
+ memcpy(new->data, packet, size);
276
+
277
+ if (p) {
278
+ p->next = new;
279
+ } else {
280
+ con->priority_queue_start = new;
281
+ }
282
+
283
+ con->priority_queue_end = new;
284
+ return 1;
285
+ }
286
+
287
+ /* return 1 on success.
288
+ * return 0 if could not send packet.
289
+ * return -1 on failure (connection must be killed).
290
+ */
291
+ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length,
292
+ _Bool priority)
293
+ {
294
+ if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE)
295
+ return -1;
296
+
297
+ _Bool sendpriority = 1;
298
+
299
+ if (send_pending_data(con) == -1) {
300
+ if (priority) {
301
+ sendpriority = 0;
302
+ } else {
303
+ return 0;
304
+ }
305
+ }
306
+
307
+ uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES];
308
+
309
+ uint16_t c_length = htons(length + crypto_box_MACBYTES);
310
+ memcpy(packet, &c_length, sizeof(uint16_t));
311
+ int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
312
+
313
+ if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t)))
314
+ return -1;
315
+
316
+ if (priority) {
317
+ len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0;
318
+
319
+ if (len <= 0) {
320
+ len = 0;
321
+ }
322
+
323
+ increment_nonce(con->sent_nonce);
324
+
325
+ if ((unsigned int)len == sizeof(packet)) {
326
+ return 1;
327
+ }
328
+
329
+ return add_priority(con, packet, sizeof(packet), len);
330
+ }
331
+
332
+ len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL);
333
+
334
+ if (len <= 0)
335
+ return 0;
336
+
337
+ increment_nonce(con->sent_nonce);
338
+
339
+ if ((unsigned int)len == sizeof(packet))
340
+ return 1;
341
+
342
+ memcpy(con->last_packet, packet, sizeof(packet));
343
+ con->last_packet_length = sizeof(packet);
344
+ con->last_packet_sent = len;
345
+ return 1;
346
+ }
347
+
348
+ /* return 1 on success.
349
+ * return 0 if could not send packet.
350
+ * return -1 on failure (connection must be killed).
351
+ */
352
+ int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
353
+ {
354
+ uint8_t packet[1 + crypto_box_PUBLICKEYBYTES];
355
+ packet[0] = TCP_PACKET_ROUTING_REQUEST;
356
+ memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
357
+ return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1);
358
+ }
359
+
360
+ void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
361
+ const uint8_t *public_key), void *object)
362
+ {
363
+ con->response_callback = response_callback;
364
+ con->response_callback_object = object;
365
+ }
366
+
367
+ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
368
+ uint8_t connection_id, uint8_t status), void *object)
369
+ {
370
+ con->status_callback = status_callback;
371
+ con->status_callback_object = object;
372
+ }
373
+
374
+ static int send_ping_response(TCP_Client_Connection *con);
375
+ static int send_ping_request(TCP_Client_Connection *con);
376
+
377
+ /* return 1 on success.
378
+ * return 0 if could not send packet.
379
+ * return -1 on failure.
380
+ */
381
+ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)
382
+ {
383
+ if (con_id >= NUM_CLIENT_CONNECTIONS)
384
+ return -1;
385
+
386
+ if (con->connections[con_id].status != 2)
387
+ return -1;
388
+
389
+ if (send_ping_response(con) == 0 || send_ping_request(con) == 0)
390
+ return 0;
391
+
392
+ uint8_t packet[1 + length];
393
+ packet[0] = con_id + NUM_RESERVED_PORTS;
394
+ memcpy(packet + 1, data, length);
395
+ return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0);
396
+ }
397
+
398
+ /* return 1 on success.
399
+ * return 0 if could not send packet.
400
+ * return -1 on failure.
401
+ */
402
+ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length)
403
+ {
404
+ if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH)
405
+ return -1;
406
+
407
+ uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length];
408
+ packet[0] = TCP_PACKET_OOB_SEND;
409
+ memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
410
+ memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length);
411
+ return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0);
412
+ }
413
+
414
+
415
+ /* Set the number that will be used as an argument in the callbacks related to con_id.
416
+ *
417
+ * When not set by this function, the number is ~0.
418
+ *
419
+ * return 0 on success.
420
+ * return -1 on failure.
421
+ */
422
+ int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
423
+ {
424
+ if (con_id >= NUM_CLIENT_CONNECTIONS)
425
+ return -1;
426
+
427
+ if (con->connections[con_id].status == 0)
428
+ return -1;
429
+
430
+ con->connections[con_id].number = number;
431
+ return 0;
432
+ }
433
+
434
+ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
435
+ uint8_t connection_id, const uint8_t *data, uint16_t length), void *object)
436
+ {
437
+ con->data_callback = data_callback;
438
+ con->data_callback_object = object;
439
+ }
440
+
441
+ void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
442
+ const uint8_t *data, uint16_t length), void *object)
443
+ {
444
+ con->oob_data_callback = oob_data_callback;
445
+ con->oob_data_callback_object = object;
446
+ }
447
+
448
+ /* return 1 on success.
449
+ * return 0 if could not send packet.
450
+ * return -1 on failure (connection must be killed).
451
+ */
452
+ static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id)
453
+ {
454
+ uint8_t packet[1 + 1];
455
+ packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
456
+ packet[1] = id;
457
+ return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1);
458
+ }
459
+
460
+ /* return 1 on success.
461
+ * return 0 if could not send packet.
462
+ * return -1 on failure (connection must be killed).
463
+ */
464
+ static int send_ping_request(TCP_Client_Connection *con)
465
+ {
466
+ if (!con->ping_request_id)
467
+ return 1;
468
+
469
+ uint8_t packet[1 + sizeof(uint64_t)];
470
+ packet[0] = TCP_PACKET_PING;
471
+ memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
472
+ int ret;
473
+
474
+ if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
475
+ con->ping_request_id = 0;
476
+ }
477
+
478
+ return ret;
479
+ }
480
+
481
+ /* return 1 on success.
482
+ * return 0 if could not send packet.
483
+ * return -1 on failure (connection must be killed).
484
+ */
485
+ static int send_ping_response(TCP_Client_Connection *con)
486
+ {
487
+ if (!con->ping_response_id)
488
+ return 1;
489
+
490
+ uint8_t packet[1 + sizeof(uint64_t)];
491
+ packet[0] = TCP_PACKET_PONG;
492
+ memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
493
+ int ret;
494
+
495
+ if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
496
+ con->ping_response_id = 0;
497
+ }
498
+
499
+ return ret;
500
+ }
501
+
502
+ /* return 1 on success.
503
+ * return 0 if could not send packet.
504
+ * return -1 on failure (connection must be killed).
505
+ */
506
+ int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
507
+ {
508
+ if (con_id >= NUM_CLIENT_CONNECTIONS)
509
+ return -1;
510
+
511
+ con->connections[con_id].status = 0;
512
+ con->connections[con_id].number = 0;
513
+ return send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS);
514
+ }
515
+
516
+ /* return 1 on success.
517
+ * return 0 if could not send packet.
518
+ * return -1 on failure (connection must be killed).
519
+ */
520
+ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
521
+ {
522
+ uint8_t packet[1 + length];
523
+ packet[0] = TCP_PACKET_ONION_REQUEST;
524
+ memcpy(packet + 1, data, length);
525
+ return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0);
526
+ }
527
+
528
+ void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
529
+ uint16_t length), void *object)
530
+ {
531
+ con->onion_callback = onion_callback;
532
+ con->onion_callback_object = object;
533
+ }
534
+
535
+ /* Create new TCP connection to ip_port/public_key
536
+ */
537
+ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
538
+ const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
539
+ {
540
+ if (networking_at_startup() != 0) {
541
+ return NULL;
542
+ }
543
+
544
+ if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6)
545
+ return NULL;
546
+
547
+ uint8_t family = ip_port.ip.family;
548
+
549
+ if (proxy_info)
550
+ family = proxy_info->ip_port.ip.family;
551
+
552
+ sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
553
+
554
+ if (!sock_valid(sock)) {
555
+ return NULL;
556
+ }
557
+
558
+ if (!set_socket_nosigpipe(sock)) {
559
+ kill_sock(sock);
560
+ return 0;
561
+ }
562
+
563
+ if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
564
+ kill_sock(sock);
565
+ return NULL;
566
+ }
567
+
568
+ TCP_Client_Connection *temp = calloc(sizeof(TCP_Client_Connection), 1);
569
+
570
+ if (temp == NULL) {
571
+ kill_sock(sock);
572
+ return NULL;
573
+ }
574
+
575
+ temp->sock = sock;
576
+ memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES);
577
+ memcpy(temp->self_public_key, self_public_key, crypto_box_PUBLICKEYBYTES);
578
+ encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
579
+ temp->ip_port = ip_port;
580
+
581
+ if (proxy_info) {
582
+ temp->status = TCP_CLIENT_PROXY_CONNECTING;
583
+ temp->proxy_info = *proxy_info;
584
+ socks5_generate_handshake(temp);
585
+ } else {
586
+ temp->status = TCP_CLIENT_CONNECTING;
587
+
588
+ if (generate_handshake(temp) == -1) {
589
+ kill_sock(sock);
590
+ free(temp);
591
+ return NULL;
592
+ }
593
+ }
594
+
595
+ temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
596
+
597
+ return temp;
598
+ }
599
+
600
+ /* return 0 on success
601
+ * return -1 on failure
602
+ */
603
+ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length)
604
+ {
605
+ if (length <= 1)
606
+ return -1;
607
+
608
+ switch (data[0]) {
609
+ case TCP_PACKET_ROUTING_RESPONSE: {
610
+ if (length != 1 + 1 + crypto_box_PUBLICKEYBYTES)
611
+ return -1;
612
+
613
+ if (data[1] < NUM_RESERVED_PORTS)
614
+ return 0;
615
+
616
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
617
+
618
+ if (conn->connections[con_id].status != 0)
619
+ return 0;
620
+
621
+ conn->connections[con_id].status = 1;
622
+ conn->connections[con_id].number = ~0;
623
+ memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES);
624
+
625
+ if (conn->response_callback)
626
+ conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
627
+
628
+ return 0;
629
+ }
630
+
631
+ case TCP_PACKET_CONNECTION_NOTIFICATION: {
632
+ if (length != 1 + 1)
633
+ return -1;
634
+
635
+ if (data[1] < NUM_RESERVED_PORTS)
636
+ return -1;
637
+
638
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
639
+
640
+ if (conn->connections[con_id].status != 1)
641
+ return 0;
642
+
643
+ conn->connections[con_id].status = 2;
644
+
645
+ if (conn->status_callback)
646
+ conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
647
+ conn->connections[con_id].status);
648
+
649
+ return 0;
650
+ }
651
+
652
+ case TCP_PACKET_DISCONNECT_NOTIFICATION: {
653
+ if (length != 1 + 1)
654
+ return -1;
655
+
656
+ if (data[1] < NUM_RESERVED_PORTS)
657
+ return -1;
658
+
659
+ uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
660
+
661
+ if (conn->connections[con_id].status == 0)
662
+ return 0;
663
+
664
+ if (conn->connections[con_id].status != 2)
665
+ return 0;
666
+
667
+ conn->connections[con_id].status = 1;
668
+
669
+ if (conn->status_callback)
670
+ conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
671
+ conn->connections[con_id].status);
672
+
673
+ return 0;
674
+ }
675
+
676
+ case TCP_PACKET_PING: {
677
+ if (length != 1 + sizeof(uint64_t))
678
+ return -1;
679
+
680
+ uint64_t ping_id;
681
+ memcpy(&ping_id, data + 1, sizeof(uint64_t));
682
+ conn->ping_response_id = ping_id;
683
+ send_ping_response(conn);
684
+ return 0;
685
+ }
686
+
687
+ case TCP_PACKET_PONG: {
688
+ if (length != 1 + sizeof(uint64_t))
689
+ return -1;
690
+
691
+ uint64_t ping_id;
692
+ memcpy(&ping_id, data + 1, sizeof(uint64_t));
693
+
694
+ if (ping_id) {
695
+ if (ping_id == conn->ping_id) {
696
+ conn->ping_id = 0;
697
+ }
698
+
699
+ return 0;
700
+ } else {
701
+ return -1;
702
+ }
703
+ }
704
+
705
+ case TCP_PACKET_OOB_RECV: {
706
+ if (length <= 1 + crypto_box_PUBLICKEYBYTES)
707
+ return -1;
708
+
709
+ if (conn->oob_data_callback)
710
+ conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES,
711
+ length - (1 + crypto_box_PUBLICKEYBYTES));
712
+
713
+ return 0;
714
+ }
715
+
716
+ case TCP_PACKET_ONION_RESPONSE: {
717
+ conn->onion_callback(conn->onion_callback_object, data + 1, length - 1);
718
+ return 0;
719
+ }
720
+
721
+ default: {
722
+ if (data[0] < NUM_RESERVED_PORTS)
723
+ return -1;
724
+
725
+ uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
726
+
727
+ if (conn->data_callback)
728
+ conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1);
729
+ }
730
+ }
731
+
732
+ return 0;
733
+ }
734
+
735
+ static int do_confirmed_TCP(TCP_Client_Connection *conn)
736
+ {
737
+ send_pending_data(conn);
738
+ send_ping_response(conn);
739
+ send_ping_request(conn);
740
+
741
+ uint8_t packet[MAX_PACKET_SIZE];
742
+ int len;
743
+
744
+ if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
745
+ uint64_t ping_id = random_64b();
746
+
747
+ if (!ping_id)
748
+ ++ping_id;
749
+
750
+ conn->ping_request_id = conn->ping_id = ping_id;
751
+ send_ping_request(conn);
752
+ conn->last_pinged = unix_time();
753
+ }
754
+
755
+ if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
756
+ conn->status = TCP_CLIENT_DISCONNECTED;
757
+ return 0;
758
+ }
759
+
760
+ while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
761
+ conn->recv_nonce, packet, sizeof(packet)))) {
762
+ if (len == -1) {
763
+ conn->status = TCP_CLIENT_DISCONNECTED;
764
+ break;
765
+ }
766
+
767
+ if (handle_TCP_packet(conn, packet, len) == -1) {
768
+ conn->status = TCP_CLIENT_DISCONNECTED;
769
+ break;
770
+ }
771
+ }
772
+
773
+ return 0;
774
+ }
775
+
776
+ /* Run the TCP connection
777
+ */
778
+ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
779
+ {
780
+ unix_time_update();
781
+
782
+ if (TCP_connection->status == TCP_CLIENT_DISCONNECTED) {
783
+ return;
784
+ }
785
+
786
+ if (TCP_connection->status == TCP_CLIENT_PROXY_CONNECTING) {
787
+ if (send_pending_data(TCP_connection) == 0) {
788
+ int ret = socks5_read_handshake_response(TCP_connection);
789
+
790
+ if (ret == -1) {
791
+ TCP_connection->kill_at = 0;
792
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
793
+ }
794
+
795
+ if (ret == 1) {
796
+ socks5_generate_connection_request(TCP_connection);
797
+ TCP_connection->status = TCP_CLIENT_PROXY_UNCONFIRMED;
798
+ }
799
+ }
800
+ }
801
+
802
+ if (TCP_connection->status == TCP_CLIENT_PROXY_UNCONFIRMED) {
803
+ if (send_pending_data(TCP_connection) == 0) {
804
+ int ret = socks5_read_connection_response(TCP_connection);
805
+
806
+ if (ret == -1) {
807
+ TCP_connection->kill_at = 0;
808
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
809
+ }
810
+
811
+ if (ret == 1) {
812
+ generate_handshake(TCP_connection);
813
+ TCP_connection->status = TCP_CLIENT_CONNECTING;
814
+ }
815
+ }
816
+ }
817
+
818
+ if (TCP_connection->status == TCP_CLIENT_CONNECTING) {
819
+ if (send_pending_data(TCP_connection) == 0) {
820
+ TCP_connection->status = TCP_CLIENT_UNCONFIRMED;
821
+ }
822
+ }
823
+
824
+ if (TCP_connection->status == TCP_CLIENT_UNCONFIRMED) {
825
+ uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
826
+ int len = read_TCP_packet(TCP_connection->sock, data, sizeof(data));
827
+
828
+ if (sizeof(data) == len) {
829
+ if (handle_handshake(TCP_connection, data) == 0) {
830
+ TCP_connection->kill_at = ~0;
831
+ TCP_connection->status = TCP_CLIENT_CONFIRMED;
832
+ } else {
833
+ TCP_connection->kill_at = 0;
834
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
835
+ }
836
+ }
837
+ }
838
+
839
+ if (TCP_connection->status == TCP_CLIENT_CONFIRMED) {
840
+ do_confirmed_TCP(TCP_connection);
841
+ }
842
+
843
+ if (TCP_connection->kill_at <= unix_time()) {
844
+ TCP_connection->status = TCP_CLIENT_DISCONNECTED;
845
+ }
846
+ }
847
+
848
+ /* Kill the TCP connection
849
+ */
850
+ void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
851
+ {
852
+ if (TCP_connection == NULL)
853
+ return;
854
+
855
+ kill_sock(TCP_connection->sock);
856
+ memset(TCP_connection, 0, sizeof(TCP_Client_Connection));
857
+ free(TCP_connection);
858
+ }