/**
 * PEERINFO calls this function to let us know about a possible peer
 * that we might want to connect to.
 *
 * @param cls closure (not used)
 * @param peer potential peer to connect to
 * @param hello HELLO for this peer (or NULL)
 * @param err_msg NULL if successful, otherwise contains error message
 */
static void
process_peer (void *cls, const struct GNUNET_PeerIdentity *peer,
              const struct GNUNET_HELLO_Message *hello, const char *err_msg)
{
  struct Peer *pos;

  if (err_msg != NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                _("Error in communication with PEERINFO service: %s\n"),
                err_msg);
    GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
    peerinfo_notify = GNUNET_PEERINFO_notify (cfg, &process_peer, NULL);
    return;
  }
  GNUNET_assert (peer != NULL);
  if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
    return;                     /* that's me! */
  if (hello == NULL)
  {
    /* free existing HELLO, if any */
    pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
    if (NULL != pos)
    {
      GNUNET_free_non_null (pos->hello);
      pos->hello = NULL;
      if (pos->filter != NULL)
      {
        GNUNET_CONTAINER_bloomfilter_free (pos->filter);
        pos->filter = NULL;
      }
      if ((GNUNET_NO == pos->is_connected) && (GNUNET_NO == pos->is_friend) &&
          (0 ==
           GNUNET_TIME_absolute_get_remaining (pos->
                                               greylisted_until).rel_value))
        free_peer (NULL, &pos->pid.hashPubKey, pos);
    }
    return;
  }
  consider_for_advertising (hello);
  pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
  if (pos == NULL)
    pos = make_peer (peer, hello, GNUNET_NO);
  GNUNET_assert (NULL != pos);
  if (GNUNET_YES == pos->is_connected)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already connected to peer `%s'\n",
                GNUNET_i2s (peer));
    return;
  }
  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value > 0)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already tried peer `%s' recently\n",
                GNUNET_i2s (peer));
    return;                     /* peer still greylisted */
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering connecting to peer `%s'\n",
              GNUNET_i2s (peer));
  schedule_attempt_connect (pos);
}
Exemplo n.º 2
0
void
__CUT__void_node_test_make_node_null_key()
{
    peer p = make_peer(0, 0, 0);
    node n = make_node(0, p);
    ASSERT(!n, "");
}
Exemplo n.º 3
0
/**
 * PEERINFO calls this function to let us know about a possible peer
 * that we might want to connect to.
 *
 * @param cls closure (not used)
 * @param peer potential peer to connect to
 * @param hello HELLO for this peer (or NULL)
 * @param err_msg NULL if successful, otherwise contains error message
 */
static void
process_peer (void *cls,
              const struct GNUNET_PeerIdentity *peer,
              const struct GNUNET_HELLO_Message *hello,
              const char *err_msg)
{
  struct Peer *pos;

  if (NULL != err_msg)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                _("Error in communication with PEERINFO service: %s\n"),
                err_msg);
    GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
    peerinfo_notify = GNUNET_PEERINFO_notify (cfg,
                                              GNUNET_NO,
                                              &process_peer,
                                              NULL);
    return;
  }
  GNUNET_assert (NULL != peer);
  if (0 == memcmp (&my_identity,
                   peer,
                   sizeof (struct GNUNET_PeerIdentity)))
    return;                     /* that's me! */
  if (NULL == hello)
  {
    /* free existing HELLO, if any */
    pos = GNUNET_CONTAINER_multipeermap_get (peers,
                                             peer);
    if (NULL != pos)
    {
      GNUNET_free_non_null (pos->hello);
      pos->hello = NULL;
      if (NULL != pos->filter)
      {
        GNUNET_CONTAINER_bloomfilter_free (pos->filter);
        pos->filter = NULL;
      }
      if ( (NULL == pos->mq) &&
           (GNUNET_NO == pos->is_friend) )
        free_peer (NULL,
                   &pos->pid,
                   pos);
    }
    return;
  }
  consider_for_advertising (hello);
  pos = GNUNET_CONTAINER_multipeermap_get (peers,
                                           peer);
  if (NULL == pos)
    pos = make_peer (peer,
                     hello,
                     GNUNET_NO);
  attempt_connect (pos);
}
Exemplo n.º 4
0
/**
 * Method called whenever a peer connects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 * @param mq message queue for communicating with @a peer
 * @return our `struct Peer` for @a peer
 */
static void *
connect_notify (void *cls,
                const struct GNUNET_PeerIdentity *peer,
		struct GNUNET_MQ_Handle *mq)
{
  struct Peer *pos;
  uint64_t flags;
  const void *extra;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core told us that we are connecting to `%s'\n",
              GNUNET_i2s (peer));
  if (0 == memcmp (&my_identity,
                   peer,
                   sizeof (struct GNUNET_PeerIdentity)))
    return NULL;
  extra = GNUNET_CORE_get_mq_options (GNUNET_YES,
				      GNUNET_CORE_PRIO_BEST_EFFORT,
				      &flags);
  GNUNET_MQ_set_options (mq,
			 flags,
			 extra);
  connection_count++;
  GNUNET_STATISTICS_set (stats,
                         gettext_noop ("# peers connected"),
                         connection_count,
                         GNUNET_NO);
  pos = GNUNET_CONTAINER_multipeermap_get (peers,
                                           peer);
  if (NULL == pos)
  {
    pos = make_peer (peer,
                     NULL,
                     GNUNET_NO);
  }
  else
  {
    GNUNET_assert (NULL == pos->mq);
  }
  pos->mq = mq;
  if (pos->is_friend)
  {
    friend_count++;
    if ( (friend_count == minimum_friend_count) &&
         (GNUNET_YES != friends_only) )
      whitelist_peers ();
    GNUNET_STATISTICS_set (stats,
                           gettext_noop ("# friends connected"),
                           friend_count,
                           GNUNET_NO);
  }
  reschedule_hellos (NULL,
                     peer,
                     pos);
  return pos;
}
/**
 * We've gotten a HELLO from another peer.  Consider it for
 * advertising.
 *
 * @param hello the HELLO we got
 */
static void
consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
{
  int have_address;
  struct GNUNET_PeerIdentity pid;
  struct GNUNET_TIME_Absolute dt;
  struct GNUNET_HELLO_Message *nh;
  struct Peer *peer;
  uint16_t size;

  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
  {
    GNUNET_break (0);
    return;
  }
  if (0 == memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
    return;                     /* that's me! */
  have_address = GNUNET_NO;
  GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &address_iterator,
                                  &have_address);
  if (GNUNET_NO == have_address)
    return;                     /* no point in advertising this one... */
  peer = GNUNET_CONTAINER_multihashmap_get (peers, &pid.hashPubKey);
  if (NULL == peer)
  {
    peer = make_peer (&pid, hello, GNUNET_NO);
  }
  else if (peer->hello != NULL)
  {
    dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ());
    if (dt.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
      return;                   /* nothing new here */
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Found `%s' from peer `%s' for advertising\n", "HELLO",
              GNUNET_i2s (&pid));
  if (peer->hello != NULL)
  {
    nh = GNUNET_HELLO_merge (peer->hello, hello);
    GNUNET_free (peer->hello);
    peer->hello = nh;
  }
  else
  {
    size = GNUNET_HELLO_size (hello);
    peer->hello = GNUNET_malloc (size);
    memcpy (peer->hello, hello, size);
  }
  if (peer->filter != NULL)
    GNUNET_CONTAINER_bloomfilter_free (peer->filter);
  setup_filter (peer);
  /* since we have a new HELLO to pick from, re-schedule all
   * HELLO requests that are not bound by the HELLO send rate! */
  GNUNET_CONTAINER_multihashmap_iterate (peers, &reschedule_hellos, peer);
}
Exemplo n.º 6
0
void* pcu_msg_pack(pcu_msg* m, int id, size_t size)
{
  if (m->state != pack_state)
    reel_fail("PCU_Comm_Pack called at the wrong time");
  pcu_msg_peer* peer = find_peer(m->peers,id);
  if (!peer)
  {
    peer = make_peer(id);
    pcu_aa_insert(&(peer->node),&(m->peers),peer_less);
  }
  return pcu_push_buffer(&(peer->message.buffer),size);
}
Exemplo n.º 7
0
/**
 * Function called with reservation result.
 *
 * @param cls closure with the reservation command (`struct Command`)
 * @param peer identifies the peer
 * @param amount set to the amount that was actually reserved or unreserved;
 *               either the full requested amount or zero (no partial reservations)
 * @param res_delay if the reservation could not be satisfied (amount was 0), how
 *        long should the client wait until re-trying?
 */
static void
reservation_cb (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                int32_t amount,
                struct GNUNET_TIME_Relative res_delay)
{
  struct Command *cmd = cls;
  struct GNUNET_PeerIdentity pid;

  cmd->details.reserve_bandwidth.rc = NULL;
  make_peer (cmd->details.reserve_bandwidth.pid,
             &pid);
  GNUNET_assert (0 == memcmp (peer,
                              &pid,
                              sizeof (struct GNUNET_PeerIdentity)));
  switch (cmd->details.reserve_bandwidth.expected_result)
  {
  case GNUNET_OK:
    if (amount != cmd->details.reserve_bandwidth.amount)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  "Unexpectedly failed to reserve %d/%d bytes with delay %s!\n",
                  (int) amount,
                  (int) cmd->details.reserve_bandwidth.amount,
                  GNUNET_STRINGS_relative_time_to_string (res_delay,
                                                          GNUNET_YES));
      GNUNET_break (0);
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    break;
  case GNUNET_NO:
    GNUNET_break ( (0 != amount) ||
                   (0 != res_delay.rel_value_us) );
    break;
  case GNUNET_SYSERR:
    if ( (amount != 0) ||
         (0 == res_delay.rel_value_us) )
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  "Unexpectedly reserved %d bytes with delay %s!\n",
                  (int) amount,
                  GNUNET_STRINGS_relative_time_to_string (res_delay,
                                                          GNUNET_YES));
      GNUNET_break (0);
      GNUNET_SCHEDULER_shutdown ();
      return;
    }
    break;
  }
  off++;
  run_interpreter ();
}
Exemplo n.º 8
0
void
__CUT__void_node_test_make_node()
{
    uint32_t exp[3] = { 0x81fb346d, 0x17368bd9, 0xd5dd941e };
    peer p = make_peer(0, 0, 0);

    node n = make_node(exp, p);
    ASSERT(n, "");
    ASSERT(n->key[0] == exp[0], "expected 0x%x, got 0x%x", exp[0], n->key[0]);
    ASSERT(n->key[1] == exp[1], "expected 0x%x, got 0x%x", exp[1], n->key[1]);
    ASSERT(n->key[2] == exp[2], "expected 0x%x, got 0x%x", exp[2], n->key[2]);
    ASSERT(n->peer == p, "expected %p, got %p", p, n->peer);
}
Exemplo n.º 9
0
static void
peers_connect(struct peers* p, int id, struct sockaddr_in* addr)
{
	p->peers = realloc(p->peers, sizeof(struct peer*) * (p->peers_count+1));
	p->peers[p->peers_count] = make_peer(p, id, addr);
	
	struct peer* peer = p->peers[p->peers_count];
	bufferevent_setcb(peer->bev, on_read, NULL, on_peer_event, peer);
	peer->reconnect_ev = evtimer_new(p->base, on_connection_timeout, peer);
	connect_peer(peer);

	p->peers_count++;
}
Exemplo n.º 10
0
/**
 * Generate a fake address based on the given parameters.
 *
 * @param pid number of the peer
 * @param num number of the address at peer @a pid
 * @param addr_flags flags to use for the address
 * @return the address
 */
static struct GNUNET_HELLO_Address *
make_address (uint32_t pid,
              uint32_t num,
              enum GNUNET_HELLO_AddressInfo addr_flags)
{
  struct GNUNET_PeerIdentity pk;
  uint32_t nbo;

  nbo = htonl (num);
  make_peer (pid,
             &pk);
  return GNUNET_HELLO_address_allocate (&pk,
                                        "test",
                                        &nbo,
                                        sizeof (nbo),
                                        addr_flags);
}
Exemplo n.º 11
0
/**
 * Method called whenever a peer connects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 * @param atsi performance data
 * @param atsi_count number of records in 'atsi'
 */
static void
connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_ATS_Information *atsi,
                unsigned int atsi_count)
{
  struct Peer *pos;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core told us that we are connecting to `%s'\n",
              GNUNET_i2s (peer));
  if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
    return;

  connection_count++;
  GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"),
                         connection_count, GNUNET_NO);
  pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
  if (NULL == pos)
  {
    pos = make_peer (peer, NULL, GNUNET_NO);
    GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
  }
  else
  {
    GNUNET_assert (GNUNET_NO == pos->is_connected);
    pos->greylisted_until.abs_value = 0;        /* remove greylisting */
  }
  pos->is_connected = GNUNET_YES;
  pos->connect_attempts = 0;    /* re-set back-off factor */
  if (pos->is_friend)
  {
    if ((friend_count == minimum_friend_count - 1) &&
        (GNUNET_YES != friends_only))
      whitelist_peers ();
    friend_count++;
    GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"),
                           friend_count, GNUNET_NO);
  }
  reschedule_hellos (NULL, &peer->hashPubKey, pos);
}
Exemplo n.º 12
0
/**
 * Process friend found in FRIENDS file.
 *
 * @param cls pointer to an `unsigned int` to be incremented per friend found
 * @param pid identity of the friend
 */
static void
handle_friend (void *cls,
               const struct GNUNET_PeerIdentity *pid)
{
  unsigned int *entries_found = cls;
  struct Peer *fl;

  if (0 == memcmp (pid,
                   &my_identity,
                   sizeof (struct GNUNET_PeerIdentity)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Found myself `%s' in friend list (useless, ignored)\n"),
                GNUNET_i2s (pid));
    return;
  }
  (*entries_found)++;
  fl = make_peer (pid, NULL, GNUNET_YES);
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              _("Found friend `%s' in configuration\n"),
              GNUNET_i2s (&fl->pid));
}
Exemplo n.º 13
0
static void
on_accept(struct evconnlistener *l, evutil_socket_t fd,
	struct sockaddr* addr, int socklen, void *arg)
{
	struct peer* peer;
	struct peers* peers = arg;

	peers->clients = realloc(peers->clients,
		sizeof(struct peer*) * (peers->clients_count+1));
	peers->clients[peers->clients_count] = 
		make_peer(peers, peers->clients_count, (struct sockaddr_in*)addr);
	
	peer = peers->clients[peers->clients_count];
	bufferevent_setfd(peer->bev, fd);
	bufferevent_setcb(peer->bev, on_read, NULL, on_client_event, peer);
	bufferevent_enable(peer->bev, EV_READ|EV_WRITE);
	socket_set_nodelay(fd);
	
	paxos_log_info("Accepted connection from %s:%d",
		inet_ntoa(((struct sockaddr_in*)addr)->sin_addr),
		ntohs(((struct sockaddr_in*)addr)->sin_port));
	
	peers->clients_count++;
}
Exemplo n.º 14
0
/**
 * Read the friends file.
 */
static void
read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
  char *fn;
  char *data;
  size_t pos;
  struct GNUNET_PeerIdentity pid;
  uint64_t fsize;
  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
  unsigned int entries_found;
  struct Peer *fl;

  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_filename (cfg, "TOPOLOGY", "FRIENDS", &fn))
  {
    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
			       "topology", "FRIENDS");
    return;
  }
  if (GNUNET_OK != GNUNET_DISK_file_test (fn))
    GNUNET_DISK_fn_write (fn, NULL, 0,
                          GNUNET_DISK_PERM_USER_READ |
                          GNUNET_DISK_PERM_USER_WRITE);
  if (GNUNET_OK != GNUNET_DISK_file_size (fn,
      &fsize, GNUNET_NO, GNUNET_YES))
  {
    if ((friends_only) || (minimum_friend_count > 0))
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                  _("Could not read friends list `%s'\n"), fn);
    GNUNET_free (fn);
    return;
  }
  if (fsize == 0)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Friends file `%s' is empty.\n"),
                fn);
    GNUNET_free (fn);
    return;
  }
  data = GNUNET_malloc_large (fsize);
  if (data == NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to read friends list from `%s': out of memory\n"),
                fn);
    GNUNET_free (fn);
    return;
  }
  if (fsize != GNUNET_DISK_fn_read (fn, data, fsize))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Failed to read friends list from `%s'\n"), fn);
    GNUNET_free (fn);
    GNUNET_free (data);
    return;
  }
  entries_found = 0;
  pos = 0;
  while ((pos < fsize) && isspace ((unsigned char) data[pos]))
    pos++;
  while ((fsize >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
         (pos <=
          fsize - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
  {
    memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
    if (!isspace
        ((unsigned char)
         enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  _
                  ("Syntax error in topology specification at offset %llu, skipping bytes.\n"),
                  (unsigned long long) pos);
      pos++;
      while ((pos < fsize) && (!isspace ((unsigned char) data[pos])))
        pos++;
      continue;
    }
    enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
    if (GNUNET_OK !=
        GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  _
                  ("Syntax error in topology specification at offset %llu, skipping bytes `%s'.\n"),
                  (unsigned long long) pos, &enc);
    }
    else
    {
      if (0 != memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
      {
        entries_found++;
        fl = make_peer (&pid, NULL, GNUNET_YES);
        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                    _("Found friend `%s' in configuration\n"),
                    GNUNET_i2s (&fl->pid));
      }
      else
      {
        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                    _("Found myself `%s' in friend list (useless, ignored)\n"),
                    GNUNET_i2s (&pid));
      }
    }
    pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
    while ((pos < fsize) && isspace ((unsigned char) data[pos]))
      pos++;
  }
  GNUNET_free (data);
  GNUNET_free (fn);
  GNUNET_STATISTICS_update (stats, gettext_noop ("# friends in configuration"),
                            entries_found, GNUNET_NO);
  if ((minimum_friend_count > entries_found) && (friends_only == GNUNET_NO))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _
                ("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n"));
  }
  if ((minimum_friend_count > target_connection_count) &&
      (friends_only == GNUNET_NO))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _
                ("More friendly connections required than target total number of connections.\n"));
  }
}
Exemplo n.º 15
0
/**
 * Main interpreter loop. Runs the steps of the test.
 *
 * @param cls NULL
 * @param tc unused
 */
static void
interpreter (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)

{
  struct Command *cmd;

  interpreter_task = NULL;
  while (1)
  {
    cmd = &test_commands[off];
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "#%u: %d %s\n",
                off,
                (int) cmd->code,
                (NULL != cmd->label) ? cmd->label : "");
    switch (cmd->code)
    {
    case CMD_END_PASS:
      ret = 0;
      GNUNET_SCHEDULER_shutdown ();
      return;
    case CMD_ADD_ADDRESS:
      {
        struct GNUNET_HELLO_Address *addr;
        struct GNUNET_ATS_Session *session;

        addr = make_address (cmd->details.add_address.pid,
                             cmd->details.add_address.addr_num,
                             cmd->details.add_address.addr_flags);
        session = make_session (cmd->details.add_address.session);
        if (cmd->details.add_address.expect_fail)
          GNUNET_log_skip (1, GNUNET_NO);
        cmd->details.add_address.ar
          = GNUNET_ATS_address_add (sched_ats,
                                    addr,
                                    session,
                                    &cmd->details.add_address.properties);
        GNUNET_free (addr);
        if (cmd->details.add_address.expect_fail)
        {
          GNUNET_log_skip (0, GNUNET_YES);
        }
        else if (NULL == cmd->details.add_address.ar)
        {
          GNUNET_break (0);
          GNUNET_SCHEDULER_shutdown ();
          return;
        }
        off++;
        break;
      }
    case CMD_DEL_ADDRESS:
      {
        struct Command *add;

        add = find_command (CMD_ADD_ADDRESS,
                            cmd->details.del_address.add_label);
        GNUNET_assert (NULL != add->details.add_address.ar);
        GNUNET_ATS_address_destroy (add->details.add_address.ar);
        add->details.add_address.ar = NULL;
        off++;
        break;
      }
    case CMD_AWAIT_ADDRESS_SUGGESTION:
      {
        struct GNUNET_PeerIdentity pid;
        struct GNUNET_HELLO_Address *addr;
        struct Command *add;
        struct AddressSuggestData *asd;
        int done;

        make_peer (cmd->details.await_address_suggestion.pid,
                   &pid);
        asd = find_address_suggestion (&pid);
        if (NULL == asd)
          return;
        if (GNUNET_NO == asd->active)
          return; /* last suggestion was to disconnect, wait longer */
        done = GNUNET_YES;
        if (NULL != cmd->details.await_address_suggestion.add_label)
        {
          done = GNUNET_NO;
          add = find_command (CMD_ADD_ADDRESS,
                              cmd->details.await_address_suggestion.add_label);
          addr = make_address (add->details.add_address.pid,
                               add->details.add_address.addr_num,
                               add->details.add_address.addr_flags);
          if ( (asd->session ==
                make_session (add->details.add_address.session)) &&
               (0 ==
                GNUNET_HELLO_address_cmp (addr,
                                          asd->address)) )
            done = GNUNET_YES;
          GNUNET_free (addr);
        }
        if (GNUNET_NO == done)
          return;
        off++;
        break;
      }
    case CMD_AWAIT_DISCONNECT_SUGGESTION:
      {
        struct GNUNET_PeerIdentity pid;
        struct AddressSuggestData *asd;

        make_peer (cmd->details.await_disconnect_suggestion.pid,
                   &pid);
        asd = find_address_suggestion (&pid);
        if (NULL == asd)
          return; /* odd, no suggestion at all yet!? */
        if (GNUNET_YES == asd->active)
          return; /* last suggestion was to activate, wait longer */
        /* last suggestion was to deactivate, condition satisfied! */
        off++;
        break;
      }
    case CMD_REQUEST_CONNECTION_START:
      {
        struct GNUNET_PeerIdentity pid;

        make_peer (cmd->details.request_connection_start.pid,
                   &pid);
        cmd->details.request_connection_start.csh
          = GNUNET_ATS_connectivity_suggest (con_ats,
                                             &pid,
                                             1);
        off++;
        break;
      }
    case CMD_REQUEST_CONNECTION_STOP:
      {
        struct Command *start;

        start = find_command (CMD_REQUEST_CONNECTION_START,
                              cmd->details.request_connection_stop.connect_label);
        GNUNET_ATS_connectivity_suggest_cancel (start->details.request_connection_start.csh);
        start->details.request_connection_start.csh = NULL;
        off++;
        break;
      }
    case CMD_AWAIT_ADDRESS_INFORMATION:
      {
        struct AddressInformationData *aid;
        struct Command *add;
        struct Command *update;
        struct GNUNET_HELLO_Address *addr;
        const struct GNUNET_ATS_Properties *cmp;

        add = find_command (CMD_ADD_ADDRESS,
                            cmd->details.await_address_information.add_label);
        update = find_command (CMD_UPDATE_ADDRESS,
                               cmd->details.await_address_information.update_label);
        addr = make_address (add->details.add_address.pid,
                             add->details.add_address.addr_num,
                             add->details.add_address.addr_flags);
        aid = find_address_information (addr);
        GNUNET_free (addr);
        if (NULL == update)
          cmp = &add->details.add_address.properties;
        else
          cmp = &update->details.update_address.properties;
        if ( (NULL != aid) &&
             (cmp->delay.rel_value_us == aid->properties.delay.rel_value_us) &&
             (cmp->utilization_out == aid->properties.utilization_out) &&
             (cmp->utilization_in == aid->properties.utilization_in) &&
             (cmp->distance == aid->properties.distance) &&
             (cmp->scope == aid->properties.scope) )
        {
          off++;
          break;
        }
        return;
      }
    case CMD_UPDATE_ADDRESS:
      {
        struct Command *add;

        add = find_command (CMD_ADD_ADDRESS,
                            cmd->details.update_address.add_label);
        GNUNET_assert (NULL != add->details.add_address.ar);
        GNUNET_ATS_address_update (add->details.add_address.ar,
                                   &cmd->details.update_address.properties);
        off++;
        break;
      }
    case CMD_ADD_SESSION:
      {
        struct Command *add;
        struct GNUNET_ATS_Session *session;

        add = find_command (CMD_ADD_ADDRESS,
                            cmd->details.add_session.add_label);
        session = make_session (cmd->details.add_session.session);
        GNUNET_assert (NULL != add->details.add_address.ar);
        GNUNET_ATS_address_add_session (add->details.add_address.ar,
                                        session);
        off++;
        break;
      }
    case CMD_DEL_SESSION:
      {
        struct Command *add_address;
        struct Command *add_session;
        struct GNUNET_ATS_Session *session;

        add_session = find_command (CMD_ADD_SESSION,
                                    cmd->details.del_session.add_session_label);
        add_address = find_command (CMD_ADD_ADDRESS,
                                    add_session->details.add_session.add_label);
        GNUNET_assert (NULL != add_address->details.add_address.ar);
        session = make_session (add_session->details.add_session.session);
        GNUNET_ATS_address_del_session (add_address->details.add_address.ar,
                                        session);
        off++;
        break;
      }
    case CMD_CHANGE_PREFERENCE:
      {
        struct GNUNET_PeerIdentity pid;

        make_peer (cmd->details.change_preference.pid,
                   &pid);
        GNUNET_ATS_performance_change_preference (perf_ats,
                                                  &pid,
                                                  GNUNET_ATS_PREFERENCE_END);
        off++;
        break;
      }
    case CMD_PROVIDE_FEEDBACK:
      {
        struct GNUNET_PeerIdentity pid;

        make_peer (cmd->details.provide_feedback.pid,
                   &pid);
        GNUNET_ATS_performance_give_feedback (perf_ats,
                                              &pid,
                                              cmd->details.provide_feedback.scope,
                                              GNUNET_ATS_PREFERENCE_END);
        off++;
        break;
      }
    case CMD_LIST_ADDRESSES:
      {
        struct GNUNET_PeerIdentity pid;

        make_peer (cmd->details.list_addresses.pid,
                   &pid);
        cmd->details.list_addresses.alh
          = GNUNET_ATS_performance_list_addresses (perf_ats,
                                                   &pid,
                                                   cmd->details.list_addresses.all,
                                                   &info_cb,
                                                   cmd);
        return;
      }
    case CMD_RESERVE_BANDWIDTH:
      {
        struct GNUNET_PeerIdentity pid;

        make_peer (cmd->details.reserve_bandwidth.pid,
                   &pid);
        cmd->details.reserve_bandwidth.rc
          = GNUNET_ATS_reserve_bandwidth (perf_ats,
                                          &pid,
                                          cmd->details.reserve_bandwidth.amount,
                                          &reservation_cb,
                                          cmd);
        return;
      }
    case CMD_SLEEP:
      off++;
      interpreter_task = GNUNET_SCHEDULER_add_delayed (cmd->details.sleep.delay,
                                                       &interpreter,
                                                       NULL);
      return;
    } /* end switch */
  } /* end while(1) */
}