diff options
author | David Barksdale <amatus@amat.us> | 2017-12-29 09:56:10 -0600 |
---|---|---|
committer | David Barksdale <amatus@amat.us> | 2017-12-29 09:57:35 -0600 |
commit | 5c05ea3ca25382022d21766b6e2d876c4dabd95d (patch) | |
tree | 45bc9806fa78d184ad4cd93ad042e1843bdabb5b /src | |
parent | 9b6545e5fffced93341002c8ff7580a417867bcd (diff) | |
download | gnunet-5c05ea3ca25382022d21766b6e2d876c4dabd95d.tar.gz gnunet-5c05ea3ca25382022d21766b6e2d876c4dabd95d.zip |
Combine logic for attaching paths
This fixes issue #4909.
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/gnunet-service-cadet_paths.c | 155 |
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 | */ |
194 | static void | 198 | static void |
195 | path_destroy (struct CadetPeerPath *path) | 199 | attach_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 | |||
228 | GCPP_release (struct CadetPeerPath *path) | 246 | GCPP_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)); |