summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/CMakeLists.txt4
-rw-r--r--core/DHT.c1004
-rw-r--r--core/DHT.h2
-rw-r--r--core/LAN_discovery.c61
-rw-r--r--core/LAN_discovery.h7
-rw-r--r--core/Lossless_UDP.c429
-rw-r--r--core/Lossless_UDP.h96
-rw-r--r--core/Messenger.c89
-rw-r--r--core/Messenger.h36
-rw-r--r--core/net_crypto.c83
-rw-r--r--core/network.c47
-rw-r--r--core/network.h17
12 files changed, 1196 insertions, 679 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 44ae980c..36acb6cf 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -1,5 +1,5 @@
1cmake_minimum_required(VERSION 2.6.0) 1cmake_minimum_required(VERSION 2.6.0)
2project(core C) 2project(toxcore C)
3 3
4if(WIN32) 4if(WIN32)
5 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/) 5 include_directories(${CMAKE_HOME_DIRECTORY}/sodium/include/)
@@ -16,4 +16,4 @@ set(core_sources
16 LAN_discovery.c 16 LAN_discovery.c
17 Messenger.c) 17 Messenger.c)
18 18
19add_library(core ${core_sources}) 19add_library(toxcore SHARED ${core_sources})
diff --git a/core/DHT.c b/core/DHT.c
index 5039f710..5d5910e0 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -21,102 +21,156 @@
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 uint8_t client_id[CLIENT_ID_SIZE];
55 IP_Port ip_port; 66 IP_Port ip_port;
56} Node_format; 67 uint64_t timestamp;
68 uint64_t last_pinged;
69
70 /* Returned by this node. Either our friend or us */
71 IP_Port ret_ip_port;
72 uint64_t ret_timestamp;
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 uint64_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 uint64_t punching_timestamp;
88 uint64_t recvNATping_timestamp;
89 uint64_t NATping_id;
90 uint64_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 uint64_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 * id, uint8_t * id1, uint8_t * id2)
91{ 123{
92 uint32_t i; 124 size_t i;
125 uint8_t distance1, distance2;
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
129 distance1 = abs(id[i] ^ id1[i]);
130 distance2 = abs(id[i] ^ id2[i]);
131
132 if(distance1 < distance2)
95 return 1; 133 return 1;
96 else if(abs(client_id[i] ^ client_id1[i]) > abs(client_id[i] ^ client_id2[i])) 134 if(distance1 > distance2)
97 return 2; 135 return 2;
98 } 136 }
99 return 0; 137 return 0;
100} 138}
101 139
140int ipport_equal(IP_Port a, IP_Port b)
141{
142 return (a.ip.i == b.ip.i) && (a.port == b.port);
143}
144
145int id_equal(uint8_t* a, uint8_t* b)
146{
147 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
148}
149
150int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout)
151{
152 return timestamp + timeout <= time_now;
153}
154
102/* check if client with client_id is already in list of length length. 155/* 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. 156 * 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. 157 * if the id is already in the list with a different ip_port, update it.
105 return True(1) or False(0) 158 * return True(1) or False(0)
106 TODO: maybe optimize this. */ 159 *
160 * TODO: maybe optimize this.
161 */
107int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) 162int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port)
108{ 163{
109 uint32_t i; 164 uint32_t i;
110 uint32_t temp_time = unix_time(); 165 uint64_t temp_time = unix_time();
111 166
112 for(i = 0; i < length; ++i) { 167 for(i = 0; i < length; ++i) {
113 /*If ip_port is assigned to a different client_id replace it*/ 168 /*If ip_port is assigned to a different client_id replace it*/
114 if(list[i].ip_port.ip.i == ip_port.ip.i && 169 if(ipport_equal(list[i].ip_port, ip_port)) {
115 list[i].ip_port.port == ip_port.port) {
116 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 170 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
117 } 171 }
118 172
119 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 173 if(id_equal(list[i].client_id, client_id)) {
120 /* Refresh the client timestamp. */ 174 /* Refresh the client timestamp. */
121 list[i].timestamp = temp_time; 175 list[i].timestamp = temp_time;
122 list[i].ip_port.ip.i = ip_port.ip.i; 176 list[i].ip_port.ip.i = ip_port.ip.i;
@@ -125,88 +179,138 @@ int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_
125 } 179 }
126 } 180 }
127 return 0; 181 return 0;
128
129} 182}
130 183
131/* check if client with client_id is already in node format list of length length. 184/* check if client with client_id is already in node format list of length length.
132 return True(1) or False(0) */ 185 * return True(1) or False(0)
186 */
133int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) 187int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id)
134{ 188{
135 uint32_t i; 189 uint32_t i;
136 for(i = 0; i < length; ++i) 190
137 if(memcmp(list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) 191 for(i = 0; i < length; ++i) {
192 if(id_equal(list[i].client_id, client_id))
138 return 1; 193 return 1;
194 }
195
139 return 0; 196 return 0;
140} 197}
141 198
142/*Return the friend number from the client_id 199/* Returns the friend number from the client_id, or -1 if a failure occurs
143 Return -1 if failure, number of friend if success*/ 200 */
144static int friend_number(uint8_t * client_id) 201static int friend_number(uint8_t * client_id)
145{ 202{
146 uint32_t i; 203 uint32_t i;
147 for(i = 0; i < num_friends; ++i) 204
148 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) /* Equal */ 205 for(i = 0; i < num_friends; ++i) {
206 if(id_equal(friends_list[i].client_id, client_id))
149 return i; 207 return i;
208 }
209
150 return -1; 210 return -1;
151} 211}
152 212
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: 213/* 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. 214 * put them in the nodes_list and return how many were found.
160 TODO: Make this function much more efficient. */ 215 *
216 * TODO: For the love of based Allah make this function cleaner and much more efficient.
217 */
161int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) 218int get_close_nodes(uint8_t * client_id, Node_format * nodes_list)
162{ 219{
163 uint32_t i, j, k; 220 uint32_t i, j, k;
164 int num_nodes=0; 221 uint64_t temp_time = unix_time();
165 uint32_t temp_time = unix_time(); 222 int num_nodes = 0, closest, tout, inlist;
166 for(i = 0; i < LCLIENT_LIST; ++i) 223
167 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time && 224 for (i = 0; i < LCLIENT_LIST; ++i) {
168 !client_in_nodelist(nodes_list, MAX_SENT_NODES,close_clientlist[i].client_id)) { 225 tout = is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
169 /* if node is good and not already in list. */ 226 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id);
227
228 /* if node isn't good or is already in list. */
229 if(tout || inlist)
230 continue;
231
232 if(num_nodes < MAX_SENT_NODES) {
233
234 memcpy( nodes_list[num_nodes].client_id,
235 close_clientlist[i].client_id,
236 CLIENT_ID_SIZE );
237
238 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port;
239 num_nodes++;
240
241 } else {
242
243 for(j = 0; j < MAX_SENT_NODES; ++j) {
244 closest = id_closest( client_id,
245 nodes_list[j].client_id,
246 close_clientlist[i].client_id );
247 if(closest == 2) {
248 memcpy( nodes_list[j].client_id,
249 close_clientlist[i].client_id,
250 CLIENT_ID_SIZE);
251
252 nodes_list[j].ip_port = close_clientlist[i].ip_port;
253 break;
254 }
255 }
256 }
257 }
258
259 for(i = 0; i < num_friends; ++i) {
260 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
261
262 tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
263 inlist = client_in_nodelist( nodes_list,
264 MAX_SENT_NODES,
265 friends_list[i].client_list[j].client_id);
266
267 /* if node isn't good or is already in list. */
268 if(tout || inlist)
269 continue;
270
170 if(num_nodes < MAX_SENT_NODES) { 271 if(num_nodes < MAX_SENT_NODES) {
171 memcpy(nodes_list[num_nodes].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 272
172 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; 273 memcpy( nodes_list[num_nodes].client_id,
274 friends_list[i].client_list[j].client_id,
275 CLIENT_ID_SIZE);
276
277 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port;
173 num_nodes++; 278 num_nodes++;
174 } else for(j = 0; j < MAX_SENT_NODES; ++j) 279 } else {
175 if(id_closest(client_id, nodes_list[j].client_id, close_clientlist[i].client_id) == 2) { 280 for(k = 0; k < MAX_SENT_NODES; ++k) {
176 memcpy(nodes_list[j].client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE); 281
177 nodes_list[j].ip_port = close_clientlist[i].ip_port; 282 closest = id_closest( client_id,
283 nodes_list[k].client_id,
284 friends_list[i].client_list[j].client_id );
285 if(closest == 2) {
286 memcpy( nodes_list[k].client_id,
287 friends_list[i].client_list[j].client_id,
288 CLIENT_ID_SIZE );
289
290 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port;
178 break; 291 break;
179 } 292 }
180 } 293 }
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 } 294 }
295 }
296 }
198 return num_nodes; 297 return num_nodes;
199} 298}
200 299
201/* replace first bad (or empty) node with this one 300/* replace first bad (or empty) node with this one
202 return 0 if successful 301 * return 0 if successful
203 return 1 if not (list contains no bad nodes) */ 302 * 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 */ 303 */
304int replace_bad( Client_data * list,
305 uint32_t length,
306 uint8_t * client_id,
307 IP_Port ip_port )
205{ 308{
206 uint32_t i; 309 uint32_t i;
207 uint32_t temp_time = unix_time(); 310 uint64_t temp_time = unix_time();
208 for(i = 0; i < length; ++i) 311 for(i = 0; i < length; ++i) {
209 if(list[i].timestamp + BAD_NODE_TIMEOUT < temp_time) { /* if node is bad. */ 312 /* if node is bad */
313 if(is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) {
210 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 314 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
211 list[i].ip_port = ip_port; 315 list[i].ip_port = ip_port;
212 list[i].timestamp = temp_time; 316 list[i].timestamp = temp_time;
@@ -215,15 +319,20 @@ int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Por
215 list[i].ret_timestamp = 0; 319 list[i].ret_timestamp = 0;
216 return 0; 320 return 0;
217 } 321 }
322 }
218 323
219 return 1; 324 return 1;
220} 325}
221 326
222/* replace the first good node that is further to the comp_client_id than that of the client_id in the list */ 327/* 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) 328int replace_good( Client_data * list,
329 uint32_t length,
330 uint8_t * client_id,
331 IP_Port ip_port,
332 uint8_t * comp_client_id )
224{ 333{
225 uint32_t i; 334 uint32_t i;
226 uint32_t temp_time = unix_time(); 335 uint64_t temp_time = unix_time();
227 336
228 for(i = 0; i < length; ++i) 337 for(i = 0; i < length; ++i)
229 if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) { 338 if(id_closest(comp_client_id, list[i].client_id, client_id) == 2) {
@@ -239,75 +348,109 @@ int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Po
239 return 1; 348 return 1;
240} 349}
241 350
242/* Attempt to add client with ip_port and client_id to the friends client list and close_clientlist */ 351/* Attempt to add client with ip_port and client_id to the friends client list
352 * and close_clientlist
353 */
243void addto_lists(IP_Port ip_port, uint8_t * client_id) 354void addto_lists(IP_Port ip_port, uint8_t * client_id)
244{ 355{
245 uint32_t i; 356 uint32_t i;
246 357
247 /* NOTE: current behavior if there are two clients with the same id is to replace the first ip by the second. */ 358 /* 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)) 359 * to replace the first ip by the second.
249 if(replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) 360 */
361 if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
362 if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
250 /* if we can't replace bad nodes we try replacing good ones */ 363 /* 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); 364 replace_good( close_clientlist,
365 LCLIENT_LIST,
366 client_id,
367 ip_port,
368 self_public_key );
369 }
370 }
371
372 for (i = 0; i < num_friends; ++i) {
373 if (!client_in_list( friends_list[i].client_list,
374 MAX_FRIEND_CLIENTS,
375 client_id,
376 ip_port )) {
252 377
253 for(i = 0; i < num_friends; ++i) 378 if (replace_bad( friends_list[i].client_list,
254 if(!client_in_list(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 379 MAX_FRIEND_CLIENTS,
255 if(replace_bad(friends_list[i].client_list, MAX_FRIEND_CLIENTS, client_id, ip_port)) 380 client_id,
381 ip_port )) {
256 /* if we can't replace bad nodes we try replacing good ones. */ 382 /* 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); 383 replace_good( friends_list[i].client_list,
384 MAX_FRIEND_CLIENTS,
385 client_id,
386 ip_port,
387 friends_list[i].client_id );
388 }
389 }
390 }
258} 391}
259 392
260/* If client_id is a friend or us, update ret_ip_port 393/* 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 */ 394 * nodeclient_id is the id of the node that sent us this info
395 */
262void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) 396void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id)
263{ 397{
264 uint32_t i, j; 398 uint32_t i, j;
265 uint32_t temp_time = unix_time(); 399 uint64_t temp_time = unix_time();
266 if(memcmp(client_id, self_public_key, CLIENT_ID_SIZE) == 0) { 400
267 for(i = 0; i < LCLIENT_LIST; ++i) 401 if (id_equal(client_id, self_public_key)) {
268 if(memcmp(nodeclient_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) { 402
403 for (i = 0; i < LCLIENT_LIST; ++i) {
404 if (id_equal(nodeclient_id, close_clientlist[i].client_id)) {
269 close_clientlist[i].ret_ip_port = ip_port; 405 close_clientlist[i].ret_ip_port = ip_port;
270 close_clientlist[i].ret_timestamp = temp_time; 406 close_clientlist[i].ret_timestamp = temp_time;
271 return; 407 return;
272 } 408 }
273 } else 409 }
274 for(i = 0; i < num_friends; ++i) 410
275 if(memcmp(client_id, friends_list[i].client_id, CLIENT_ID_SIZE) == 0) 411 } else {
276 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 412
277 if(memcmp(nodeclient_id, friends_list[i].client_list[j].client_id, CLIENT_ID_SIZE) == 0) { 413 for (i = 0; i < num_friends; ++i) {
414 if (id_equal(client_id, friends_list[i].client_id)) {
415
416 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
417 if (id_equal(nodeclient_id, friends_list[i].client_list[j].client_id)) {
278 friends_list[i].client_list[j].ret_ip_port = ip_port; 418 friends_list[i].client_list[j].ret_ip_port = ip_port;
279 friends_list[i].client_list[j].ret_timestamp = temp_time; 419 friends_list[i].client_list[j].ret_timestamp = temp_time;
280 return; 420 return;
281 } 421 }
282} 422 }
423 }
424 }
283 425
284/* ping timeout in seconds */ 426 }
285#define PING_TIMEOUT 5 427}
286 428
287/* check if we are currently pinging an ip_port and/or a ping_id 429/* check if we are currently pinging an ip_port and/or a ping_id variables with
288 variables with values of zero will not be checked. 430 * values of zero will not be checked. If we are already, return 1 else return 0
289 if we are already, return 1 431 *
290 else return 0 432 * TODO: optimize this
291TODO: optimize this */ 433 */
292int is_pinging(IP_Port ip_port, uint64_t ping_id) 434int is_pinging(IP_Port ip_port, uint64_t ping_id)
293{ 435{
294 uint32_t i; 436 uint32_t i;
295 uint8_t pinging; 437 uint8_t pinging;
296 uint32_t temp_time = unix_time(); 438 uint64_t temp_time = unix_time();
297 439
298 for(i = 0; i < LPING_ARRAY; ++i ) 440 for (i = 0; i < LPING_ARRAY; ++i ) {
299 if((pings[i].timestamp + PING_TIMEOUT) > temp_time) { 441 if (!is_timeout(temp_time, pings[i].timestamp, PING_TIMEOUT)) {
300 pinging = 0; 442 pinging = 0;
301 if(ip_port.ip.i != 0) 443
302 if(pings[i].ip_port.ip.i == ip_port.ip.i && 444 if (ip_port.ip.i != 0 && ipport_equal(pings[i].ip_port, ip_port))
303 pings[i].ip_port.port == ip_port.port)
304 ++pinging;
305 if(ping_id != 0)
306 if(pings[i].ping_id == ping_id)
307 ++pinging; 445 ++pinging;
308 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 446
447 if (ping_id != 0 && pings[i].ping_id == ping_id)
448 ++pinging;
449
450 if (pinging == ((ping_id != 0) + (ip_port.ip.i != 0)))
309 return 1; 451 return 1;
310 } 452 }
453 }
311 454
312 return 0; 455 return 0;
313} 456}
@@ -317,44 +460,48 @@ int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
317{ 460{
318 uint32_t i; 461 uint32_t i;
319 uint8_t pinging; 462 uint8_t pinging;
320 uint32_t temp_time = unix_time(); 463 uint64_t temp_time = unix_time();
321 464
322 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) 465 for(i = 0; i < LSEND_NODES_ARRAY; ++i ) {
323 if((send_nodes[i].timestamp + PING_TIMEOUT) > temp_time) { 466 if(!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) {
324 pinging = 0; 467 pinging = 0;
325 if(ip_port.ip.i != 0) 468
326 if(send_nodes[i].ip_port.ip.i == ip_port.ip.i && 469 if(ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port))
327 send_nodes[i].ip_port.port == ip_port.port)
328 ++pinging; 470 ++pinging;
329 if(ping_id != 0) 471
330 if(send_nodes[i].ping_id == ping_id) 472 if(ping_id != 0 && send_nodes[i].ping_id == ping_id)
331 ++pinging; 473 ++pinging;
474
332 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 475 if(pinging == (ping_id != 0) + (ip_port.ip.i != 0))
333 return 1; 476 return 1;
334
335 } 477 }
478 }
336 479
337 return 0; 480 return 0;
338} 481}
339 482
340/* Add a new ping request to the list of ping requests 483/* Add a new ping request to the list of ping requests
341 returns the ping_id to put in the ping request 484 * returns the ping_id to put in the ping request
342 returns 0 if problem. 485 * returns 0 if problem.
343 TODO: optimize this */ 486 *
487 * TODO: optimize this
488 */
344uint64_t add_pinging(IP_Port ip_port) 489uint64_t add_pinging(IP_Port ip_port)
345{ 490{
346 uint32_t i, j; 491 uint32_t i, j;
347 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 492 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
348 uint32_t temp_time = unix_time(); 493 uint64_t temp_time = unix_time();
349 494
350 for(i = 0; i < PING_TIMEOUT; ++i ) 495 for(i = 0; i < PING_TIMEOUT; ++i ) {
351 for(j = 0; j < LPING_ARRAY; ++j ) 496 for(j = 0; j < LPING_ARRAY; ++j ) {
352 if((pings[j].timestamp + PING_TIMEOUT - i) < temp_time) { 497 if(is_timeout(temp_time, pings[j].timestamp, PING_TIMEOUT - i)) {
353 pings[j].timestamp = temp_time; 498 pings[j].timestamp = temp_time;
354 pings[j].ip_port = ip_port; 499 pings[j].ip_port = ip_port;
355 pings[j].ping_id = ping_id; 500 pings[j].ping_id = ping_id;
356 return ping_id; 501 return ping_id;
357 } 502 }
503 }
504 }
358 505
359 return 0; 506 return 0;
360} 507}
@@ -364,28 +511,29 @@ uint64_t add_gettingnodes(IP_Port ip_port)
364{ 511{
365 uint32_t i, j; 512 uint32_t i, j;
366 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 513 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
367 uint32_t temp_time = unix_time(); 514 uint64_t temp_time = unix_time();
368 515
369 for(i = 0; i < PING_TIMEOUT; ++i ) 516 for(i = 0; i < PING_TIMEOUT; ++i ) {
370 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) 517 for(j = 0; j < LSEND_NODES_ARRAY; ++j ) {
371 if((send_nodes[j].timestamp + PING_TIMEOUT - i) < temp_time) { 518 if(is_timeout(temp_time, send_nodes[j].timestamp, PING_TIMEOUT - i)) {
372 send_nodes[j].timestamp = temp_time; 519 send_nodes[j].timestamp = temp_time;
373 send_nodes[j].ip_port = ip_port; 520 send_nodes[j].ip_port = ip_port;
374 send_nodes[j].ping_id = ping_id; 521 send_nodes[j].ping_id = ping_id;
375 return ping_id; 522 return ping_id;
376 } 523 }
524 }
525 }
377 526
378 return 0; 527 return 0;
379} 528}
380 529
381/* send a ping request 530/* 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. */ 531 * in the last 5 seconds.
532 */
383static int pingreq(IP_Port ip_port, uint8_t * public_key) 533static int pingreq(IP_Port ip_port, uint8_t * public_key)
384{ 534{
385 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 535 /* check if packet is gonna be sent to ourself */
386 return 1; 536 if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0))
387
388 if(is_pinging(ip_port, 0))
389 return 1; 537 return 1;
390 538
391 uint64_t ping_id = add_pinging(ip_port); 539 uint64_t ping_id = add_pinging(ip_port);
@@ -397,9 +545,16 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
397 uint8_t nonce[crypto_box_NONCEBYTES]; 545 uint8_t nonce[crypto_box_NONCEBYTES];
398 random_nonce(nonce); 546 random_nonce(nonce);
399 547
400 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 548 int len = encrypt_data( public_key,
549 self_secret_key,
550 nonce,
551 (uint8_t *)&ping_id,
552 sizeof(ping_id),
553 encrypt );
554
401 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 555 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
402 return -1; 556 return -1;
557
403 data[0] = 0; 558 data[0] = 0;
404 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 559 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
405 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 560 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -412,7 +567,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
412static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) 567static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
413{ 568{
414 /* check if packet is gonna be sent to ourself */ 569 /* check if packet is gonna be sent to ourself */
415 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) 570 if(id_equal(public_key, self_public_key))
416 return 1; 571 return 1;
417 572
418 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING]; 573 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING];
@@ -420,9 +575,15 @@ static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id)
420 uint8_t nonce[crypto_box_NONCEBYTES]; 575 uint8_t nonce[crypto_box_NONCEBYTES];
421 random_nonce(nonce); 576 random_nonce(nonce);
422 577
423 int len = encrypt_data(public_key, self_secret_key, nonce, (uint8_t *)&ping_id, sizeof(ping_id), encrypt); 578 int len = encrypt_data( public_key,
579 self_secret_key, nonce,
580 (uint8_t *)&ping_id,
581 sizeof(ping_id),
582 encrypt );
583
424 if(len != sizeof(ping_id) + ENCRYPTION_PADDING) 584 if(len != sizeof(ping_id) + ENCRYPTION_PADDING)
425 return -1; 585 return -1;
586
426 data[0] = 1; 587 data[0] = 1;
427 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 588 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
428 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 589 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
@@ -435,10 +596,7 @@ 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) 596static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
436{ 597{
437 /* check if packet is gonna be sent to ourself */ 598 /* check if packet is gonna be sent to ourself */
438 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) 599 if(id_equal(public_key, self_public_key) || is_gettingnodes(ip_port, 0))
439 return 1;
440
441 if(is_gettingnodes(ip_port, 0))
442 return 1; 600 return 1;
443 601
444 uint64_t ping_id = add_gettingnodes(ip_port); 602 uint64_t ping_id = add_gettingnodes(ip_port);
@@ -455,21 +613,29 @@ static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id)
455 memcpy(plain, &ping_id, sizeof(ping_id)); 613 memcpy(plain, &ping_id, sizeof(ping_id));
456 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); 614 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
457 615
458 int len = encrypt_data(public_key, self_secret_key, nonce, plain, sizeof(ping_id) + CLIENT_ID_SIZE, encrypt); 616 int len = encrypt_data( public_key,
617 self_secret_key,
618 nonce,
619 plain,
620 sizeof(ping_id) + CLIENT_ID_SIZE,
621 encrypt );
459 622
460 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 623 if(len != sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING)
461 return -1; 624 return -1;
625
462 data[0] = 2; 626 data[0] = 2;
463 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 627 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE);
464 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 628 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
465 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 629 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
630
466 return sendpacket(ip_port, data, sizeof(data)); 631 return sendpacket(ip_port, data, sizeof(data));
467} 632}
468 633
469/* send a send nodes response */ 634/* send a send nodes response */
470static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) 635static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id)
471{ 636{
472 if(memcmp(public_key, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is gonna be sent to ourself */ 637 /* check if packet is gonna be sent to ourself */
638 if(id_equal(public_key, self_public_key))
473 return 1; 639 return 1;
474 640
475 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 641 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
@@ -489,8 +655,12 @@ static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id,
489 memcpy(plain, &ping_id, sizeof(ping_id)); 655 memcpy(plain, &ping_id, sizeof(ping_id));
490 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 656 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
491 657
492 int len = encrypt_data(public_key, self_secret_key, nonce, plain, 658 int len = encrypt_data( public_key,
493 sizeof(ping_id) + num_nodes * sizeof(Node_format), encrypt); 659 self_secret_key,
660 nonce,
661 plain,
662 sizeof(ping_id) + num_nodes * sizeof(Node_format),
663 encrypt );
494 664
495 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 665 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING)
496 return -1; 666 return -1;
@@ -503,26 +673,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); 673 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
504} 674}
505 675
506/* Packet handling functions 676/* Packet handling functions, one to handle each types of packets we receive
507 One to handle each types of packets we receive 677 * Returns 0 if handled correctly, 1 if packet is bad.
508 return 0 if handled correctly, 1 if packet is bad. */ 678 */
509int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) 679int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)
510{ 680{
511 uint64_t ping_id; 681 uint64_t ping_id;
512 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 682 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
513 return 1; 683 return 1;
684
514 /* check if packet is from ourself. */ 685 /* check if packet is from ourself. */
515 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 686 if(id_equal(packet + 1, self_public_key))
516 return 1; 687 return 1;
517 688
518 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 689 int len = decrypt_data( packet + 1,
519 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 690 self_secret_key,
520 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 691 packet + 1 + CLIENT_ID_SIZE,
692 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
693 sizeof(ping_id) + ENCRYPTION_PADDING,
694 (uint8_t *)&ping_id );
695
521 if(len != sizeof(ping_id)) 696 if(len != sizeof(ping_id))
522 return 1; 697 return 1;
523 698
524 pingres(source, packet + 1, ping_id); 699 pingres(source, packet + 1, ping_id);
525
526 pingreq(source, packet + 1); /* TODO: make this smarter? */ 700 pingreq(source, packet + 1); /* TODO: make this smarter? */
527 701
528 return 0; 702 return 0;
@@ -533,12 +707,18 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
533 uint64_t ping_id; 707 uint64_t ping_id;
534 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING) 708 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING)
535 return 1; 709 return 1;
536 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) /* check if packet is from ourself. */ 710
711 /* check if packet is from ourself. */
712 if(id_equal(packet + 1, self_public_key))
537 return 1; 713 return 1;
538 714
539 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 715 int len = decrypt_data( packet + 1,
540 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 716 self_secret_key,
541 sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t *)&ping_id); 717 packet + 1 + CLIENT_ID_SIZE,
718 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
719 sizeof(ping_id) + ENCRYPTION_PADDING,
720 (uint8_t *)&ping_id );
721
542 if(len != sizeof(ping_id)) 722 if(len != sizeof(ping_id))
543 return 1; 723 return 1;
544 724
@@ -547,25 +727,30 @@ int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
547 return 0; 727 return 0;
548 } 728 }
549 return 1; 729 return 1;
550
551} 730}
552 731
553int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) 732int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
554{ 733{
555 uint64_t ping_id; 734 uint64_t ping_id;
556 if(length != 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING) 735
736 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
737 + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING ))
557 return 1; 738 return 1;
739
558 /* check if packet is from ourself. */ 740 /* check if packet is from ourself. */
559 if(memcmp(packet + 1, self_public_key, CLIENT_ID_SIZE) == 0) 741 if (id_equal(packet + 1, self_public_key))
560 return 1; 742 return 1;
561 743
562 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 744 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
563 745
564 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 746 int len = decrypt_data( packet + 1,
565 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 747 self_secret_key,
566 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, plain); 748 packet + 1 + CLIENT_ID_SIZE,
749 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
750 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING,
751 plain );
567 752
568 if(len != sizeof(ping_id) + CLIENT_ID_SIZE) 753 if (len != sizeof(ping_id) + CLIENT_ID_SIZE)
569 return 1; 754 return 1;
570 755
571 memcpy(&ping_id, plain, sizeof(ping_id)); 756 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -574,29 +759,28 @@ int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
574 pingreq(source, packet + 1); /* TODO: make this smarter? */ 759 pingreq(source, packet + 1); /* TODO: make this smarter? */
575 760
576 return 0; 761 return 0;
577
578} 762}
579 763
580int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) 764int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
581{ 765{
582 uint64_t ping_id; 766 uint64_t ping_id;
583 /* TODO: make this more readable */ 767 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
584 if(length > (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 768 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
585 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING) || 769
586 (length - (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 770 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) ||
587 + ENCRYPTION_PADDING)) % (sizeof(Node_format)) != 0 || 771 ((length - cid_size) % sizeof(Node_format)) != 0 ||
588 length < 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 772 (length < cid_size + sizeof(Node_format)))
589 + sizeof(Node_format) + ENCRYPTION_PADDING) {
590 return 1; 773 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 774
775 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format);
595 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 776 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES];
596 777
597 int len = decrypt_data(packet + 1, self_secret_key, packet + 1 + CLIENT_ID_SIZE, 778 int len = decrypt_data(
598 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 779 packet + 1,
599 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain); 780 self_secret_key,
781 packet + 1 + CLIENT_ID_SIZE,
782 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
783 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
600 784
601 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 785 if(len != sizeof(ping_id) + num_nodes * sizeof(Node_format))
602 return 1; 786 return 1;
@@ -619,18 +803,20 @@ int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)
619 return 0; 803 return 0;
620} 804}
621 805
622/* END of packet handling functions */ 806/*----------------------------------------------------------------------------------*/
807/*------------------------END of packet handling functions--------------------------*/
623 808
624int DHT_addfriend(uint8_t * client_id) 809int DHT_addfriend(uint8_t * client_id)
625{ 810{
626 Friend * temp; 811 Friend * temp;
627 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 812 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1));
628 if(temp == NULL) 813 if (temp == NULL)
629 return 1; 814 return 1;
630 815
631 friends_list = temp; 816 friends_list = temp;
632 memset(&friends_list[num_friends], 0, sizeof(Friend)); 817 memset(&friends_list[num_friends], 0, sizeof(Friend));
633 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); 818 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE);
819
634 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 820 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
635 ++num_friends; 821 ++num_friends;
636 return 0; 822 return 0;
@@ -640,17 +826,25 @@ int DHT_delfriend(uint8_t * client_id)
640{ 826{
641 uint32_t i; 827 uint32_t i;
642 Friend * temp; 828 Friend * temp;
643 for(i = 0; i < num_friends; ++i) 829 for (i = 0; i < num_friends; ++i) {
644 /* Equal */ 830 /* Equal */
645 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 831 if (id_equal(friends_list[i].client_id, client_id)) {
646 --num_friends; 832 --num_friends;
647 if(num_friends != i) 833
648 memcpy(friends_list[i].client_id, friends_list[num_friends].client_id, CLIENT_ID_SIZE); 834 if (num_friends != i) {
835 memcpy( friends_list[i].client_id,
836 friends_list[num_friends].client_id,
837 CLIENT_ID_SIZE );
838 }
839
649 temp = realloc(friends_list, sizeof(Friend) * (num_friends)); 840 temp = realloc(friends_list, sizeof(Friend) * (num_friends));
650 if(temp != NULL) 841 if (temp == NULL)
651 friends_list = temp; 842 return 1;
843
844 friends_list = temp;
652 return 0; 845 return 0;
653 } 846 }
847 }
654 848
655 return 1; 849 return 1;
656} 850}
@@ -659,95 +853,94 @@ int DHT_delfriend(uint8_t * client_id)
659IP_Port DHT_getfriendip(uint8_t * client_id) 853IP_Port DHT_getfriendip(uint8_t * client_id)
660{ 854{
661 uint32_t i, j; 855 uint32_t i, j;
856 uint64_t temp_time = unix_time();
662 IP_Port empty = {{{0}}, 0}; 857 IP_Port empty = {{{0}}, 0};
663 uint32_t temp_time = unix_time(); 858
664 for(i = 0; i < num_friends; ++i) 859 for (i = 0; i < num_friends; ++i) {
665 /* Equal */ 860 /* Equal */
666 if(memcmp(friends_list[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { 861 if (id_equal(friends_list[i].client_id, client_id)) {
667 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 862 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 && 863 if (id_equal(friends_list[i].client_list[j].client_id, client_id) && !is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT))
669 friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time)
670 return friends_list[i].client_list[j].ip_port; 864 return friends_list[i].client_list[j].ip_port;
671 865 }
672 return empty; 866 return empty;
673 } 867 }
868 }
674 empty.ip.i = 1; 869 empty.ip.i = 1;
675 return empty; 870 return empty;
676
677} 871}
678 872
679/* The timeout after which a node is discarded completely. */ 873/* Ping each client in the "friends" list every 60 seconds. Send a get nodes request
680#define Kill_NODE_TIMEOUT 300 874 * every 20 seconds to a random good node for each "friend" in our "friends" list.
681 875 */
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() 876void doDHTFriends()
691{ 877{
692 uint32_t i, j; 878 uint32_t i, j;
693 uint32_t temp_time = unix_time(); 879 uint64_t temp_time = unix_time();
694 uint32_t rand_node; 880 uint32_t rand_node;
695 uint32_t index[MAX_FRIEND_CLIENTS]; 881 uint32_t index[MAX_FRIEND_CLIENTS];
696 882
697 for(i = 0; i < num_friends; ++i) { 883 for (i = 0; i < num_friends; ++i) {
698 uint32_t num_nodes = 0; 884 uint32_t num_nodes = 0;
699 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 885 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. */ 886 /* if node is not dead. */
701 if((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 887 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
702 pingreq(friends_list[i].client_list[j].ip_port, friends_list[i].client_list[j].client_id); 888 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
889 pingreq( friends_list[i].client_list[j].ip_port,
890 friends_list[i].client_list[j].client_id );
703 friends_list[i].client_list[j].last_pinged = temp_time; 891 friends_list[i].client_list[j].last_pinged = temp_time;
704 } 892 }
705 if(friends_list[i].client_list[j].timestamp + BAD_NODE_TIMEOUT > temp_time) { /* if node is good. */ 893 /* if node is good. */
894 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
706 index[num_nodes] = j; 895 index[num_nodes] = j;
707 ++num_nodes; 896 ++num_nodes;
708 } 897 }
709 } 898 }
899 }
710 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 900 if(friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
711 rand_node = rand() % num_nodes; 901 rand_node = rand() % num_nodes;
712 getnodes(friends_list[i].client_list[index[rand_node]].ip_port, 902 getnodes( friends_list[i].client_list[index[rand_node]].ip_port,
713 friends_list[i].client_list[index[rand_node]].client_id, 903 friends_list[i].client_list[index[rand_node]].client_id,
714 friends_list[i].client_id); 904 friends_list[i].client_id );
715 friends_list[i].lastgetnode = temp_time; 905 friends_list[i].lastgetnode = temp_time;
716 } 906 }
717 } 907 }
718} 908}
719 909
720static uint32_t close_lastgetnodes; 910static uint64_t close_lastgetnodes;
721 911
722/* Ping each client in the close nodes list every 60 seconds. 912/* 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. */ 913 * Send a get nodes request every 20 seconds to a random good node in the list.
724void doClose() /* tested */ 914 */
915void doClose()
725{ 916{
726 uint32_t i; 917 uint32_t i;
727 uint32_t temp_time = unix_time(); 918 uint64_t temp_time = unix_time();
728 uint32_t num_nodes = 0; 919 uint32_t num_nodes = 0;
729 uint32_t rand_node; 920 uint32_t rand_node;
730 uint32_t index[LCLIENT_LIST]; 921 uint32_t index[LCLIENT_LIST];
731 922
732 for(i = 0; i < LCLIENT_LIST; ++i) 923 for (i = 0; i < LCLIENT_LIST; ++i) {
733 /* if node is not dead. */ 924 /* if node is not dead. */
734 if(close_clientlist[i].timestamp + Kill_NODE_TIMEOUT > temp_time) { 925 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
735 if((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 926 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
736 pingreq(close_clientlist[i].ip_port, close_clientlist[i].client_id); 927 pingreq( close_clientlist[i].ip_port,
928 close_clientlist[i].client_id );
737 close_clientlist[i].last_pinged = temp_time; 929 close_clientlist[i].last_pinged = temp_time;
738 } 930 }
739 /* if node is good. */ 931 /* if node is good. */
740 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) { 932 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
741 index[num_nodes] = i; 933 index[num_nodes] = i;
742 ++num_nodes; 934 ++num_nodes;
743 } 935 }
744 } 936 }
937 }
745 938
746 if(close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 939 if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
747 rand_node = rand() % num_nodes; 940 rand_node = rand() % num_nodes;
748 getnodes(close_clientlist[index[rand_node]].ip_port, 941 getnodes( close_clientlist[index[rand_node]].ip_port,
749 close_clientlist[index[rand_node]].client_id, 942 close_clientlist[index[rand_node]].client_id,
750 self_public_key); 943 self_public_key );
751 close_lastgetnodes = temp_time; 944 close_lastgetnodes = temp_time;
752 } 945 }
753} 946}
@@ -758,123 +951,155 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t * public_key)
758} 951}
759 952
760/* send the given packet to node with client_id 953/* send the given packet to node with client_id
761 returns -1 if failure */ 954 * returns -1 if failure
955 */
762int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) 956int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length)
763{ 957{
764 uint32_t i; 958 uint32_t i;
765 for(i = 0; i < LCLIENT_LIST; ++i) 959
766 if(memcmp(client_id, close_clientlist[i].client_id, CLIENT_ID_SIZE) == 0) 960 for (i = 0; i < LCLIENT_LIST; ++i) {
961 if (id_equal(client_id, close_clientlist[i].client_id))
767 return sendpacket(close_clientlist[i].ip_port, packet, length); 962 return sendpacket(close_clientlist[i].ip_port, packet, length);
963 }
964
768 return -1; 965 return -1;
769} 966}
770 967
771/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist 968/* 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 969 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
773 returns the number of ips returned 970 * returns the number of ips returned
774 return 0 if we are connected to friend or if no ips were found. 971 * return 0 if we are connected to friend or if no ips were found.
775 returns -1 if no such friend*/ 972 * returns -1 if no such friend
973 */
776static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) 974static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num)
777{ 975{
778 int num_ips = 0; 976 int num_ips = 0;
779 uint32_t i; 977 uint32_t i;
780 uint32_t temp_time = unix_time(); 978 uint64_t temp_time = unix_time();
781 if(friend_num >= num_friends) 979
980 if (friend_num >= num_friends)
782 return -1; 981 return -1;
783 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 982
983 Friend * friend = &friends_list[friend_num];
984 Client_data * client;
985
986 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
987 client = &friend->client_list[i];
988
784 /*If ip is not zero and node is good */ 989 /*If ip is not zero and node is good */
785 if(friends_list[friend_num].client_list[i].ret_ip_port.ip.i != 0 && 990 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
786 friends_list[friend_num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 991
787 if(memcmp(friends_list[friend_num].client_list[i].client_id, friends_list[friend_num].client_id, CLIENT_ID_SIZE) == 0 ) 992 if (id_equal(client->client_id, friend->client_id))
788 return 0; 993 return 0;
789 ip_portlist[num_ips] = friends_list[friend_num].client_list[i].ret_ip_port; 994
995 ip_portlist[num_ips] = client->ret_ip_port;
790 ++num_ips; 996 ++num_ips;
791 } 997 }
998 }
792 return num_ips; 999 return num_ips;
793} 1000}
794 1001
795/* Send the following packet to everyone who tells us they are connected to friend_id 1002/* 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 */ 1003 * returns the number of nodes it sent the packet to
1004 */
797int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 1005int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
798{ 1006{
799 uint32_t i, j; 1007 int num = friend_number(friend_id);
800 uint32_t sent = 0; 1008 if (num == -1)
801 uint32_t temp_time = unix_time(); 1009 return 0;
802 for(i = 0; i < num_friends; ++i) 1010
803 /* Equal */ 1011 uint32_t i, sent = 0;
804 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) { 1012 uint64_t temp_time = unix_time();
805 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 1013 Friend * friend = &friends_list[num];
806 /*If ip is not zero and node is good */ 1014 Client_data * client;
807 if(friends_list[i].client_list[j].ret_ip_port.ip.i != 0 && 1015
808 friends_list[i].client_list[j].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) 1016 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
809 if(sendpacket(friends_list[i].client_list[j].ip_port, packet, length) == length) 1017 client = &friend->client_list[i];
810 ++sent; 1018
811 return sent; 1019 /*If ip is not zero and node is good */
1020 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
1021
1022 if (sendpacket(client->ip_port, packet, length) == length)
1023 ++sent;
812 } 1024 }
813 return 0; 1025 }
1026 return sent;
814} 1027}
815 1028
816/* Send the following packet to one random person who tells us they are connected to friend_id 1029/* 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 */ 1030* returns the number of nodes it sent the packet to
1031*/
818int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) 1032int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length)
819{ 1033{
820 int num = friend_number(friend_id); 1034 int num = friend_number(friend_id);
821 if(num == -1) 1035 if (num == -1)
822 return 0; 1036 return 0;
823 1037
1038 Friend * friend = &friends_list[num];
1039 Client_data * client;
1040
824 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1041 IP_Port ip_list[MAX_FRIEND_CLIENTS];
825 int n = 0; 1042 int n = 0;
826 uint32_t i; 1043 uint32_t i;
827 uint32_t temp_time = unix_time(); 1044 uint64_t temp_time = unix_time();
828 for(i = 0; i < MAX_FRIEND_CLIENTS; ++i) 1045
1046 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1047 client = &friend->client_list[i];
1048
829 /*If ip is not zero and node is good */ 1049 /*If ip is not zero and node is good */
830 if(friends_list[num].client_list[i].ret_ip_port.ip.i != 0 && 1050 if(client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
831 friends_list[num].client_list[i].ret_timestamp + BAD_NODE_TIMEOUT > temp_time) { 1051 ip_list[n] = client->ip_port;
832 ip_list[n] = friends_list[num].client_list[i].ip_port;
833 ++n; 1052 ++n;
834 } 1053 }
835 if(n < 1) 1054 }
1055 if (n < 1)
836 return 0; 1056 return 0;
837 if(sendpacket(ip_list[rand() % n], packet, length) == length) 1057 if (sendpacket(ip_list[rand() % n], packet, length) == length)
838 return 1; 1058 return 1;
839 return 0; 1059 return 0;
840} 1060}
841 1061
842/* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist 1062/* 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 1063 * ip_portlist must be at least MAX_FRIEND_CLIENTS big
844 returns the number of ips returned 1064 * returns the number of ips returned
845 return 0 if we are connected to friend or if no ips were found. 1065 * return 0 if we are connected to friend or if no ips were found.
846 returns -1 if no such friend*/ 1066 * returns -1 if no such friend
1067 */
847int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) 1068int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id)
848{ 1069{
849
850 uint32_t i; 1070 uint32_t i;
851 for(i = 0; i < num_friends; ++i) 1071 for (i = 0; i < num_friends; ++i) {
852 /* Equal */ 1072 /* Equal */
853 if(memcmp(friends_list[i].client_id, friend_id, CLIENT_ID_SIZE) == 0) 1073 if (id_equal(friends_list[i].client_id, friend_id))
854 return friend_iplist(ip_portlist, i); 1074 return friend_iplist(ip_portlist, i);
1075 }
855 return -1; 1076 return -1;
856} 1077}
857 1078
858/*BEGINNING OF NAT PUNCHING FUNCTIONS*/ 1079/*----------------------------------------------------------------------------------*/
1080/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
859 1081
860int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) 1082int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
861{ 1083{
862 uint8_t data[sizeof(uint64_t) + 1]; 1084 uint8_t data[sizeof(uint64_t) + 1];
1085 uint8_t packet[MAX_DATA_SIZE];
1086
1087 int num = 0;
1088
863 data[0] = type; 1089 data[0] = type;
864 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 1090 memcpy(data + 1, &ping_id, sizeof(uint64_t));
1091 /* 254 is NAT ping request packet id */
1092 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254);
865 1093
866 uint8_t packet[MAX_DATA_SIZE]; 1094 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; 1095 return -1;
870 1096
871 int num = 0; 1097 if (type == 0) /*If packet is request use many people to route it*/
1098 num = route_tofriend(public_key, packet, len);
1099 else if (type == 1) /*If packet is response use only one person to route it*/
1100 num = routeone_tofriend(public_key, packet, len);
872 1101
873 if(type == 0) 1102 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; 1103 return -1;
879 return num; 1104 return num;
880} 1105}
@@ -882,45 +1107,54 @@ int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
882/* Handle a recieved ping request for */ 1107/* Handle a recieved ping request for */
883int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) 1108int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
884{ 1109{
885 if(length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 1110 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING
886 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 1111 && length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
887 return 1; 1112 return 1;
1113
888 /* check if request is for us. */ 1114 /* check if request is for us. */
889 if(memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 1115 if (id_equal(packet + 1, self_public_key)) {
890 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 1116 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
891 uint8_t data[MAX_DATA_SIZE]; 1117 uint8_t data[MAX_DATA_SIZE];
1118
892 int len = handle_request(public_key, data, packet, length); 1119 int len = handle_request(public_key, data, packet, length);
893 if(len != sizeof(uint64_t) + 1) 1120 if (len != sizeof(uint64_t) + 1)
894 return 1; 1121 return 1;
1122
895 uint64_t ping_id; 1123 uint64_t ping_id;
896 memcpy(&ping_id, data + 1, sizeof(uint64_t)); 1124 memcpy(&ping_id, data + 1, sizeof(uint64_t));
897 1125
898 int friendnumber = friend_number(public_key); 1126 int friendnumber = friend_number(public_key);
899 if(friendnumber == -1) 1127 if (friendnumber == -1)
900 return 1; 1128 return 1;
901 1129
902 if(data[0] == 0) { 1130 Friend * friend = &friends_list[friendnumber];
903 send_NATping(public_key, ping_id, 1); /*1 is reply*/ 1131
904 friends_list[friendnumber].recvNATping_timestamp = unix_time(); 1132 if (data[0] == 0) {
1133 /* 1 is reply */
1134 send_NATping(public_key, ping_id, 1);
1135 friend->recvNATping_timestamp = unix_time();
905 return 0; 1136 return 0;
906 } else if (data[0] == 1) 1137 } else if (data[0] == 1) {
907 if(friends_list[friendnumber].NATping_id == ping_id) { 1138 if (friend->NATping_id == ping_id) {
908 friends_list[friendnumber].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 1139 friend->NATping_id = ((uint64_t)random_int() << 32) + random_int();
909 friends_list[friendnumber].hole_punching = 1; 1140 friend->hole_punching = 1;
910 return 0; 1141 return 0;
911 } 1142 }
1143 }
912 return 1; 1144 return 1;
913 } 1145 }
1146
914 /* if request is not for us, try routing it. */ 1147 /* if request is not for us, try routing it. */
915 else if(route_packet(packet + 1, packet, length) == length) 1148 route_packet(packet + 1, packet, length);
916 return 0; 1149
917 return 0; 1150 return 0;
918} 1151}
919 1152
920/*Get the most common ip in the ip_portlist 1153/* Get the most common ip in the ip_portlist
921 Only return ip if it appears in list min_num or more 1154 * Only return ip if it appears in list min_num or more
922 len must not be bigger than MAX_FRIEND_CLIENTS 1155 * len must not be bigger than MAX_FRIEND_CLIENTS
923 return ip of 0 if failure */ 1156 * return ip of 0 if failure
1157 */
924static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) 1158static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
925{ 1159{
926 IP zero = {{0}}; 1160 IP zero = {{0}};
@@ -929,40 +1163,45 @@ static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num)
929 1163
930 uint32_t i, j; 1164 uint32_t i, j;
931 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0}; 1165 uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
1166
932 for(i = 0; i < len; ++i) { 1167 for(i = 0; i < len; ++i) {
933 for(j = 0; j < len; ++j) 1168 for(j = 0; j < len; ++j) {
934 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i) 1169 if(ip_portlist[i].ip.i == ip_portlist[j].ip.i)
935 ++numbers[i]; 1170 ++numbers[i];
1171 }
936 if(numbers[i] >= min_num) 1172 if(numbers[i] >= min_num)
937 return ip_portlist[i].ip; 1173 return ip_portlist[i].ip;
938 } 1174 }
939 return zero; 1175 return zero;
940} 1176}
941 1177
942/*Return all the ports for one ip in a list 1178/* Return all the ports for one ip in a list
943 portlist must be at least len long 1179 * portlist must be at least len long
944 where len is the length of ip_portlist 1180 * where len is the length of ip_portlist
945 returns the number of ports and puts the list of ports in portlist*/ 1181 * returns the number of ports and puts the list of ports in portlist
1182 */
946static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) 1183static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip)
947{ 1184{
948 uint32_t i; 1185 uint32_t i;
949 uint16_t num = 0; 1186 uint16_t num = 0;
950 for(i = 0; i < len; ++i) 1187
1188 for(i = 0; i < len; ++i) {
951 if(ip_portlist[i].ip.i == ip.i) { 1189 if(ip_portlist[i].ip.i == ip.i) {
952 portlist[num] = ntohs(ip_portlist[i].port); 1190 portlist[num] = ntohs(ip_portlist[i].port);
953 ++num; 1191 ++num;
954 } 1192 }
1193 }
955 return num; 1194 return num;
956} 1195}
957 1196
958#define MAX_PUNCHING_PORTS 32
959
960static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) 1197static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num)
961{ 1198{
962 if(numports > MAX_FRIEND_CLIENTS || numports == 0) 1199 if(numports > MAX_FRIEND_CLIENTS || numports == 0)
963 return; 1200 return;
1201
964 uint32_t i; 1202 uint32_t i;
965 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1203 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
1204
966 for(i = friends_list[friend_num].punching_index; i != top; i++) { 1205 for(i = friends_list[friend_num].punching_index; i != top; i++) {
967 /*TODO: improve port guessing algorithm*/ 1206 /*TODO: improve port guessing algorithm*/
968 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); 1207 uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1);
@@ -972,30 +1211,29 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t
972 friends_list[friend_num].punching_index = i; 1211 friends_list[friend_num].punching_index = i;
973} 1212}
974 1213
975/*Interval in seconds between punching attempts*/
976#define PUNCH_INTERVAL 10
977
978static void doNAT() 1214static void doNAT()
979{ 1215{
980 uint32_t i; 1216 uint32_t i;
981 uint32_t temp_time = unix_time(); 1217 uint64_t temp_time = unix_time();
982 for(i = 0; i < num_friends; ++i) { 1218
1219 for (i = 0; i < num_friends; ++i) {
983 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1220 IP_Port ip_list[MAX_FRIEND_CLIENTS];
984 int num = friend_iplist(ip_list, i); 1221 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 1222
1223 /*If already connected or friend is not online don't try to hole punch*/
1224 if (num < MAX_FRIEND_CLIENTS/2)
1225 continue;
989 1226
990 if(friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1227 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*/ 1228 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/
992 friends_list[i].NATping_timestamp = temp_time; 1229 friends_list[i].NATping_timestamp = temp_time;
993 } 1230 }
994 if(friends_list[i].hole_punching == 1 && 1231 if (friends_list[i].hole_punching == 1 &&
995 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1232 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
996 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) { 1233 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL*2 >= temp_time) {
1234
997 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2); 1235 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS/2);
998 if(ip.i == 0) 1236 if (ip.i == 0)
999 continue; 1237 continue;
1000 1238
1001 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1239 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1008,7 +1246,8 @@ static void doNAT()
1008 } 1246 }
1009} 1247}
1010 1248
1011/*END OF NAT PUNCHING FUNCTIONS*/ 1249/*----------------------------------------------------------------------------------*/
1250/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
1012 1251
1013int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) 1252int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
1014{ 1253{
@@ -1057,17 +1296,22 @@ void DHT_save(uint8_t * data)
1057} 1296}
1058 1297
1059/* load the DHT from data of size size; 1298/* load the DHT from data of size size;
1060 return -1 if failure 1299 * return -1 if failure
1061 return 0 if success */ 1300 * return 0 if success
1301 */
1062int DHT_load(uint8_t * data, uint32_t size) 1302int DHT_load(uint8_t * data, uint32_t size)
1063{ 1303{
1064 if(size < sizeof(close_clientlist)) 1304 if(size < sizeof(close_clientlist))
1065 return -1; 1305 return -1;
1306
1066 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) 1307 if((size - sizeof(close_clientlist)) % sizeof(Friend) != 0)
1067 return -1; 1308 return -1;
1309
1068 uint32_t i, j; 1310 uint32_t i, j;
1069 /* uint32_t temp_time = unix_time(); */
1070 uint16_t temp; 1311 uint16_t temp;
1312 /* uint64_t temp_time = unix_time(); */
1313
1314 Client_data * client;
1071 1315
1072 temp = (size - sizeof(close_clientlist))/sizeof(Friend); 1316 temp = (size - sizeof(close_clientlist))/sizeof(Friend);
1073 1317
@@ -1076,29 +1320,35 @@ int DHT_load(uint8_t * data, uint32_t size)
1076 1320
1077 for(i = 0; i < temp; ++i) { 1321 for(i = 0; i < temp; ++i) {
1078 DHT_addfriend(tempfriends_list[i].client_id); 1322 DHT_addfriend(tempfriends_list[i].client_id);
1079 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) 1323
1080 if(tempfriends_list[i].client_list[j].timestamp != 0) { 1324 for(j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1081 getnodes(tempfriends_list[i].client_list[j].ip_port, 1325 client = &tempfriends_list[i].client_list[j];
1082 tempfriends_list[i].client_list[j].client_id, tempfriends_list[i].client_id); 1326 if(client->timestamp != 0)
1083 } 1327 getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id);
1328 }
1084 } 1329 }
1085 } 1330 }
1086 Client_data * tempclose_clientlist = (Client_data *)data; 1331 Client_data * tempclose_clientlist = (Client_data *)data;
1087 1332
1088 for(i = 0; i < LCLIENT_LIST; ++i) 1333 for(i = 0; i < LCLIENT_LIST; ++i) {
1089 if(tempclose_clientlist[i].timestamp != 0) 1334 if(tempclose_clientlist[i].timestamp != 0)
1090 DHT_bootstrap(tempclose_clientlist[i].ip_port, tempclose_clientlist[i].client_id); 1335 DHT_bootstrap( tempclose_clientlist[i].ip_port,
1336 tempclose_clientlist[i].client_id );
1337 }
1091 return 0; 1338 return 0;
1092} 1339}
1093 1340
1094/* returns 0 if we are not connected to the DHT 1341/* returns 0 if we are not connected to the DHT
1095 returns 1 if we are */ 1342 * returns 1 if we are
1343 */
1096int DHT_isconnected() 1344int DHT_isconnected()
1097{ 1345{
1098 uint32_t i; 1346 uint32_t i;
1099 uint32_t temp_time = unix_time(); 1347 uint64_t temp_time = unix_time();
1100 for(i = 0; i < LCLIENT_LIST; ++i) 1348
1101 if(close_clientlist[i].timestamp + BAD_NODE_TIMEOUT > temp_time) 1349 for(i = 0; i < LCLIENT_LIST; ++i) {
1350 if(!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT))
1102 return 1; 1351 return 1;
1352 }
1103 return 0; 1353 return 0;
1104} 1354}
diff --git a/core/DHT.h b/core/DHT.h
index dbb640a5..ffa02087 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -31,7 +31,7 @@ extern "C" {
31#endif 31#endif
32 32
33/* Current time, unix format */ 33/* Current time, unix format */
34#define unix_time() ((uint32_t)time(NULL)) 34#define unix_time() ((uint64_t)time(NULL))
35 35
36/* size of the client_id in bytes */ 36/* size of the client_id in bytes */
37#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES 37#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c
index 0a23914d..72e00d32 100644
--- a/core/LAN_discovery.c
+++ b/core/LAN_discovery.c
@@ -23,13 +23,70 @@
23 23
24#include "LAN_discovery.h" 24#include "LAN_discovery.h"
25 25
26#define MAX_INTERFACES 16
26 27
27/*Return the broadcast ip 28#ifdef __linux
28 TODO: make it return the real one, not the 255.255.255.255 one.*/ 29/* get the first working broadcast address that's not from "lo"
30 * returns higher than 0 on success
31 * returns 0 on error */
32uint32_t get_broadcast(void)
33{
34 /* not sure how many platforms this will
35 * run on, so it's wrapped in __linux for now */
36 struct sockaddr_in *sock_holder = NULL;
37 struct ifreq i_faces[MAX_INTERFACES];
38 struct ifconf ifconf;
39 int count = 0;
40 int sock = 0;
41 int i = 0;
42
43 /* configure ifconf for the ioctl call */
44 if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
45 perror("[!] get_broadcast: socket() error");
46 return 0;
47 }
48
49 memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
50
51 ifconf.ifc_buf = (char *)i_faces;
52 ifconf.ifc_len = sizeof(i_faces);
53 count = ifconf.ifc_len / sizeof(struct ifreq);
54 if(ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
55 perror("get_broadcast: ioctl() error");
56 return 0;
57 }
58
59 for(i = 0; i < count; i++) {
60 /* skip the loopback interface, as it's useless */
61 if(strcmp(i_faces[i].ifr_name, "lo") != 0) {
62 if(ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
63 perror("[!] get_broadcast: ioctl error");
64 return 0;
65 }
66
67 /* just to clarify where we're getting the values from */
68 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
69 break;
70 }
71 }
72 close(sock);
73
74 return sock_holder->sin_addr.s_addr;
75}
76#endif
77
78/* Return the broadcast ip */
29IP broadcast_ip() 79IP broadcast_ip()
30{ 80{
31 IP ip; 81 IP ip;
82 #ifdef __linux
83 ip.i = get_broadcast();
84 if(ip.i == 0)
85 /* error errored, but try anyway? */
86 ip.i = ~0;
87 #else
32 ip.i = ~0; 88 ip.i = ~0;
89 #endif
33 return ip; 90 return ip;
34} 91}
35 92
diff --git a/core/LAN_discovery.h b/core/LAN_discovery.h
index 4ca65c03..96a6e6ad 100644
--- a/core/LAN_discovery.h
+++ b/core/LAN_discovery.h
@@ -28,6 +28,13 @@
28 28
29#include "DHT.h" 29#include "DHT.h"
30 30
31/* used for get_broadcast() */
32#ifdef __linux
33#include <sys/ioctl.h>
34#include <arpa/inet.h>
35#include <linux/netdevice.h>
36#endif
37
31#ifdef __cplusplus 38#ifdef __cplusplus
32extern "C" { 39extern "C" {
33#endif 40#endif
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index 6be8328f..33b8eb19 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -21,67 +21,95 @@
21 * 21 *
22 */ 22 */
23 23
24/* TODO: clean this file a bit. 24/*
25 There are a couple of useless variables to get rid of. */ 25 * TODO: clean this file a bit.
26 * There are a couple of useless variables to get rid of.
27 */
28
26#include "Lossless_UDP.h" 29#include "Lossless_UDP.h"
27 30
28/* maximum data packets in sent and receive queues. */ 31/* maximum data packets in sent and receive queues. */
29#define MAX_QUEUE_NUM 16 32#define MAX_QUEUE_NUM 16
30
31/* maximum length of the data in the data packets */
32/* #define MAX_DATA_SIZE 1024 */ /* defined in Lossless_UDP.h */
33 33
34/* maximum number of data packets in the buffer */ 34/* maximum number of data packets in the buffer */
35#define BUFFER_PACKET_NUM (16-1) 35#define BUFFER_PACKET_NUM (16-1)
36 36
37/* Lossless UDP connection timeout. 37/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
38timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
39#define CONNEXION_TIMEOUT 5 38#define CONNEXION_TIMEOUT 5
40 39
41/* initial amount of sync/hanshake packets to send per second. */ 40/* initial amount of sync/hanshake packets to send per second. */
42#define SYNC_RATE 2 41#define SYNC_RATE 2
43 42
44/* initial send rate of data. */ 43/* initial send rate of data. */
45#define DATA_SYNC_RATE 30 44#define DATA_SYNC_RATE 30
46 45
47typedef struct { 46typedef struct {
48 uint8_t data[MAX_DATA_SIZE]; 47 uint8_t data[MAX_DATA_SIZE];
49 uint16_t size; 48 uint16_t size;
50} Data; 49} Data;
51 50
52typedef struct { 51typedef struct {
53 IP_Port ip_port; 52 IP_Port ip_port;
54 uint8_t status; /* 0 if connection is dead, 1 if attempting handshake, 53
55 2 if handshake is done (we start sending SYNC packets) 54 /*
56 3 if we are sending SYNC packets and can send data 55 * 0 if connection is dead, 1 if attempting handshake,
57 4 if the connection has timed out. */ 56 * 2 if handshake is done (we start sending SYNC packets)
58 57 * 3 if we are sending SYNC packets and can send data
59 uint8_t inbound; /* 1 or 2 if connection was initiated by someone else, 0 if not. 58 * 4 if the connection has timed out.
60 2 if incoming_connection() has not returned it yet, 1 if it has. */ 59 */
61 60 uint8_t status;
62 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */ 61
63 uint16_t data_rate; /* current data packet send rate packets per second. */ 62 /*
64 uint64_t last_SYNC; /* time at which our last SYNC packet was sent. */ 63 * 1 or 2 if connection was initiated by someone else, 0 if not.
65 uint64_t last_sent; /* time at which our last data or handshake packet was sent. */ 64 * 2 if incoming_connection() has not returned it yet, 1 if it has.
66 uint64_t last_recvSYNC; /* time at which we last received a SYNC packet from the other */ 65 */
67 uint64_t last_recvdata; /* time at which we last received a DATA packet from the other */ 66 uint8_t inbound;
68 uint64_t killat; /* time at which to kill the connection */ 67
69 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ 68 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
70 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ 69 uint16_t data_rate; /* current data packet send rate packets per second. */
71 uint32_t handshake_id1; 70
72 uint32_t handshake_id2; 71 uint64_t last_SYNC; /* time our last SYNC packet was sent. */
73 uint32_t recv_packetnum; /* number of data packets received (also used as handshake_id1) */ 72 uint64_t last_sent; /* time our last data or handshake packet was sent. */
74 uint32_t orecv_packetnum; /* number of packets received by the other peer */ 73 uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */
75 uint32_t sent_packetnum; /* number of data packets sent */ 74 uint64_t last_recvdata; /* time we last received a DATA packet from the other */
76 uint32_t osent_packetnum; /* number of packets sent by the other peer. */ 75 uint64_t killat; /* time to kill the connection */
77 uint32_t sendbuff_packetnum; /* number of latest packet written onto the sendbuffer */ 76
78 uint32_t successful_sent; /* we know all packets before that number were successfully sent */ 77 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */
79 uint32_t successful_read; /* packet number of last packet read with the read_packet function */ 78 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */
80 uint32_t req_packets[BUFFER_PACKET_NUM]; /* list of currently requested packet numbers(by the other person) */ 79
81 uint16_t num_req_paquets; /* total number of currently requested packets(by the other person) */ 80 uint32_t handshake_id1;
82 uint8_t recv_counter; 81 uint32_t handshake_id2;
83 uint8_t send_counter; 82
84 uint8_t timeout; /* connection timeout in seconds. */ 83 /* number of data packets received (also used as handshake_id1) */
84 uint32_t recv_packetnum;
85
86 /* number of packets received by the other peer */
87 uint32_t orecv_packetnum;
88
89 /* number of data packets sent */
90 uint32_t sent_packetnum;
91
92 /* number of packets sent by the other peer. */
93 uint32_t osent_packetnum;
94
95 /* number of latest packet written onto the sendbuffer */
96 uint32_t sendbuff_packetnum;
97
98 /* we know all packets before that number were successfully sent */
99 uint32_t successful_sent;
100
101 /* packet number of last packet read with the read_packet function */
102 uint32_t successful_read;
103
104 /* list of currently requested packet numbers(by the other person) */
105 uint32_t req_packets[BUFFER_PACKET_NUM];
106
107 /* total number of currently requested packets(by the other person) */
108 uint16_t num_req_paquets;
109
110 uint8_t recv_counter;
111 uint8_t send_counter;
112 uint8_t timeout; /* connection timeout in seconds. */
85} Connection; 113} Connection;
86 114
87 115
@@ -94,26 +122,33 @@ static uint32_t connections_number; /* Number of connections in connections arra
94 122
95/* Functions */ 123/* Functions */
96 124
97/* get connection id from IP_Port 125/*
98 return -1 if there are no connections like we are looking for 126 * Get connection id from IP_Port
99 return id if it found it */ 127 * Return -1 if there are no connections like we are looking for
128 * Return id if it found it
129 */
100int getconnection_id(IP_Port ip_port) 130int getconnection_id(IP_Port ip_port)
101{ 131{
102 uint32_t i; 132 uint32_t i;
103 for (i = 0; i < MAX_CONNECTIONS; ++i) { 133 for (i = 0; i < MAX_CONNECTIONS; ++i) {
104 if (connections[i].ip_port.ip.i == ip_port.ip.i && 134 if (connections[i].ip_port.ip.i == ip_port.ip.i &&
105 connections[i].ip_port.port == ip_port.port && connections[i].status > 0) 135 connections[i].ip_port.port == ip_port.port &&
136 connections[i].status > 0)
106 return i; 137 return i;
107 } 138 }
139
108 return -1; 140 return -1;
109} 141}
110 142
111/* table of random numbers used below. */ 143/* table of random numbers used below. */
112static uint32_t randtable[6][256]; 144static uint32_t randtable[6][256];
113 145
114/* generate a handshake_id which depends on the ip_port. 146/*
115 this function will always give one unique handshake_id per ip_port. 147 * Generate a handshake_id which depends on the ip_port.
116 TODO: make this better */ 148 * This function will always give one unique handshake_id per ip_port.
149 *
150 * TODO: make this better
151 */
117uint32_t handshake_id(IP_Port source) 152uint32_t handshake_id(IP_Port source)
118{ 153{
119 uint32_t id = 0, i; 154 uint32_t id = 0, i;
@@ -124,21 +159,27 @@ uint32_t handshake_id(IP_Port source)
124 } 159 }
125 if (id == 0) /* id can't be zero */ 160 if (id == 0) /* id can't be zero */
126 id = 1; 161 id = 1;
162
127 return id; 163 return id;
128} 164}
129 165
130/* change the hnshake id associated with that ip_port 166/*
131 TODO: make this better */ 167 * Change the hanshake id associated with that ip_port
168 *
169 * TODO: make this better
170 */
132void change_handshake(IP_Port source) 171void change_handshake(IP_Port source)
133{ 172{
134 uint8_t rand = random_int() % 4; 173 uint8_t rand = random_int() % 4;
135 randtable[rand][((uint8_t *)&source)[rand]] = random_int(); 174 randtable[rand][((uint8_t *)&source)[rand]] = random_int();
136} 175}
137 176
138/* initialize a new connection to ip_port 177/*
139 returns an integer corresponding to the connection id. 178 * Initialize a new connection to ip_port
140 return -1 if it could not initialize the connection. 179 * Returns an integer corresponding to the connection idt
141 if there already was an existing connection to that ip_port return its number. */ 180 * Return -1 if it could not initialize the connectiont
181 * If there already was an existing connection to that ip_port return its number.
182 */
142int new_connection(IP_Port ip_port) 183int new_connection(IP_Port ip_port)
143{ 184{
144 int connect = getconnection_id(ip_port); 185 int connect = getconnection_id(ip_port);
@@ -148,8 +189,10 @@ int new_connection(IP_Port ip_port)
148 if(connections_number == connections_length) { 189 if(connections_number == connections_length) {
149 Connection * temp; 190 Connection * temp;
150 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 191 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
192
151 if(temp == NULL) 193 if(temp == NULL)
152 return -1; 194 return -1;
195
153 memset(&temp[connections_length], 0, sizeof(Connection)); 196 memset(&temp[connections_length], 0, sizeof(Connection));
154 ++connections_length; 197 ++connections_length;
155 connections = temp; 198 connections = temp;
@@ -159,31 +202,38 @@ int new_connection(IP_Port ip_port)
159 for (i = 0; i < MAX_CONNECTIONS; ++i) { 202 for (i = 0; i < MAX_CONNECTIONS; ++i) {
160 if(connections[i].status == 0) { 203 if(connections[i].status == 0) {
161 memset(&connections[i], 0, sizeof(Connection)); 204 memset(&connections[i], 0, sizeof(Connection));
162 connections[i].ip_port = ip_port; 205 uint32_t handshake_id1 = handshake_id(ip_port);
163 connections[i].status = 1; 206
164 connections[i].inbound = 0; 207 connections[i] = (Connection) {
165 connections[i].handshake_id1 = handshake_id(ip_port); 208 .ip_port = ip_port,
166 connections[i].sent_packetnum = connections[i].handshake_id1; 209 .status = 1,
167 connections[i].sendbuff_packetnum = connections[i].handshake_id1; 210 .inbound = 0,
168 connections[i].successful_sent = connections[i].handshake_id1; 211 .handshake_id1 = handshake_id1,
169 connections[i].SYNC_rate = SYNC_RATE; 212 .sent_packetnum = handshake_id1,
170 connections[i].data_rate = DATA_SYNC_RATE; 213 .sendbuff_packetnum = handshake_id1,
171 connections[i].last_recvSYNC = current_time(); 214 .successful_sent = handshake_id1,
172 connections[i].last_sent = current_time(); 215 .SYNC_rate = SYNC_RATE,
173 connections[i].killat = ~0; 216 .data_rate = DATA_SYNC_RATE,
174 connections[i].send_counter = 0; 217 .last_recvSYNC = current_time(),
175 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 218 .last_sent = current_time(),
176 connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 219 .killat = ~0,
220 .send_counter = 0,
221 /* add randomness to timeout to prevent connections getting stuck in a loop. */
222 .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT
223 };
177 ++connections_number; 224 ++connections_number;
225
178 return i; 226 return i;
179 } 227 }
180 } 228 }
181 return -1; 229 return -1;
182} 230}
183 231
184/* initialize a new inbound connection from ip_port 232/*
185 returns an integer corresponding to the connection id. 233 * Initialize a new inbound connection from ip_port
186 return -1 if it could not initialize the connection. */ 234 * Returns an integer corresponding to the connection id.
235 * Return -1 if it could not initialize the connection.
236 */
187int new_inconnection(IP_Port ip_port) 237int new_inconnection(IP_Port ip_port)
188{ 238{
189 if (getconnection_id(ip_port) != -1) 239 if (getconnection_id(ip_port) != -1)
@@ -192,8 +242,10 @@ int new_inconnection(IP_Port ip_port)
192 if(connections_number == connections_length) { 242 if(connections_number == connections_length) {
193 Connection * temp; 243 Connection * temp;
194 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 244 temp = realloc(connections, sizeof(Connection) * (connections_length + 1));
245
195 if(temp == NULL) 246 if(temp == NULL)
196 return -1; 247 return -1;
248
197 memset(&temp[connections_length], 0, sizeof(Connection)); 249 memset(&temp[connections_length], 0, sizeof(Connection));
198 ++connections_length; 250 ++connections_length;
199 connections = temp; 251 connections = temp;
@@ -203,18 +255,24 @@ int new_inconnection(IP_Port ip_port)
203 for (i = 0; i < MAX_CONNECTIONS; ++i) { 255 for (i = 0; i < MAX_CONNECTIONS; ++i) {
204 if (connections[i].status == 0) { 256 if (connections[i].status == 0) {
205 memset(&connections[i], 0, sizeof(Connection)); 257 memset(&connections[i], 0, sizeof(Connection));
206 connections[i].ip_port = ip_port; 258 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
207 connections[i].status = 2; 259
208 connections[i].inbound = 2; 260 connections[i] = (Connection){
209 connections[i].SYNC_rate = SYNC_RATE; 261 .ip_port = ip_port,
210 connections[i].data_rate = DATA_SYNC_RATE; 262 .status = 2,
211 connections[i].last_recvSYNC = current_time(); 263 .inbound = 2,
212 connections[i].last_sent = current_time(); 264 .SYNC_rate = SYNC_RATE,
213 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 265 .data_rate = DATA_SYNC_RATE,
214 connections[i].timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 266 .last_recvSYNC = current_time(),
215 /* if this connection isn't handled within the timeout kill it. */ 267 .last_sent = current_time(),
216 connections[i].killat = current_time() + 1000000UL*connections[i].timeout; 268 .send_counter = 127,
217 connections[i].send_counter = 127; 269
270 /* add randomness to timeout to prevent connections getting stuck in a loop. */
271 .timeout = timeout,
272
273 /* if this connection isn't handled within the timeout kill it. */
274 .killat = current_time() + 1000000UL*timeout
275 };
218 ++connections_number; 276 ++connections_number;
219 return i; 277 return i;
220 } 278 }
@@ -222,8 +280,10 @@ int new_inconnection(IP_Port ip_port)
222 return -1; 280 return -1;
223} 281}
224 282
225/* returns an integer corresponding to the next connection in our incoming connection list 283/*
226 return -1 if there are no new incoming connections in the list. */ 284 * Returns an integer corresponding to the next connection in our incoming connection list.
285 * Return -1 if there are no new incoming connections in the list.
286 */
227int incoming_connection() 287int incoming_connection()
228{ 288{
229 uint32_t i; 289 uint32_t i;
@@ -233,9 +293,11 @@ int incoming_connection()
233 return i; 293 return i;
234 } 294 }
235 } 295 }
296
236 return -1; 297 return -1;
237} 298}
238/*Try to free some memory from the connections array.*/ 299
300/* Try to free some memory from the connections array. */
239static void free_connections() 301static void free_connections()
240{ 302{
241 uint32_t i; 303 uint32_t i;
@@ -245,16 +307,20 @@ static void free_connections()
245 307
246 if(connections_length == i) 308 if(connections_length == i)
247 return; 309 return;
310
248 Connection * temp; 311 Connection * temp;
249 temp = realloc(connections, sizeof(Connection) * i); 312 temp = realloc(connections, sizeof(Connection) * i);
250 if(temp == NULL && i != 0) 313 if(temp == NULL && i != 0)
251 return; 314 return;
315
252 connections = temp; 316 connections = temp;
253 connections_length = i; 317 connections_length = i;
254} 318}
255 319
256/* return -1 if it could not kill the connection. 320/*
257 return 0 if killed successfully */ 321 * Return -1 if it could not kill the connection.
322 * Return 0 if killed successfully
323 */
258int kill_connection(int connection_id) 324int kill_connection(int connection_id)
259{ 325{
260 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 326 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -269,9 +335,11 @@ int kill_connection(int connection_id)
269 return -1; 335 return -1;
270} 336}
271 337
272/* kill connection in seconds seconds. 338/*
273 return -1 if it can not kill the connection. 339 * Kill connection in seconds.
274 return 0 if it will kill it */ 340 * Return -1 if it can not kill the connection.
341 * Return 0 if it will kill it.
342 */
275int kill_connection_in(int connection_id, uint32_t seconds) 343int kill_connection_in(int connection_id, uint32_t seconds)
276{ 344{
277 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 345 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) {
@@ -283,12 +351,14 @@ int kill_connection_in(int connection_id, uint32_t seconds)
283 return -1; 351 return -1;
284} 352}
285 353
286/* check if connection is connected 354/*
287 return 0 no. 355 * Check if connection is connected:
288 return 1 if attempting handshake 356 * Return 0 no.
289 return 2 if handshake is done 357 * Return 1 if attempting handshake.
290 return 3 if fully connected 358 * Return 2 if handshake is done.
291 return 4 if timed out and waiting to be killed */ 359 * Return 3 if fully connected.
360 * Return 4 if timed out and waiting to be killed.
361 */
292int is_connected(int connection_id) 362int is_connected(int connection_id)
293{ 363{
294 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) 364 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS)
@@ -327,8 +397,10 @@ char id_packet(int connection_id)
327{ 397{
328 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 398 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS)
329 return -1; 399 return -1;
400
330 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) 401 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0)
331 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; 402 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0];
403
332 return -1; 404 return -1;
333} 405}
334 406
@@ -338,7 +410,7 @@ int read_packet(int connection_id, uint8_t * data)
338{ 410{
339 if (recvqueue(connection_id) != 0) { 411 if (recvqueue(connection_id) != 0) {
340 uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; 412 uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM;
341 uint16_t size = connections[connection_id].recvbuffer[index].size; 413 uint16_t size = connections[connection_id].recvbuffer[index].size;
342 memcpy(data, connections[connection_id].recvbuffer[index].data, size); 414 memcpy(data, connections[connection_id].recvbuffer[index].data, size);
343 ++connections[connection_id].successful_read; 415 ++connections[connection_id].successful_read;
344 connections[connection_id].recvbuffer[index].size = 0; 416 connections[connection_id].recvbuffer[index].size = 0;
@@ -347,14 +419,15 @@ int read_packet(int connection_id, uint8_t * data)
347 return 0; 419 return 0;
348} 420}
349 421
350/* return 0 if data could not be put in packet queue 422/*
351 return 1 if data was put into the queue */ 423 * Return 0 if data could not be put in packet queue
424 * Return 1 if data was put into the queue
425 */
352int write_packet(int connection_id, uint8_t * data, uint32_t length) 426int write_packet(int connection_id, uint8_t * data, uint32_t length)
353{ 427{
354 if (length > MAX_DATA_SIZE) 428 if (length > MAX_DATA_SIZE || length == 0)
355 return 0;
356 if (length == 0)
357 return 0; 429 return 0;
430
358 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { 431 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) {
359 uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; 432 uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM;
360 memcpy(connections[connection_id].sendbuffer[index].data, data, length); 433 memcpy(connections[connection_id].sendbuffer[index].data, data, length);
@@ -362,6 +435,7 @@ int write_packet(int connection_id, uint8_t * data, uint32_t length)
362 connections[connection_id].sendbuff_packetnum++; 435 connections[connection_id].sendbuff_packetnum++;
363 return 1; 436 return 1;
364 } 437 }
438
365 return 0; 439 return 0;
366} 440}
367 441
@@ -371,8 +445,11 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
371 uint32_t number = 0; 445 uint32_t number = 0;
372 uint32_t i; 446 uint32_t i;
373 uint32_t temp; 447 uint32_t temp;
374 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) /* don't request packets if the buffer is full. */ 448
449 /* don't request packets if the buffer is full. */
450 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1))
375 return 0; 451 return 0;
452
376 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) { 453 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) {
377 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 454 if(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) {
378 temp = htonl(i); 455 temp = htonl(i);
@@ -380,14 +457,19 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
380 ++number; 457 ++number;
381 } 458 }
382 } 459 }
460
383 if(number == 0) 461 if(number == 0)
384 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; 462 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum;
463
385 return number; 464 return number;
386} 465}
387 466
388/* Packet sending functions 467/*
389 One per packet type. 468 * BEGIN Packet sending functions
390 see docs/Lossless_UDP.txt for more information. */ 469 * One per packet type.
470 * see docs/Lossless_UDP.txt for more information.
471 */
472
391int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) 473int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
392{ 474{
393 uint8_t packet[1 + 4 + 4]; 475 uint8_t packet[1 + 4 + 4];
@@ -398,21 +480,22 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i
398 memcpy(packet + 1, &temp, 4); 480 memcpy(packet + 1, &temp, 4);
399 temp = htonl(handshake_id2); 481 temp = htonl(handshake_id2);
400 memcpy(packet + 5, &temp, 4); 482 memcpy(packet + 5, &temp, 4);
483
401 return sendpacket(ip_port, packet, sizeof(packet)); 484 return sendpacket(ip_port, packet, sizeof(packet));
402} 485}
403 486
404int send_SYNC(uint32_t connection_id) 487int send_SYNC(uint32_t connection_id)
405{ 488{
406
407 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; 489 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)];
408 uint16_t index = 0; 490 uint16_t index = 0;
409 491
410 IP_Port ip_port = connections[connection_id].ip_port; 492 IP_Port ip_port = connections[connection_id].ip_port;
411 uint8_t counter = connections[connection_id].send_counter; 493 uint8_t counter = connections[connection_id].send_counter;
412 uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); 494 uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum);
413 uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); 495 uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum);
496
414 uint32_t requested[BUFFER_PACKET_NUM]; 497 uint32_t requested[BUFFER_PACKET_NUM];
415 uint32_t number = missing_packets(connection_id, requested); 498 uint32_t number = missing_packets(connection_id, requested);
416 499
417 packet[0] = 17; 500 packet[0] = 17;
418 index += 1; 501 index += 1;
@@ -462,17 +545,24 @@ int send_DATA(uint32_t connection_id)
462 return 0; 545 return 0;
463} 546}
464 547
465/* END of packet sending functions */ 548/*
549 * END of packet sending functions
550 *
551 *
552 * BEGIN Packet handling functions
553 * One to handle each type of packets we receive
554 */
555
466 556
467/* Packet handling functions 557/* Return 0 if handled correctly, 1 if packet is bad. */
468 One to handle each type of packets we receive
469 return 0 if handled correctly, 1 if packet is bad. */
470int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) 558int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
471{ 559{
472 if (length != (1 + 4 + 4)) 560 if (length != (1 + 4 + 4))
473 return 1; 561 return 1;
562
474 uint32_t temp; 563 uint32_t temp;
475 uint32_t handshake_id1, handshake_id2; 564 uint32_t handshake_id1, handshake_id2;
565
476 int connection = getconnection_id(source); 566 int connection = getconnection_id(source);
477 memcpy(&temp, packet + 1, 4); 567 memcpy(&temp, packet + 1, 4);
478 handshake_id1 = ntohl(temp); 568 handshake_id1 = ntohl(temp);
@@ -485,21 +575,22 @@ int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
485 } 575 }
486 if (is_connected(connection) != 1) 576 if (is_connected(connection) != 1)
487 return 1; 577 return 1;
488 if (handshake_id2 == connections[connection].handshake_id1) { /* if handshake_id2 is what we sent previously as handshake_id1 */ 578
579 /* if handshake_id2 is what we sent previously as handshake_id1 */
580 if (handshake_id2 == connections[connection].handshake_id1) {
489 connections[connection].status = 2; 581 connections[connection].status = 2;
490 /* NOTE: is this necessary? 582 /* NOTE: is this necessary?
491 connections[connection].handshake_id2 = handshake_id1; */ 583 connections[connection].handshake_id2 = handshake_id1; */
492 connections[connection].orecv_packetnum = handshake_id2; 584 connections[connection].orecv_packetnum = handshake_id2;
493 connections[connection].osent_packetnum = handshake_id1; 585 connections[connection].osent_packetnum = handshake_id1;
494 connections[connection].recv_packetnum = handshake_id1; 586 connections[connection].recv_packetnum = handshake_id1;
495 connections[connection].successful_read = handshake_id1; 587 connections[connection].successful_read = handshake_id1;
496 } 588 }
497 return 0;
498 589
590 return 0;
499} 591}
500 592
501/* returns 1 if sync packet is valid 593/* returns 1 if sync packet is valid 0 if not. */
502 0 if not. */
503int SYNC_valid(uint32_t length) 594int SYNC_valid(uint32_t length)
504{ 595{
505 if (length < 4 + 4 + 2) 596 if (length < 4 + 4 + 2)
@@ -510,19 +601,19 @@ int SYNC_valid(uint32_t length)
510 return 1; 601 return 1;
511} 602}
512 603
513/* case 1: */ 604/* case 1 in handle_SYNC: */
514int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) 605int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum)
515{ 606{
516 if (handshake_id(source) == recv_packetnum) { 607 if (handshake_id(source) == recv_packetnum) {
517 int x = new_inconnection(source); 608 int x = new_inconnection(source);
518 if (x != -1) { 609 if (x != -1) {
519 connections[x].orecv_packetnum = recv_packetnum; 610 connections[x].orecv_packetnum = recv_packetnum;
520 connections[x].sent_packetnum = recv_packetnum; 611 connections[x].sent_packetnum = recv_packetnum;
521 connections[x].sendbuff_packetnum = recv_packetnum; 612 connections[x].sendbuff_packetnum = recv_packetnum;
522 connections[x].successful_sent = recv_packetnum; 613 connections[x].successful_sent = recv_packetnum;
523 connections[x].osent_packetnum = sent_packetnum; 614 connections[x].osent_packetnum = sent_packetnum;
524 connections[x].recv_packetnum = sent_packetnum; 615 connections[x].recv_packetnum = sent_packetnum;
525 connections[x].successful_read = sent_packetnum; 616 connections[x].successful_read = sent_packetnum;
526 617
527 return x; 618 return x;
528 } 619 }
@@ -530,7 +621,7 @@ int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnu
530 return -1; 621 return -1;
531} 622}
532 623
533/* case 2: */ 624/* case 2 in handle_SYNC: */
534int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 625int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum)
535{ 626{
536 if (recv_packetnum == connections[connection_id].orecv_packetnum) { 627 if (recv_packetnum == connections[connection_id].orecv_packetnum) {
@@ -543,7 +634,7 @@ int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
543 } 634 }
544 return 1; 635 return 1;
545} 636}
546/* case 3: */ 637/* case 3 in handle_SYNC: */
547int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, 638int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets,
548 uint16_t number) 639 uint16_t number)
549{ 640{
@@ -553,17 +644,25 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
553 uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ 644 uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */
554 uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); 645 uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum);
555 uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); 646 uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum);
556 if (comp_1 <= BUFFER_PACKET_NUM && comp_2 <= BUFFER_PACKET_NUM && comp_counter < 10 && comp_counter != 0) { /* packet valid */ 647
648 /* packet valid */
649 if (comp_1 <= BUFFER_PACKET_NUM &&
650 comp_2 <= BUFFER_PACKET_NUM &&
651 comp_counter < 10 && comp_counter != 0) {
652
557 connections[connection_id].orecv_packetnum = recv_packetnum; 653 connections[connection_id].orecv_packetnum = recv_packetnum;
558 connections[connection_id].osent_packetnum = sent_packetnum; 654 connections[connection_id].osent_packetnum = sent_packetnum;
559 connections[connection_id].successful_sent = recv_packetnum; 655 connections[connection_id].successful_sent = recv_packetnum;
560 connections[connection_id].last_recvSYNC = current_time(); 656 connections[connection_id].last_recvSYNC = current_time();
561 connections[connection_id].recv_counter = counter; 657 connections[connection_id].recv_counter = counter;
658
562 ++connections[connection_id].send_counter; 659 ++connections[connection_id].send_counter;
660
563 for (i = 0; i < number; ++i) { 661 for (i = 0; i < number; ++i) {
564 temp = ntohl(req_packets[i]); 662 temp = ntohl(req_packets[i]);
565 memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); 663 memcpy(connections[connection_id].req_packets + i, &temp, 4 * number);
566 } 664 }
665
567 connections[connection_id].num_req_paquets = number; 666 connections[connection_id].num_req_paquets = number;
568 return 0; 667 return 0;
569 } 668 }
@@ -575,6 +674,7 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
575 674
576 if (!SYNC_valid(length)) 675 if (!SYNC_valid(length))
577 return 1; 676 return 1;
677
578 int connection = getconnection_id(source); 678 int connection = getconnection_id(source);
579 uint8_t counter; 679 uint8_t counter;
580 uint32_t temp; 680 uint32_t temp;
@@ -587,19 +687,27 @@ int handle_SYNC(uint8_t *packet, uint32_t length, IP_Port source)
587 recv_packetnum = ntohl(temp); 687 recv_packetnum = ntohl(temp);
588 memcpy(&temp,packet + 6, 4); 688 memcpy(&temp,packet + 6, 4);
589 sent_packetnum = ntohl(temp); 689 sent_packetnum = ntohl(temp);
690
590 if (number != 0) 691 if (number != 0)
591 memcpy(req_packets, packet + 10, 4 * number); 692 memcpy(req_packets, packet + 10, 4 * number);
693
592 if (connection == -1) 694 if (connection == -1)
593 return handle_SYNC1(source, recv_packetnum, sent_packetnum); 695 return handle_SYNC1(source, recv_packetnum, sent_packetnum);
696
594 if (connections[connection].status == 2) 697 if (connections[connection].status == 2)
595 return handle_SYNC2(connection, counter, recv_packetnum, sent_packetnum); 698 return handle_SYNC2(connection, counter,
699 recv_packetnum, sent_packetnum);
700
596 if (connections[connection].status == 3) 701 if (connections[connection].status == 3)
597 return handle_SYNC3(connection, counter, recv_packetnum, sent_packetnum, req_packets, number); 702 return handle_SYNC3(connection, counter, recv_packetnum,
703 sent_packetnum, req_packets, number);
598 return 0; 704 return 0;
599} 705}
600 706
601/* add a packet to the received buffer and set the recv_packetnum of the connection to its proper value. 707/*
602 return 1 if data was too big, 0 if not. */ 708 * Add a packet to the received buffer and set the recv_packetnum of the
709 * connection to its proper value. Return 1 if data was too big, 0 if not.
710 */
603int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) 711int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
604{ 712{
605 if (size > MAX_DATA_SIZE) 713 if (size > MAX_DATA_SIZE)
@@ -608,16 +716,22 @@ int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
608 uint32_t i; 716 uint32_t i;
609 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; 717 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM;
610 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; 718 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum;
719
611 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 720 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
612 if (i == data_num) { 721 if (i == data_num) {
613 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 722 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size);
723
614 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; 724 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
615 connections[connection_id].last_recvdata = current_time(); 725 connections[connection_id].last_recvdata = current_time();
616 if (sent_packet < BUFFER_PACKET_NUM) 726
727 if (sent_packet < BUFFER_PACKET_NUM) {
617 connections[connection_id].osent_packetnum = data_num; 728 connections[connection_id].osent_packetnum = data_num;
729 }
730
618 break; 731 break;
619 } 732 }
620 } 733 }
734
621 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 735 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) {
622 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) 736 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
623 connections[connection_id].recv_packetnum = i; 737 connections[connection_id].recv_packetnum = i;
@@ -635,25 +749,30 @@ int handle_data(uint8_t *packet, uint32_t length, IP_Port source)
635 if (connection == -1) 749 if (connection == -1)
636 return 1; 750 return 1;
637 751
638 if (connections[connection].status != 3) /* Drop the data packet if connection is not connected. */ 752 /* Drop the data packet if connection is not connected. */
753 if (connections[connection].status != 3)
639 return 1; 754 return 1;
640 755
641 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) 756 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
642 return 1; 757 return 1;
758
643 uint32_t temp; 759 uint32_t temp;
644 uint32_t number; 760 uint32_t number;
645 uint16_t size = length - 1 - 4; 761 uint16_t size = length - 1 - 4;
646 762
647 memcpy(&temp, packet + 1, 4); 763 memcpy(&temp, packet + 1, 4);
648 number = ntohl(temp); 764 number = ntohl(temp);
765
649 return add_recv(connection, number, packet + 5, size); 766 return add_recv(connection, number, packet + 5, size);
650} 767}
651 768
652/* END of packet handling functions */ 769/*
770 * END of packet handling functions
771 */
653 772
654int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) 773int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
655{ 774{
656 switch (packet[0]) { //TODO: check if no break statement is correct??? 775 switch (packet[0]) {
657 case 16: 776 case 16:
658 return handle_handshake(packet, length, source); 777 return handle_handshake(packet, length, source);
659 778
@@ -670,8 +789,10 @@ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source)
670 return 0; 789 return 0;
671} 790}
672 791
673/* Send handshake requests 792/*
674 handshake packets are sent at the same rate as SYNC packets */ 793 * Send handshake requests
794 * handshake packets are sent at the same rate as SYNC packets
795 */
675void doNew() 796void doNew()
676{ 797{
677 uint32_t i; 798 uint32_t i;
@@ -684,10 +805,13 @@ void doNew()
684 } 805 }
685 806
686 /* kill all timed out connections */ 807 /* kill all timed out connections */
687 if ( connections[i].status > 0 && (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && 808 if (connections[i].status > 0 &&
688 connections[i].status != 4) 809 (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time &&
689 /* kill_connection(i); */ 810 connections[i].status != 4) {
690 connections[i].status = 4; 811 connections[i].status = 4;
812 /* kill_connection(i); */
813 }
814
691 if (connections[i].status > 0 && connections[i].killat < temp_time) 815 if (connections[i].status > 0 && connections[i].killat < temp_time)
692 kill_connection(i); 816 kill_connection(i);
693 } 817 }
@@ -720,11 +844,13 @@ void doData()
720 } 844 }
721} 845}
722 846
723/* TODO: flow control.
724 automatically adjusts send rates of packets for optimal transmission. */
725
726#define MAX_SYNC_RATE 10 847#define MAX_SYNC_RATE 10
727 848
849/*
850 * Automatically adjusts send rates of packets for optimal transmission.
851 *
852 * TODO: flow control.
853 */
728void adjustRates() 854void adjustRates()
729{ 855{
730 uint32_t i; 856 uint32_t i;
@@ -744,8 +870,7 @@ void adjustRates()
744 } 870 }
745} 871}
746 872
747/* Call this function a couple times per second 873/* Call this function a couple times per second It's the main loop. */
748 It's the main loop. */
749void doLossless_UDP() 874void doLossless_UDP()
750{ 875{
751 doNew(); 876 doNew();
diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h
index 033bc480..573e1ab9 100644
--- a/core/Lossless_UDP.h
+++ b/core/Lossless_UDP.h
@@ -33,70 +33,90 @@ extern "C" {
33/* maximum length of the data in the data packets */ 33/* maximum length of the data in the data packets */
34#define MAX_DATA_SIZE 1024 34#define MAX_DATA_SIZE 1024
35 35
36/* Functions */ 36/*
37 37 * Initialize a new connection to ip_port
38/* initialize a new connection to ip_port 38 * Returns an integer corresponding to the connection id.
39 returns an integer corresponding to the connection id. 39 * Return -1 if it could not initialize the connection.
40 return -1 if it could not initialize the connection. 40 * Return number if there already was an existing connection to that ip_port.
41 if there already was an existing connection to that ip_port return its number. */ 41 */
42int new_connection(IP_Port ip_port); 42int new_connection(IP_Port ip_port);
43 43
44/* get connection id from IP_Port 44/*
45 return -1 if there are no connections like we are looking for 45 * Get connection id from IP_Port.
46 return id if it found it */ 46 * Return -1 if there are no connections like we are looking for.
47 * Return id if it found it .
48 */
47int getconnection_id(IP_Port ip_port); 49int getconnection_id(IP_Port ip_port);
48 50
49/* returns an integer corresponding to the next connection in our imcoming connection list 51/*
50 return -1 if there are no new incoming connections in the list. */ 52 * Returns an int corresponding to the next connection in our imcoming connection list
53 * Return -1 if there are no new incoming connections in the list.
54 */
51int incoming_connection(); 55int incoming_connection();
52 56
53/* return -1 if it could not kill the connection. 57/*
54 return 0 if killed successfully */ 58 * Return -1 if it could not kill the connection.
59 * Return 0 if killed successfully
60 */
55int kill_connection(int connection_id); 61int kill_connection(int connection_id);
56 62
57/* kill connection in seconds seconds. 63/*
58 return -1 if it can not kill the connection. 64 * Kill connection in seconds seconds.
59 return 0 if it will kill it */ 65 * Return -1 if it can not kill the connection.
66 * Return 0 if it will kill it
67 */
60int kill_connection_in(int connection_id, uint32_t seconds); 68int kill_connection_in(int connection_id, uint32_t seconds);
61 69
62/* returns the ip_port of the corresponding connection. 70/*
63 return 0 if there is no such connection. */ 71 * Returns the ip_port of the corresponding connection.
72 * Return 0 if there is no such connection.
73 */
64IP_Port connection_ip(int connection_id); 74IP_Port connection_ip(int connection_id);
65 75
66/* returns the id of the next packet in the queue 76/*
67 return -1 if no packet in queue */ 77 * Returns the id of the next packet in the queue
78 * Return -1 if no packet in queue
79 */
68char id_packet(int connection_id); 80char id_packet(int connection_id);
69 81
70/* return 0 if there is no received data in the buffer. 82/*
71 return length of received packet if successful */ 83 * Return 0 if there is no received data in the buffer.
84 * Return length of received packet if successful
85 */
72int read_packet(int connection_id, uint8_t *data); 86int read_packet(int connection_id, uint8_t *data);
73 87
74/* return 0 if data could not be put in packet queue 88/*
75 return 1 if data was put into the queue */ 89 * Return 0 if data could not be put in packet queue
90 * Return 1 if data was put into the queue
91 */
76int write_packet(int connection_id, uint8_t *data, uint32_t length); 92int write_packet(int connection_id, uint8_t *data, uint32_t length);
77 93
78/* returns the number of packets in the queue waiting to be successfully sent. */ 94/* Returns the number of packets in the queue waiting to be successfully sent. */
79uint32_t sendqueue(int connection_id); 95uint32_t sendqueue(int connection_id);
80 96
81/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ 97/*
98 * returns the number of packets in the queue waiting to be successfully
99 * read with read_packet(...)
100 */
82uint32_t recvqueue(int connection_id); 101uint32_t recvqueue(int connection_id);
83 102
84/* check if connection is connected 103/* Check if connection is connected:
85 return 0 no. 104 * Return 0 no.
86 return 1 if attempting handshake 105 * Return 1 if attempting handshake.
87 return 2 if handshake is done 106 * Return 2 if handshake is done.
88 return 3 if fully connected 107 * Return 3 if fully connected.
89 return 4 if timed out and wating to be killed */ 108 * Return 4 if timed out and wating to be killed.
109 */
90int is_connected(int connection_id); 110int is_connected(int connection_id);
91 111
92/* Call this function a couple times per second 112/* Call this function a couple times per second It's the main loop. */
93 It's the main loop. */
94void doLossless_UDP(); 113void doLossless_UDP();
95 114
96 115/*
97/* if we receive a Lossless_UDP packet we call this function so it can be handled. 116 * If we receive a Lossless_UDP packet, call this function so it can be handled.
98 return 0 if packet is handled correctly. 117 * Return 0 if packet is handled correctly.
99 return 1 if it didn't handle the packet or if the packet was shit. */ 118 * Return 1 if it didn't handle the packet or if the packet was shit.
119 */
100int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); 120int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
101 121
102#ifdef __cplusplus 122#ifdef __cplusplus
diff --git a/core/Messenger.c b/core/Messenger.c
index eb59b81a..c768633e 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -27,7 +27,7 @@
27typedef struct { 27typedef struct {
28 uint8_t client_id[CLIENT_ID_SIZE]; 28 uint8_t client_id[CLIENT_ID_SIZE];
29 int crypt_connection_id; 29 int crypt_connection_id;
30 int friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */ 30 uint64_t friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */
31 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */ 31 uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
32 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */ 32 uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
33 uint8_t name[MAX_NAME_LENGTH]; 33 uint8_t name[MAX_NAME_LENGTH];
@@ -71,12 +71,6 @@ int getfriend_id(uint8_t *client_id)
71 return -1; 71 return -1;
72} 72}
73 73
74/* Returns number of friends */
75int getnumfriends()
76{
77 return numfriends;
78}
79
80/* copies the public key associated to that friend id into client_id buffer. 74/* copies the public key associated to that friend id into client_id buffer.
81 make sure that client_id is of size CLIENT_ID_SIZE. 75 make sure that client_id is of size CLIENT_ID_SIZE.
82 return 0 if success 76 return 0 if success
@@ -94,29 +88,36 @@ int getclient_id(int friend_id, uint8_t *client_id)
94 return -1; 88 return -1;
95} 89}
96 90
97/* add a friend 91/*
98 set the data that will be sent along with friend request 92 * add a friend
99 client_id is the client id of the friend 93 * set the data that will be sent along with friend request
100 data is the data and length is the length 94 * client_id is the client id of the friend
101 returns the friend number if success 95 * data is the data and length is the length
102 return -1 if key length is wrong. 96 * returns the friend number if success
103 return -2 if user's own key 97 * return FA_TOOLONG if message length is too long
104 return -3 if already a friend 98 * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
105 return -4 for other*/ 99 * return FAERR_OWNKEY if user's own key
100 * return FAERR_ALREADYSENT if friend request already sent or already a friend
101 * return FAERR_UNKNOWN for unknown error
102 */
106int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) 103int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
107{ 104{
108 if (length == 0 || length >= 105 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
109 (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) 106 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
110 return -1; 107 + crypto_box_ZEROBYTES))
108 return FAERR_TOOLONG;
109 if (length < 1)
110 return FAERR_NOMESSAGE;
111 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) 111 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
112 return -2; 112 return FAERR_OWNKEY;
113 if (getfriend_id(client_id) != -1) 113 if (getfriend_id(client_id) != -1)
114 return -3; 114 return FAERR_ALREADYSENT;
115
115 uint32_t i; 116 uint32_t i;
116 for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ 117 for (i = 0; i <= numfriends; ++i) { /*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
117 if(friendlist[i].status == 0) { 118 if(friendlist[i].status == NOFRIEND) {
118 DHT_addfriend(client_id); 119 DHT_addfriend(client_id);
119 friendlist[i].status = 1; 120 friendlist[i].status = FRIEND_ADDED;
120 friendlist[i].crypt_connection_id = -1; 121 friendlist[i].crypt_connection_id = -1;
121 friendlist[i].friend_request_id = -1; 122 friendlist[i].friend_request_id = -1;
122 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 123 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
@@ -129,7 +130,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
129 return i; 130 return i;
130 } 131 }
131 } 132 }
132 return -4; 133 return FAERR_UNKNOWN;
133} 134}
134 135
135int m_addfriend_norequest(uint8_t * client_id) 136int m_addfriend_norequest(uint8_t * client_id)
@@ -138,9 +139,9 @@ int m_addfriend_norequest(uint8_t * client_id)
138 return -1; 139 return -1;
139 uint32_t i; 140 uint32_t i;
140 for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/ 141 for (i = 0; i <= numfriends; ++i) {/*TODO: dynamic memory allocation, this will segfault if there are more than MAX_NUM_FRIENDS*/
141 if(friendlist[i].status == 0) { 142 if(friendlist[i].status == NOFRIEND) {
142 DHT_addfriend(client_id); 143 DHT_addfriend(client_id);
143 friendlist[i].status = 2; 144 friendlist[i].status = FRIEND_REQUESTED;
144 friendlist[i].crypt_connection_id = -1; 145 friendlist[i].crypt_connection_id = -1;
145 friendlist[i].friend_request_id = -1; 146 friendlist[i].friend_request_id = -1;
146 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 147 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
@@ -168,7 +169,7 @@ int m_delfriend(int friendnumber)
168 uint32_t i; 169 uint32_t i;
169 170
170 for (i = numfriends; i != 0; --i) { 171 for (i = numfriends; i != 0; --i) {
171 if (friendlist[i-1].status != 0) 172 if (friendlist[i-1].status != NOFRIEND)
172 break; 173 break;
173 } 174 }
174 numfriends = i; 175 numfriends = i;
@@ -176,15 +177,15 @@ int m_delfriend(int friendnumber)
176 return 0; 177 return 0;
177} 178}
178 179
179/* return 4 if friend is online 180/* return FRIEND_ONLINE if friend is online
180 return 3 if friend is confirmed 181 return FRIEND_CONFIRMED if friend is confirmed
181 return 2 if the friend request was sent 182 return FRIEND_REQUESTED if the friend request was sent
182 return 1 if the friend was added 183 return FRIEND_ADDED if the friend was added
183 return 0 if there is no friend with that number */ 184 return NOFRIEND if there is no friend with that number */
184int m_friendstatus(int friendnumber) 185int m_friendstatus(int friendnumber)
185{ 186{
186 if (friendnumber < 0 || friendnumber >= numfriends) 187 if (friendnumber < 0 || friendnumber >= numfriends)
187 return 0; 188 return NOFRIEND;
188 return friendlist[friendnumber].status; 189 return friendlist[friendnumber].status;
189} 190}
190 191
@@ -195,7 +196,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
195{ 196{
196 if (friendnumber < 0 || friendnumber >= numfriends) 197 if (friendnumber < 0 || friendnumber >= numfriends)
197 return 0; 198 return 0;
198 if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) 199 if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE)
199 /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ 200 /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
200 return 0; 201 return 0;
201 uint8_t temp[MAX_DATA_SIZE]; 202 uint8_t temp[MAX_DATA_SIZE];
@@ -384,15 +385,15 @@ static void doFriends()
384 int len; 385 int len;
385 uint8_t temp[MAX_DATA_SIZE]; 386 uint8_t temp[MAX_DATA_SIZE];
386 for (i = 0; i < numfriends; ++i) { 387 for (i = 0; i < numfriends; ++i) {
387 if (friendlist[i].status == 1) { 388 if (friendlist[i].status == FRIEND_ADDED) {
388 int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 389 int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
389 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */ 390 if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
390 friendlist[i].status = 2; 391 friendlist[i].status = FRIEND_REQUESTED;
391 else if (fr > 0) 392 else if (fr > 0)
392 friendlist[i].status = 2; 393 friendlist[i].status = FRIEND_REQUESTED;
393 } 394 }
394 if (friendlist[i].status == 2 || friendlist[i].status == 3) { /* friend is not online */ 395 if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
395 if (friendlist[i].status == 2) { 396 if (friendlist[i].status == FRIEND_REQUESTED) {
396 if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/ 397 if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
397 send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size); 398 send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
398 friendlist[i].friend_request_id = unix_time(); 399 friendlist[i].friend_request_id = unix_time();
@@ -405,7 +406,7 @@ static void doFriends()
405 friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip); 406 friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
406 break; 407 break;
407 case 3: /* Connection is established */ 408 case 3: /* Connection is established */
408 friendlist[i].status = 4; 409 friendlist[i].status = FRIEND_ONLINE;
409 break; 410 break;
410 case 4: 411 case 4:
411 crypto_kill(friendlist[i].crypt_connection_id); 412 crypto_kill(friendlist[i].crypt_connection_id);
@@ -415,7 +416,7 @@ static void doFriends()
415 break; 416 break;
416 } 417 }
417 } 418 }
418 while (friendlist[i].status == 4) { /* friend is online */ 419 while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
419 if (friendlist[i].name_sent == 0) { 420 if (friendlist[i].name_sent == 0) {
420 if (m_sendname(i, self_name, self_name_length)) 421 if (m_sendname(i, self_name, self_name_length))
421 friendlist[i].name_sent = 1; 422 friendlist[i].name_sent = 1;
@@ -455,7 +456,7 @@ static void doFriends()
455 if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ 456 if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
456 crypto_kill(friendlist[i].crypt_connection_id); 457 crypto_kill(friendlist[i].crypt_connection_id);
457 friendlist[i].crypt_connection_id = -1; 458 friendlist[i].crypt_connection_id = -1;
458 friendlist[i].status = 3; 459 friendlist[i].status = FRIEND_CONFIRMED;
459 } 460 }
460 break; 461 break;
461 } 462 }
@@ -476,7 +477,7 @@ static void doInbound()
476 friendlist[friend_id].crypt_connection_id = 477 friendlist[friend_id].crypt_connection_id =
477 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); 478 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
478 479
479 friendlist[friend_id].status = 3; 480 friendlist[friend_id].status = FRIEND_CONFIRMED;
480 } 481 }
481 } 482 }
482} 483}
@@ -484,7 +485,7 @@ static void doInbound()
484/*Interval in seconds between LAN discovery packet sending*/ 485/*Interval in seconds between LAN discovery packet sending*/
485#define LAN_DISCOVERY_INTERVAL 60 486#define LAN_DISCOVERY_INTERVAL 60
486 487
487static uint32_t last_LANdiscovery; 488static uint64_t last_LANdiscovery;
488 489
489/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ 490/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
490static void LANdiscovery() 491static void LANdiscovery()
diff --git a/core/Messenger.h b/core/Messenger.h
index 9ce96fb4..acf62a32 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -42,18 +42,36 @@ extern "C" {
42#define PACKET_ID_USERSTATUS 49 42#define PACKET_ID_USERSTATUS 49
43#define PACKET_ID_MESSAGE 64 43#define PACKET_ID_MESSAGE 64
44 44
45/* status definitions */
46#define FRIEND_ONLINE 4
47#define FRIEND_CONFIRMED 3
48#define FRIEND_REQUESTED 2
49#define FRIEND_ADDED 1
50#define NOFRIEND 0
51
52/* errors for m_addfriend
53 * FAERR - Friend Add Error */
54#define FAERR_TOOLONG -1
55#define FAERR_NOMESSAGE -2
56#define FAERR_OWNKEY -3
57#define FAERR_ALREADYSENT -4
58#define FAERR_UNKNOWN -5
59
45/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased 60/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased
46 to an absurdly large number later */ 61 to an absurdly large number later */
47 62
48/* add a friend 63/*
49 set the data that will be sent along with friend request 64 * add a friend
50 client_id is the client id of the friend 65 * set the data that will be sent along with friend request
51 data is the data and length is the length 66 * client_id is the client id of the friend
52 returns the friend number if success 67 * data is the data and length is the length
53 return -1 if key length is wrong. 68 * returns the friend number if success
54 return -2 if user's own key 69 * return -1 if message length is too long
55 return -3 if already a friend 70 * return -2 if no message (message length must be >= 1 byte)
56 return -4 for other*/ 71 * return -3 if user's own key
72 * return -4 if friend request already sent or already a friend
73 * return -5 for unknown error
74 */
57int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); 75int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length);
58 76
59 77
diff --git a/core/net_crypto.c b/core/net_crypto.c
index a437c5ee..3b5b67f4 100644
--- a/core/net_crypto.c
+++ b/core/net_crypto.c
@@ -48,6 +48,12 @@ typedef struct {
48 48
49static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; 49static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS];
50 50
51#define CONN_NO_CONNECTION 0
52#define CONN_HANDSHAKE_SENT 1
53#define CONN_NOT_CONFIRMED 2
54#define CONN_ESTABLISHED 3
55#define CONN_TIMED_OUT 4
56
51#define MAX_INCOMING 64 57#define MAX_INCOMING 64
52 58
53/* keeps track of the connection numbers for friends request so we can check later if they were sent */ 59/* keeps track of the connection numbers for friends request so we can check later if they were sent */
@@ -60,23 +66,28 @@ static int incoming_connections[MAX_INCOMING];
60int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, 66int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
61 uint8_t *plain, uint32_t length, uint8_t *encrypted) 67 uint8_t *plain, uint32_t length, uint8_t *encrypted)
62{ 68{
63 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0) 69 if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0)
64 return -1; 70 return -1;
65 71
66 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0}; 72 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
67 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; 73 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
68 uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0};
69 74
70 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ 75 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
71 76
72 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key); 77 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key);
73 78
74 /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */ 79 /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero
75 if (memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0) 80 apparently memcmp should not be used so we do this instead:*/
81 uint32_t i;
82 uint32_t check = 0;
83 for(i = 0; i < crypto_box_BOXZEROBYTES; ++i) {
84 check |= temp_encrypted[i] ^ 0;
85 }
86 if(check != 0)
76 return -1; 87 return -1;
77 88
78 /* unpad the encrypted message */ 89 /* unpad the encrypted message */
79 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); 90 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
80 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; 91 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
81} 92}
82 93
@@ -90,9 +101,8 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
90 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) 101 if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
91 return -1; 102 return -1;
92 103
93 uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES]; 104 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES];
94 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; 105 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0};
95 uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
96 106
97 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ 107 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
98 108
@@ -100,12 +110,18 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
100 nonce, public_key, secret_key) == -1) 110 nonce, public_key, secret_key) == -1)
101 return -1; 111 return -1;
102 112
103 /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */ 113 /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero
104 if (memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0) 114 apparently memcmp should not be used so we do this instead:*/
115 uint32_t i;
116 uint32_t check = 0;
117 for(i = 0; i < crypto_box_ZEROBYTES; ++i) {
118 check |= temp_plain[i] ^ 0;
119 }
120 if(check != 0)
105 return -1; 121 return -1;
106 122
107 /* unpad the plain message */ 123 /* unpad the plain message */
108 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES); 124 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
109 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; 125 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
110} 126}
111 127
@@ -137,7 +153,7 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
137{ 153{
138 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 154 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
139 return 0; 155 return 0;
140 if (crypto_connections[crypt_connection_id].status != 3) 156 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
141 return 0; 157 return 0;
142 uint8_t temp_data[MAX_DATA_SIZE]; 158 uint8_t temp_data[MAX_DATA_SIZE];
143 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); 159 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
@@ -163,7 +179,7 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
163 return 0; 179 return 0;
164 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) 180 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
165 return 0; 181 return 0;
166 if (crypto_connections[crypt_connection_id].status != 3) 182 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
167 return 0; 183 return 0;
168 uint8_t temp_data[MAX_DATA_SIZE]; 184 uint8_t temp_data[MAX_DATA_SIZE];
169 int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, 185 int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
@@ -283,7 +299,7 @@ int getcryptconnection_id(uint8_t *public_key)
283{ 299{
284 uint32_t i; 300 uint32_t i;
285 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 301 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
286 if (crypto_connections[i].status > 0) 302 if (crypto_connections[i].status != CONN_NO_CONNECTION)
287 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) 303 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
288 return i; 304 return i;
289 } 305 }
@@ -303,12 +319,12 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port)
303 return -1; 319 return -1;
304 } 320 }
305 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 321 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
306 if (crypto_connections[i].status == 0) { 322 if (crypto_connections[i].status == CONN_NO_CONNECTION) {
307 int id = new_connection(ip_port); 323 int id = new_connection(ip_port);
308 if (id == -1) 324 if (id == -1)
309 return -1; 325 return -1;
310 crypto_connections[i].number = id; 326 crypto_connections[i].number = id;
311 crypto_connections[i].status = 1; 327 crypto_connections[i].status = CONN_HANDSHAKE_SENT;
312 random_nonce(crypto_connections[i].recv_nonce); 328 random_nonce(crypto_connections[i].recv_nonce);
313 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 329 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
314 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); 330 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
@@ -362,9 +378,10 @@ int crypto_kill(int crypt_connection_id)
362{ 378{
363 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 379 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
364 return 1; 380 return 1;
365 if (crypto_connections[crypt_connection_id].status != 0) { 381 if (crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) {
366 crypto_connections[crypt_connection_id].status = 0; 382 crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION;
367 kill_connection(crypto_connections[crypt_connection_id].number); 383 kill_connection(crypto_connections[crypt_connection_id].number);
384 memset(&crypto_connections[crypt_connection_id], 0 ,sizeof(Crypto_Connection));
368 crypto_connections[crypt_connection_id].number = ~0; 385 crypto_connections[crypt_connection_id].number = ~0;
369 return 0; 386 return 0;
370 } 387 }
@@ -385,9 +402,9 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
385 return -1; 402 return -1;
386 }*/ 403 }*/
387 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 404 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
388 if(crypto_connections[i].status == 0) { 405 if(crypto_connections[i].status == CONN_NO_CONNECTION) {
389 crypto_connections[i].number = connection_id; 406 crypto_connections[i].number = connection_id;
390 crypto_connections[i].status = 2; 407 crypto_connections[i].status = CONN_NOT_CONFIRMED;
391 random_nonce(crypto_connections[i].recv_nonce); 408 random_nonce(crypto_connections[i].recv_nonce);
392 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); 409 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
393 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 410 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
@@ -400,9 +417,9 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
400 crypto_connections[i].sessionpublic_key) == 1) { 417 crypto_connections[i].sessionpublic_key) == 1) {
401 increment_nonce(crypto_connections[i].recv_nonce); 418 increment_nonce(crypto_connections[i].recv_nonce);
402 uint32_t zero = 0; 419 uint32_t zero = 0;
403 crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */ 420 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
404 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 421 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
405 crypto_connections[i].status = 2; /* set it to its proper value right after. */ 422 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
406 return i; 423 return i;
407 } 424 }
408 return -1; /* this should never happen. */ 425 return -1; /* this should never happen. */
@@ -418,7 +435,7 @@ int is_cryptoconnected(int crypt_connection_id)
418{ 435{
419 if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) 436 if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS)
420 return crypto_connections[crypt_connection_id].status; 437 return crypto_connections[crypt_connection_id].status;
421 return 0; 438 return CONN_NO_CONNECTION;
422} 439}
423 440
424/* Generate our public and private keys 441/* Generate our public and private keys
@@ -477,7 +494,7 @@ static void receive_crypto()
477{ 494{
478 uint32_t i; 495 uint32_t i;
479 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 496 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
480 if (crypto_connections[i].status == 1) { 497 if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
481 uint8_t temp_data[MAX_DATA_SIZE]; 498 uint8_t temp_data[MAX_DATA_SIZE];
482 uint8_t secret_nonce[crypto_box_NONCEBYTES]; 499 uint8_t secret_nonce[crypto_box_NONCEBYTES];
483 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 500 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
@@ -494,17 +511,17 @@ static void receive_crypto()
494 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 511 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
495 increment_nonce(crypto_connections[i].sent_nonce); 512 increment_nonce(crypto_connections[i].sent_nonce);
496 uint32_t zero = 0; 513 uint32_t zero = 0;
497 crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */ 514 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
498 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 515 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
499 crypto_connections[i].status = 2; /* set it to its proper value right after. */ 516 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
500 } 517 }
501 } 518 }
502 } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does 519 } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
503 crypto_kill(crypto_connections[i].number); 520 crypto_kill(crypto_connections[i].number);
504 521
505 } 522 }
506 if (crypto_connections[i].status == 2) { 523 if (crypto_connections[i].status == CONN_NOT_CONFIRMED) {
507 if (id_packet(crypto_connections[i].number) == 3) { 524 if (id_packet(crypto_connections[i].number) == CONN_ESTABLISHED) {
508 uint8_t temp_data[MAX_DATA_SIZE]; 525 uint8_t temp_data[MAX_DATA_SIZE];
509 uint8_t data[MAX_DATA_SIZE]; 526 uint8_t data[MAX_DATA_SIZE];
510 int length = read_packet(crypto_connections[i].number, temp_data); 527 int length = read_packet(crypto_connections[i].number, temp_data);
@@ -514,7 +531,7 @@ static void receive_crypto()
514 uint32_t zero = 0; 531 uint32_t zero = 0;
515 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { 532 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
516 increment_nonce(crypto_connections[i].recv_nonce); 533 increment_nonce(crypto_connections[i].recv_nonce);
517 crypto_connections[i].status = 3; 534 crypto_connections[i].status = CONN_ESTABLISHED;
518 535
519 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ 536 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
520 kill_connection_in(crypto_connections[i].number, 3000000); 537 kill_connection_in(crypto_connections[i].number, 3000000);
@@ -543,8 +560,8 @@ static void killTimedout()
543{ 560{
544 uint32_t i; 561 uint32_t i;
545 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 562 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
546 if (crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4) 563 if (crypto_connections[i].status != CONN_NO_CONNECTION && is_connected(crypto_connections[i].number) == 4)
547 crypto_connections[i].status = 4; 564 crypto_connections[i].status = CONN_TIMED_OUT;
548 else if (is_connected(crypto_connections[i].number) == 4) { 565 else if (is_connected(crypto_connections[i].number) == 4) {
549 kill_connection(crypto_connections[i].number); 566 kill_connection(crypto_connections[i].number);
550 crypto_connections[i].number = ~0; 567 crypto_connections[i].number = ~0;
diff --git a/core/network.c b/core/network.c
index a7a4efcd..c58549bf 100644
--- a/core/network.c
+++ b/core/network.c
@@ -164,25 +164,42 @@ void shutdown_networking()
164 return; 164 return;
165} 165}
166 166
167/* resolves provided address to a binary data in network byte order 167/*
168 address is ASCII null terminated string 168 resolve_addr():
169 address should represent IPv4, IPv6 or a hostname 169 address should represent IPv4 or a hostname with A record
170 on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i 170
171 on failure returns -1 */ 171 returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
172int resolve_addr(const char *address) 172 returns 0 on failure
173
174 TODO: Fix ipv6 support
175*/
176uint32_t resolve_addr(const char *address)
173{ 177{
174 struct addrinfo hints; 178 struct addrinfo *server = NULL;
179 struct addrinfo hints;
180 int rc;
181 uint32_t addr;
182
175 memset(&hints, 0, sizeof(hints)); 183 memset(&hints, 0, sizeof(hints));
176 hints.ai_family = AF_UNSPEC; //support both IPv4 and IPv6 184 hints.ai_family = AF_INET; // IPv4 only right now.
177 hints.ai_socktype = SOCK_DGRAM; //type of socket Tox uses 185 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
178 186
179 struct addrinfo *server = NULL; 187 rc = getaddrinfo(address, "echo", &hints, &server);
180 188
181 int success = getaddrinfo(address, "echo", &hints, &server); 189 // Lookup failed.
182 if(success != 0) 190 if(rc != 0) {
183 return -1; 191 return 0;
192 }
193
194 // IPv4 records only..
195 if(server->ai_family != AF_INET) {
196 freeaddrinfo(server);
197 return 0;
198 }
199
200
201 addr = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr;
184 202
185 int resolved = ((struct sockaddr_in*)server->ai_addr)->sin_addr.s_addr;
186 freeaddrinfo(server); 203 freeaddrinfo(server);
187 return resolved; 204 return addr;
188} 205}
diff --git a/core/network.h b/core/network.h
index 3277070c..a7559ebe 100644
--- a/core/network.h
+++ b/core/network.h
@@ -57,6 +57,7 @@
57#include <sodium.h> 57#include <sodium.h>
58#else 58#else
59#include <crypto_box.h> 59#include <crypto_box.h>
60#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
60#endif 61#endif
61 62
62#ifdef __cplusplus 63#ifdef __cplusplus
@@ -116,12 +117,16 @@ int init_networking(IP ip, uint16_t port);
116/* function to cleanup networking stuff(doesn't do much right now) */ 117/* function to cleanup networking stuff(doesn't do much right now) */
117void shutdown_networking(); 118void shutdown_networking();
118 119
119/* resolves provided address to a binary data in network byte order 120/*
120 address is ASCII null terminated string 121 resolve_addr():
121 address should represent IPv4, IPv6 or a hostname 122 address should represent IPv4 or a hostname with A record
122 on success returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i 123
123 on failure returns -1 */ 124 returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
124int resolve_addr(const char *address); 125 returns 0 on failure
126
127 TODO: Fix ipv6 support
128*/
129uint32_t resolve_addr(const char *address);
125 130
126#ifdef __cplusplus 131#ifdef __cplusplus
127} 132}