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.
- checksums.yaml +4 -4
- data/ProjectTox-Core/AUTHORS +0 -0
- data/ProjectTox-Core/ChangeLog +0 -0
- data/ProjectTox-Core/INSTALL +370 -0
- data/ProjectTox-Core/INSTALL.md +455 -56
- data/ProjectTox-Core/Makefile.am +35 -0
- data/ProjectTox-Core/NEWS +0 -0
- data/ProjectTox-Core/README +43 -0
- data/ProjectTox-Core/README.md +34 -44
- data/ProjectTox-Core/auto_tests/Makefile.inc +110 -0
- data/ProjectTox-Core/auto_tests/TCP_test.c +519 -0
- data/ProjectTox-Core/auto_tests/assoc_test.c +160 -0
- data/ProjectTox-Core/auto_tests/crypto_test.c +302 -0
- data/ProjectTox-Core/auto_tests/dht_test.c +362 -0
- data/ProjectTox-Core/auto_tests/encryptsave_test.c +104 -0
- data/ProjectTox-Core/auto_tests/friends_test.c +238 -0
- data/ProjectTox-Core/auto_tests/helpers.h +15 -0
- data/ProjectTox-Core/auto_tests/messenger_test.c +365 -0
- data/ProjectTox-Core/auto_tests/network_test.c +171 -0
- data/ProjectTox-Core/auto_tests/onion_test.c +363 -0
- data/ProjectTox-Core/auto_tests/skeleton_test.c +49 -0
- data/ProjectTox-Core/auto_tests/tox_test.c +454 -0
- data/ProjectTox-Core/auto_tests/toxav_basic_test.c +597 -0
- data/ProjectTox-Core/auto_tests/toxav_many_test.c +402 -0
- data/ProjectTox-Core/autogen.sh +6 -0
- data/ProjectTox-Core/build/Makefile.am +14 -0
- data/ProjectTox-Core/configure.ac +694 -0
- data/ProjectTox-Core/dist-build/android-arm.sh +3 -0
- data/ProjectTox-Core/dist-build/android-armv7.sh +3 -0
- data/ProjectTox-Core/dist-build/android-build.sh +59 -0
- data/ProjectTox-Core/dist-build/android-mips.sh +3 -0
- data/ProjectTox-Core/dist-build/android-x86.sh +3 -0
- data/ProjectTox-Core/docs/Group-Chats.md +71 -0
- data/ProjectTox-Core/docs/Hardening.txt +60 -0
- data/ProjectTox-Core/docs/Hardening_docs.txt +30 -0
- data/ProjectTox-Core/docs/Prevent_Tracking.txt +160 -0
- data/ProjectTox-Core/docs/TCP_Network.txt +154 -0
- data/ProjectTox-Core/docs/TODO +62 -0
- data/ProjectTox-Core/docs/Tox_middle_level_network_protocol.txt +120 -0
- data/ProjectTox-Core/docs/av_api.md +194 -0
- data/ProjectTox-Core/libtoxav.pc.in +11 -0
- data/ProjectTox-Core/libtoxcore.pc.in +11 -0
- data/ProjectTox-Core/m4/ax_have_epoll.m4 +104 -0
- data/ProjectTox-Core/m4/ax_pthread.m4 +317 -0
- data/ProjectTox-Core/m4/pkg.m4 +199 -0
- data/ProjectTox-Core/other/DHT_bootstrap.c +121 -58
- data/ProjectTox-Core/other/DHTnodes +3 -0
- data/ProjectTox-Core/other/Makefile.inc +20 -0
- data/ProjectTox-Core/other/bootstrap_node_packets.c +65 -0
- data/ProjectTox-Core/other/tox.png +0 -0
- data/ProjectTox-Core/testing/DHT_test.c +170 -98
- data/ProjectTox-Core/testing/Makefile.inc +112 -0
- data/ProjectTox-Core/testing/Messenger_test.c +133 -69
- data/ProjectTox-Core/testing/dns3_test.c +115 -0
- data/ProjectTox-Core/testing/misc_tools.c +59 -13
- data/ProjectTox-Core/testing/nTox.c +1127 -264
- data/ProjectTox-Core/testing/nTox.h +10 -19
- data/ProjectTox-Core/testing/tox_shell.c +159 -0
- data/ProjectTox-Core/testing/tox_sync.c +299 -0
- data/ProjectTox-Core/tools/README +11 -0
- data/ProjectTox-Core/tools/astylerc +11 -0
- data/ProjectTox-Core/tools/pre-commit +17 -0
- data/ProjectTox-Core/toxav/Makefile.inc +36 -0
- data/ProjectTox-Core/toxav/codec.c +357 -0
- data/ProjectTox-Core/toxav/codec.h +116 -0
- data/ProjectTox-Core/toxav/msi.c +1949 -0
- data/ProjectTox-Core/toxav/msi.h +267 -0
- data/ProjectTox-Core/toxav/rtp.c +600 -0
- data/ProjectTox-Core/toxav/rtp.h +196 -0
- data/ProjectTox-Core/toxav/toxav.c +1148 -0
- data/ProjectTox-Core/toxav/toxav.h +389 -0
- data/ProjectTox-Core/toxcore/DHT.c +2521 -0
- data/ProjectTox-Core/toxcore/DHT.h +412 -0
- data/ProjectTox-Core/toxcore/LAN_discovery.c +322 -0
- data/ProjectTox-Core/{core → toxcore}/LAN_discovery.h +17 -12
- data/ProjectTox-Core/toxcore/Makefile.inc +67 -0
- data/ProjectTox-Core/toxcore/Messenger.c +3006 -0
- data/ProjectTox-Core/toxcore/Messenger.h +818 -0
- data/ProjectTox-Core/toxcore/TCP_client.c +858 -0
- data/ProjectTox-Core/toxcore/TCP_client.h +156 -0
- data/ProjectTox-Core/toxcore/TCP_server.c +1332 -0
- data/ProjectTox-Core/toxcore/TCP_server.h +181 -0
- data/ProjectTox-Core/toxcore/assoc.c +1033 -0
- data/ProjectTox-Core/toxcore/assoc.h +104 -0
- data/ProjectTox-Core/toxcore/crypto_core.c +278 -0
- data/ProjectTox-Core/toxcore/crypto_core.h +151 -0
- data/ProjectTox-Core/toxcore/friend_requests.c +175 -0
- data/ProjectTox-Core/toxcore/friend_requests.h +83 -0
- data/ProjectTox-Core/toxcore/group_chats.c +837 -0
- data/ProjectTox-Core/toxcore/group_chats.h +199 -0
- data/ProjectTox-Core/toxcore/list.c +256 -0
- data/ProjectTox-Core/toxcore/list.h +85 -0
- data/ProjectTox-Core/toxcore/logger.c +153 -0
- data/ProjectTox-Core/toxcore/logger.h +84 -0
- data/ProjectTox-Core/toxcore/misc_tools.h +70 -0
- data/ProjectTox-Core/toxcore/net_crypto.c +2753 -0
- data/ProjectTox-Core/toxcore/net_crypto.h +410 -0
- data/ProjectTox-Core/toxcore/network.c +979 -0
- data/ProjectTox-Core/toxcore/network.h +367 -0
- data/ProjectTox-Core/toxcore/onion.c +540 -0
- data/ProjectTox-Core/toxcore/onion.h +150 -0
- data/ProjectTox-Core/toxcore/onion_announce.c +433 -0
- data/ProjectTox-Core/toxcore/onion_announce.h +139 -0
- data/ProjectTox-Core/toxcore/onion_client.c +1347 -0
- data/ProjectTox-Core/toxcore/onion_client.h +253 -0
- data/ProjectTox-Core/toxcore/ping.c +346 -0
- data/ProjectTox-Core/toxcore/ping.h +47 -0
- data/ProjectTox-Core/toxcore/ping_array.c +162 -0
- data/ProjectTox-Core/toxcore/ping_array.h +75 -0
- data/ProjectTox-Core/toxcore/tox.c +940 -0
- data/ProjectTox-Core/toxcore/tox.h +734 -0
- data/ProjectTox-Core/toxcore/util.c +193 -0
- data/ProjectTox-Core/toxcore/util.h +63 -0
- data/ProjectTox-Core/toxdns/Makefile.inc +29 -0
- data/ProjectTox-Core/toxdns/toxdns.c +238 -0
- data/ProjectTox-Core/toxdns/toxdns.h +88 -0
- data/ProjectTox-Core/toxencryptsave/Makefile.inc +45 -0
- data/ProjectTox-Core/toxencryptsave/toxencryptsave.c +179 -0
- data/ProjectTox-Core/toxencryptsave/toxencryptsave.h +74 -0
- data/interfaces/libtox.i +2 -6
- data/lib/ffi-tox/libtox.rb +406 -28
- metadata +124 -46
- data/ProjectTox-Core/CMakeLists.txt +0 -50
- data/ProjectTox-Core/cmake/FindLIBCONFIG.cmake +0 -15
- data/ProjectTox-Core/cmake/FindNaCl.cmake +0 -17
- data/ProjectTox-Core/cmake/FindSODIUM.cmake +0 -15
- data/ProjectTox-Core/core/CMakeLists.txt +0 -19
- data/ProjectTox-Core/core/DHT.c +0 -1104
- data/ProjectTox-Core/core/DHT.h +0 -111
- data/ProjectTox-Core/core/LAN_discovery.c +0 -79
- data/ProjectTox-Core/core/Lossless_UDP.c +0 -755
- data/ProjectTox-Core/core/Lossless_UDP.h +0 -106
- data/ProjectTox-Core/core/Messenger.c +0 -596
- data/ProjectTox-Core/core/Messenger.h +0 -165
- data/ProjectTox-Core/core/friend_requests.c +0 -131
- data/ProjectTox-Core/core/friend_requests.h +0 -51
- data/ProjectTox-Core/core/net_crypto.c +0 -575
- data/ProjectTox-Core/core/net_crypto.h +0 -134
- data/ProjectTox-Core/core/network.c +0 -205
- data/ProjectTox-Core/core/network.h +0 -134
- data/ProjectTox-Core/docs/commands.md +0 -25
- data/ProjectTox-Core/docs/start_guide.de.md +0 -40
- data/ProjectTox-Core/docs/start_guide.md +0 -38
- data/ProjectTox-Core/other/CMakeLists.txt +0 -9
- data/ProjectTox-Core/testing/CMakeLists.txt +0 -18
- data/ProjectTox-Core/testing/DHT_cryptosendfiletest.c +0 -228
- data/ProjectTox-Core/testing/DHT_sendfiletest.c +0 -176
- data/ProjectTox-Core/testing/Lossless_UDP_testclient.c +0 -214
- data/ProjectTox-Core/testing/Lossless_UDP_testserver.c +0 -201
- data/ProjectTox-Core/testing/misc_tools.h +0 -29
- data/ProjectTox-Core/testing/nTox_win32.c +0 -387
- data/ProjectTox-Core/testing/nTox_win32.h +0 -40
- data/ProjectTox-Core/testing/rect.py +0 -45
@@ -0,0 +1,412 @@
|
|
1
|
+
/* DHT.h
|
2
|
+
*
|
3
|
+
* An implementation of the DHT as seen in http://wiki.tox.im/index.php/DHT
|
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 DHT_H
|
25
|
+
#define DHT_H
|
26
|
+
|
27
|
+
#include "crypto_core.h"
|
28
|
+
#include "network.h"
|
29
|
+
#include "ping_array.h"
|
30
|
+
|
31
|
+
/* Size of the client_id in bytes. */
|
32
|
+
#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
|
33
|
+
|
34
|
+
/* Maximum number of clients stored per friend. */
|
35
|
+
#define MAX_FRIEND_CLIENTS 8
|
36
|
+
|
37
|
+
/* A list of the clients mathematically closest to ours. */
|
38
|
+
#define LCLIENT_LIST 32
|
39
|
+
|
40
|
+
/* The max number of nodes to send with send nodes. */
|
41
|
+
#define MAX_SENT_NODES 4
|
42
|
+
|
43
|
+
/* Ping timeout in seconds */
|
44
|
+
#define PING_TIMEOUT 3
|
45
|
+
|
46
|
+
/* size of DHT ping arrays. */
|
47
|
+
#define DHT_PING_ARRAY_SIZE 512
|
48
|
+
|
49
|
+
/* Ping interval in seconds for each node in our lists. */
|
50
|
+
#define PING_INTERVAL 60
|
51
|
+
|
52
|
+
/* The number of seconds for a non responsive node to become bad. */
|
53
|
+
#define PINGS_MISSED_NODE_GOES_BAD 1
|
54
|
+
#define PING_ROUNDTRIP 2
|
55
|
+
#define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP))
|
56
|
+
|
57
|
+
/* Redefinitions of variables for safe transfer over wire. */
|
58
|
+
#define TOX_AF_INET 2
|
59
|
+
#define TOX_AF_INET6 10
|
60
|
+
#define TOX_TCP_INET 130
|
61
|
+
#define TOX_TCP_INET6 138
|
62
|
+
|
63
|
+
/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
|
64
|
+
#define DHT_FAKE_FRIEND_NUMBER 4
|
65
|
+
|
66
|
+
/* Functions to transfer ips safely across wire. */
|
67
|
+
void to_net_family(IP *ip);
|
68
|
+
void to_host_family(IP *ip);
|
69
|
+
|
70
|
+
typedef struct {
|
71
|
+
IP_Port ip_port;
|
72
|
+
uint64_t timestamp;
|
73
|
+
} IPPTs;
|
74
|
+
|
75
|
+
typedef struct {
|
76
|
+
/* Node routes request correctly (true (1) or false/didn't check (0)) */
|
77
|
+
uint8_t routes_requests_ok;
|
78
|
+
/* Time which we last checked this.*/
|
79
|
+
uint64_t routes_requests_timestamp;
|
80
|
+
uint8_t routes_requests_pingedid[CLIENT_ID_SIZE];
|
81
|
+
/* Node sends correct send_node (true (1) or false/didn't check (0)) */
|
82
|
+
uint8_t send_nodes_ok;
|
83
|
+
/* Time which we last checked this.*/
|
84
|
+
uint64_t send_nodes_timestamp;
|
85
|
+
uint8_t send_nodes_pingedid[CLIENT_ID_SIZE];
|
86
|
+
/* Node can be used to test other nodes (true (1) or false/didn't check (0)) */
|
87
|
+
uint8_t testing_requests;
|
88
|
+
/* Time which we last checked this.*/
|
89
|
+
uint64_t testing_timestamp;
|
90
|
+
uint8_t testing_pingedid[CLIENT_ID_SIZE];
|
91
|
+
} Hardening;
|
92
|
+
|
93
|
+
typedef struct {
|
94
|
+
IP_Port ip_port;
|
95
|
+
uint64_t timestamp;
|
96
|
+
uint64_t last_pinged;
|
97
|
+
|
98
|
+
Hardening hardening;
|
99
|
+
/* Returned by this node. Either our friend or us. */
|
100
|
+
IP_Port ret_ip_port;
|
101
|
+
uint64_t ret_timestamp;
|
102
|
+
} IPPTsPng;
|
103
|
+
|
104
|
+
typedef struct {
|
105
|
+
uint8_t client_id[CLIENT_ID_SIZE];
|
106
|
+
IPPTsPng assoc4;
|
107
|
+
IPPTsPng assoc6;
|
108
|
+
} Client_data;
|
109
|
+
|
110
|
+
/*----------------------------------------------------------------------------------*/
|
111
|
+
|
112
|
+
typedef struct {
|
113
|
+
/* 1 if currently hole punching, otherwise 0 */
|
114
|
+
uint8_t hole_punching;
|
115
|
+
uint32_t punching_index;
|
116
|
+
uint32_t tries;
|
117
|
+
uint32_t punching_index2;
|
118
|
+
|
119
|
+
uint64_t punching_timestamp;
|
120
|
+
uint64_t recvNATping_timestamp;
|
121
|
+
uint64_t NATping_id;
|
122
|
+
uint64_t NATping_timestamp;
|
123
|
+
} NAT;
|
124
|
+
|
125
|
+
typedef struct {
|
126
|
+
uint8_t client_id[CLIENT_ID_SIZE];
|
127
|
+
Client_data client_list[MAX_FRIEND_CLIENTS];
|
128
|
+
|
129
|
+
/* Time at which the last get_nodes request was sent. */
|
130
|
+
uint64_t lastgetnode;
|
131
|
+
/* number of times get_node packets were sent. */
|
132
|
+
uint32_t bootstrap_times;
|
133
|
+
|
134
|
+
/* Symetric NAT hole punching stuff. */
|
135
|
+
NAT nat;
|
136
|
+
} DHT_Friend;
|
137
|
+
|
138
|
+
typedef struct __attribute__ ((__packed__))
|
139
|
+
{
|
140
|
+
uint8_t client_id[CLIENT_ID_SIZE];
|
141
|
+
IP_Port ip_port;
|
142
|
+
}
|
143
|
+
Node_format;
|
144
|
+
|
145
|
+
/* Pack number of nodes into data of maxlength length.
|
146
|
+
*
|
147
|
+
* return length of packed nodes on success.
|
148
|
+
* return -1 on failure.
|
149
|
+
*/
|
150
|
+
int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number);
|
151
|
+
|
152
|
+
/* Unpack data of length into nodes of size max_num_nodes.
|
153
|
+
* Put the length of the data processed in processed_data_len.
|
154
|
+
* tcp_enabled sets if TCP nodes are expected (true) or not (false).
|
155
|
+
*
|
156
|
+
* return number of unpacked nodes on success.
|
157
|
+
* return -1 on failure.
|
158
|
+
*/
|
159
|
+
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
|
160
|
+
uint16_t length, uint8_t tcp_enabled);
|
161
|
+
|
162
|
+
|
163
|
+
/*----------------------------------------------------------------------------------*/
|
164
|
+
/* struct to store some shared keys so we don't have to regenerate them for each request. */
|
165
|
+
#define MAX_KEYS_PER_SLOT 4
|
166
|
+
#define KEYS_TIMEOUT 600
|
167
|
+
typedef struct {
|
168
|
+
struct {
|
169
|
+
uint8_t client_id[CLIENT_ID_SIZE];
|
170
|
+
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
171
|
+
uint32_t times_requested;
|
172
|
+
uint8_t stored; /* 0 if not, 1 if is */
|
173
|
+
uint64_t time_last_requested;
|
174
|
+
} keys[256 * MAX_KEYS_PER_SLOT];
|
175
|
+
} Shared_Keys;
|
176
|
+
|
177
|
+
/*----------------------------------------------------------------------------------*/
|
178
|
+
|
179
|
+
typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey,
|
180
|
+
const uint8_t *data, uint32_t len);
|
181
|
+
|
182
|
+
typedef struct {
|
183
|
+
cryptopacket_handler_callback function;
|
184
|
+
void *object;
|
185
|
+
} Cryptopacket_Handles;
|
186
|
+
|
187
|
+
typedef struct {
|
188
|
+
Networking_Core *net;
|
189
|
+
|
190
|
+
Client_data close_clientlist[LCLIENT_LIST];
|
191
|
+
uint64_t close_lastgetnodes;
|
192
|
+
uint32_t close_bootstrap_times;
|
193
|
+
|
194
|
+
/* Note: this key should not be/is not used to transmit any sensitive materials */
|
195
|
+
uint8_t secret_symmetric_key[crypto_box_KEYBYTES];
|
196
|
+
/* DHT keypair */
|
197
|
+
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
|
198
|
+
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
|
199
|
+
|
200
|
+
DHT_Friend *friends_list;
|
201
|
+
uint16_t num_friends;
|
202
|
+
|
203
|
+
// Used after loading of file (tox_load), but no longer needed after connect (tox_connect)
|
204
|
+
// Unsure if friends_list and num_friends could just be used instead?
|
205
|
+
int has_loaded_friends_clients; // Whether or not we have loaded on the first do_DHT
|
206
|
+
DHT_Friend *loaded_friends_list;
|
207
|
+
uint32_t loaded_num_friends;
|
208
|
+
Client_data *loaded_clients_list;
|
209
|
+
uint32_t loaded_num_clients;
|
210
|
+
|
211
|
+
Shared_Keys shared_keys_recv;
|
212
|
+
Shared_Keys shared_keys_sent;
|
213
|
+
|
214
|
+
struct PING *ping;
|
215
|
+
Ping_Array dht_ping_array;
|
216
|
+
Ping_Array dht_harden_ping_array;
|
217
|
+
#ifdef ENABLE_ASSOC_DHT
|
218
|
+
struct Assoc *assoc;
|
219
|
+
#endif
|
220
|
+
uint64_t last_run;
|
221
|
+
|
222
|
+
Cryptopacket_Handles cryptopackethandlers[256];
|
223
|
+
} DHT;
|
224
|
+
/*----------------------------------------------------------------------------------*/
|
225
|
+
|
226
|
+
/* Shared key generations are costly, it is therefor smart to store commonly used
|
227
|
+
* ones so that they can re used later without being computed again.
|
228
|
+
*
|
229
|
+
* If shared key is already in shared_keys, copy it to shared_key.
|
230
|
+
* else generate it into shared_key and copy it to shared_keys
|
231
|
+
*/
|
232
|
+
void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *client_id);
|
233
|
+
|
234
|
+
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
235
|
+
* for packets that we receive.
|
236
|
+
*/
|
237
|
+
void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *client_id);
|
238
|
+
|
239
|
+
/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key
|
240
|
+
* for packets that we send.
|
241
|
+
*/
|
242
|
+
void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *client_id);
|
243
|
+
|
244
|
+
void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id);
|
245
|
+
|
246
|
+
/* Add a new friend to the friends list.
|
247
|
+
* client_id must be CLIENT_ID_SIZE bytes long.
|
248
|
+
*
|
249
|
+
* return 0 if success.
|
250
|
+
* return 1 if failure (friends list is full).
|
251
|
+
*/
|
252
|
+
int DHT_addfriend(DHT *dht, const uint8_t *client_id);
|
253
|
+
|
254
|
+
/* Delete a friend from the friends list.
|
255
|
+
* client_id must be CLIENT_ID_SIZE bytes long.
|
256
|
+
*
|
257
|
+
* return 0 if success.
|
258
|
+
* return 1 if failure (client_id not in friends list).
|
259
|
+
*/
|
260
|
+
int DHT_delfriend(DHT *dht, const uint8_t *client_id);
|
261
|
+
|
262
|
+
/* Get ip of friend.
|
263
|
+
* client_id must be CLIENT_ID_SIZE bytes long.
|
264
|
+
* ip must be 4 bytes long.
|
265
|
+
* port must be 2 bytes long.
|
266
|
+
*
|
267
|
+
* !!! Signature changed !!!
|
268
|
+
*
|
269
|
+
* OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
|
270
|
+
*
|
271
|
+
* return ip if success.
|
272
|
+
* return ip of 0 if failure (This means the friend is either offline or we have not found him yet).
|
273
|
+
* return ip of 1 if friend is not in list.
|
274
|
+
*
|
275
|
+
* NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
|
276
|
+
*
|
277
|
+
* return -1, -- if client_id does NOT refer to a friend
|
278
|
+
* return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
|
279
|
+
* return 1, ip if client_id refers to a friend and we found him
|
280
|
+
*/
|
281
|
+
int DHT_getfriendip(const DHT *dht, const uint8_t *client_id, IP_Port *ip_port);
|
282
|
+
|
283
|
+
/* Compares client_id1 and client_id2 with client_id.
|
284
|
+
*
|
285
|
+
* return 0 if both are same distance.
|
286
|
+
* return 1 if client_id1 is closer.
|
287
|
+
* return 2 if client_id2 is closer.
|
288
|
+
*/
|
289
|
+
int id_closest(const uint8_t *id, const uint8_t *id1, const uint8_t *id2);
|
290
|
+
|
291
|
+
/* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know
|
292
|
+
* and put them in nodes_list (must be MAX_SENT_NODES big).
|
293
|
+
*
|
294
|
+
* sa_family = family (IPv4 or IPv6) (0 if we don't care)?
|
295
|
+
* is_LAN = return some LAN ips (true or false)
|
296
|
+
* want_good = do we want tested nodes or not? (TODO)
|
297
|
+
*
|
298
|
+
* return the number of nodes returned.
|
299
|
+
*
|
300
|
+
*/
|
301
|
+
int get_close_nodes(const DHT *dht, const uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family,
|
302
|
+
uint8_t is_LAN, uint8_t want_good);
|
303
|
+
|
304
|
+
|
305
|
+
/* Put up to max_num nodes in nodes from the closelist.
|
306
|
+
*
|
307
|
+
* return the number of nodes.
|
308
|
+
*/
|
309
|
+
uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num);
|
310
|
+
|
311
|
+
/* Put up to max_num random nodes in nodes.
|
312
|
+
*
|
313
|
+
* return the number of nodes.
|
314
|
+
*
|
315
|
+
* NOTE:this is used to pick nodes for paths.
|
316
|
+
*/
|
317
|
+
uint16_t random_nodes_path(const DHT *dht, Node_format *nodes, uint16_t max_num);
|
318
|
+
|
319
|
+
/* Run this function at least a couple times per second (It's the main loop). */
|
320
|
+
void do_DHT(DHT *dht);
|
321
|
+
|
322
|
+
/*
|
323
|
+
* Use these two functions to bootstrap the client.
|
324
|
+
*/
|
325
|
+
/* Sends a "get nodes" request to the given node with ip, port and public_key
|
326
|
+
* to setup connections
|
327
|
+
*/
|
328
|
+
void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
|
329
|
+
/* Resolves address into an IP address. If successful, sends a "get nodes"
|
330
|
+
* request to the given node with ip, port and public_key to setup connections
|
331
|
+
*
|
332
|
+
* address can be a hostname or an IP address (IPv4 or IPv6).
|
333
|
+
* if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses
|
334
|
+
* if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first,
|
335
|
+
* then IPv4 addresses.
|
336
|
+
*
|
337
|
+
* returns 1 if the address could be converted into an IP address
|
338
|
+
* returns 0 otherwise
|
339
|
+
*/
|
340
|
+
int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
|
341
|
+
uint16_t port, const uint8_t *public_key);
|
342
|
+
|
343
|
+
/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.
|
344
|
+
*
|
345
|
+
* returns 0 if successful
|
346
|
+
* returns -1 otherwise
|
347
|
+
*/
|
348
|
+
int DHT_connect_after_load(DHT *dht);
|
349
|
+
|
350
|
+
/* ROUTING FUNCTIONS */
|
351
|
+
|
352
|
+
/* Send the given packet to node with client_id.
|
353
|
+
*
|
354
|
+
* return -1 if failure.
|
355
|
+
*/
|
356
|
+
int route_packet(const DHT *dht, const uint8_t *client_id, const uint8_t *packet, uint32_t length);
|
357
|
+
|
358
|
+
/* Send the following packet to everyone who tells us they are connected to friend_id.
|
359
|
+
*
|
360
|
+
* return number of nodes it sent the packet to.
|
361
|
+
*/
|
362
|
+
int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint32_t length);
|
363
|
+
|
364
|
+
/* Function to handle crypto packets.
|
365
|
+
*/
|
366
|
+
void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object);
|
367
|
+
|
368
|
+
/* NAT PUNCHING FUNCTIONS */
|
369
|
+
|
370
|
+
/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist.
|
371
|
+
* ip_portlist must be at least MAX_FRIEND_CLIENTS big.
|
372
|
+
*
|
373
|
+
* returns number of ips returned.
|
374
|
+
* returns -1 if no such friend.
|
375
|
+
*/
|
376
|
+
int friend_ips(const DHT *dht, IP_Port *ip_portlist, const uint8_t *friend_id);
|
377
|
+
|
378
|
+
/* SAVE/LOAD functions */
|
379
|
+
|
380
|
+
/* Get the size of the DHT (for saving). */
|
381
|
+
uint32_t DHT_size(const DHT *dht);
|
382
|
+
|
383
|
+
/* Save the DHT in data where data is an array of size DHT_size(). */
|
384
|
+
void DHT_save(DHT *dht, uint8_t *data);
|
385
|
+
|
386
|
+
/* Load the DHT from data of size size.
|
387
|
+
*
|
388
|
+
* return -1 if failure.
|
389
|
+
* return 0 if success.
|
390
|
+
*/
|
391
|
+
int DHT_load(DHT *dht, const uint8_t *data, uint32_t length);
|
392
|
+
|
393
|
+
/* Initialize DHT. */
|
394
|
+
DHT *new_DHT(Networking_Core *net);
|
395
|
+
|
396
|
+
void kill_DHT(DHT *dht);
|
397
|
+
|
398
|
+
/* return 0 if we are not connected to the DHT.
|
399
|
+
* return 1 if we are.
|
400
|
+
*/
|
401
|
+
int DHT_isconnected(const DHT *dht);
|
402
|
+
|
403
|
+
/* return 0 if we are not connected or only connected to lan peers with the DHT.
|
404
|
+
* return 1 if we are.
|
405
|
+
*/
|
406
|
+
int DHT_non_lan_connected(const DHT *dht);
|
407
|
+
|
408
|
+
|
409
|
+
int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *client_id);
|
410
|
+
|
411
|
+
#endif
|
412
|
+
|
@@ -0,0 +1,322 @@
|
|
1
|
+
/* LAN_discovery.c
|
2
|
+
*
|
3
|
+
* LAN discovery implementation.
|
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
|
+
#ifdef HAVE_CONFIG_H
|
25
|
+
#include "config.h"
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#include "LAN_discovery.h"
|
29
|
+
#include "util.h"
|
30
|
+
|
31
|
+
#define MAX_INTERFACES 16
|
32
|
+
|
33
|
+
|
34
|
+
static int broadcast_count = -1;
|
35
|
+
static IP_Port broadcast_ip_port[MAX_INTERFACES];
|
36
|
+
|
37
|
+
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
38
|
+
|
39
|
+
#include <iphlpapi.h>
|
40
|
+
|
41
|
+
static void fetch_broadcast_info(uint16_t port)
|
42
|
+
{
|
43
|
+
broadcast_count = 0;
|
44
|
+
|
45
|
+
IP_ADAPTER_INFO *pAdapterInfo = malloc(sizeof(pAdapterInfo));
|
46
|
+
unsigned long ulOutBufLen = sizeof(pAdapterInfo);
|
47
|
+
|
48
|
+
if (pAdapterInfo == NULL) {
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
|
53
|
+
free(pAdapterInfo);
|
54
|
+
pAdapterInfo = malloc(ulOutBufLen);
|
55
|
+
|
56
|
+
if (pAdapterInfo == NULL) {
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
int ret;
|
62
|
+
|
63
|
+
if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
|
64
|
+
IP_ADAPTER_INFO *pAdapter = pAdapterInfo;
|
65
|
+
|
66
|
+
while (pAdapter) {
|
67
|
+
IP gateway = {0}, subnet_mask = {0};
|
68
|
+
|
69
|
+
if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
|
70
|
+
&& addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
|
71
|
+
if (gateway.family == AF_INET && subnet_mask.family == AF_INET) {
|
72
|
+
IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
|
73
|
+
ip_port->ip.family = AF_INET;
|
74
|
+
uint32_t gateway_ip = ntohl(gateway.ip4.uint32), subnet_ip = ntohl(subnet_mask.ip4.uint32);
|
75
|
+
uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1;
|
76
|
+
ip_port->ip.ip4.uint32 = htonl(broadcast_ip);
|
77
|
+
ip_port->port = port;
|
78
|
+
broadcast_count++;
|
79
|
+
|
80
|
+
if (broadcast_count >= MAX_INTERFACES) {
|
81
|
+
return;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
pAdapter = pAdapter->Next;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
#elif defined(__linux__)
|
92
|
+
|
93
|
+
static void fetch_broadcast_info(uint16_t port)
|
94
|
+
{
|
95
|
+
/* Not sure how many platforms this will run on,
|
96
|
+
* so it's wrapped in __linux for now.
|
97
|
+
* Definitely won't work like this on Windows...
|
98
|
+
*/
|
99
|
+
broadcast_count = 0;
|
100
|
+
sock_t sock = 0;
|
101
|
+
|
102
|
+
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
103
|
+
return;
|
104
|
+
|
105
|
+
/* Configure ifconf for the ioctl call. */
|
106
|
+
struct ifreq i_faces[MAX_INTERFACES];
|
107
|
+
memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
|
108
|
+
|
109
|
+
struct ifconf ifconf;
|
110
|
+
ifconf.ifc_buf = (char *)i_faces;
|
111
|
+
ifconf.ifc_len = sizeof(i_faces);
|
112
|
+
|
113
|
+
if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
|
114
|
+
close(sock);
|
115
|
+
return;
|
116
|
+
}
|
117
|
+
|
118
|
+
/* ifconf.ifc_len is set by the ioctl() to the actual length used;
|
119
|
+
* on usage of the complete array the call should be repeated with
|
120
|
+
* a larger array, not done (640kB and 16 interfaces shall be
|
121
|
+
* enough, for everybody!)
|
122
|
+
*/
|
123
|
+
int i, count = ifconf.ifc_len / sizeof(struct ifreq);
|
124
|
+
|
125
|
+
for (i = 0; i < count; i++) {
|
126
|
+
/* there are interfaces with are incapable of broadcast */
|
127
|
+
if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0)
|
128
|
+
continue;
|
129
|
+
|
130
|
+
/* moot check: only AF_INET returned (backwards compat.) */
|
131
|
+
if (i_faces[i].ifr_broadaddr.sa_family != AF_INET)
|
132
|
+
continue;
|
133
|
+
|
134
|
+
struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
|
135
|
+
|
136
|
+
if (broadcast_count >= MAX_INTERFACES) {
|
137
|
+
close(sock);
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
IP_Port *ip_port = &broadcast_ip_port[broadcast_count];
|
142
|
+
ip_port->ip.family = AF_INET;
|
143
|
+
ip_port->ip.ip4.in_addr = sock4->sin_addr;
|
144
|
+
ip_port->port = port;
|
145
|
+
broadcast_count++;
|
146
|
+
}
|
147
|
+
|
148
|
+
close(sock);
|
149
|
+
}
|
150
|
+
|
151
|
+
#else //TODO: Other platforms?
|
152
|
+
|
153
|
+
static void fetch_broadcast_info(uint16_t port)
|
154
|
+
{
|
155
|
+
broadcast_count = 0;
|
156
|
+
}
|
157
|
+
|
158
|
+
#endif
|
159
|
+
/* Send packet to all IPv4 broadcast addresses
|
160
|
+
*
|
161
|
+
* return 1 if sent to at least one broadcast target.
|
162
|
+
* return 0 on failure to find any valid broadcast target.
|
163
|
+
*/
|
164
|
+
static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8_t *data, uint16_t length)
|
165
|
+
{
|
166
|
+
/* fetch only once? on every packet? every X seconds?
|
167
|
+
* old: every packet, new: once */
|
168
|
+
if (broadcast_count < 0)
|
169
|
+
fetch_broadcast_info(port);
|
170
|
+
|
171
|
+
if (!broadcast_count)
|
172
|
+
return 0;
|
173
|
+
|
174
|
+
int i;
|
175
|
+
|
176
|
+
for (i = 0; i < broadcast_count; i++)
|
177
|
+
sendpacket(net, broadcast_ip_port[i], data, length);
|
178
|
+
|
179
|
+
return 1;
|
180
|
+
}
|
181
|
+
|
182
|
+
/* Return the broadcast ip. */
|
183
|
+
static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
|
184
|
+
{
|
185
|
+
IP ip;
|
186
|
+
ip_reset(&ip);
|
187
|
+
|
188
|
+
if (family_socket == AF_INET6) {
|
189
|
+
if (family_broadcast == AF_INET6) {
|
190
|
+
ip.family = AF_INET6;
|
191
|
+
/* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
|
192
|
+
/* FE80::*: MUST be exact, for that we would need to look over all
|
193
|
+
* interfaces and check in which status they are */
|
194
|
+
ip.ip6.uint8[ 0] = 0xFF;
|
195
|
+
ip.ip6.uint8[ 1] = 0x02;
|
196
|
+
ip.ip6.uint8[15] = 0x01;
|
197
|
+
} else if (family_broadcast == AF_INET) {
|
198
|
+
ip.family = AF_INET6;
|
199
|
+
ip.ip6.uint32[0] = 0;
|
200
|
+
ip.ip6.uint32[1] = 0;
|
201
|
+
ip.ip6.uint32[2] = htonl(0xFFFF);
|
202
|
+
ip.ip6.uint32[3] = INADDR_BROADCAST;
|
203
|
+
}
|
204
|
+
} else if (family_socket == AF_INET) {
|
205
|
+
if (family_broadcast == AF_INET) {
|
206
|
+
ip.family = AF_INET;
|
207
|
+
ip.ip4.uint32 = INADDR_BROADCAST;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
return ip;
|
212
|
+
}
|
213
|
+
|
214
|
+
/* return 0 if ip is a LAN ip.
|
215
|
+
* return -1 if it is not.
|
216
|
+
*/
|
217
|
+
int LAN_ip(IP ip)
|
218
|
+
{
|
219
|
+
if (ip.family == AF_INET) {
|
220
|
+
IP4 ip4 = ip.ip4;
|
221
|
+
|
222
|
+
/* Loopback. */
|
223
|
+
if (ip4.uint8[0] == 127)
|
224
|
+
return 0;
|
225
|
+
|
226
|
+
/* 10.0.0.0 to 10.255.255.255 range. */
|
227
|
+
if (ip4.uint8[0] == 10)
|
228
|
+
return 0;
|
229
|
+
|
230
|
+
/* 172.16.0.0 to 172.31.255.255 range. */
|
231
|
+
if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31)
|
232
|
+
return 0;
|
233
|
+
|
234
|
+
/* 192.168.0.0 to 192.168.255.255 range. */
|
235
|
+
if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168)
|
236
|
+
return 0;
|
237
|
+
|
238
|
+
/* 169.254.1.0 to 169.254.254.255 range. */
|
239
|
+
if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
|
240
|
+
&& ip4.uint8[2] != 255)
|
241
|
+
return 0;
|
242
|
+
|
243
|
+
/* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10)
|
244
|
+
* (shared address space to stack another layer of NAT) */
|
245
|
+
if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40))
|
246
|
+
return 0;
|
247
|
+
|
248
|
+
} else if (ip.family == AF_INET6) {
|
249
|
+
|
250
|
+
/* autogenerated for each interface: FE80::* (up to FEBF::*)
|
251
|
+
FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
|
252
|
+
if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) ||
|
253
|
+
((ip.ip6.uint8[0] == 0xFE) && ((ip.ip6.uint8[1] & 0xC0) == 0x80)))
|
254
|
+
return 0;
|
255
|
+
|
256
|
+
/* embedded IPv4-in-IPv6 */
|
257
|
+
if (IPV6_IPV4_IN_V6(ip.ip6)) {
|
258
|
+
IP ip4;
|
259
|
+
ip4.family = AF_INET;
|
260
|
+
ip4.ip4.uint32 = ip.ip6.uint32[3];
|
261
|
+
return LAN_ip(ip4);
|
262
|
+
}
|
263
|
+
|
264
|
+
/* localhost in IPv6 (::1) */
|
265
|
+
if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1))
|
266
|
+
return 0;
|
267
|
+
}
|
268
|
+
|
269
|
+
return -1;
|
270
|
+
}
|
271
|
+
|
272
|
+
static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint32_t length)
|
273
|
+
{
|
274
|
+
DHT *dht = object;
|
275
|
+
|
276
|
+
if (LAN_ip(source.ip) == -1)
|
277
|
+
return 1;
|
278
|
+
|
279
|
+
if (length != crypto_box_PUBLICKEYBYTES + 1)
|
280
|
+
return 1;
|
281
|
+
|
282
|
+
DHT_bootstrap(dht, source, packet + 1);
|
283
|
+
return 0;
|
284
|
+
}
|
285
|
+
|
286
|
+
|
287
|
+
int send_LANdiscovery(uint16_t port, DHT *dht)
|
288
|
+
{
|
289
|
+
uint8_t data[crypto_box_PUBLICKEYBYTES + 1];
|
290
|
+
data[0] = NET_PACKET_LAN_DISCOVERY;
|
291
|
+
id_copy(data + 1, dht->self_public_key);
|
292
|
+
|
293
|
+
send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
|
294
|
+
|
295
|
+
int res = -1;
|
296
|
+
IP_Port ip_port;
|
297
|
+
ip_port.port = port;
|
298
|
+
|
299
|
+
/* IPv6 multicast */
|
300
|
+
if (dht->net->family == AF_INET6) {
|
301
|
+
ip_port.ip = broadcast_ip(AF_INET6, AF_INET6);
|
302
|
+
|
303
|
+
if (ip_isset(&ip_port.ip))
|
304
|
+
if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0)
|
305
|
+
res = 1;
|
306
|
+
}
|
307
|
+
|
308
|
+
/* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */
|
309
|
+
ip_port.ip = broadcast_ip(dht->net->family, AF_INET);
|
310
|
+
|
311
|
+
if (ip_isset(&ip_port.ip))
|
312
|
+
if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES))
|
313
|
+
res = 1;
|
314
|
+
|
315
|
+
return res;
|
316
|
+
}
|
317
|
+
|
318
|
+
|
319
|
+
void LANdiscovery_init(DHT *dht)
|
320
|
+
{
|
321
|
+
networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
|
322
|
+
}
|