예제 #1
0
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);
  }
}