summaryrefslogtreecommitdiff
path: root/core/DHT.c
diff options
context:
space:
mode:
authorJeffail <ash.jeffs@gmail.com>2013-08-01 20:45:21 +0100
committerJeffail <ash.jeffs@gmail.com>2013-08-01 20:45:21 +0100
commitab8f549c65922e0c46554c1d79cb75de52200ea0 (patch)
treea3641dc140692068d28f1238dd577b9172b6e639 /core/DHT.c
parentf6c510b3ccd3b5850b714831c61d96baa58da4b5 (diff)
Refactored most of DHT.c, added local vim config
Diffstat (limited to 'core/DHT.c')
-rw-r--r--core/DHT.c952
1 files changed, 585 insertions, 367 deletions
diff --git a/core/DHT.c b/core/DHT.c
index 5039f710..8dbbe562 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -21,93 +21,131 @@
21 * 21 *
22 */ 22 */
23 23
24#include "DHT.h" 24/*----------------------------------------------------------------------------------*/
25 25
26typedef struct { 26#include "DHT.h"
27 uint8_t client_id[CLIENT_ID_SIZE];
28 IP_Port ip_port;
29 uint32_t timestamp;
30 uint32_t last_pinged;
31 IP_Port ret_ip_port;/* The ip_port returned by this node for the friend
32 (for nodes in friends_list) or us (for nodes in close_clientlist) */
33 uint32_t ret_timestamp;
34} Client_data;
35 27
36/* maximum number of clients stored per friend. */ 28/* maximum number of clients stored per friend. */
37#define MAX_FRIEND_CLIENTS 8 29#define MAX_FRIEND_CLIENTS 8
38 30
39typedef struct { 31/* A list of the clients mathematically closest to ours. */
40 uint8_t client_id[CLIENT_ID_SIZE]; 32#define LCLIENT_LIST 32
41 Client_data client_list[MAX_FRIEND_CLIENTS]; 33
42 uint32_t lastgetnode; /* time at which the last get_nodes request was sent. */ 34/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
43 35#define LPING_ARRAY 256
44 /*Symetric NAT hole punching stuff*/ 36
45 uint8_t hole_punching; /*0 if not hole punching, 1 if currently hole punching */ 37#define LSEND_NODES_ARRAY LPING_ARRAY/2
46 uint32_t punching_index; 38
47 uint32_t punching_timestamp; 39/* the number of seconds for a non responsive node to become bad. */
48 uint32_t recvNATping_timestamp; 40#define BAD_NODE_TIMEOUT 70
49 uint64_t NATping_id; 41
50 uint32_t NATping_timestamp; 42/* the max number of nodes to send with send nodes. */
51} Friend; 43#define MAX_SENT_NODES 8
44
45/* ping timeout in seconds */
46#define PING_TIMEOUT 5
47
48/* The timeout after which a node is discarded completely. */
49#define Kill_NODE_TIMEOUT 300
50
51/* ping interval in seconds for each node in our lists. */
52#define PING_INTERVAL 60
53
54/* ping interval in seconds for each random sending of a get nodes request. */
55#define GET_NODE_INTERVAL 10
56
57#define MAX_PUNCHING_PORTS 32
58
59/*Interval in seconds between punching attempts*/
60#define PUNCH_INTERVAL 10
61
62/*----------------------------------------------------------------------------------*/
52 63
53typedef struct { 64typedef struct {
54 uint8_t client_id[CLIENT_ID_SIZE]; 65 IP_Port ip_port;
55 IP_Port ip_port; 66 uint8_t client_id[CLIENT_ID_SIZE];
56} Node_format; 67 uint32_t timestamp;
68 uint32_t last_pinged;
69 uint32_t ret_timestamp;
70
71 /* Returned by this node. Either our friend or us */
72 IP_Port ret_ip_port;
73} Client_data;
57 74
58typedef struct { 75typedef struct {
59 IP_Port ip_port; 76 uint8_t client_id[CLIENT_ID_SIZE];
60 uint64_t ping_id; 77 Client_data client_list[MAX_FRIEND_CLIENTS];
61 uint32_t timestamp;
62 78
63} Pinged; 79 /* time at which the last get_nodes request was sent. */
80 uint32_t lastgetnode;
64 81
65/* Our client id/public key */ 82 /* Symetric NAT hole punching stuff */
66uint8_t self_public_key[CLIENT_ID_SIZE];
67uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
68 83
69/* TODO: Move these out of here and put them into the .c file. 84 /* 1 if currently hole punching, otherwise 0 */
70 A list of the clients mathematically closest to ours. */ 85 uint8_t hole_punching;
71#define LCLIENT_LIST 32 86 uint32_t punching_index;
72static Client_data close_clientlist[LCLIENT_LIST]; 87 uint32_t punching_timestamp;
88 uint32_t recvNATping_timestamp;
89 uint64_t NATping_id;
90 uint32_t NATping_timestamp;
91} Friend;
73 92
74static Friend * friends_list; 93typedef struct {
75static uint16_t num_friends; 94 uint8_t client_id[CLIENT_ID_SIZE];
95 IP_Port ip_port;
96} Node_format;
76 97
77/* The list of ip ports along with the ping_id of what we sent them and a timestamp */ 98typedef struct {
78#define LPING_ARRAY 256 99 IP_Port ip_port;
100 uint64_t ping_id;
101 uint32_t timestamp;
102} Pinged;
79 103
80static Pinged pings[LPING_ARRAY]; 104/*----------------------------------------------------------------------------------*/
81 105
82#define LSEND_NODES_ARRAY LPING_ARRAY/2 106 /* Our client id/public key */
107uint8_t self_public_key[CLIENT_ID_SIZE];
108uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
109static Client_data close_clientlist[LCLIENT_LIST];
110static Friend * friends_list;
111static uint16_t num_friends;
112static Pinged pings[LPING_ARRAY];
113static Pinged send_nodes[LSEND_NODES_ARRAY];
83 114
84static Pinged send_nodes[LSEND_NODES_ARRAY]; 115/*----------------------------------------------------------------------------------*/
85 116
86/* Compares client_id1 and client_id2 with client_id 117/* Compares client_id1 and client_id2 with client_id
87 return 0 if both are same distance 118 * return 0 if both are same distance
88 return 1 if client_id1 is closer 119 * return 1 if client_id1 is closer
89 return 2 if client_id2 is closer */ 120 * return 2 if client_id2 is closer
90int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2) /* tested */ 121 */
122int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2)
91{ 123{
92 uint32_t i; 124 uint32_t i;
125 uint8_t tmp1, tmp2;
126
93 for(i = 0; i < CLIENT_ID_SIZE; ++i) { 127 for(i = 0; i < CLIENT_ID_SIZE; ++i) {
94 if(abs(client_id[i] ^ client_id1[i]) < abs(client_id[i] ^ client_id2[i])) 128 tmp1 = abs(client_id[i] ^ client_id1[i]);
129 tmp2 = abs(client_id[i] ^ client_id2[i]);
130
131 if(tmp1 < tmp2)
95 return 1; 132 return 1;
96 else if(abs(client_id[i] ^ client_id1[i]) > abs(client_id[i] ^ client_id2[i])) 133 else if(tmp1 > tmp2)
97 return 2; 134 return 2;
98 } 135 }
99 return 0; 136 return 0;
100} 137}
101 138
102/* check if client with client_id is already in list of length length. 139/* check if client with client_id is already in list of length length.
103 if it is set it's corresponding timestamp to current time. 140 * if it is then set its corresponding timestamp to current time.
104 if the id is already in the list with a different ip_port, update it. 141 * if the id is already in the list with a different ip_port, update it.
105 return True(1) or False(0) 142 * return True(1) or False(0)
106 TODO: maybe optimize this. */ 143 *
144 * TODO: maybe optimize this.
145 */
107int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) 146int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port)
108{ 147{
109 uint32_t i; 148 uint32_t i, temp_time = unix_time();
110 uint32_t temp_time = unix_time();
111 149
112 for(i = 0; i < length; ++i) { 150 for(i = 0; i < length; ++i) {
113 /*If ip_port is assigned to a different client_id replace it*/ 151 /*If ip_port is assigned to a different client_id replace it*/
@@ -125,88 +163,130 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_
125 } 163 }
126 } 164 }
127 return 0; 165 return 0;
128
129} 166}
130 167
131/* check if client with client_id is already in node format list of length length. 168/* check if client with client_id is already in node format list of length length.
132 return True(1) or False(0) */ 169 * return True(1) or False(0)
170 */
133int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) 171int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id)
134{ 172{
135 uint32_t i; 173 uint32_t i;
136 for(i = 0; i < length; ++i) 174 for(i = 0; i < length; ++i) {
137 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) 175 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0)
138 return 1; 176 return 1;
177 }
139 return 0; 178 return 0;
140} 179}
141 180
142/*Return the friend number from the client_id 181/* Returns the friend number from the client_id, or -1 if a failure occurs
143 Return -1 if failure, number of friend if success*/ 182 */
144static int friend_number(uint8_t * client_id) 183static int friend_number(uint8_t * client_id)
145{ 184{
146 uint32_t i; 185 uint32_t i;
147 for(i = 0; i < num_friends; ++i) 186 for(i = 0; i < num_friends; ++i) {
148 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ 187 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0)
149 return i; 188 return i;
189 }
150 return -1; 190 return -1;
151} 191}
152 192
153/* the number of seconds for a non responsive node to become bad. */
154#define BAD_NODE_TIMEOUT 70
155/* the max number of nodes to send with send nodes. */
156#define MAX_SENT_NODES 8
157
158/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 193/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
159 put them in the nodes_list and return how many were found. 194 * put them in the nodes_list and return how many were found.
160 TODO: Make this function much more efficient. */ 195 *
196 * TODO: For the love of based Allah make this function cleaner and much more efficient.
197 */
161int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) 198int get_close_nodes(uint8_t * client_id, Node_format * nodes_list)
162{ 199{
163 uint32_t i, j, k; 200 uint32_t i, j, k, temp_time = unix_time();
164 int num_nodes=0; 201 int num_nodes = 0, closest, tout, inlist;
165 uint32_t temp_time = unix_time(); 202
166 for(i = 0; i < LCLIENT_LIST; ++i) 203 for (i = 0; i < LCLIENT_LIST; ++i) {
167 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time && 204 tout = close_clientlist[i].timestamp <= temp_time - BAD_NODE_TIMEOUT;
168 !client_in_nodelist(nodes_list, MAX_SENT_NODES,close_clientlist[i].client_id)) { 205 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id);
169 /* if node is good and not already in list. */ 206
207 /* if node isn't good or is already in list. */
208 if(tout || inlist)
209 continue;
210
211 if(num_nodes < MAX_SENT_NODES) {
212
213 memcpy( nodes_list[num_nodes].client_id,
214 close_clientlist[i].client_id,
215 CLIENT_ID_SIZE );
216
217 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port;
218 num_nodes++;
219 } else {
220 for(j = 0; j < MAX_SENT_NODES; ++j) {
221 closest = id_closest( client_id,
222 nodes_list[j].client_id,
223 close_clientlist[i].client_id );
224 if(closest == 2) {
225 memcpy( nodes_list[j].client_id,
226 close_clientlist[i].client_id,
227 CLIENT_ID_SIZE);
228
229 nodes_list[j].ip_port = close_clientlist[i].ip_port;
230 break;
231 }
232 }
233 }
234 }
235
236 for(i = 0; i < num_friends; ++i) {
237 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
238 tout = friends_list[i].client_list[j].timestamp <= temp_time - BAD_NODE_TIMEOUT;
239 inlist = client_in_nodelist( nodes_list,
240 MAX_SENT_NODES,
241 friends_list[i].client_list[j].client_id);
242
243 /* if node isn't good or is already in list. */
244 if(tout || inlist)
245 continue;
246
170 if(num_nodes < MAX_SENT_NODES) { 247 if(num_nodes < MAX_SENT_NODES) {
171 memcpy(nodes_list[num_nodes].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 248
172 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; 249 memcpy( nodes_list[num_nodes].client_id,
250 friends_list[i].client_list[j].client_id,
251 CLIENT_ID_SIZE);
252
253 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
173 num_nodes++; 254 num_nodes++;
174 } else for(j = 0; j < MAX_SENT_NODES; ++j) 255 } else {
175 if(id_closest(client_id, nodes_list[j].client_id, close_clientlist[i].client_id) == 2) { 256 for(k = 0; k < MAX_SENT_NODES; ++k) {
176 memcpy(nodes_list[j].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 257
177 nodes_list[j].ip_port = close_clientlist[i].ip_port; 258 closest = id_closest( client_id,
259 nodes_list[k].client_id,
260 friends_list[i].client_list[j].client_id );
261 if(closest == 2) {
262 memcpy( nodes_list[k].client_id,
263 friends_list[i].client_list[j].client_id,
264 CLIENT_ID_SIZE );
265
266 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
178 break; 267 break;
179 } 268 }
180 } 269 }
181
182 for(i = 0; i < num_friends; ++i)
183 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j)
184 if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time &&
185 !client_in_nodelist(nodes_list, MAX_SENT_NODES,friends_list[i].client_list[j].client_id)) {
186 /* if node is good and not already in list. */
187 if(num_nodes < MAX_SENT_NODES) {
188 memcpy(nodes_list[num_nodes].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE);
189 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
190 num_nodes++;
191 } else for(k = 0; k < MAX_SENT_NODES; ++k)
192 if(id_closest(client_id, nodes_list[k].client_id, friends_list[i].client_list[j].client_id) == 2) {
193 memcpy(nodes_list[k].client_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE);
194 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
195 break;
196 }
197 } 270 }
271 }
272 }
198 return num_nodes; 273 return num_nodes;
199} 274}
200 275
201/* replace first bad (or empty) node with this one 276/* replace first bad (or empty) node with this one
202 return 0 if successful 277 * return 0 if successful
203 return 1 if not (list contains no bad nodes) */ 278 * return 1 if not (list contains no bad nodes)
204int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) /* tested */ 279 */
280int replace_bad( Client_data * list,
281 uint32_t length,
282 uint8_t * client_id,
283 IP_Port ip_port )
205{ 284{
206 uint32_t i; 285 uint32_t i;
207 uint32_t temp_time = unix_time(); 286 uint32_t temp_time = unix_time();
208 for(i = 0; i < length; ++i) 287 for(i = 0; i < length; ++i) {
209 if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) { /* if node is bad. */ 288 /* if node is bad */
289 if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) {
210 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 290 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
211 list[i].ip_port = ip_port; 291 list[i].ip_port = ip_port;
212 list[i].timestamp = temp_time; 292 list[i].timestamp = temp_time;
@@ -215,12 +295,17 @@ int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Por
215 list[i].ret_timestamp = 0; 295 list[i].ret_timestamp = 0;
216 return 0; 296 return 0;
217 } 297 }
298 }
218 299
219 return 1; 300 return 1;
220} 301}
221 302
222/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */ 303/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */
223int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port, uint8_t * comp_client_id) 304int replace_good( Client_data * list,
305 uint32_t length,
306 uint8_t * client_id,
307 IP_Port ip_port,
308 uint8_t * comp_client_id )
224{ 309{
225 uint32_t i; 310 uint32_t i;
226 uint32_t temp_time = unix_time(); 311 uint32_t temp_time = unix_time();
@@ -239,75 +324,109 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po
239 return 1; 324 return 1;
240} 325}
241 326
242/* Attempt to add client with ip_port and client_id to the friends client list and close_clientlist */ 327/* Attempt to add client with ip_port and client_id to the friends client list
328 * and close_clientlist
329 */
243void addto_lists(IP_Port ip_port, uint8_t * client_id) 330void addto_lists(IP_Port ip_port, uint8_t * client_id)
244{ 331{
245 uint32_t i; 332 uint32_t i;
246 333
247 /* NOTE: current behavior if there are two clients with the same id is to replace the first ip by the second. */ 334 /* NOTE: current behavior if there are two clients with the same id is
248 if(!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) 335 * to replace the first ip by the second.
249 if(replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) 336 */
337 if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
338 if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
250 /* if we can't replace bad nodes we try replacing good ones */ 339 /* if we can't replace bad nodes we try replacing good ones */
251 replace_good(close_clientlist, LCLIENT_LIST, client_id, ip_port, self_public_key); 340 replace_good( close_clientlist,
341 LCLIENT_LIST,
342 client_id,
343 ip_port,
344 self_public_key );
345 }
346 }
252 347
253 for(i = 0; i < num_friends; ++i) 348 for (i = 0; i < num_friends; ++i) {
254 if(!client_in_list(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 349 if (!client_in_list( friends_list[i].client_list,
255 if(replace_bad(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 350 MAX_FRIEND_CLIENTS,
351 client_id,
352 ip_port )) {
353
354 if (replace_bad( friends_list[i].client_list,
355 MAX_FRIEND_CLIENTS,
356 client_id,
357 ip_port )) {
256 /* if we can't replace bad nodes we try replacing good ones. */ 358 /* if we can't replace bad nodes we try replacing good ones. */
257 replace_good(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port, friends_list[i].client_id); 359 replace_good( friends_list[i].client_list,
360 MAX_FRIEND_CLIENTS,
361 client_id,
362 ip_port,
363 friends_list[i].client_id );
364 }
365 }
366 }
258} 367}
259 368
260/* If client_id is a friend or us, update ret_ip_port 369/* If client_id is a friend or us, update ret_ip_port
261 nodeclient_id is the id of the node that sent us this info */ 370 * nodeclient_id is the id of the node that sent us this info
371 */
262void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) 372void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id)
263{ 373{
264 uint32_t i, j; 374 uint32_t i, j, temp_time = unix_time();
265 uint32_t temp_time = unix_time(); 375
266 if(memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) { 376 if (memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) {
267 for(i = 0; i < LCLIENT_LIST; ++i) 377 for (i = 0; i < LCLIENT_LIST; ++i) {
268 if(memcmp(nodeclient_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) { 378
379 if (memcmp( nodeclient_id,
380 close_clientlist[i].client_id,
381 CLIENT_ID_SIZE ) == 0) {
269 close_clientlist[i].ret_ip_port = ip_port; 382 close_clientlist[i].ret_ip_port = ip_port;
270 close_clientlist[i].ret_timestamp = temp_time; 383 close_clientlist[i].ret_timestamp = temp_time;
271 return; 384 return;
272 } 385 }
273 } else 386 }
274 for(i = 0; i < num_friends; ++i) 387 } else {
275 if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) 388 for (i = 0; i < num_friends; ++i) {
276 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 389 if (memcmp( client_id,
277 if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) { 390 friends_list[i].client_id,
391 CLIENT_ID_SIZE ) == 0) {
392 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
393
394 if (memcmp( nodeclient_id,
395 friends_list[i].client_list[j].client_id,
396 CLIENT_ID_SIZE ) == 0) {
278 friends_list[i].client_list[j].ret_ip_port = ip_port; 397 friends_list[i].client_list[j].ret_ip_port = ip_port;
279 friends_list[i].client_list[j].ret_timestamp = temp_time; 398 friends_list[i].client_list[j].ret_timestamp = temp_time;
280 return; 399 return;
281 } 400 }
401 }
402 }
403 }
404 }
282} 405}
283 406
284/* ping timeout in seconds */ 407/* check if we are currently pinging an ip_port and/or a ping_id variables with
285#define PING_TIMEOUT 5 408 * values of zero will not be checked. If we are already, return 1 else return 0
286 409 *
287/* check if we are currently pinging an ip_port and/or a ping_id 410 * TODO: optimize this
288 variables with values of zero will not be checked. 411 */
289 if we are already, return 1
290 else return 0
291TODO: optimize this */
292int is_pinging(IP_Port ip_port, uint64_t ping_id) 412int is_pinging(IP_Port ip_port, uint64_t ping_id)
293{ 413{
294 uint32_t i; 414 uint32_t i, temp_time = unix_time();
295 uint8_t pinging; 415 uint8_t pinging;
296 uint32_t temp_time = unix_time();
297 416
298 for(i = 0; i < LPING_ARRAY; ++i ) 417 for (i = 0; i < LPING_ARRAY; ++i ) {
299 if((pings[i].timestamp + PING_TIMEOUT) > temp_time) { 418 if ((pings[i].timestamp + PING_TIMEOUT) > temp_time) {
300 pinging = 0; 419 pinging = 0;
301 if(ip_port.ip.i != 0) 420 if (ip_port.ip.i != 0 &&
302 if(pings[i].ip_port.ip.i == ip_port.ip.i && 421 pings[i].ip_port.ip.i == ip_port.ip.i &&
303 pings[i].ip_port.port == ip_port.port) 422 pings[i].ip_port.port == ip_port.port)
304 ++pinging; 423 ++pinging;
305 if(ping_id != 0) 424 if (ping_id != 0 && pings[i].ping_id == ping_id)
306 if(pings[i].ping_id == ping_id) 425 ++pinging;
307 ++pinging; 426 if (pinging == ((ping_id != 0) + (ip_port.ip.i != 0)))
308 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
309 return 1; 427 return 1;
310 } 428 }
429 }
311 430
312 return 0; 431 return 0;
313} 432}
@@ -315,46 +434,47 @@ int is_pinging(IP_Port ip_port, uint64_t ping_id)
315/* Same as last function but for get_node requests. */ 434/* Same as last function but for get_node requests. */
316int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) 435int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
317{ 436{
318 uint32_t i; 437 uint32_t i, temp_time = unix_time();
319 uint8_t pinging; 438 uint8_t pinging;
320 uint32_t temp_time = unix_time();
321 439
322 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) 440 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) {
323 if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) { 441 if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) {
324 pinging = 0; 442 pinging = 0;
325 if(ip_port.ip.i != 0) 443 if(ip_port.ip.i != 0 &&
326 if(send_nodes[i].ip_port.ip.i == ip_port.ip.i && 444 send_nodes[i].ip_port.ip.i == ip_port.ip.i &&
327 send_nodes[i].ip_port.port == ip_port.port) 445 send_nodes[i].ip_port.port == ip_port.port)
328 ++pinging; 446 ++pinging;
329 if(ping_id != 0) 447 if(ping_id != 0 && send_nodes[i].ping_id == ping_id)
330 if(send_nodes[i].ping_id == ping_id)
331 ++pinging; 448 ++pinging;
332 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 449 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
333 return 1; 450 return 1;
334
335 } 451 }
452 }
336 453
337 return 0; 454 return 0;
338} 455}
339 456
340/* Add a new ping request to the list of ping requests 457/* Add a new ping request to the list of ping requests
341 returns the ping_id to put in the ping request 458 * returns the ping_id to put in the ping request
342 returns 0 if problem. 459 * returns 0 if problem.
343 TODO: optimize this */ 460 *
461 * TODO: optimize this
462 */
344uint64_t add_pinging(IP_Port ip_port) 463uint64_t add_pinging(IP_Port ip_port)
345{ 464{
346 uint32_t i, j; 465 uint32_t i, j, temp_time = unix_time();
347 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 466 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
348 uint32_t temp_time = unix_time();
349 467
350 for(i = 0; i < PING_TIMEOUT; ++i ) 468 for(i = 0; i < PING_TIMEOUT; ++i ) {
351 for(j = 0; j < LPING_ARRAY; ++j ) 469 for(j = 0; j < LPING_ARRAY; ++j ) {
352 if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) { 470 if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) {
353 pings[j].timestamp = temp_time; 471 pings[j].timestamp = temp_time;
354 pings[j].ip_port = ip_port; 472 pings[j].ip_port = ip_port;
355 pings[j].ping_id = ping_id; 473 pings[j].ping_id = ping_id;
356 return ping_id; 474 return ping_id;
357 } 475 }
476 }
477 }
358 478
359 return 0; 479 return 0;
360} 480}
@@ -366,26 +486,28 @@ uint64_t add_gettingnodes(IP_Port ip_port)
366 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 486 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
367 uint32_t temp_time = unix_time(); 487 uint32_t temp_time = unix_time();
368 488
369 for(i = 0; i < PING_TIMEOUT; ++i ) 489 for(i = 0; i < PING_TIMEOUT; ++i ) {
370 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) 490 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) {
371 if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) { 491 if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) {
372 send_nodes[j].timestamp = temp_time; 492 send_nodes[j].timestamp = temp_time;
373 send_nodes[j].ip_port = ip_port; 493 send_nodes[j].ip_port = ip_port;
374 send_nodes[j].ping_id = ping_id; 494 send_nodes[j].ping_id = ping_id;
375 return ping_id; 495 return ping_id;
376 } 496 }
497 }
498 }
377 499
378 return 0; 500 return 0;
379} 501}
380 502
381/* send a ping request 503/* send a ping request, only works if none has been sent to that ip/port
382 Ping request only works if none has been sent to that ip/port in the last 5 seconds. */ 504 * in the last 5 seconds.
505 */
383static int pingreq(IP_Port ip_port, uint8_t * public_key) 506static int pingreq(IP_Port ip_port, uint8_t * public_key)
384{ 507{
385 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 508 /* check if packet is gonna be sent to ourself */
386 return 1; 509 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0
387 510 || is_pinging(ip_port, 0))
388 if(is_pinging(ip_port, 0))
389 return 1; 511 return 1;
390 512
391 uint64_t ping_id = add_pinging(ip_port); 513 uint64_t ping_id = add_pinging(ip_port);
@@ -397,9 +519,16 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
397 uint8_t nonce[crypto_box_NONCEBYTES]; 519 uint8_t nonce[crypto_box_NONCEBYTES];
398 random_nonce(nonce); 520 random_nonce(nonce);
399 521
400 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 522 int len = encrypt_data( public_key,
523 self_secret_key,
524 nonce,
525 (uint8_t *)&ping_id,
526 sizeof(ping_id),
527 encrypt );
528
401 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 529 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
402 return -1; 530 return -1;
531
403 data[0] = 0; 532 data[0] = 0;
404 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 533 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
405 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 534 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -420,9 +549,15 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
420 uint8_t nonce[crypto_box_NONCEBYTES]; 549 uint8_t nonce[crypto_box_NONCEBYTES];
421 random_nonce(nonce); 550 random_nonce(nonce);
422 551
423 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 552 int len = encrypt_data( public_key,
553 self_secret_key, nonce,
554 (uint8_t *)&ping_id,
555 sizeof(ping_id),
556 encrypt );
557
424 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 558 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
425 return -1; 559 return -1;
560
426 data[0] = 1; 561 data[0] = 1;
427 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 562 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
428 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 563 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -435,10 +570,8 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
435static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) 570static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
436{ 571{
437 /* check if packet is gonna be sent to ourself */ 572 /* check if packet is gonna be sent to ourself */
438 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) 573 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0
439 return 1; 574 || is_gettingnodes(ip_port, 0))
440
441 if(is_gettingnodes(ip_port, 0))
442 return 1; 575 return 1;
443 576
444 uint64_t ping_id = add_gettingnodes(ip_port); 577 uint64_t ping_id = add_gettingnodes(ip_port);
@@ -455,21 +588,29 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
455 memcpy(plain, &ping_id, sizeof(ping_id)); 588 memcpy(plain, &ping_id, sizeof(ping_id));
456 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); 589 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
457 590
458 int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, encrypt); 591 int len = encrypt_data( public_key,
592 self_secret_key,
593 nonce,
594 plain,
595 sizeof(ping_id) + CLIENT_ID_SIZE,
596 encrypt );
459 597
460 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 598 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING)
461 return -1; 599 return -1;
600
462 data[0] = 2; 601 data[0] = 2;
463 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 602 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
464 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 603 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
465 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 604 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
605
466 return sendpacket(ip_port, data, sizeof(data)); 606 return sendpacket(ip_port, data, sizeof(data));
467} 607}
468 608
469/* send a send nodes response */ 609/* send a send nodes response */
470static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) 610static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id)
471{ 611{
472 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 612 /* check if packet is gonna be sent to ourself */
613 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0)
473 return 1; 614 return 1;
474 615
475 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 616 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
@@ -489,8 +630,12 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
489 memcpy(plain, &ping_id, sizeof(ping_id)); 630 memcpy(plain, &ping_id, sizeof(ping_id));
490 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 631 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
491 632
492 int len = encrypt_data(public_key, self_secret_key, nonce, plain, 633 int len = encrypt_data( public_key,
493 sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt); 634 self_secret_key,
635 nonce,
636 plain,
637 sizeof(ping_id) + num_nodes * sizeof(Node_format),
638 encrypt );
494 639
495 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 640 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING)
496 return -1; 641 return -1;
@@ -503,26 +648,30 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
503 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 648 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
504} 649}
505 650
506/* Packet handling functions 651/* Packet handling functions, one to handle each types of packets we receive
507 One to handle each types of packets we receive 652 * Returns 0 if handled correctly, 1 if packet is bad.
508 return 0 if handled correctly, 1 if packet is bad. */ 653 */
509int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) 654int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)
510{ 655{
511 uint64_t ping_id; 656 uint64_t ping_id;
512 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 657 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
513 return 1; 658 return 1;
659
514 /* check if packet is from ourself. */ 660 /* check if packet is from ourself. */
515 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 661 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0)
516 return 1; 662 return 1;
517 663
518 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 664 int len = decrypt_data( packet + 1,
519 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 665 self_secret_key,
520 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 666 packet + 1 + CLIENT_ID_SIZE,
667 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
668 sizeof(ping_id) + ENCRYPTION_PADDING,
669 (uint8_t *)&ping_id );
670
521 if(len != sizeof(ping_id)) 671 if(len != sizeof(ping_id))
522 return 1; 672 return 1;
523 673
524 pingres(source, packet + 1, ping_id); 674 pingres(source, packet + 1, ping_id);
525
526 pingreq(source, packet + 1); /* TODO: make this smarter? */ 675 pingreq(source, packet + 1); /* TODO: make this smarter? */
527 676
528 return 0; 677 return 0;
@@ -533,12 +682,18 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
533 uint64_t ping_id; 682 uint64_t ping_id;
534 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 683 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
535 return 1; 684 return 1;
536 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ 685
686 /* check if packet is from ourself. */
687 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0)
537 return 1; 688 return 1;
538 689
539 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 690 int len = decrypt_data( packet + 1,
540 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 691 self_secret_key,
541 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 692 packet + 1 + CLIENT_ID_SIZE,
693 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
694 sizeof(ping_id) + ENCRYPTION_PADDING,
695 (uint8_t *)&ping_id );
696
542 if(len != sizeof(ping_id)) 697 if(len != sizeof(ping_id))
543 return 1; 698 return 1;
544 699
@@ -547,25 +702,30 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
547 return 0; 702 return 0;
548 } 703 }
549 return 1; 704 return 1;
550
551} 705}
552 706
553int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) 707int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
554{ 708{
555 uint64_t ping_id; 709 uint64_t ping_id;
556 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 710
711 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
712 + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING ))
557 return 1; 713 return 1;
714
558 /* check if packet is from ourself. */ 715 /* check if packet is from ourself. */
559 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 716 if (memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0)
560 return 1; 717 return 1;
561 718
562 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 719 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
563 720
564 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 721 int len = decrypt_data( packet + 1,
565 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 722 self_secret_key,
566 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain); 723 packet + 1 + CLIENT_ID_SIZE,
724 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
725 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING,
726 plain );
567 727
568 if(len != sizeof(ping_id) + CLIENT_ID_SIZE) 728 if (len != sizeof(ping_id) + CLIENT_ID_SIZE)
569 return 1; 729 return 1;
570 730
571 memcpy(&ping_id, plain, sizeof(ping_id)); 731 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -574,29 +734,28 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
574 pingreq(source, packet + 1); /* TODO: make this smarter? */ 734 pingreq(source, packet + 1); /* TODO: make this smarter? */
575 735
576 return 0; 736 return 0;
577
578} 737}
579 738
580int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) 739int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
581{ 740{
582 uint64_t ping_id; 741 uint64_t ping_id;
583 /* TODO: make this more readable */ 742 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
584 if(length > (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 743 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
585 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING) || 744
586 (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 745 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) ||
587 + ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 || 746 ((length - cid_size) % sizeof(Node_format)) != 0 ||
588 length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 747 (length < cid_size + sizeof(Node_format)))
589 + sizeof(Node_format) + ENCRYPTION_PADDING) {
590 return 1; 748 return 1;
591 }
592 uint32_t num_nodes = (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
593 + sizeof(ping_id) + ENCRYPTION_PADDING)) / sizeof(Node_format);
594 749
750 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format);
595 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 751 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
596 752
597 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 753 int len = decrypt_data(
598 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 754 packet + 1,
599 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain); 755 self_secret_key,
756 packet + 1 + CLIENT_ID_SIZE,
757 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
758 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
600 759
601 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 760 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format))
602 return 1; 761 return 1;
@@ -619,18 +778,20 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
619 return 0; 778 return 0;
620} 779}
621 780
622/* END of packet handling functions */ 781/*----------------------------------------------------------------------------------*/
782/*------------------------END of packet handling functions--------------------------*/
623 783
624int DHT_addfriend(uint8_t * client_id) 784int DHT_addfriend(uint8_t * client_id)
625{ 785{
626 Friend * temp; 786 Friend * temp;
627 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 787 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1));
628 if(temp == NULL) 788 if (temp == NULL)
629 return 1; 789 return 1;
630 790
631 friends_list = temp; 791 friends_list = temp;
632 memset(&friends_list[num_friends], 0, sizeof(Friend)); 792 memset(&friends_list[num_friends], 0, sizeof(Friend));
633 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); 793 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE);
794
634 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 795 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
635 ++num_friends; 796 ++num_friends;
636 return 0; 797 return 0;
@@ -640,17 +801,21 @@ int DHT_delfriend(uint8_t * client_id)
640{ 801{
641 uint32_t i; 802 uint32_t i;
642 Friend * temp; 803 Friend * temp;
643 for(i = 0; i < num_friends; ++i) 804 for (i = 0; i < num_friends; ++i) {
644 /* Equal */ 805 /* Equal */
645 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 806 if (memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) {
646 --num_friends; 807 --num_friends;
647 if(num_friends != i) 808 if (num_friends != i) {
648 memcpy(friends_list[i].client_id, friends_list[num_friends].client_id, CLIENT_ID_SIZE); 809 memcpy( friends_list[i].client_id,
810 friends_list[num_friends].client_id,
811 CLIENT_ID_SIZE );
812 }
649 temp = realloc(friends_list, sizeof(Friend) * (num_friends)); 813 temp = realloc(friends_list, sizeof(Friend) * (num_friends));
650 if(temp != NULL) 814 if (temp != NULL)
651 friends_list = temp; 815 friends_list = temp;
652 return 0; 816 return 0;
653 } 817 }
818 }
654 819
655 return 1; 820 return 1;
656} 821}
@@ -658,35 +823,29 @@ int DHT_delfriend(uint8_t * client_id)
658/* TODO: Optimize this. */ 823/* TODO: Optimize this. */
659IP_Port DHT_getfriendip(uint8_t * client_id) 824IP_Port DHT_getfriendip(uint8_t * client_id)
660{ 825{
661 uint32_t i, j; 826 uint32_t i, j, temp_time = unix_time();
662 IP_Port empty = {{{0}}, 0}; 827 IP_Port empty = {{{0}}, 0};
663 uint32_t temp_time = unix_time(); 828
664 for(i = 0; i < num_friends; ++i) 829 for (i = 0; i < num_friends; ++i) {
665 /* Equal */ 830 /* Equal */
666 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 831 if (memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) {
667 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 832 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
668 if(memcmp(friends_list[i].client_list[j].client_id, client_id, CLIENT_ID_SIZE) == 0 && 833 if (memcmp( friends_list[i].client_list[j].client_id,
834 client_id,
835 CLIENT_ID_SIZE ) == 0 &&
669 friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) 836 friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time)
670 return friends_list[i].client_list[j].ip_port; 837 return friends_list[i].client_list[j].ip_port;
671 838 }
672 return empty; 839 return empty;
673 } 840 }
841 }
674 empty.ip.i = 1; 842 empty.ip.i = 1;
675 return empty; 843 return empty;
676
677} 844}
678 845
679/* The timeout after which a node is discarded completely. */ 846/* Ping each client in the "friends" list every 60 seconds. Send a get nodes request
680#define Kill_NODE_TIMEOUT 300 847 * every 20 seconds to a random good node for each "friend" in our "friends" list.
681 848 */
682/* ping interval in seconds for each node in our lists. */
683#define PING_INTERVAL 60
684
685/* ping interval in seconds for each random sending of a get nodes request. */
686#define GET_NODE_INTERVAL 10
687
688/* Ping each client in the "friends" list every 60 seconds.
689 Send a get nodes request every 20 seconds to a random good node for each "friend" in our "friends" list. */
690void doDHTFriends() 849void doDHTFriends()
691{ 850{
692 uint32_t i, j; 851 uint32_t i, j;
@@ -694,24 +853,28 @@ void doDHTFriends()
694 uint32_t rand_node; 853 uint32_t rand_node;
695 uint32_t index[MAX_FRIEND_CLIENTS]; 854 uint32_t index[MAX_FRIEND_CLIENTS];
696 855
697 for(i = 0; i < num_friends; ++i) { 856 for (i = 0; i < num_friends; ++i) {
698 uint32_t num_nodes = 0; 857 uint32_t num_nodes = 0;
699 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 858 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
700 if(friends_list[i].client_list[j].timestamp + Kill_NODE_TIMEOUT > temp_time) { /* if node is not dead. */ 859 /* if node is not dead. */
701 if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 860 if (friends_list[i].client_list[j].timestamp + Kill_NODE_TIMEOUT > temp_time) {
702 pingreq(friends_list[i].client_list[j].ip_port, friends_list[i].client_list[j].client_id); 861 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
862 pingreq( friends_list[i].client_list[j].ip_port,
863 friends_list[i].client_list[j].client_id );
703 friends_list[i].client_list[j].last_pinged = temp_time; 864 friends_list[i].client_list[j].last_pinged = temp_time;
704 } 865 }
705 if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) { /* if node is good. */ 866 /* if node is good. */
867 if (friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) {
706 index[num_nodes] = j; 868 index[num_nodes] = j;
707 ++num_nodes; 869 ++num_nodes;
708 } 870 }
709 } 871 }
872 }
710 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 873 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
711 rand_node = rand() % num_nodes; 874 rand_node = rand() % num_nodes;
712 getnodes(friends_list[i].client_list[index[rand_node]].ip_port, 875 getnodes( friends_list[i].client_list[index[rand_node]].ip_port,
713 friends_list[i].client_list[index[rand_node]].client_id, 876 friends_list[i].client_list[index[rand_node]].client_id,
714 friends_list[i].client_id); 877 friends_list[i].client_id );
715 friends_list[i].lastgetnode = temp_time; 878 friends_list[i].lastgetnode = temp_time;
716 } 879 }
717 } 880 }
@@ -720,8 +883,9 @@ void doDHTFriends()
720static uint32_t close_lastgetnodes; 883static uint32_t close_lastgetnodes;
721 884
722/* Ping each client in the close nodes list every 60 seconds. 885/* Ping each client in the close nodes list every 60 seconds.
723 Send a get nodes request every 20 seconds to a random good node in the list. */ 886 * Send a get nodes request every 20 seconds to a random good node in the list.
724void doClose() /* tested */ 887 */
888void doClose()
725{ 889{
726 uint32_t i; 890 uint32_t i;
727 uint32_t temp_time = unix_time(); 891 uint32_t temp_time = unix_time();
@@ -729,25 +893,27 @@ void doClose() /* tested */
729 uint32_t rand_node; 893 uint32_t rand_node;
730 uint32_t index[LCLIENT_LIST]; 894 uint32_t index[LCLIENT_LIST];
731 895
732 for(i = 0; i < LCLIENT_LIST; ++i) 896 for (i = 0; i < LCLIENT_LIST; ++i) {
733 /* if node is not dead. */ 897 /* if node is not dead. */
734 if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) { 898 if (close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) {
735 if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 899 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
736 pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id); 900 pingreq( close_clientlist[i].ip_port,
901 close_clientlist[i].client_id );
737 close_clientlist[i].last_pinged = temp_time; 902 close_clientlist[i].last_pinged = temp_time;
738 } 903 }
739 /* if node is good. */ 904 /* if node is good. */
740 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { 905 if (close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) {
741 index[num_nodes] = i; 906 index[num_nodes] = i;
742 ++num_nodes; 907 ++num_nodes;
743 } 908 }
744 } 909 }
910 }
745 911
746 if(close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 912 if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
747 rand_node = rand() % num_nodes; 913 rand_node = rand() % num_nodes;
748 getnodes(close_clientlist[index[rand_node]].ip_port, 914 getnodes( close_clientlist[index[rand_node]].ip_port,
749 close_clientlist[index[rand_node]].client_id, 915 close_clientlist[index[rand_node]].client_id,
750 self_public_key); 916 self_public_key );
751 close_lastgetnodes = temp_time; 917 close_lastgetnodes = temp_time;
752 } 918 }
753} 919}
@@ -758,123 +924,153 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key)
758} 924}
759 925
760/* send the given packet to node with client_id 926/* send the given packet to node with client_id
761 returns -1 if failure */ 927 * returns -1 if failure
928 */
762int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) 929int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length)
763{ 930{
764 uint32_t i; 931 uint32_t i;
765 for(i = 0; i < LCLIENT_LIST; ++i) 932 for (i = 0; i < LCLIENT_LIST; ++i) {
766 if(memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) 933 if (memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0)
767 return sendpacket(close_clientlist[i].ip_port, packet, length); 934 return sendpacket(close_clientlist[i].ip_port, packet, length);
935 }
768 return -1; 936 return -1;
769} 937}
770 938
771/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist 939/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist
772 ip_portlist must be at least MAX_FRIEND_CLIENTS big 940 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
773 returns the number of ips returned 941 * returns the number of ips returned
774 return 0 if we are connected to friend or if no ips were found. 942 * return 0 if we are connected to friend or if no ips were found.
775 returns -1 if no such friend*/ 943 * returns -1 if no such friend
944 */
776static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) 945static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num)
777{ 946{
778 int num_ips = 0; 947 int num_ips = 0;
779 uint32_t i; 948 uint32_t i, temp_time = unix_time();
780 uint32_t temp_time = unix_time(); 949
781 if(friend_num >= num_friends) 950 if (friend_num >= num_friends)
782 return -1; 951 return -1;
783 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 952
953 Friend * friend = &friends_list[friend_num];
954 Client_data * client;
955
956 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
957 client = &friend->client_list[i];
958
784 /*If ip is not zero and node is good */ 959 /*If ip is not zero and node is good */
785 if(friends_list[friend_num].client_list[i].ret_ip_port.ip.i != 0 && 960 if (client->ret_ip_port.ip.i != 0 &&
786 friends_list[friend_num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 961 client->ret_timestamp + BAD_NODE_TIMEOUT > temp_time) {
787 if(memcmp(friends_list[friend_num].client_list[i].client_id, friends_list[friend_num].client_id, CLIENT_ID_SIZE) == 0 ) 962
963 if (memcmp(client->client_id, friend->client_id, CLIENT_ID_SIZE) == 0)
788 return 0; 964 return 0;
789 ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port; 965
966 ip_portlist[num_ips] = client->ret_ip_port;
790 ++num_ips; 967 ++num_ips;
791 } 968 }
969 }
792 return num_ips; 970 return num_ips;
793} 971}
794 972
795/* Send the following packet to everyone who tells us they are connected to friend_id 973/* Send the following packet to everyone who tells us they are connected to friend_id
796 returns the number of nodes it sent the packet to */ 974 * returns the number of nodes it sent the packet to
975 */
797int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 976int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
798{ 977{
799 uint32_t i, j; 978 int num = friend_number(friend_id);
800 uint32_t sent = 0; 979 if (num == -1)
801 uint32_t temp_time = unix_time(); 980 return 0;
802 for(i = 0; i < num_friends; ++i) 981
803 /* Equal */ 982 uint32_t i, sent = 0, temp_time = unix_time();
804 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { 983 Friend * friend = &friends_list[num];
805 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 984 Client_data * client;
806 /*If ip is not zero and node is good */ 985
807 if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && 986 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
808 friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) 987 client = &friend->client_list[i];
809 if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length) 988
810 ++sent; 989 /*If ip is not zero and node is good */
811 return sent; 990 if (client->ret_ip_port.ip.i != 0 &&
991 client->ret_timestamp + BAD_NODE_TIMEOUT > temp_time) {
992
993 if (sendpacket(client->ip_port, packet, length) == length)
994 ++sent;
812 } 995 }
813 return 0; 996 }
997 return sent;
814} 998}
815 999
816/* Send the following packet to one random person who tells us they are connected to friend_id 1000/* Send the following packet to one random person who tells us they are connected to friend_id
817 returns the number of nodes it sent the packet to */ 1001* returns the number of nodes it sent the packet to
1002*/
818int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 1003int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
819{ 1004{
820 int num = friend_number(friend_id); 1005 int num = friend_number(friend_id);
821 if(num == -1) 1006 if (num == -1)
822 return 0; 1007 return 0;
823 1008
1009 Friend * friend = &friends_list[num];
1010 Client_data * client;
1011
824 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1012 IP_Port ip_list[MAX_FRIEND_CLIENTS];
825 int n = 0; 1013 int n = 0;
826 uint32_t i; 1014 uint32_t i, temp_time = unix_time();
827 uint32_t temp_time = unix_time(); 1015
828 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 1016 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1017 client = &friend->client_list[i];
1018
829 /*If ip is not zero and node is good */ 1019 /*If ip is not zero and node is good */
830 if(friends_list[num].client_list[i].ret_ip_port.ip.i != 0 && 1020 if(client->ret_ip_port.ip.i != 0 &&
831 friends_list[num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 1021 client->ret_timestamp + BAD_NODE_TIMEOUT > temp_time) {
832 ip_list[n] = friends_list[num].client_list[i].ip_port; 1022 ip_list[n] = client->ip_port;
833 ++n; 1023 ++n;
834 } 1024 }
835 if(n < 1) 1025 }
1026 if (n < 1)
836 return 0; 1027 return 0;
837 if(sendpacket(ip_list[rand() % n], packet, length) == length) 1028 if (sendpacket(ip_list[rand() % n], packet, length) == length)
838 return 1; 1029 return 1;
839 return 0; 1030 return 0;
840} 1031}
841 1032
842/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist 1033/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist
843 ip_portlist must be at least MAX_FRIEND_CLIENTS big 1034 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
844 returns the number of ips returned 1035 * returns the number of ips returned
845 return 0 if we are connected to friend or if no ips were found. 1036 * return 0 if we are connected to friend or if no ips were found.
846 returns -1 if no such friend*/ 1037 * returns -1 if no such friend
1038 */
847int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) 1039int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id)
848{ 1040{
849
850 uint32_t i; 1041 uint32_t i;
851 for(i = 0; i < num_friends; ++i) 1042 for (i = 0; i < num_friends; ++i) {
852 /* Equal */ 1043 /* Equal */
853 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) 1044 if (memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0)
854 return friend_iplist(ip_portlist, i); 1045 return friend_iplist(ip_portlist, i);
1046 }
855 return -1; 1047 return -1;
856} 1048}
857 1049
858/*BEGINNING OF NAT PUNCHING FUNCTIONS*/ 1050/*----------------------------------------------------------------------------------*/
1051/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
859 1052
860int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) 1053int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
861{ 1054{
862 uint8_t data[sizeof(uint64_t) + 1]; 1055 uint8_t data[sizeof(uint64_t) + 1];
1056 uint8_t packet[MAX_DATA_SIZE];
1057
1058 /* 254 is NAT ping request packet id */
1059 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254);
1060 int num = 0;
1061
863 data[0] = type; 1062 data[0] = type;
864 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 1063 memcpy(data + 1, &ping_id, sizeof(uint64_t));
865 1064
866 uint8_t packet[MAX_DATA_SIZE]; 1065 if (len == -1)
867 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); /* 254 is NAT ping request packet id */
868 if(len == -1)
869 return -1; 1066 return -1;
870 1067
871 int num = 0; 1068 if (type == 0) /*If packet is request use many people to route it*/
1069 num = route_tofriend(public_key, packet, len);
1070 else if (type == 1) /*If packet is response use only one person to route it*/
1071 num = routeone_tofriend(public_key, packet, len);
872 1072
873 if(type == 0) 1073 if (num == 0)
874 num = route_tofriend(public_key, packet, len);/*If packet is request use many people to route it*/
875 else if(type == 1)
876 num = routeone_tofriend(public_key, packet, len);/*If packet is response use only one person to route it*/
877 if(num == 0)
878 return -1; 1074 return -1;
879 return num; 1075 return num;
880} 1076}
@@ -882,45 +1078,54 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
882/* Handle a recieved ping request for */ 1078/* Handle a recieved ping request for */
883int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) 1079int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
884{ 1080{
885 if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 1081 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING
886 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 1082 && length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
887 return 1; 1083 return 1;
1084
888 /* check if request is for us. */ 1085 /* check if request is for us. */
889 if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 1086 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
890 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 1087 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
891 uint8_t data[MAX_DATA_SIZE]; 1088 uint8_t data[MAX_DATA_SIZE];
1089
892 int len = handle_request(public_key, data, packet, length); 1090 int len = handle_request(public_key, data, packet, length);
893 if(len != sizeof(uint64_t) + 1) 1091 if (len != sizeof(uint64_t) + 1)
894 return 1; 1092 return 1;
1093
895 uint64_t ping_id; 1094 uint64_t ping_id;
896 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 1095 memcpy(&ping_id, data + 1, sizeof(uint64_t));
897 1096
898 int friendnumber = friend_number(public_key); 1097 int friendnumber = friend_number(public_key);
899 if(friendnumber == -1) 1098 if (friendnumber == -1)
900 return 1; 1099 return 1;
901 1100
902 if(data[0] == 0) { 1101 Friend * friend = &friends_list[friendnumber];
903 send_NATping(public_key, ping_id, 1); /*1 is reply*/ 1102
904 friends_list[friendnumber].recvNATping_timestamp = unix_time(); 1103 if (data[0] == 0) {
1104 /* 1 is reply */
1105 send_NATping(public_key, ping_id, 1);
1106 friend->recvNATping_timestamp = unix_time();
905 return 0; 1107 return 0;
906 } else if (data[0] == 1) 1108 } else if (data[0] == 1) {
907 if(friends_list[friendnumber].NATping_id == ping_id) { 1109 if (friend->NATping_id == ping_id) {
908 friends_list[friendnumber].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 1110 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int();
909 friends_list[friendnumber].hole_punching = 1; 1111 friend->hole_punching = 1;
910 return 0; 1112 return 0;
911 } 1113 }
1114 }
912 return 1; 1115 return 1;
913 } 1116 }
1117
914 /* if request is not for us, try routing it. */ 1118 /* if request is not for us, try routing it. */
915 else if(route_packet(packet + 1, packet, length) == length) 1119 route_packet(packet + 1, packet, length);
916 return 0; 1120
917 return 0; 1121 return 0;
918} 1122}
919 1123
920/*Get the most common ip in the ip_portlist 1124/* Get the most common ip in the ip_portlist
921 Only return ip if it appears in list min_num or more 1125 * Only return ip if it appears in list min_num or more
922 len must not be bigger than MAX_FRIEND_CLIENTS 1126 * len must not be bigger than MAX_FRIEND_CLIENTS
923 return ip of 0 if failure */ 1127 * return ip of 0 if failure
1128 */
924static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) 1129static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
925{ 1130{
926 IP zero = {{0}}; 1131 IP zero = {{0}};
@@ -929,40 +1134,45 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
929 1134
930 uint32_t i, j; 1135 uint32_t i, j;
931 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; 1136 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
1137
932 for(i = 0; i < len; ++i) { 1138 for(i = 0; i < len; ++i) {
933 for(j = 0; j < len; ++j) 1139 for(j = 0; j < len; ++j) {
934 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) 1140 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i)
935 ++numbers[i]; 1141 ++numbers[i];
1142 }
936 if(numbers[i] >= min_num) 1143 if(numbers[i] >= min_num)
937 return ip_portlist[i].ip; 1144 return ip_portlist[i].ip;
938 } 1145 }
939 return zero; 1146 return zero;
940} 1147}
941 1148
942/*Return all the ports for one ip in a list 1149/* Return all the ports for one ip in a list
943 portlist must be at least len long 1150 * portlist must be at least len long
944 where len is the length of ip_portlist 1151 * where len is the length of ip_portlist
945 returns the number of ports and puts the list of ports in portlist*/ 1152 * returns the number of ports and puts the list of ports in portlist
1153 */
946static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) 1154static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip)
947{ 1155{
948 uint32_t i; 1156 uint32_t i;
949 uint16_t num = 0; 1157 uint16_t num = 0;
950 for(i = 0; i < len; ++i) 1158
1159 for(i = 0; i < len; ++i) {
951 if(ip_portlist[i].ip.i == ip.i) { 1160 if(ip_portlist[i].ip.i == ip.i) {
952 portlist[num] = ntohs(ip_portlist[i].port); 1161 portlist[num] = ntohs(ip_portlist[i].port);
953 ++num; 1162 ++num;
954 } 1163 }
1164 }
955 return num; 1165 return num;
956} 1166}
957 1167
958#define MAX_PUNCHING_PORTS 32
959
960static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) 1168static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num)
961{ 1169{
962 if(numports > MAX_FRIEND_CLIENTS || numports == 0) 1170 if(numports > MAX_FRIEND_CLIENTS || numports == 0)
963 return; 1171 return;
1172
964 uint32_t i; 1173 uint32_t i;
965 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1174 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
1175
966 for(i = friends_list[friend_num].punching_index; i != top; i++) { 1176 for(i = friends_list[friend_num].punching_index; i != top; i++) {
967 /*TODO: improve port guessing algorithm*/ 1177 /*TODO: improve port guessing algorithm*/
968 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); 1178 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1);
@@ -972,30 +1182,28 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t
972 friends_list[friend_num].punching_index = i; 1182 friends_list[friend_num].punching_index = i;
973} 1183}
974 1184
975/*Interval in seconds between punching attempts*/
976#define PUNCH_INTERVAL 10
977
978static void doNAT() 1185static void doNAT()
979{ 1186{
980 uint32_t i; 1187 uint32_t i, temp_time = unix_time();
981 uint32_t temp_time = unix_time(); 1188
982 for(i = 0; i < num_friends; ++i) { 1189 for (i = 0; i < num_friends; ++i) {
983 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1190 IP_Port ip_list[MAX_FRIEND_CLIENTS];
984 int num = friend_iplist(ip_list, i); 1191 int num = friend_iplist(ip_list, i);
985 /*If we are connected to friend or if friend is not online don't try to hole punch with him*/
986 if(num < MAX_FRIEND_CLIENTS/2)
987 continue;
988 1192
1193 /*If already connected or friend is not online don't try to hole punch*/
1194 if (num < MAX_FRIEND_CLIENTS/2)
1195 continue;
989 1196
990 if(friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1197 if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) {
991 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ 1198 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/
992 friends_list[i].NATping_timestamp = temp_time; 1199 friends_list[i].NATping_timestamp = temp_time;
993 } 1200 }
994 if(friends_list[i].hole_punching == 1 && 1201 if (friends_list[i].hole_punching == 1 &&
995 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1202 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
996 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) { 1203 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) {
1204
997 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); 1205 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2);
998 if(ip.i == 0) 1206 if (ip.i == 0)
999 continue; 1207 continue;
1000 1208
1001 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1209 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1057,17 +1265,22 @@ void DHT_save(uint8_t * data)
1057} 1265}
1058 1266
1059/* load the DHT from data of size size; 1267/* load the DHT from data of size size;
1060 return -1 if failure 1268 * return -1 if failure
1061 return 0 if success */ 1269 * return 0 if success
1270 */
1062int DHT_load(uint8_t * data, uint32_t size) 1271int DHT_load(uint8_t * data, uint32_t size)
1063{ 1272{
1064 if(size < sizeof(close_clientlist)) 1273 if(size < sizeof(close_clientlist))
1065 return -1; 1274 return -1;
1275
1066 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) 1276 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0)
1067 return -1; 1277 return -1;
1278
1068 uint32_t i, j; 1279 uint32_t i, j;
1069 /* uint32_t temp_time = unix_time(); */
1070 uint16_t temp; 1280 uint16_t temp;
1281 /* uint32_t temp_time = unix_time(); */
1282
1283 Client_data * client;
1071 1284
1072 temp = (size - sizeof(close_clientlist))/sizeof(Friend); 1285 temp = (size - sizeof(close_clientlist))/sizeof(Friend);
1073 1286
@@ -1076,29 +1289,34 @@ int DHT_load(uint8_t * data, uint32_t size)
1076 1289
1077 for(i = 0; i < temp; ++i) { 1290 for(i = 0; i < temp; ++i) {
1078 DHT_addfriend(tempfriends_list[i].client_id); 1291 DHT_addfriend(tempfriends_list[i].client_id);
1079 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 1292
1080 if(tempfriends_list[i].client_list[j].timestamp != 0) { 1293 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1081 getnodes(tempfriends_list[i].client_list[j].ip_port, 1294 client = &tempfriends_list[i].client_list[j];
1082 tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id); 1295 if(client->timestamp != 0)
1083 } 1296 getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id);
1297 }
1084 } 1298 }
1085 } 1299 }
1086 Client_data * tempclose_clientlist = (Client_data *)data; 1300 Client_data * tempclose_clientlist = (Client_data *)data;
1087 1301
1088 for(i = 0; i < LCLIENT_LIST; ++i) 1302 for(i = 0; i < LCLIENT_LIST; ++i) {
1089 if(tempclose_clientlist[i].timestamp != 0) 1303 if(tempclose_clientlist[i].timestamp != 0)
1090 DHT_bootstrap(tempclose_clientlist[i].ip_port, tempclose_clientlist[i].client_id); 1304 DHT_bootstrap( tempclose_clientlist[i].ip_port,
1305 tempclose_clientlist[i].client_id );
1306 }
1091 return 0; 1307 return 0;
1092} 1308}
1093 1309
1094/* returns 0 if we are not connected to the DHT 1310/* returns 0 if we are not connected to the DHT
1095 returns 1 if we are */ 1311 * returns 1 if we are
1312 */
1096int DHT_isconnected() 1313int DHT_isconnected()
1097{ 1314{
1098 uint32_t i; 1315 uint32_t i, temp_time = unix_time();
1099 uint32_t temp_time = unix_time(); 1316
1100 for(i = 0; i < LCLIENT_LIST; ++i) 1317 for(i = 0; i < LCLIENT_LIST; ++i) {
1101 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) 1318 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time)
1102 return 1; 1319 return 1;
1320 }
1103 return 0; 1321 return 0;
1104} 1322}