void all_paths_enumeratort::complete_path(patht &path, int succ) { if(path.empty()) return; path_nodet &node=path.back(); extend_path(path, node.loc, succ); goto_programt::targett end=path.back().loc; if(end==loop_header || loop.find(end)==loop.end()) return; complete_path(path, 0); }
/** * Create a peer path based on the result of a DHT lookup. If we * already know this path, or one that is longer, simply return NULL. * Otherwise, we try to extend an existing path, or create a new one * if applicable. * * @param get_path path of the get request * @param get_path_length lenght of @a get_path * @param put_path path of the put request * @param put_path_length length of the @a put_path * @return a path through the network */ void GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct CheckMatchContext cm_ctx; struct CadetPeer *cpath[get_path_length + put_path_length]; struct CadetPeerPath *path; struct GNUNET_CONTAINER_HeapNode *hn; int i; /* precompute 'cpath' so we can avoid doing the lookups lots of times */ for (unsigned int off=0;off<get_path_length + put_path_length;off++) { const struct GNUNET_PeerIdentity *pid; pid = (off < get_path_length) ? &get_path[get_path_length - off] : &put_path[get_path_length + put_path_length - off]; cpath[off] = GCP_get (pid, GNUNET_YES); } /* First figure out if this path is a subset of an existing path, an extension of an existing path, or a new path. */ cm_ctx.cpath = cpath; cm_ctx.match = NULL; for (i=get_path_length + put_path_length-1;i>=0;i--) { GCP_iterate_paths_at (cpath[i], (unsigned int) i, &check_match, &cm_ctx); if (NULL != cm_ctx.match) { if (i == get_path_length + put_path_length - 1) { /* Existing path includes this one, nothing to do! */ return; } if (cm_ctx.match->entries_length == i + 1) { /* Existing path ends in the middle of new path, extend it! */ extend_path (cm_ctx.match, &cpath[i], get_path_length + put_path_length - i); return; } } } /* No match at all, create completely new path */ path = GNUNET_new (struct CadetPeerPath); /* First, try to attach it */ hn = NULL; for (i=get_path_length + put_path_length-1;i>=0;i--) { path->entries_length = i; /* FIXME: note that path->desirability is used, but not yet initialized here! */ hn = GCP_attach_path (cpath[i], path, (unsigned int) i); if (NULL != hn) break; } if (NULL == hn) { /* None of the peers on the path care about it. */ GNUNET_free (path); return; } path->hn = hn; path->entries_length = i; path->entries = GNUNET_new_array (path->entries_length, struct CadetPeerPathEntry); for (;i>=0;i--) { struct CadetPeerPathEntry *entry = &path->entries[i]; entry->peer = cpath[i]; entry->path = path; GCP_path_entry_add (entry->peer, entry, i); } }