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