summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-09-14 17:10:10 +0200
committerCoren[m] <Break@Ocean>2013-09-14 17:10:10 +0200
commit36e5636406c019390f96c2a02c17c850143d21b9 (patch)
tree67221777efb70daaf12d2e5cb77470efb473d1f5 /toxcore/DHT.c
parenta7d059a13008bff51422aac97768f44a693c4f47 (diff)
DHT.c:
- get_close_nodes(): refactored the inner loop out into get_close_nodes_inner()
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c205
1 files changed, 82 insertions, 123 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 2a5b03a4..8557a5e0 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -193,137 +193,96 @@ static int friend_number(DHT *dht, uint8_t *client_id)
193 return -1; 193 return -1;
194} 194}
195 195
196/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 196/*
197 * put them in the nodes_list and return how many were found. 197 * helper for get_close_nodes(). argument list is a monster :D
198 *
199 * TODO: For the love of based Allah make this function cleaner and much more efficient.
200 */ 198 */
201static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) 199static int get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list,
200 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
201 time_t timestamp, int *num_nodes_ptr)
202{ 202{
203 uint32_t i, j, k; 203 int num_nodes = 0;
204 uint64_t temp_time = unix_time(); 204 int i, tout, inlist, ipv46x, j, closest;
205 int num_nodes = 0, closest, tout, inlist, ipv46x; 205 for(i = 0; i < client_list_length; i++) {
206 206 Client_data *client = &client_list[i];
207 for (i = 0; i < LCLIENT_LIST; ++i) { 207 tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT);
208 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id);
209 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
210
211 /*
212 * NET_PACKET_SEND_NODES sends ONLY AF_INET
213 * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
214 * it could send both, but then a) packet size is an issue and
215 * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
216 * sent anyways for backwards compatibility)
217 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
218 * partner node understands - that's true if *they* are on IPv6
219 *
220 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
221 * our connections, instead we have to look if it is an embedded
222 * IPv4-in-IPv6 here and convert it down in sendnodes().
223 */
224#ifdef TOX_ENABLE_IPV6
225 IP *client_ip = &dht->close_clientlist[i].ip_port.ip;
226 sa_family_t ip_treat_as_family = client_ip->family;
227 if ((dht->c->lossless_udp->net->family == AF_INET6) &&
228 (client_ip->family == AF_INET6)) {
229 /* socket is AF_INET6, address claims AF_INET6:
230 * check for embedded IPv4-in-IPv6 */
231 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6))
232 ip_treat_as_family = AF_INET;
233 }
234
235 ipv46x = !(sa_family == ip_treat_as_family);
236#else
237 ipv46x = !(sa_family == AF_INET);
238#endif
239
240 /* If node isn't good or is already in list. */
241 if (tout || inlist || ipv46x)
242 continue;
243
244 if (num_nodes < MAX_SENT_NODES) {
245
246 memcpy( nodes_list[num_nodes].client_id,
247 dht->close_clientlist[i].client_id,
248 CLIENT_ID_SIZE );
249
250 nodes_list[num_nodes].ip_port = dht->close_clientlist[i].ip_port;
251 num_nodes++;
252
253 } else {
254
255 for (j = 0; j < MAX_SENT_NODES; ++j) {
256 closest = id_closest( client_id,
257 nodes_list[j].client_id,
258 dht->close_clientlist[i].client_id );
259
260 if (closest == 2) {
261 memcpy( nodes_list[j].client_id,
262 dht->close_clientlist[i].client_id,
263 CLIENT_ID_SIZE);
264
265 nodes_list[j].ip_port = dht->close_clientlist[i].ip_port;
266 break;
267 }
268 }
269 }
270 }
271
272 for (i = 0; i < dht->num_friends; ++i) {
273 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
274
275 tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
276 inlist = client_in_nodelist( nodes_list,
277 MAX_SENT_NODES,
278 dht->friends_list[i].client_list[j].client_id);
279 209
280#ifdef TOX_ENABLE_IPV6 210#ifdef TOX_ENABLE_IPV6
281 IP *client_ip = &dht->friends_list[i].client_list[j].ip_port.ip; 211 IP *client_ip = &client->ip_port.ip;
282 sa_family_t ip_treat_as_family = client_ip->family; 212
283 if ((dht->c->lossless_udp->net->family == AF_INET6) && 213 /*
284 (client_ip->family == AF_INET6)) { 214 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
285 /* socket is AF_INET6, address claims AF_INET6: 215 * our connections, instead we have to look if it is an embedded
286 * check for embedded IPv4-in-IPv6 */ 216 * IPv4-in-IPv6 here and convert it down in sendnodes().
287 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6)) 217 */
288 ip_treat_as_family = AF_INET; 218 sa_family_t ip_treat_as_family = client_ip->family;
289 } 219 if ((dht->c->lossless_udp->net->family == AF_INET6) &&
290 220 (client_ip->family == AF_INET6)) {
291 ipv46x = !(sa_family == ip_treat_as_family); 221 /* socket is AF_INET6, address claims AF_INET6:
222 * check for embedded IPv4-in-IPv6 */
223 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6))
224 ip_treat_as_family = AF_INET;
225 }
226
227 ipv46x = !(sa_family == ip_treat_as_family);
292#else 228#else
293 ipv46x = sa_family != AF_INET; 229 ipv46x = !(sa_family == AF_INET);
294#endif 230#endif
295 231
296 /* If node isn't good or is already in list. */ 232 /* If node isn't good or is already in list. */
297 if (tout || inlist || ipv46x) 233 if (tout || inlist || ipv46x)
298 continue; 234 continue;
299 235
300 if (num_nodes < MAX_SENT_NODES) { 236 if (num_nodes < MAX_SENT_NODES) {
301 237 memcpy(nodes_list[num_nodes].client_id,
302 memcpy( nodes_list[num_nodes].client_id, 238 client->client_id,
303 dht->friends_list[i].client_list[j].client_id, 239 CLIENT_ID_SIZE );
304 CLIENT_ID_SIZE); 240
305 241 nodes_list[num_nodes].ip_port = client->ip_port;
306 nodes_list[num_nodes].ip_port = dht->friends_list[i].client_list[j].ip_port; 242 num_nodes++;
307 num_nodes++; 243 } else {
308 } else { 244 /* see if node_list contains a client_id that's "further away"
309 for (k = 0; k < MAX_SENT_NODES; ++k) { 245 * compared to the one we're looking at at the moment, if there
310 246 * is, replace it
311 closest = id_closest( client_id, 247 */
312 nodes_list[k].client_id, 248 for (j = 0; j < MAX_SENT_NODES; ++j) {
313 dht->friends_list[i].client_list[j].client_id ); 249 closest = id_closest( client_id,
314 250 nodes_list[j].client_id,
315 if (closest == 2) { 251 client->client_id );
316 memcpy( nodes_list[k].client_id, 252
317 dht->friends_list[i].client_list[j].client_id, 253 /* second client_id is closer than current: change to it */
318 CLIENT_ID_SIZE ); 254 if (closest == 2) {
255 memcpy( nodes_list[j].client_id,
256 client->client_id,
257 CLIENT_ID_SIZE);
258
259 nodes_list[j].ip_port = client->ip_port;
260 break;
261 }
262 }
263 }
264 }
265
266 *num_nodes_ptr = num_nodes;
267}
319 268
320 nodes_list[k].ip_port = dht->friends_list[i].client_list[j].ip_port; 269/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
321 break; 270 * put them in the nodes_list and return how many were found.
322 } 271 *
323 } 272 * TODO: For the love of based <your favorite deity, in doubt use "love"> make
324 } 273 * this function cleaner and much more efficient.
325 } 274 */
326 } 275static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
276{
277 time_t timestamp = unix_time();
278 int num_nodes = 0, i;
279 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
280 dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes);
281
282 for (i = 0; i < dht->num_friends; ++i)
283 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
284 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
285 timestamp, &num_nodes);
327 286
328 return num_nodes; 287 return num_nodes;
329} 288}