aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Barksdale <amatus@amat.us>2017-12-29 09:56:10 -0600
committerDavid Barksdale <amatus@amat.us>2017-12-29 09:57:35 -0600
commit5c05ea3ca25382022d21766b6e2d876c4dabd95d (patch)
tree45bc9806fa78d184ad4cd93ad042e1843bdabb5b
parent9b6545e5fffced93341002c8ff7580a417867bcd (diff)
downloadgnunet-5c05ea3ca25382022d21766b6e2d876c4dabd95d.tar.gz
gnunet-5c05ea3ca25382022d21766b6e2d876c4dabd95d.zip
Combine logic for attaching paths
This fixes issue #4909.
-rw-r--r--src/cadet/gnunet-service-cadet_paths.c155
1 files changed, 59 insertions, 96 deletions
diff --git a/src/cadet/gnunet-service-cadet_paths.c b/src/cadet/gnunet-service-cadet_paths.c
index 0ec7ff3d7..9dd6f1ddd 100644
--- a/src/cadet/gnunet-service-cadet_paths.c
+++ b/src/cadet/gnunet-service-cadet_paths.c
@@ -179,7 +179,7 @@ GCPP_del_connection (struct CadetPeerPath *path,
179 GCC_2s (cc), 179 GCC_2s (cc),
180 GCPP_2s (path), 180 GCPP_2s (path),
181 off); 181 off);
182 GNUNET_assert (off < path->entries_length); /* FIXME: #4909: This assertion fails sometimes! */ 182 GNUNET_assert (off < path->entries_length);
183 entry = path->entries[off]; 183 entry = path->entries[off];
184 GNUNET_assert (cc == entry->cc); 184 GNUNET_assert (cc == entry->cc);
185 entry->cc = NULL; 185 entry->cc = NULL;
@@ -187,33 +187,51 @@ GCPP_del_connection (struct CadetPeerPath *path,
187 187
188 188
189/** 189/**
190 * This path is no longer needed, free resources. 190 * Tries to attach @a path to a peer, working backwards from the end
191 * and stopping at @a stop_at. If path->hn is NULL on return then the
192 * path was not attached and you can assume that path->entries_length
193 * is equal to @a stop_at.
191 * 194 *
192 * @param path path resources to free 195 * @param path the path to attach
196 * @param stop_at the path length at which to stop trying
193 */ 197 */
194static void 198static void
195path_destroy (struct CadetPeerPath *path) 199attach_path (struct CadetPeerPath *path, unsigned int stop_at)
196{ 200{
197 LOG (GNUNET_ERROR_TYPE_DEBUG, 201 GNUNET_assert (NULL == path->hn);
198 "Destroying path %s\n", 202
199 GCPP_2s (path)); 203 /* Try to attach this path to a peer, working backwards from the end. */
200 for (unsigned int i=0;i<path->entries_length;i++) 204 while (path->entries_length > stop_at)
201 { 205 {
202 struct CadetPeerPathEntry *entry = path->entries[i]; 206 unsigned int end = path->entries_length - 1;
207 struct CadetPeerPathEntry *entry = path->entries[end];
208 int force = GNUNET_NO;
203 209
210 recalculate_path_desirability (path);
211 /* If the entry already has a connection using it, force attach. */
204 if (NULL != entry->cc) 212 if (NULL != entry->cc)
205 { 213 force = GNUNET_YES;
206 struct CadetTConnection *ct; 214 path->hn = GCP_attach_path (entry->peer,
215 path,
216 end,
217 force);
218 if (NULL != path->hn)
219 break;
207 220
208 ct = GCC_get_ct (entry->cc); 221 /* Attach failed, trim this entry from the path. */
209 if (NULL != ct) 222 GNUNET_assert (NULL == entry->cc);
210 GCT_connection_lost (ct); 223 GCP_path_entry_remove (entry->peer,
211 GCC_destroy_without_tunnel (entry->cc); 224 entry,
212 } 225 end);
213 GNUNET_free (entry); 226 GNUNET_free (entry);
227 path->entries[end] = NULL;
228 path->entries_length--;
214 } 229 }
215 GNUNET_free (path->entries); 230
216 GNUNET_free (path); 231 /* Shrink array to actual path length. */
232 GNUNET_array_grow (path->entries,
233 path->entries_length,
234 path->entries_length);
217} 235}
218 236
219 237
@@ -228,7 +246,6 @@ void
228GCPP_release (struct CadetPeerPath *path) 246GCPP_release (struct CadetPeerPath *path)
229{ 247{
230 struct CadetPeerPathEntry *entry; 248 struct CadetPeerPathEntry *entry;
231 int force;
232 249
233 LOG (GNUNET_ERROR_TYPE_DEBUG, 250 LOG (GNUNET_ERROR_TYPE_DEBUG,
234 "Owner releases path %s\n", 251 "Owner releases path %s\n",
@@ -236,34 +253,23 @@ GCPP_release (struct CadetPeerPath *path)
236 path->hn = NULL; 253 path->hn = NULL;
237 entry = path->entries[path->entries_length - 1]; 254 entry = path->entries[path->entries_length - 1];
238 GNUNET_assert (path == entry->path); 255 GNUNET_assert (path == entry->path);
239 while (1) 256 GNUNET_assert (NULL == entry->cc);
257 /* cut 'off' end of path */
258 GCP_path_entry_remove (entry->peer,
259 entry,
260 path->entries_length - 1);
261 GNUNET_free (entry);
262 path->entries[path->entries_length - 1] = NULL;
263 path->entries_length--;
264 /* see if new peer at the end likes this path any better */
265 attach_path (path, 0);
266 if (NULL == path->hn)
240 { 267 {
241 /* cut 'off' end of path */ 268 /* nobody wants us, discard the path */
242 GNUNET_assert (NULL == entry->cc); 269 GNUNET_assert (0 == path->entries_length);
243 GCP_path_entry_remove (entry->peer, 270 GNUNET_assert (NULL == path->entries);
244 entry, 271 GNUNET_free (path);
245 path->entries_length - 1);
246 path->entries_length--; /* We don't bother shrinking the 'entries' array,
247 as it's probably not worth it. */
248 GNUNET_free (entry);
249 if (0 == path->entries_length)
250 break; /* the end */
251
252 /* see if new peer at the end likes this path any better */
253 entry = path->entries[path->entries_length - 1];
254 GNUNET_assert (path == entry->path);
255 force = (NULL == entry->cc) ? GNUNET_NO : GNUNET_YES;
256 path->hn = GCP_attach_path (entry->peer,
257 path,
258 path->entries_length - 1,
259 force);
260 if (NULL != path->hn)
261 return; /* yep, got attached, we are done. */
262 GNUNET_assert (GNUNET_NO == force);
263 } 272 }
264
265 /* nobody wants us, discard the path */
266 path_destroy (path);
267} 273}
268 274
269 275
@@ -422,33 +428,13 @@ extend_path (struct CadetPeerPath *path,
422 path, 428 path,
423 path->hn); 429 path->hn);
424 path->hn = NULL; 430 path->hn = NULL;
425 for (i=num_peers-1;i>=0;i--) 431 path->entries_length = old_len + num_peers;
426 { 432 attach_path (path, old_len);
427 struct CadetPeerPathEntry *entry = path->entries[old_len + i];
428
429 path->entries_length = old_len + i + 1;
430 recalculate_path_desirability (path);
431 if (NULL != entry->cc)
432 force = GNUNET_YES;
433 path->hn = GCP_attach_path (peers[i],
434 path,
435 old_len + (unsigned int) i,
436 force);
437 if (NULL != path->hn)
438 break;
439 GCP_path_entry_remove (entry->peer,
440 entry,
441 old_len + i);
442 GNUNET_free (entry);
443 path->entries[old_len + i] = NULL;
444 }
445 if (NULL == path->hn) 433 if (NULL == path->hn)
446 { 434 {
447 /* none of the peers is interested in this path; 435 /* none of the peers is interested in this path;
448 shrink path back and re-attach. */ 436 re-attach. */
449 GNUNET_array_grow (path->entries, 437 GNUNET_assert (old_len == path->entries_length);
450 path->entries_length,
451 old_len);
452 path->hn = GCP_attach_path (path->entries[old_len - 1]->peer, 438 path->hn = GCP_attach_path (path->entries[old_len - 1]->peer,
453 path, 439 path,
454 old_len - 1, 440 old_len - 1,
@@ -483,7 +469,6 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
483 struct CadetPeer *cpath[get_path_length + put_path_length]; 469 struct CadetPeer *cpath[get_path_length + put_path_length];
484 struct CheckMatchContext cm_ctx; 470 struct CheckMatchContext cm_ctx;
485 struct CadetPeerPath *path; 471 struct CadetPeerPath *path;
486 struct GNUNET_CONTAINER_HeapNode *hn;
487 int i; 472 int i;
488 unsigned int skip; 473 unsigned int skip;
489 unsigned int total_len; 474 unsigned int total_len;
@@ -587,39 +572,17 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path,
587 } 572 }
588 573
589 /* Finally, try to attach it */ 574 /* Finally, try to attach it */
590 hn = NULL; 575 attach_path (path, 0);
591 for (i=total_len-1;i>=0;i--) 576 if (NULL == path->hn)
592 {
593 struct CadetPeerPathEntry *entry = path->entries[i];
594
595 path->entries_length = i + 1;
596 recalculate_path_desirability (path);
597 hn = GCP_attach_path (cpath[i],
598 path,
599 (unsigned int) i,
600 GNUNET_NO);
601 if (NULL != hn)
602 break;
603 GCP_path_entry_remove (entry->peer,
604 entry,
605 i);
606 GNUNET_free (entry);
607 path->entries[i] = NULL;
608 }
609 if (NULL == hn)
610 { 577 {
611 /* None of the peers on the path care about it. */ 578 /* None of the peers on the path care about it. */
612 LOG (GNUNET_ERROR_TYPE_DEBUG, 579 LOG (GNUNET_ERROR_TYPE_DEBUG,
613 "Path discovered from DHT is not interesting to us\n"); 580 "Path discovered from DHT is not interesting to us\n");
614 GNUNET_free (path->entries); 581 GNUNET_assert (0 == path->entries_length);
582 GNUNET_assert (NULL == path->entries);
615 GNUNET_free (path); 583 GNUNET_free (path);
616 return; 584 return;
617 } 585 }
618 path->hn = hn;
619 /* Shrink path to actual useful length */
620 GNUNET_array_grow (path->entries,
621 path->entries_length,
622 i + 1);
623 LOG (GNUNET_ERROR_TYPE_DEBUG, 586 LOG (GNUNET_ERROR_TYPE_DEBUG,
624 "Created new path %s based on information from DHT\n", 587 "Created new path %s based on information from DHT\n",
625 GCPP_2s (path)); 588 GCPP_2s (path));