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,410 @@
1
+ /* net_crypto.h
2
+ *
3
+ * Functions for the core network crypto.
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+ #ifndef NET_CRYPTO_H
25
+ #define NET_CRYPTO_H
26
+
27
+ #include "DHT.h"
28
+ #include "TCP_client.h"
29
+ #include <pthread.h>
30
+
31
+ #define CRYPTO_CONN_NO_CONNECTION 0
32
+ #define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets
33
+ #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets
34
+ #define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets
35
+ #define CRYPTO_CONN_ESTABLISHED 4
36
+ #define CRYPTO_CONN_TIMED_OUT 5
37
+
38
+ #define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */
39
+
40
+ /* Minimum packet rate per second. */
41
+ #define CRYPTO_PACKET_MIN_RATE 8.0
42
+
43
+ /* Minimum packet queue max length. */
44
+ #define CRYPTO_MIN_QUEUE_LENGTH 16
45
+
46
+ #define MAX_CRYPTO_PACKET_SIZE 1400
47
+
48
+ #define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES)
49
+
50
+ /* Max size of data in packets TODO*/
51
+ #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
52
+
53
+ /* Interval in ms between sending cookie request/handshake packets. */
54
+ #define CRYPTO_SEND_PACKET_INTERVAL 500
55
+ /* The maximum number of times we try to send the cookie request and handshake
56
+ before giving up. */
57
+ #define MAX_NUM_SENDPACKET_TRIES 8
58
+
59
+ /* The timeout of no received UDP packets before the direct UDP connection is considered dead. */
60
+ #define UDP_DIRECT_TIMEOUT (MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL * 2)
61
+
62
+ #define PACKET_ID_PADDING 0
63
+ #define PACKET_ID_REQUEST 1
64
+ #define PACKET_ID_KILL 2
65
+
66
+ #define CRYPTO_RESERVED_PACKETS 16
67
+
68
+ #define MAX_TCP_CONNECTIONS 32
69
+ #define MAX_TCP_RELAYS_PEER 4
70
+
71
+ #define STATUS_TCP_NULL 0
72
+ #define STATUS_TCP_OFFLINE 1
73
+ #define STATUS_TCP_INVISIBLE 2 /* we know the other peer is connected to this relay but he isn't appearing online */
74
+ #define STATUS_TCP_ONLINE 3
75
+
76
+ /* All packets starting with a byte in this range are considered lossy packets. */
77
+ #define PACKET_ID_LOSSY_RANGE_START 192
78
+ #define PACKET_ID_LOSSY_RANGE_SIZE 63
79
+
80
+ #define CRYPTO_MAX_PADDING 8 /* All packets will be padded a number of bytes based on this number. */
81
+
82
+
83
+ #define CONGESTION_QUEUE_ARRAY_SIZE 8
84
+
85
+ typedef struct {
86
+ uint64_t time;
87
+ uint16_t length;
88
+ uint8_t data[MAX_CRYPTO_DATA_SIZE];
89
+ } Packet_Data;
90
+
91
+ typedef struct {
92
+ Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
93
+ uint32_t buffer_start;
94
+ uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
95
+ } Packets_Array;
96
+
97
+ typedef struct {
98
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
99
+ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
100
+ uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
101
+ uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* Our public key for this session. */
102
+ uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */
103
+ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
104
+ uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */
105
+ uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
106
+ * 2 if we are sending handshake packets
107
+ * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
108
+ * 4 if the connection is established.
109
+ * 5 if the connection is timed out.
110
+ */
111
+ uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
112
+ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */
113
+ uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */
114
+ uint64_t dht_public_key_timestamp; /* Timestamp of the last time we confirmed the key was correct. */
115
+
116
+ uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
117
+ uint16_t temp_packet_length;
118
+ uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
119
+ uint32_t temp_packet_num_sent;
120
+
121
+ IP_Port ip_port; /* The ip and port to contact this guy directly.*/
122
+ uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */
123
+
124
+ Packets_Array send_array;
125
+ Packets_Array recv_array;
126
+
127
+ int (*connection_status_callback)(void *object, int id, uint8_t status);
128
+ void *connection_status_callback_object;
129
+ int connection_status_callback_id;
130
+
131
+ int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length);
132
+ void *connection_data_callback_object;
133
+ int connection_data_callback_id;
134
+
135
+ int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length);
136
+ void *connection_lossy_data_callback_object;
137
+ int connection_lossy_data_callback_id;
138
+
139
+ uint64_t last_request_packet_sent;
140
+
141
+ uint32_t packet_counter;
142
+ double packet_recv_rate;
143
+ uint64_t packet_counter_set;
144
+
145
+ double packet_send_rate;
146
+ uint32_t packets_left;
147
+ uint64_t last_packets_left_set;
148
+
149
+ uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
150
+ long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE];
151
+ uint32_t packets_sent;
152
+
153
+ uint8_t killed; /* set to 1 to kill the connection. */
154
+
155
+ uint8_t status_tcp[MAX_TCP_CONNECTIONS]; /* set to one of STATUS_TCP_* */
156
+ uint8_t con_number_tcp[MAX_TCP_CONNECTIONS];
157
+
158
+ Node_format tcp_relays[MAX_TCP_RELAYS_PEER];
159
+ uint16_t num_tcp_relays;
160
+
161
+ uint8_t maximum_speed_reached;
162
+
163
+ pthread_mutex_t mutex;
164
+ } Crypto_Connection;
165
+
166
+ typedef struct {
167
+ IP_Port source;
168
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */
169
+ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer. */
170
+ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
171
+ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
172
+ uint8_t *cookie;
173
+ uint8_t cookie_length;
174
+ } New_Connection;
175
+
176
+ typedef struct {
177
+ DHT *dht;
178
+
179
+ Crypto_Connection *crypto_connections;
180
+ TCP_Client_Connection *tcp_connections_new[MAX_TCP_CONNECTIONS];
181
+ TCP_Client_Connection *tcp_connections[MAX_TCP_CONNECTIONS];
182
+ pthread_mutex_t tcp_mutex;
183
+
184
+ pthread_mutex_t connections_mutex;
185
+ unsigned int connection_use_counter;
186
+
187
+ uint32_t crypto_connections_length; /* Length of connections array. */
188
+
189
+ /* Our public and secret keys. */
190
+ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
191
+ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
192
+
193
+ /* The secret key used for cookies */
194
+ uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
195
+
196
+ int (*new_connection_callback)(void *object, New_Connection *n_c);
197
+ void *new_connection_callback_object;
198
+
199
+ /* The current optimal sleep time */
200
+ uint32_t current_sleep_time;
201
+
202
+ BS_LIST ip_port_list;
203
+
204
+ int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length);
205
+ void *tcp_onion_callback_object;
206
+
207
+ uint8_t proxy_set;
208
+ TCP_Proxy_Info proxy_info;
209
+ } Net_Crypto;
210
+
211
+
212
+ /* Set function to be called when someone requests a new connection to us.
213
+ *
214
+ * The set function should return -1 on failure and 0 on success.
215
+ *
216
+ * n_c is only valid for the duration of the function call.
217
+ */
218
+ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
219
+ void *object);
220
+
221
+ /* Accept a crypto connection.
222
+ *
223
+ * return -1 on failure.
224
+ * return connection id on success.
225
+ */
226
+ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
227
+
228
+ /* Create a crypto connection.
229
+ * If one to that real public key already exists, return it.
230
+ *
231
+ * return -1 on failure.
232
+ * return connection id on success.
233
+ */
234
+ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key);
235
+
236
+ /* Copy friends DHT public key into dht_key.
237
+ *
238
+ * return 0 on failure (no key copied).
239
+ * return timestamp on success (key copied).
240
+ */
241
+ uint64_t get_connection_dht_key(const Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key);
242
+
243
+ /* Set the DHT public key of the crypto connection.
244
+ * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
245
+ * the other peer.
246
+ *
247
+ * return -1 on failure.
248
+ * return 0 on success.
249
+ */
250
+ int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, const uint8_t *dht_public_key,
251
+ uint64_t timestamp);
252
+
253
+ /* Set the direct ip of the crypto connection.
254
+ *
255
+ * return -1 on failure.
256
+ * return 0 on success.
257
+ */
258
+ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port);
259
+
260
+ /* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
261
+ *
262
+ * The set function should return -1 on failure and 0 on success.
263
+ * Note that if this function is set, the connection will clear itself on disconnect.
264
+ * Object and id will be passed to this function untouched.
265
+ * status is 1 if the connection is going online, 0 if it is going offline.
266
+ *
267
+ * return -1 on failure.
268
+ * return 0 on success.
269
+ */
270
+ int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
271
+ int (*connection_status_callback)(void *object, int id, uint8_t status), void *object, int id);
272
+
273
+ /* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.
274
+ *
275
+ * The set function should return -1 on failure and 0 on success.
276
+ * Object and id will be passed to this function untouched.
277
+ *
278
+ * return -1 on failure.
279
+ * return 0 on success.
280
+ */
281
+ int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
282
+ int id, uint8_t *data, uint16_t length), void *object, int id);
283
+
284
+
285
+ /* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
286
+ *
287
+ * The set function should return -1 on failure and 0 on success.
288
+ * Object and id will be passed to this function untouched.
289
+ *
290
+ * return -1 on failure.
291
+ * return 0 on success.
292
+ */
293
+ int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
294
+ int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length), void *object,
295
+ int id);
296
+
297
+ /* returns the number of packet slots left in the sendbuffer.
298
+ * return 0 if failure.
299
+ */
300
+ uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id);
301
+
302
+ /* Sends a lossless cryptopacket.
303
+ *
304
+ * return -1 if data could not be put in packet queue.
305
+ * return positive packet number if data was put into the queue.
306
+ *
307
+ * The first byte of data must be in the CRYPTO_RESERVED_PACKETS to PACKET_ID_LOSSY_RANGE_START range.
308
+ *
309
+ * congestion_control: should congestion control apply to this packet?
310
+ */
311
+ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint32_t length,
312
+ uint8_t congestion_control);
313
+
314
+ /* Check if packet_number was received by the other side.
315
+ *
316
+ * packet_number must be a valid packet number of a packet sent on this connection.
317
+ *
318
+ * return -1 on failure.
319
+ * return 0 on success.
320
+ */
321
+ int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number);
322
+
323
+ /* return -1 on failure.
324
+ * return 0 on success.
325
+ *
326
+ * Sends a lossy cryptopacket. (first byte must in the PACKET_ID_LOSSY_RANGE_*)
327
+ */
328
+ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint32_t length);
329
+
330
+ /* Add a tcp relay, associating it to a crypt_connection_id.
331
+ *
332
+ * return 0 if it was added.
333
+ * return -1 if it wasn't.
334
+ */
335
+ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key);
336
+
337
+ /* Add a tcp relay to the array.
338
+ *
339
+ * return 0 if it was added.
340
+ * return -1 if it wasn't.
341
+ */
342
+ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key);
343
+
344
+ /* Set the function to be called when an onion response packet is received by one of the TCP connections.
345
+ */
346
+ void tcp_onion_response_handler(Net_Crypto *c, int (*tcp_onion_callback)(void *object, const uint8_t *data,
347
+ uint16_t length), void *object);
348
+
349
+ /* Send an onion packet via a random connected TCP relay.
350
+ *
351
+ * return 0 on success.
352
+ * return -1 on failure.
353
+ */
354
+ int send_tcp_onion_request(Net_Crypto *c, const uint8_t *data, uint16_t length);
355
+
356
+ /* Copy a maximum of num TCP relays we are connected to to tcp_relays.
357
+ * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
358
+ *
359
+ * return number of relays copied to tcp_relays on success.
360
+ * return 0 on failure.
361
+ */
362
+ unsigned int copy_connected_tcp_relays(const Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
363
+
364
+ /* Kill a crypto connection.
365
+ *
366
+ * return -1 on failure.
367
+ * return 0 on success.
368
+ */
369
+ int crypto_kill(Net_Crypto *c, int crypt_connection_id);
370
+
371
+
372
+ /* return one of CRYPTO_CONN_* values indicating the state of the connection.
373
+ *
374
+ * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
375
+ */
376
+ unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected);
377
+
378
+
379
+ /* Generate our public and private keys.
380
+ * Only call this function the first time the program starts.
381
+ */
382
+ void new_keys(Net_Crypto *c);
383
+
384
+ /* Save the public and private keys to the keys array.
385
+ * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
386
+ */
387
+ void save_keys(const Net_Crypto *c, uint8_t *keys);
388
+
389
+ /* Load the public and private keys from the keys array.
390
+ * Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES.
391
+ */
392
+ void load_keys(Net_Crypto *c, const uint8_t *keys);
393
+
394
+ /* Create new instance of Net_Crypto.
395
+ * Sets all the global connection variables to their default values.
396
+ */
397
+ Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info);
398
+
399
+ /* return the optimal interval in ms for running do_net_crypto.
400
+ */
401
+ uint32_t crypto_run_interval(const Net_Crypto *c);
402
+
403
+ /* Main loop. */
404
+ void do_net_crypto(Net_Crypto *c);
405
+
406
+ void kill_net_crypto(Net_Crypto *c);
407
+
408
+
409
+
410
+ #endif
@@ -0,0 +1,979 @@
1
+ /* network.c
2
+ *
3
+ * Functions for the core networking.
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+ #if (_WIN32_WINNT >= _WIN32_WINNT_WINXP)
25
+ #define _WIN32_WINNT 0x501
26
+ #endif
27
+
28
+ #ifdef HAVE_CONFIG_H
29
+ #include "config.h"
30
+ #endif
31
+
32
+ #include "logger.h"
33
+
34
+ #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
35
+ #include <errno.h>
36
+ #endif
37
+
38
+ #ifdef __APPLE__
39
+ #include <mach/clock.h>
40
+ #include <mach/mach.h>
41
+ #endif
42
+
43
+ #include "network.h"
44
+ #include "util.h"
45
+
46
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
47
+
48
+ static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize)
49
+ {
50
+ if (family == AF_INET) {
51
+ struct sockaddr_in saddr;
52
+ memset(&saddr, 0, sizeof(saddr));
53
+
54
+ saddr.sin_family = AF_INET;
55
+ saddr.sin_addr = *(struct in_addr *)addr;
56
+
57
+ DWORD len = bufsize;
58
+
59
+ if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len))
60
+ return NULL;
61
+
62
+ return buf;
63
+ } else if (family == AF_INET6) {
64
+ struct sockaddr_in6 saddr;
65
+ memset(&saddr, 0, sizeof(saddr));
66
+
67
+ saddr.sin6_family = AF_INET6;
68
+ saddr.sin6_addr = *(struct in6_addr *)addr;
69
+
70
+ DWORD len = bufsize;
71
+
72
+ if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len))
73
+ return NULL;
74
+
75
+ return buf;
76
+ }
77
+
78
+ return NULL;
79
+ }
80
+
81
+ static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
82
+ {
83
+ if (family == AF_INET) {
84
+ struct sockaddr_in saddr;
85
+ memset(&saddr, 0, sizeof(saddr));
86
+
87
+ INT len = sizeof(saddr);
88
+
89
+ if (WSAStringToAddress((LPTSTR)addrString, AF_INET, NULL, (LPSOCKADDR)&saddr, &len))
90
+ return 0;
91
+
92
+ *(struct in_addr *)addrbuf = saddr.sin_addr;
93
+
94
+ return 1;
95
+ } else if (family == AF_INET6) {
96
+ struct sockaddr_in6 saddr;
97
+ memset(&saddr, 0, sizeof(saddr));
98
+
99
+ INT len = sizeof(saddr);
100
+
101
+ if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, NULL, (LPSOCKADDR)&saddr, &len))
102
+ return 0;
103
+
104
+ *(struct in6_addr *)addrbuf = saddr.sin6_addr;
105
+
106
+ return 1;
107
+ }
108
+
109
+ return 0;
110
+ }
111
+
112
+ #endif
113
+
114
+ /* Check if socket is valid.
115
+ *
116
+ * return 1 if valid
117
+ * return 0 if not valid
118
+ */
119
+ int sock_valid(sock_t sock)
120
+ {
121
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
122
+
123
+ if (sock == INVALID_SOCKET) {
124
+ #else
125
+
126
+ if (sock < 0) {
127
+ #endif
128
+ return 0;
129
+ }
130
+
131
+ return 1;
132
+ }
133
+
134
+ /* Close the socket.
135
+ */
136
+ void kill_sock(sock_t sock)
137
+ {
138
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
139
+ closesocket(sock);
140
+ #else
141
+ close(sock);
142
+ #endif
143
+ }
144
+
145
+ /* Set socket as nonblocking
146
+ *
147
+ * return 1 on success
148
+ * return 0 on failure
149
+ */
150
+ int set_socket_nonblock(sock_t sock)
151
+ {
152
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
153
+ u_long mode = 1;
154
+ return (ioctlsocket(sock, FIONBIO, &mode) == 0);
155
+ #else
156
+ return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0);
157
+ #endif
158
+ }
159
+
160
+ /* Set socket to not emit SIGPIPE
161
+ *
162
+ * return 1 on success
163
+ * return 0 on failure
164
+ */
165
+ int set_socket_nosigpipe(sock_t sock)
166
+ {
167
+ #if defined(__MACH__)
168
+ int set = 1;
169
+ return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0);
170
+ #else
171
+ return 1;
172
+ #endif
173
+ }
174
+
175
+ /* Set socket to dual (IPv4 + IPv6 socket)
176
+ *
177
+ * return 1 on success
178
+ * return 0 on failure
179
+ */
180
+ int set_socket_dualstack(sock_t sock)
181
+ {
182
+ int ipv6only = 0;
183
+ socklen_t optsize = sizeof(ipv6only);
184
+ int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&ipv6only, &optsize);
185
+
186
+ if ((res == 0) && (ipv6only == 0))
187
+ return 1;
188
+
189
+ ipv6only = 0;
190
+ return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&ipv6only, sizeof(ipv6only)) == 0);
191
+ }
192
+
193
+
194
+ /* return current UNIX time in microseconds (us). */
195
+ static uint64_t current_time_actual(void)
196
+ {
197
+ uint64_t time;
198
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
199
+ /* This probably works fine */
200
+ FILETIME ft;
201
+ GetSystemTimeAsFileTime(&ft);
202
+ time = ft.dwHighDateTime;
203
+ time <<= 32;
204
+ time |= ft.dwLowDateTime;
205
+ time -= 116444736000000000ULL;
206
+ return time / 10;
207
+ #else
208
+ struct timeval a;
209
+ gettimeofday(&a, NULL);
210
+ time = 1000000ULL * a.tv_sec + a.tv_usec;
211
+ return time;
212
+ #endif
213
+ }
214
+
215
+
216
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
217
+ static uint64_t last_monotime;
218
+ static uint64_t add_monotime;
219
+ #endif
220
+
221
+ /* return current monotonic time in milliseconds (ms). */
222
+ uint64_t current_time_monotonic(void)
223
+ {
224
+ uint64_t time;
225
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
226
+ time = (uint64_t)GetTickCount() + add_monotime;
227
+
228
+ if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */
229
+ uint32_t add = ~0;
230
+ add_monotime += add;
231
+ time += add;
232
+ }
233
+
234
+ last_monotime = time;
235
+ #else
236
+ struct timespec monotime;
237
+ #if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW)
238
+ clock_gettime(CLOCK_MONOTONIC_RAW, &monotime);
239
+ #elif defined(__APPLE__)
240
+ clock_serv_t muhclock;
241
+ mach_timespec_t machtime;
242
+
243
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
244
+ clock_get_time(muhclock, &machtime);
245
+ mach_port_deallocate(mach_task_self(), muhclock);
246
+
247
+ monotime.tv_sec = machtime.tv_sec;
248
+ monotime.tv_nsec = machtime.tv_nsec;
249
+ #else
250
+ clock_gettime(CLOCK_MONOTONIC, &monotime);
251
+ #endif
252
+ time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL);
253
+ #endif
254
+ return time;
255
+ }
256
+
257
+ /* In case no logging */
258
+ #ifndef LOGGING
259
+ #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__)
260
+ #else
261
+ #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0
262
+ #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0
263
+
264
+ #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) \
265
+ (__ip_port__) .ip; \
266
+ if (__res__ < 0) /* Windows doesn't necessarily know %zu */ \
267
+ LOGGER_INFO("[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x", \
268
+ __buffer__[0], __message__, (__buflen__ < 999 ? (uint16_t)__buflen__ : 999), 'E', \
269
+ ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), errno, strerror(errno), data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \
270
+ else if ((__res__ > 0) && ((size_t)__res__ <= __buflen__)) \
271
+ LOGGER_INFO("[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x", \
272
+ __buffer__[0], __message__, (__res__ < 999 ? (size_t)__res__ : 999), ((size_t)__res__ < __buflen__ ? '<' : '='), \
273
+ ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \
274
+ else /* empty or overwrite */ \
275
+ LOGGER_INFO("[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x", \
276
+ __buffer__[0], __message__, (size_t)__res__, (!__res__ ? '!' : '>'), __buflen__, \
277
+ ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__));
278
+
279
+ #endif /* LOGGING */
280
+
281
+ /* Basic network functions:
282
+ * Function to send packet(data) of length length to ip_port.
283
+ */
284
+ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint32_t length)
285
+ {
286
+ if (net->family == 0) /* Socket not initialized */
287
+ return -1;
288
+
289
+ /* socket AF_INET, but target IP NOT: can't send */
290
+ if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
291
+ return -1;
292
+
293
+ struct sockaddr_storage addr;
294
+ size_t addrsize = 0;
295
+
296
+ if (ip_port.ip.family == AF_INET) {
297
+ if (net->family == AF_INET6) {
298
+ /* must convert to IPV4-in-IPV6 address */
299
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
300
+
301
+ addrsize = sizeof(struct sockaddr_in6);
302
+ addr6->sin6_family = AF_INET6;
303
+ addr6->sin6_port = ip_port.port;
304
+
305
+ /* there should be a macro for this in a standards compliant
306
+ * environment, not found */
307
+ IP6 ip6;
308
+
309
+ ip6.uint32[0] = 0;
310
+ ip6.uint32[1] = 0;
311
+ ip6.uint32[2] = htonl(0xFFFF);
312
+ ip6.uint32[3] = ip_port.ip.ip4.uint32;
313
+ addr6->sin6_addr = ip6.in6_addr;
314
+
315
+ addr6->sin6_flowinfo = 0;
316
+ addr6->sin6_scope_id = 0;
317
+ } else {
318
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
319
+
320
+ addrsize = sizeof(struct sockaddr_in);
321
+ addr4->sin_family = AF_INET;
322
+ addr4->sin_addr = ip_port.ip.ip4.in_addr;
323
+ addr4->sin_port = ip_port.port;
324
+ }
325
+ } else if (ip_port.ip.family == AF_INET6) {
326
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
327
+
328
+ addrsize = sizeof(struct sockaddr_in6);
329
+ addr6->sin6_family = AF_INET6;
330
+ addr6->sin6_port = ip_port.port;
331
+ addr6->sin6_addr = ip_port.ip.ip6.in6_addr;
332
+
333
+ addr6->sin6_flowinfo = 0;
334
+ addr6->sin6_scope_id = 0;
335
+ } else {
336
+ /* unknown address type*/
337
+ return -1;
338
+ }
339
+
340
+ int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
341
+
342
+ loglogdata("O=>", data, length, ip_port, res);
343
+
344
+ return res;
345
+ }
346
+
347
+ /* Function to receive data
348
+ * ip and port of sender is put into ip_port.
349
+ * Packet data is put into data.
350
+ * Packet length is put into length.
351
+ */
352
+ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
353
+ {
354
+ memset(ip_port, 0, sizeof(IP_Port));
355
+ struct sockaddr_storage addr;
356
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
357
+ int addrlen = sizeof(addr);
358
+ #else
359
+ socklen_t addrlen = sizeof(addr);
360
+ #endif
361
+ *length = 0;
362
+ int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
363
+
364
+ if (fail_or_len < 0) {
365
+
366
+ LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK))
367
+ LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); );
368
+
369
+ return -1; /* Nothing received. */
370
+ }
371
+
372
+ *length = (uint32_t)fail_or_len;
373
+
374
+ if (addr.ss_family == AF_INET) {
375
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
376
+
377
+ ip_port->ip.family = addr_in->sin_family;
378
+ ip_port->ip.ip4.in_addr = addr_in->sin_addr;
379
+ ip_port->port = addr_in->sin_port;
380
+ } else if (addr.ss_family == AF_INET6) {
381
+ struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
382
+ ip_port->ip.family = addr_in6->sin6_family;
383
+ ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr;
384
+ ip_port->port = addr_in6->sin6_port;
385
+
386
+ if (IPV6_IPV4_IN_V6(ip_port->ip.ip6)) {
387
+ ip_port->ip.family = AF_INET;
388
+ ip_port->ip.ip4.uint32 = ip_port->ip.ip6.uint32[3];
389
+ }
390
+ } else
391
+ return -1;
392
+
393
+ loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length);
394
+
395
+ return 0;
396
+ }
397
+
398
+ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object)
399
+ {
400
+ net->packethandlers[byte].function = cb;
401
+ net->packethandlers[byte].object = object;
402
+ }
403
+
404
+ void networking_poll(Networking_Core *net)
405
+ {
406
+ if (net->family == 0) /* Socket not initialized */
407
+ return;
408
+
409
+ unix_time_update();
410
+
411
+ IP_Port ip_port;
412
+ uint8_t data[MAX_UDP_PACKET_SIZE];
413
+ uint32_t length;
414
+
415
+ while (receivepacket(net->sock, &ip_port, data, &length) != -1) {
416
+ if (length < 1) continue;
417
+
418
+ if (!(net->packethandlers[data[0]].function)) {
419
+ LOGGER_WARNING("[%02u] -- Packet has no handler", data[0]);
420
+ continue;
421
+ }
422
+
423
+ net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length);
424
+ }
425
+ }
426
+
427
+ #ifndef VANILLA_NACL
428
+ /* Used for sodium_init() */
429
+ #include <sodium.h>
430
+ #endif
431
+
432
+ uint8_t at_startup_ran = 0;
433
+ int networking_at_startup(void)
434
+ {
435
+ if (at_startup_ran != 0)
436
+ return 0;
437
+
438
+ #ifndef VANILLA_NACL
439
+
440
+ #ifdef USE_RANDOMBYTES_STIR
441
+ randombytes_stir();
442
+ #else
443
+ sodium_init();
444
+ #endif /*USE_RANDOMBYTES_STIR*/
445
+
446
+ #endif/*VANILLA_NACL*/
447
+
448
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
449
+ WSADATA wsaData;
450
+
451
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
452
+ return -1;
453
+
454
+ #endif
455
+ srand((uint32_t)current_time_actual());
456
+ at_startup_ran = 1;
457
+ return 0;
458
+ }
459
+
460
+ /* TODO: Put this somewhere
461
+ static void at_shutdown(void)
462
+ {
463
+ #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
464
+ WSACleanup();
465
+ #endif
466
+ }
467
+ */
468
+
469
+ /* Initialize networking.
470
+ * Bind to ip and port.
471
+ * ip must be in network order EX: 127.0.0.1 = (7F000001).
472
+ * port is in host byte order (this means don't worry about it).
473
+ *
474
+ * return Networking_Core object if no problems
475
+ * return NULL if there are problems.
476
+ */
477
+ Networking_Core *new_networking(IP ip, uint16_t port)
478
+ {
479
+ /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
480
+ if (ip.family != AF_INET && ip.family != AF_INET6) {
481
+ #ifdef DEBUG
482
+ fprintf(stderr, "Invalid address family: %u\n", ip.family);
483
+ #endif
484
+ return NULL;
485
+ }
486
+
487
+ if (networking_at_startup() != 0)
488
+ return NULL;
489
+
490
+ Networking_Core *temp = calloc(1, sizeof(Networking_Core));
491
+
492
+ if (temp == NULL)
493
+ return NULL;
494
+
495
+ temp->family = ip.family;
496
+ temp->port = 0;
497
+
498
+ /* Initialize our socket. */
499
+ /* add log message what we're creating */
500
+ temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP);
501
+
502
+ /* Check for socket error. */
503
+ if (!sock_valid(temp->sock)) {
504
+ #ifdef DEBUG
505
+ fprintf(stderr, "Failed to get a socket?! %u, %s\n", errno, strerror(errno));
506
+ #endif
507
+ free(temp);
508
+ return NULL;
509
+ }
510
+
511
+ /* Functions to increase the size of the send and receive UDP buffers.
512
+ */
513
+ int n = 1024 * 1024 * 2;
514
+ setsockopt(temp->sock, SOL_SOCKET, SO_RCVBUF, (char *)&n, sizeof(n));
515
+ setsockopt(temp->sock, SOL_SOCKET, SO_SNDBUF, (char *)&n, sizeof(n));
516
+
517
+ /* Enable broadcast on socket */
518
+ int broadcast = 1;
519
+ setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
520
+
521
+ /* iOS UDP sockets are weird and apparently can SIGPIPE */
522
+ if (!set_socket_nosigpipe(temp->sock)) {
523
+ kill_networking(temp);
524
+ return NULL;
525
+ }
526
+
527
+ /* Set socket nonblocking. */
528
+ if (!set_socket_nonblock(temp->sock)) {
529
+ kill_networking(temp);
530
+ return NULL;
531
+ }
532
+
533
+ /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
534
+ uint16_t *portptr = NULL;
535
+ struct sockaddr_storage addr;
536
+ size_t addrsize;
537
+
538
+ if (temp->family == AF_INET) {
539
+ struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
540
+
541
+ addrsize = sizeof(struct sockaddr_in);
542
+ addr4->sin_family = AF_INET;
543
+ addr4->sin_port = 0;
544
+ addr4->sin_addr = ip.ip4.in_addr;
545
+
546
+ portptr = &addr4->sin_port;
547
+ } else if (temp->family == AF_INET6) {
548
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
549
+
550
+ addrsize = sizeof(struct sockaddr_in6);
551
+ addr6->sin6_family = AF_INET6;
552
+ addr6->sin6_port = 0;
553
+ addr6->sin6_addr = ip.ip6.in6_addr;
554
+
555
+ addr6->sin6_flowinfo = 0;
556
+ addr6->sin6_scope_id = 0;
557
+
558
+ portptr = &addr6->sin6_port;
559
+ } else {
560
+ free(temp);
561
+ return NULL;
562
+ }
563
+
564
+ if (ip.family == AF_INET6) {
565
+ #ifdef LOGGING
566
+ int is_dualstack =
567
+ #endif /* LOGGING */
568
+ set_socket_dualstack(temp->sock);
569
+ LOGGER_DEBUG( "Dual-stack socket: %s",
570
+ is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses" );
571
+ /* multicast local nodes */
572
+ struct ipv6_mreq mreq;
573
+ memset(&mreq, 0, sizeof(mreq));
574
+ mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
575
+ mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
576
+ mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
577
+ mreq.ipv6mr_interface = 0;
578
+ #ifdef LOGGING
579
+ int res =
580
+ #endif /* LOGGING */
581
+ setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
582
+
583
+ LOGGER_DEBUG(res < 0 ? "Failed to activate local multicast membership. (%u, %s)" :
584
+ "Local multicast group FF02::1 joined successfully", errno, strerror(errno) );
585
+ }
586
+
587
+ /* a hanging program or a different user might block the standard port;
588
+ * as long as it isn't a parameter coming from the commandline,
589
+ * try a few ports after it, to see if we can find a "free" one
590
+ *
591
+ * if we go on without binding, the first sendto() automatically binds to
592
+ * a free port chosen by the system (i.e. anything from 1024 to 65535)
593
+ *
594
+ * returning NULL after bind fails has both advantages and disadvantages:
595
+ * advantage:
596
+ * we can rely on getting the port in the range 33445..33450, which
597
+ * enables us to tell joe user to open their firewall to a small range
598
+ *
599
+ * disadvantage:
600
+ * some clients might not test return of tox_new(), blindly assuming that
601
+ * it worked ok (which it did previously without a successful bind)
602
+ */
603
+ uint16_t port_to_try = port;
604
+ *portptr = htons(port_to_try);
605
+ int tries;
606
+
607
+ for (tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++) {
608
+ int res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
609
+
610
+ if (!res) {
611
+ temp->port = *portptr;
612
+
613
+ LOGGER_DEBUG("Bound successfully to %s:%u", ip_ntoa(&ip), ntohs(temp->port));
614
+
615
+ /* errno isn't reset on success, only set on failure, the failed
616
+ * binds with parallel clients yield a -EPERM to the outside if
617
+ * errno isn't cleared here */
618
+ if (tries > 0)
619
+ errno = 0;
620
+
621
+ return temp;
622
+ }
623
+
624
+ port_to_try++;
625
+
626
+ if (port_to_try > TOX_PORTRANGE_TO)
627
+ port_to_try = TOX_PORTRANGE_FROM;
628
+
629
+ *portptr = htons(port_to_try);
630
+ }
631
+
632
+ #ifdef DEBUG
633
+ fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
634
+ strerror(errno), ip_ntoa(&ip), port);
635
+ #endif
636
+ kill_networking(temp);
637
+ return NULL;
638
+ }
639
+
640
+ /* Function to cleanup networking stuff. */
641
+ void kill_networking(Networking_Core *net)
642
+ {
643
+ if (net->family != 0) /* Socket not initialized */
644
+ kill_sock(net->sock);
645
+
646
+ free(net);
647
+ return;
648
+ }
649
+
650
+
651
+ /* ip_equal
652
+ * compares two IPAny structures
653
+ * unset means unequal
654
+ *
655
+ * returns 0 when not equal or when uninitialized
656
+ */
657
+ int ip_equal(const IP *a, const IP *b)
658
+ {
659
+ if (!a || !b)
660
+ return 0;
661
+
662
+ /* same family */
663
+ if (a->family == b->family) {
664
+ if (a->family == AF_INET)
665
+ return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
666
+ else if (a->family == AF_INET6)
667
+ return a->ip6.uint64[0] == b->ip6.uint64[0] && a->ip6.uint64[1] == b->ip6.uint64[1];
668
+ else
669
+ return 0;
670
+ }
671
+
672
+ /* different family: check on the IPv6 one if it is the IPv4 one embedded */
673
+ if ((a->family == AF_INET) && (b->family == AF_INET6)) {
674
+ if (IPV6_IPV4_IN_V6(b->ip6))
675
+ return (a->ip4.in_addr.s_addr == b->ip6.uint32[3]);
676
+ } else if ((a->family == AF_INET6) && (b->family == AF_INET)) {
677
+ if (IPV6_IPV4_IN_V6(a->ip6))
678
+ return (a->ip6.uint32[3] == b->ip4.in_addr.s_addr);
679
+ }
680
+
681
+ return 0;
682
+ }
683
+
684
+ /* ipport_equal
685
+ * compares two IPAny_Port structures
686
+ * unset means unequal
687
+ *
688
+ * returns 0 when not equal or when uninitialized
689
+ */
690
+ int ipport_equal(const IP_Port *a, const IP_Port *b)
691
+ {
692
+ if (!a || !b)
693
+ return 0;
694
+
695
+ if (!a->port || (a->port != b->port))
696
+ return 0;
697
+
698
+ return ip_equal(&a->ip, &b->ip);
699
+ }
700
+
701
+ /* nulls out ip */
702
+ void ip_reset(IP *ip)
703
+ {
704
+ if (!ip)
705
+ return;
706
+
707
+ memset(ip, 0, sizeof(IP));
708
+ }
709
+
710
+ /* nulls out ip, sets family according to flag */
711
+ void ip_init(IP *ip, uint8_t ipv6enabled)
712
+ {
713
+ if (!ip)
714
+ return;
715
+
716
+ memset(ip, 0, sizeof(IP));
717
+ ip->family = ipv6enabled ? AF_INET6 : AF_INET;
718
+ }
719
+
720
+ /* checks if ip is valid */
721
+ int ip_isset(const IP *ip)
722
+ {
723
+ if (!ip)
724
+ return 0;
725
+
726
+ return (ip->family != 0);
727
+ }
728
+
729
+ /* checks if ip is valid */
730
+ int ipport_isset(const IP_Port *ipport)
731
+ {
732
+ if (!ipport)
733
+ return 0;
734
+
735
+ if (!ipport->port)
736
+ return 0;
737
+
738
+ return ip_isset(&ipport->ip);
739
+ }
740
+
741
+ /* copies an ip structure (careful about direction!) */
742
+ void ip_copy(IP *target, const IP *source)
743
+ {
744
+ if (!source || !target)
745
+ return;
746
+
747
+ memcpy(target, source, sizeof(IP));
748
+ }
749
+
750
+ /* copies an ip_port structure (careful about direction!) */
751
+ void ipport_copy(IP_Port *target, const IP_Port *source)
752
+ {
753
+ if (!source || !target)
754
+ return;
755
+
756
+ memcpy(target, source, sizeof(IP_Port));
757
+ };
758
+
759
+ /* packing and unpacking functions */
760
+ void ip_pack(uint8_t *data, const IP *source)
761
+ {
762
+ data[0] = source->family;
763
+ memcpy(data + 1, &source->ip6, SIZE_IP6);
764
+ }
765
+
766
+ void ip_unpack(IP *target, const uint8_t *data)
767
+ {
768
+ target->family = data[0];
769
+ memcpy(&target->ip6, data + 1, SIZE_IP6);
770
+ }
771
+
772
+ void ipport_pack(uint8_t *data, const IP_Port *source)
773
+ {
774
+ ip_pack(data, &source->ip);
775
+ memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
776
+ }
777
+
778
+ void ipport_unpack(IP_Port *target, const uint8_t *data)
779
+ {
780
+ ip_unpack(&target->ip, data);
781
+ memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
782
+ }
783
+
784
+ /* ip_ntoa
785
+ * converts ip into a string
786
+ * uses a static buffer, so mustn't used multiple times in the same output
787
+ */
788
+ /* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
789
+ static char addresstext[96];
790
+ const char *ip_ntoa(const IP *ip)
791
+ {
792
+ if (ip) {
793
+ if (ip->family == AF_INET) {
794
+ /* returns standard quad-dotted notation */
795
+ struct in_addr *addr = (struct in_addr *)&ip->ip4;
796
+
797
+ addresstext[0] = 0;
798
+ inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
799
+ } else if (ip->family == AF_INET6) {
800
+ /* returns hex-groups enclosed into square brackets */
801
+ struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
802
+
803
+ addresstext[0] = '[';
804
+ inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
805
+ size_t len = strlen(addresstext);
806
+ addresstext[len] = ']';
807
+ addresstext[len + 1] = 0;
808
+ } else
809
+ snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
810
+ } else
811
+ snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
812
+
813
+ /* brute force protection against lacking termination */
814
+ addresstext[sizeof(addresstext) - 1] = 0;
815
+ return addresstext;
816
+ }
817
+
818
+ /*
819
+ * addr_parse_ip
820
+ * directly parses the input into an IP structure
821
+ * tries IPv4 first, then IPv6
822
+ *
823
+ * input
824
+ * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
825
+ *
826
+ * output
827
+ * IP: family and the value is set on success
828
+ *
829
+ * returns 1 on success, 0 on failure
830
+ */
831
+ int addr_parse_ip(const char *address, IP *to)
832
+ {
833
+ if (!address || !to)
834
+ return 0;
835
+
836
+ struct in_addr addr4;
837
+
838
+ if (1 == inet_pton(AF_INET, address, &addr4)) {
839
+ to->family = AF_INET;
840
+ to->ip4.in_addr = addr4;
841
+ return 1;
842
+ }
843
+
844
+ struct in6_addr addr6;
845
+
846
+ if (1 == inet_pton(AF_INET6, address, &addr6)) {
847
+ to->family = AF_INET6;
848
+ to->ip6.in6_addr = addr6;
849
+ return 1;
850
+ }
851
+
852
+ return 0;
853
+ }
854
+
855
+ /*
856
+ * addr_resolve():
857
+ * uses getaddrinfo to resolve an address into an IP address
858
+ * uses the first IPv4/IPv6 addresses returned by getaddrinfo
859
+ *
860
+ * input
861
+ * address: a hostname (or something parseable to an IP address)
862
+ * to: to.family MUST be initialized, either set to a specific IP version
863
+ * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
864
+ * IP versions are acceptable
865
+ * extra can be NULL and is only set in special circumstances, see returns
866
+ *
867
+ * returns in *to a valid IPAny (v4/v6),
868
+ * prefers v6 if ip.family was AF_UNSPEC and both available
869
+ * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6
870
+ * returns 0 on failure
871
+ */
872
+ int addr_resolve(const char *address, IP *to, IP *extra)
873
+ {
874
+ if (!address || !to)
875
+ return 0;
876
+
877
+ sa_family_t family = to->family;
878
+
879
+ struct addrinfo *server = NULL;
880
+ struct addrinfo *walker = NULL;
881
+ struct addrinfo hints;
882
+ int rc;
883
+
884
+ memset(&hints, 0, sizeof(hints));
885
+ hints.ai_family = family;
886
+ hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
887
+
888
+ if (networking_at_startup() != 0)
889
+ return 0;
890
+
891
+ rc = getaddrinfo(address, NULL, &hints, &server);
892
+
893
+ // Lookup failed.
894
+ if (rc != 0) {
895
+ return 0;
896
+ }
897
+
898
+ IP4 ip4;
899
+ memset(&ip4, 0, sizeof(ip4));
900
+ IP6 ip6;
901
+ memset(&ip6, 0, sizeof(ip6));
902
+
903
+ for (walker = server; (walker != NULL) && (rc != 3); walker = walker->ai_next) {
904
+ switch (walker->ai_family) {
905
+ case AF_INET:
906
+ if (walker->ai_family == family) { /* AF_INET requested, done */
907
+ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
908
+ to->ip4.in_addr = addr->sin_addr;
909
+ rc = 3;
910
+ } else if (!(rc & 1)) { /* AF_UNSPEC requested, store away */
911
+ struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
912
+ ip4.in_addr = addr->sin_addr;
913
+ rc |= 1;
914
+ }
915
+
916
+ break; /* switch */
917
+
918
+ case AF_INET6:
919
+ if (walker->ai_family == family) { /* AF_INET6 requested, done */
920
+ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
921
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
922
+ to->ip6.in6_addr = addr->sin6_addr;
923
+ rc = 3;
924
+ }
925
+ } else if (!(rc & 2)) { /* AF_UNSPEC requested, store away */
926
+ if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
927
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
928
+ ip6.in6_addr = addr->sin6_addr;
929
+ rc |= 2;
930
+ }
931
+ }
932
+
933
+ break; /* switch */
934
+ }
935
+ }
936
+
937
+ if (to->family == AF_UNSPEC) {
938
+ if (rc & 2) {
939
+ to->family = AF_INET6;
940
+ to->ip6 = ip6;
941
+
942
+ if ((rc & 1) && (extra != NULL)) {
943
+ extra->family = AF_INET;
944
+ extra->ip4 = ip4;
945
+ }
946
+ } else if (rc & 1) {
947
+ to->family = AF_INET;
948
+ to->ip4 = ip4;
949
+ } else
950
+ rc = 0;
951
+ }
952
+
953
+ freeaddrinfo(server);
954
+ return rc;
955
+ }
956
+
957
+ /*
958
+ * addr_resolve_or_parse_ip
959
+ * resolves string into an IP address
960
+ *
961
+ * address: a hostname (or something parseable to an IP address)
962
+ * to: to.family MUST be initialized, either set to a specific IP version
963
+ * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
964
+ * IP versions are acceptable
965
+ * extra can be NULL and is only set in special circumstances, see returns
966
+ *
967
+ * returns in *tro a matching address (IPv6 or IPv4)
968
+ * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
969
+ * returns 1 on success
970
+ * returns 0 on failure
971
+ */
972
+ int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
973
+ {
974
+ if (!addr_resolve(address, to, extra))
975
+ if (!addr_parse_ip(address, to))
976
+ return 0;
977
+
978
+ return 1;
979
+ }