diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/CMakeLists.txt | 4 | ||||
-rw-r--r-- | core/DHT.c | 1004 | ||||
-rw-r--r-- | core/DHT.h | 2 | ||||
-rw-r--r-- | core/LAN_discovery.c | 61 | ||||
-rw-r--r-- | core/LAN_discovery.h | 7 | ||||
-rw-r--r-- | core/Lossless_UDP.c | 429 | ||||
-rw-r--r-- | core/Lossless_UDP.h | 96 | ||||
-rw-r--r-- | core/Messenger.c | 89 | ||||
-rw-r--r-- | core/Messenger.h | 36 | ||||
-rw-r--r-- | core/net_crypto.c | 83 | ||||
-rw-r--r-- | core/network.c | 47 | ||||
-rw-r--r-- | core/network.h | 17 |
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 @@ | |||
1 | cmake_minimum_required(VERSION 2.6.0) | 1 | cmake_minimum_required(VERSION 2.6.0) |
2 | project(core C) | 2 | project(toxcore C) |
3 | 3 | ||
4 | if(WIN32) | 4 | if(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 | ||
19 | add_library(core ${core_sources}) | 19 | add_library(toxcore SHARED ${core_sources}) |
@@ -21,102 +21,156 @@ | |||
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 | 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 | ||
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 | uint64_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 | uint64_t punching_timestamp; |
88 | uint64_t recvNATping_timestamp; | ||
89 | uint64_t NATping_id; | ||
90 | uint64_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 | uint64_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 * 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 | ||
140 | int ipport_equal(IP_Port a, IP_Port b) | ||
141 | { | ||
142 | return (a.ip.i == b.ip.i) && (a.port == b.port); | ||
143 | } | ||
144 | |||
145 | int id_equal(uint8_t* a, uint8_t* b) | ||
146 | { | ||
147 | return memcmp(a, b, CLIENT_ID_SIZE) == 0; | ||
148 | } | ||
149 | |||
150 | int 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 | */ | ||
107 | int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) | 162 | int 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 | */ | ||
133 | int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id) | 187 | int 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 | */ |
144 | static int friend_number(uint8_t * client_id) | 201 | static 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 | */ | ||
161 | int get_close_nodes(uint8_t * client_id, Node_format * nodes_list) | 218 | int 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) |
204 | int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port) /* tested */ | 303 | */ |
304 | int 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 */ |
223 | int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port, uint8_t * comp_client_id) | 328 | int 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 | */ | ||
243 | void addto_lists(IP_Port ip_port, uint8_t * client_id) | 354 | void 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 | */ | ||
262 | void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nodeclient_id) | 396 | void 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 |
291 | TODO: optimize this */ | 433 | */ |
292 | int is_pinging(IP_Port ip_port, uint64_t ping_id) | 434 | int 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 | */ | ||
344 | uint64_t add_pinging(IP_Port ip_port) | 489 | uint64_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 | */ | ||
383 | static int pingreq(IP_Port ip_port, uint8_t * public_key) | 533 | static 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) | |||
412 | static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) | 567 | static 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) | |||
435 | static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) | 596 | static 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 */ |
470 | static int sendnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id, uint64_t ping_id) | 635 | static 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 | */ |
509 | int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) | 679 | int 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 | ||
553 | int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) | 732 | int 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 | ||
580 | int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) | 764 | int 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 | ||
624 | int DHT_addfriend(uint8_t * client_id) | 809 | int 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) | |||
659 | IP_Port DHT_getfriendip(uint8_t * client_id) | 853 | IP_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. */ | ||
690 | void doDHTFriends() | 876 | void 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 | ||
720 | static uint32_t close_lastgetnodes; | 910 | static 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. |
724 | void doClose() /* tested */ | 914 | */ |
915 | void 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 | */ | ||
762 | int route_packet(uint8_t * client_id, uint8_t * packet, uint32_t length) | 956 | int 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 | */ | ||
776 | static int friend_iplist(IP_Port * ip_portlist, uint16_t friend_num) | 974 | static 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 | */ | ||
797 | int route_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) | 1005 | int 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 | */ | ||
818 | int routeone_tofriend(uint8_t * friend_id, uint8_t * packet, uint32_t length) | 1032 | int 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 | */ | ||
847 | int friend_ips(IP_Port * ip_portlist, uint8_t * friend_id) | 1068 | int 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 | ||
860 | int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type) | 1082 | int 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 */ |
883 | int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) | 1108 | int 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 | */ | ||
924 | static IP NAT_commonip(IP_Port * ip_portlist, uint16_t len, uint16_t min_num) | 1158 | static 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 | */ | ||
946 | static uint16_t NAT_getports(uint16_t * portlist, IP_Port * ip_portlist, uint16_t len, IP ip) | 1183 | static 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 | |||
960 | static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t friend_num) | 1197 | static 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 | |||
978 | static void doNAT() | 1214 | static 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 | ||
1013 | int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) | 1252 | int 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 | */ | ||
1062 | int DHT_load(uint8_t * data, uint32_t size) | 1302 | int 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 | */ | ||
1096 | int DHT_isconnected() | 1344 | int 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 | } |
@@ -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 */ | ||
32 | uint32_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 */ | ||
29 | IP broadcast_ip() | 79 | IP 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 |
32 | extern "C" { | 39 | extern "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 */ |
38 | timeout 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 | ||
47 | typedef struct { | 46 | typedef 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 | ||
52 | typedef struct { | 51 | typedef 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 | */ | ||
100 | int getconnection_id(IP_Port ip_port) | 130 | int 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. */ |
112 | static uint32_t randtable[6][256]; | 144 | static 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 | */ | ||
117 | uint32_t handshake_id(IP_Port source) | 152 | uint32_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 | */ | ||
132 | void change_handshake(IP_Port source) | 171 | void 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 | */ | ||
142 | int new_connection(IP_Port ip_port) | 183 | int 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 | */ | ||
187 | int new_inconnection(IP_Port ip_port) | 237 | int 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 | */ | ||
227 | int incoming_connection() | 287 | int 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. */ | ||
239 | static void free_connections() | 301 | static 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 | */ | ||
258 | int kill_connection(int connection_id) | 324 | int 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 | */ | ||
275 | int kill_connection_in(int connection_id, uint32_t seconds) | 343 | int 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 | */ | ||
292 | int is_connected(int connection_id) | 362 | int 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 | */ | ||
352 | int write_packet(int connection_id, uint8_t * data, uint32_t length) | 426 | int 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 | |||
391 | int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) | 473 | int 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 | ||
404 | int send_SYNC(uint32_t connection_id) | 487 | int 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. */ | ||
470 | int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source) | 558 | int 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. */ | ||
503 | int SYNC_valid(uint32_t length) | 594 | int 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: */ |
514 | int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) | 605 | int 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: */ |
534 | int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) | 625 | int 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: */ |
547 | int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, uint32_t * req_packets, | 638 | int 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 | */ | ||
603 | int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) | 711 | int 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 | ||
654 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source) | 773 | int 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 | */ | ||
675 | void doNew() | 796 | void 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 | */ | ||
728 | void adjustRates() | 854 | void 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. */ | ||
749 | void doLossless_UDP() | 874 | void 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 | */ |
42 | int new_connection(IP_Port ip_port); | 42 | int 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 | */ | ||
47 | int getconnection_id(IP_Port ip_port); | 49 | int 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 | */ | ||
51 | int incoming_connection(); | 55 | int 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 | */ | ||
55 | int kill_connection(int connection_id); | 61 | int 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 | */ | ||
60 | int kill_connection_in(int connection_id, uint32_t seconds); | 68 | int 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 | */ | ||
64 | IP_Port connection_ip(int connection_id); | 74 | IP_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 | */ | ||
68 | char id_packet(int connection_id); | 80 | char 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 | */ | ||
72 | int read_packet(int connection_id, uint8_t *data); | 86 | int 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 | */ | ||
76 | int write_packet(int connection_id, uint8_t *data, uint32_t length); | 92 | int 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. */ |
79 | uint32_t sendqueue(int connection_id); | 95 | uint32_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 | */ | ||
82 | uint32_t recvqueue(int connection_id); | 101 | uint32_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 | */ | ||
90 | int is_connected(int connection_id); | 110 | int 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. */ | ||
94 | void doLossless_UDP(); | 113 | void 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 | */ | ||
100 | int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source); | 120 | int 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 @@ | |||
27 | typedef struct { | 27 | typedef 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 */ | ||
75 | int 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 | */ | ||
106 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) | 103 | int 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 | ||
135 | int m_addfriend_norequest(uint8_t * client_id) | 136 | int 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 */ |
184 | int m_friendstatus(int friendnumber) | 185 | int 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 | ||
487 | static uint32_t last_LANdiscovery; | 488 | static 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*/ |
490 | static void LANdiscovery() | 491 | static 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 | */ | ||
57 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); | 75 | int 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 | ||
49 | static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; | 49 | static 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]; | |||
60 | int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 66 | int 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 |
172 | int resolve_addr(const char *address) | 172 | returns 0 on failure |
173 | |||
174 | TODO: Fix ipv6 support | ||
175 | */ | ||
176 | uint32_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) */ |
117 | void shutdown_networking(); | 118 | void 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 |
124 | int resolve_addr(const char *address); | 125 | returns 0 on failure |
126 | |||
127 | TODO: Fix ipv6 support | ||
128 | */ | ||
129 | uint32_t resolve_addr(const char *address); | ||
125 | 130 | ||
126 | #ifdef __cplusplus | 131 | #ifdef __cplusplus |
127 | } | 132 | } |