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