Esempio n. 1
0
/**
 * @brief Restore the peers on disk to #valid_peers.
 */
static void
restore_valid_peers ()
{
  off_t file_size;
  uint32_t num_peers;
  struct GNUNET_DISK_FileHandle *fh;
  char *buf;
  ssize_t size_read;
  char *iter_buf;
  char *str_repr;
  const struct GNUNET_PeerIdentity *peer;

  if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
  {
    return;
  }

  if (GNUNET_OK != GNUNET_DISK_file_test (filename_valid_peers))
  {
    return;
  }
  fh = GNUNET_DISK_file_open (filename_valid_peers,
                              GNUNET_DISK_OPEN_READ,
                              GNUNET_DISK_PERM_NONE);
  GNUNET_assert (NULL != fh);
  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &file_size));
  num_peers = file_size / 53;
  buf = GNUNET_malloc (file_size);
  size_read = GNUNET_DISK_file_read (fh, buf, file_size);
  GNUNET_assert (size_read == file_size);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "Restoring %" PRIu32 " peers from file `%s'\n",
      num_peers,
      filename_valid_peers);
  for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
  {
    str_repr = GNUNET_strndup (iter_buf, 53);
    peer = s2i_full (str_repr);
    GNUNET_free (str_repr);
    add_valid_peer (peer);
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Restored valid peer %s from disk\n",
        GNUNET_i2s_full (peer));
  }
  iter_buf = NULL;
  GNUNET_free (buf);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "num_peers: %" PRIu32 ", _size (valid_peers): %u\n",
      num_peers,
      GNUNET_CONTAINER_multipeermap_size (valid_peers));
  if (num_peers != GNUNET_CONTAINER_multipeermap_size (valid_peers))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
        "Number of restored peers does not match file size. Have probably duplicates.\n");
  }
  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "Restored %u valid peers from disk\n",
      GNUNET_CONTAINER_multipeermap_size (valid_peers));
}
Esempio n. 2
0
/**
 * @brief Store the peers currently in #valid_peers to disk.
 */
static void
store_valid_peers ()
{
  struct GNUNET_DISK_FileHandle *fh;
  uint32_t number_written_peers;
  int ret;

  if (0 == strncmp ("DISABLE", filename_valid_peers, 7))
  {
    return;
  }

  ret = GNUNET_DISK_directory_create_for_file (filename_valid_peers);
  if (GNUNET_SYSERR == ret)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
        "Not able to create directory for file `%s'\n",
        filename_valid_peers);
    GNUNET_break (0);
  }
  else if (GNUNET_NO == ret)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
        "Directory for file `%s' exists but is not writable for us\n",
        filename_valid_peers);
    GNUNET_break (0);
  }
  fh = GNUNET_DISK_file_open (filename_valid_peers,
                              GNUNET_DISK_OPEN_WRITE |
                                  GNUNET_DISK_OPEN_CREATE,
                              GNUNET_DISK_PERM_USER_READ |
                                  GNUNET_DISK_PERM_USER_WRITE);
  if (NULL == fh)
  {
    LOG (GNUNET_ERROR_TYPE_WARNING,
        "Not able to write valid peers to file `%s'\n",
        filename_valid_peers);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "Writing %u valid peers to disk\n",
      GNUNET_CONTAINER_multipeermap_size (valid_peers));
  number_written_peers =
    GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
                                           store_peer_presistently_iterator,
                                           fh);
  GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
  GNUNET_assert (number_written_peers ==
      GNUNET_CONTAINER_multipeermap_size (valid_peers));
}
Esempio n. 3
0
/**
 * Change length of view
 *
 * If size is decreased, peers with higher indices are removed.
 *
 * @param len the (maximum) length for the view
 */
void
View_change_len (uint32_t len)
{
    uint32_t i;
    uint32_t *index;

    if (GNUNET_CONTAINER_multipeermap_size (mpm) < len)
    {   /* Simply shrink */
        /* We might simply clear and free the left over space */
        GNUNET_array_grow (array, length, len);
    }
    else /* We have to remove elements */
    {
        /* TODO find a way to preserve indices */
        for (i = 0; i < len; i++)
        {
            index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
            GNUNET_assert (NULL != index);
            GNUNET_free (index);
        }
        GNUNET_array_grow (array, length, len);
        GNUNET_CONTAINER_multipeermap_destroy (mpm);
        mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO);
        for (i = 0; i < len; i++)
        {
            index = GNUNET_new (uint32_t);
            *index = i;
            GNUNET_CONTAINER_multipeermap_put (mpm, &array[i], index,
                                               GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
        }
    }
    GNUNET_assert (length == len);
}
/**
 * Create a session, a key exchange was just completed.
 *
 * @param peer peer that is now connected
 * @param kx key exchange that completed
 */
void
GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
                     struct GSC_KeyExchangeInfo *kx)
{
  struct Session *session;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Creating session for peer `%4s'\n",
              GNUNET_i2s (peer));
  session = GNUNET_new (struct Session);
  session->tmap = GSC_TYPEMAP_create ();
  session->peer = *peer;
  session->kxinfo = kx;
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (sessions,
                                                    &session->peer,
                                                    session,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"),
                         GNUNET_CONTAINER_multipeermap_size (sessions),
                         GNUNET_NO);
  GSC_CLIENTS_notify_clients_about_neighbour (peer,
                                              NULL,
                                              session->tmap);
  start_typemap_task (session);
}
/**
 * This path is no longer needed, free resources.
 *
 * @param path path resources to free
 */
static void
path_destroy (struct CadetPeerPath *path)
{
  GNUNET_assert (0 ==
                 GNUNET_CONTAINER_multipeermap_size (path->connections));
  GNUNET_CONTAINER_multipeermap_destroy (path->connections);
  GNUNET_free (path->entries);
  GNUNET_free (path);
}
/**
 * Provide an update on the `p2a` map size to statistics.
 * This function should be called whenever the `p2a` map
 * is changed.
 */
static void
publish_p2a_stat_update ()
{
  GNUNET_STATISTICS_set (GST_stats,
			 gettext_noop ("# Addresses given to ATS"),
			 GNUNET_CONTAINER_multipeermap_size (p2a) - num_blocked,
			 GNUNET_NO);
  GNUNET_STATISTICS_set (GST_stats,
                         "# blocked addresses",
                         num_blocked,
                         GNUNET_NO);
}
Esempio n. 7
0
/**
 * Get a peer by index
 *
 * @param index the index of the peer to get
 *
 * @return peer to the corresponding index.
 *         NULL if this index is not known
 */
const struct GNUNET_PeerIdentity *
View_get_peer_by_index (uint32_t index)
{
    if (index < GNUNET_CONTAINER_multipeermap_size (mpm))
    {
        return &array[index];
    }
    else
    {
        return NULL;
    }
}
/**
 * End the session with the given peer (we are no longer
 * connected).
 *
 * @param pid identity of peer to kill session with
 */
void
GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
{
  struct Session *session;
  struct GSC_ClientActiveRequest *car;
  struct SessionMessageEntry *sme;

  session = find_session (pid);
  if (NULL == session)
    return;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Destroying session for peer `%4s'\n",
              GNUNET_i2s (&session->peer));
  if (NULL != session->cork_task)
  {
    GNUNET_SCHEDULER_cancel (session->cork_task);
    session->cork_task = NULL;
  }
  while (NULL != (car = session->active_client_request_head))
  {
    GNUNET_CONTAINER_DLL_remove (session->active_client_request_head,
                                 session->active_client_request_tail, car);
    GSC_CLIENTS_reject_request (car,
                                GNUNET_NO);
  }
  while (NULL != (sme = session->sme_head))
  {
    GNUNET_CONTAINER_DLL_remove (session->sme_head,
                                 session->sme_tail,
                                 sme);
    GNUNET_free (sme);
  }
  if (NULL != session->typemap_task)
  {
    GNUNET_SCHEDULER_cancel (session->typemap_task);
    session->typemap_task = NULL;
  }
  GSC_CLIENTS_notify_clients_about_neighbour (&session->peer,
                                              session->tmap, NULL);
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_remove (sessions,
                                                       &session->peer,
                                                       session));
  GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"),
                         GNUNET_CONTAINER_multipeermap_size (sessions),
                         GNUNET_NO);
  GSC_TYPEMAP_destroy (session->tmap);
  session->tmap = NULL;
  GNUNET_free (session);
}
/**
 * Update statistics
 *
 * @param m peermap to update values from
 */
static void
update_stats (struct GNUNET_CONTAINER_MultiPeerMap *m)
{
  GNUNET_assert (NULL != m);
  GNUNET_assert (NULL != GED_stats);

  if (m == nodes_active)
  {
    GNUNET_STATISTICS_set (GED_stats, "# nodes active",
			   GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
  }
  else if (m == nodes_inactive)
  {
    GNUNET_STATISTICS_set (GED_stats, "# nodes inactive",
			   GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
  }
  else if (m == nodes_requested)
  {
    GNUNET_STATISTICS_set (GED_stats, "# nodes requested",
			   GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO);
  }
  else
    GNUNET_break (0);
}
Esempio n. 10
0
/**
 * @brief Get a random peer from @a peer_map
 *
 * @param peer_map the peer_map to get the peer from
 *
 * @return a random peer
 */
static const struct GNUNET_PeerIdentity *
get_random_peer_from_peermap (const struct
                              GNUNET_CONTAINER_MultiPeerMap *peer_map)
{
  struct GetRandPeerIteratorCls *iterator_cls;
  const struct GNUNET_PeerIdentity *ret;

  iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
  iterator_cls->index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
      GNUNET_CONTAINER_multipeermap_size (peer_map));
  (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
                                                get_rand_peer_iterator,
                                                iterator_cls);
  ret = iterator_cls->peer;
  GNUNET_free (iterator_cls);
  return ret;
}
Esempio n. 11
0
/**
 * @brief Add a given @a peer to valid peers.
 *
 * If valid peers are already #num_valid_peers_max, delete a peer previously.
 *
 * @param peer the peer that is added to the valid peers.
 *
 * @return #GNUNET_YES if no other peer had to be removed
 *         #GNUNET_NO  otherwise
 */
static int
add_valid_peer (const struct GNUNET_PeerIdentity *peer)
{
  const struct GNUNET_PeerIdentity *rand_peer;
  int ret;

  ret = GNUNET_YES;
  while (GNUNET_CONTAINER_multipeermap_size (valid_peers) >= num_valid_peers_max)
  {
    rand_peer = get_random_peer_from_peermap (valid_peers);
    GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
    ret = GNUNET_NO;
  }
  (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  return ret;
}
/**
 * Free the given entry for the neighbour.
 *
 * @param n neighbour to free
 */
static void
free_neighbour (struct Neighbour *n)
{
  struct NeighbourMessageEntry *m;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Destroying neighbour entry for peer `%s'\n",
              GNUNET_i2s (&n->peer));
  while (NULL != (m = n->message_head))
  {
    GNUNET_CONTAINER_DLL_remove (n->message_head,
                                 n->message_tail,
                                 m);
    n->queue_size--;
    GNUNET_free (m);
  }
  GNUNET_assert (0 == n->queue_size);
  if (NULL != n->th)
  {
    GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
    n->th = NULL;
  }
  GNUNET_STATISTICS_update (GSC_stats,
                            gettext_noop
                            ("# sessions terminated by transport disconnect"),
                            1, GNUNET_NO);
  if (NULL != n->kxinfo)
  {
    GSC_KX_stop (n->kxinfo);
    n->kxinfo = NULL;
  }
  if (NULL != n->retry_plaintext_task)
  {
    GNUNET_SCHEDULER_cancel (n->retry_plaintext_task);
    n->retry_plaintext_task = NULL;
  }
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_remove (neighbours,
                                                       &n->peer, n));
  GNUNET_STATISTICS_set (GSC_stats,
                         gettext_noop ("# neighbour entries allocated"),
                         GNUNET_CONTAINER_multipeermap_size (neighbours),
                         GNUNET_NO);
  GNUNET_free (n);
}
/**
 * Function called by transport to notify us that
 * a peer connected to us (on the network level).
 *
 * @param cls closure
 * @param peer the peer that connected
 */
static void
handle_transport_notify_connect (void *cls,
                                 const struct GNUNET_PeerIdentity *peer)
{
  struct Neighbour *n;

  if (0 == memcmp (peer,
                   &GSC_my_identity,
                   sizeof (struct GNUNET_PeerIdentity)))
  {
    GNUNET_break (0);
    return;
  }
  n = find_neighbour (peer);
  if (NULL != n)
  {
    /* duplicate connect notification!? */
    GNUNET_break (0);
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Peer %s exists already\n",
                GNUNET_i2s (peer));
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received connection from `%s'.\n",
              GNUNET_i2s (peer));
  n = GNUNET_new (struct Neighbour);
  n->peer = *peer;
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (neighbours,
                                                    &n->peer,
                                                    n,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  GNUNET_STATISTICS_set (GSC_stats,
                         gettext_noop ("# neighbour entries allocated"),
                         GNUNET_CONTAINER_multipeermap_size (neighbours),
                         GNUNET_NO);
  n->kxinfo = GSC_KX_start (peer);
}
Esempio n. 14
0
/**
 * Get the size of the view
 *
 * @return current number of actually contained peers
 */
unsigned int
View_size ()
{
    return GNUNET_CONTAINER_multipeermap_size (mpm);
}
/**
 * Shutdown routing subsystem.
 */
void
GDS_ROUTING_done ()
{
  GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (routing_table));
  GNUNET_CONTAINER_multipeermap_destroy (routing_table);
}
Esempio n. 16
0
    subscriber->channel = GNUNET_MESH_channel_create (mesh_handle,
                                                      NULL,
                                                      id,
                                                      GNUNET_APPLICATION_TYPE_MQTT,
                                                      GNUNET_MESH_OPTION_RELIABLE);
    subscriber->peer_added = GNUNET_NO;
    subscriber->peer_connecting = GNUNET_NO;

    subscriber->id = *id;

    GNUNET_CONTAINER_multipeermap_put (remote_subscribers, id,
      subscriber, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  }

  LOG(GNUNET_ERROR_TYPE_DEBUG, "Maintaining %d remote subscribers\n",
  			GNUNET_CONTAINER_multipeermap_size(remote_subscribers));

  add_pending_subscriber_message (subscriber, pm);
  subscriber->peer_added = GNUNET_YES;
  subscriber->peer_connecting = GNUNET_NO;
  process_pending_subscriber_messages (subscriber);
}


/**
 * Call regex search to find subscribed peers.
 *
 * @param topic of the message identification of the client
 * @param publish_msg the publish message
 */
static void
Esempio n. 17
0
/**
 * Initialize a message to clients with the current network
 * size estimate.
 *
 * @param em message to fill in
 */
static void
setup_estimate_message (struct GNUNET_NSE_ClientMessage *em)
{
  double mean;
  double sum;
  double std_dev;
  double variance;
  double val;
  double nsize;

#define WEST 1
  /* Weighted incremental algorithm for stddev according to West (1979) */
#if WEST
  double sumweight;
  double weight;
  double q;
  double r;
  double temp;

  mean = 0.0;
  sum = 0.0;
  sumweight = 0.0;
  variance = 0.0;
  for (unsigned int i = 0; i < estimate_count; i++)
  {
    unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;

    val = htonl (size_estimate_messages[j].matching_bits);
    weight = estimate_count + 1 - i;

    temp = weight + sumweight;
    q = val - mean;
    r = q * weight / temp;
    mean += r;
    sum += sumweight * q * r;
    sumweight = temp;
  }
  if (estimate_count > 0)
    variance = (sum / sumweight) * estimate_count / (estimate_count - 1.0);
#else
  /* trivial version for debugging */
  double vsq;

  /* non-weighted trivial version */
  sum = 0.0;
  vsq = 0.0;
  variance = 0.0;
  mean = 0.0;

  for (unsigned int i = 0; i < estimate_count; i++)
  {
    unsigned int j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE;

    val = htonl (size_estimate_messages[j].matching_bits);
    sum += val;
    vsq += val * val;
  }
  if (0 != estimate_count)
  {
    mean = sum / estimate_count;
    variance = (vsq - mean * sum) / (estimate_count - 1.0);     // terrible for numerical stability...
  }
#endif
  if (variance >= 0)
    std_dev = sqrt (variance);
  else
    std_dev = variance;         /* must be infinity due to estimate_count == 0 */
  current_std_dev = std_dev;
  current_size_estimate = mean;

  em->header.size = htons (sizeof (struct GNUNET_NSE_ClientMessage));
  em->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE);
  em->reserved = htonl (0);
  em->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
  {
    double se = mean - 0.332747;
    unsigned int j = GNUNET_CONTAINER_multipeermap_size (peers);
    if (0 == j)
      j = 1; /* Avoid log2(0); can only happen if CORE didn't report
		connection to self yet */
    nsize = log2 (j);
    em->size_estimate = GNUNET_hton_double (GNUNET_MAX (se,
							nsize));
    em->std_deviation = GNUNET_hton_double (std_dev);
    GNUNET_STATISTICS_set (stats,
			   "# nodes in the network (estimate)",
			   (uint64_t) pow (2, GNUNET_MAX (se,
							  nsize)),
			   GNUNET_NO);
  }
}
static int
testMap (int i)
{
  struct GNUNET_CONTAINER_MultiPeerMap *m;
  struct GNUNET_PeerIdentity k1;
  struct GNUNET_PeerIdentity k2;
  struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
  struct GNUNET_PeerIdentity key_ret;
  const char *ret;
  int j;

  CHECK (NULL != (m = GNUNET_CONTAINER_multipeermap_create (i, GNUNET_NO)));
  memset (&k1, 0, sizeof (k1));
  memset (&k2, 1, sizeof (k2));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k1));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k1, NULL));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k2, NULL));
  CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k1));
  CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k2));
  CHECK (0 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1));
  CHECK (0 == GNUNET_CONTAINER_multipeermap_size (m));
  CHECK (0 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL));
  CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL));

  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
  CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m));
  ret = GNUNET_CONTAINER_multipeermap_get (m, &k1);
  GNUNET_assert (ret != NULL);
  CHECK (0 == strcmp ("v1", ret));
  CHECK (GNUNET_NO ==
         GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
  CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m));
  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multipeermap_put (m, &k1, "v3",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  CHECK (3 == GNUNET_CONTAINER_multipeermap_size (m));
  CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (m, &k1, "v3"));
  CHECK (2 == GNUNET_CONTAINER_multipeermap_size (m));
  CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (m, &k1));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2));
  CHECK (2 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL));
  CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k2, NULL, NULL));
  CHECK (2 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL));
  iter = GNUNET_CONTAINER_multipeermap_iterator_create (m);
  CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret));
  CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret)));
  CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret));
  CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret)));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
  GNUNET_free (iter);

  CHECK (2 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1));
  for (j = 0; j < 1024; j++)
    CHECK (GNUNET_OK ==
           GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2",
                                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  iter = GNUNET_CONTAINER_multipeermap_iterator_create (m);
  for (j = 0; j < GNUNET_CONTAINER_multipeermap_size (m); j++)
    CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
  GNUNET_free (iter);

  GNUNET_CONTAINER_multipeermap_destroy (m);
  return 0;
}
/**
 * Stop server offering our hostlist.
 */
void
GNUNET_HOSTLIST_server_stop ()
{
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Hostlist server shutdown\n");
  if (NULL != hostlist_task_v6)
  {
    GNUNET_SCHEDULER_cancel (hostlist_task_v6);
    hostlist_task_v6 = NULL;
  }
  if (NULL != hostlist_task_v4)
  {
    GNUNET_SCHEDULER_cancel (hostlist_task_v4);
    hostlist_task_v4 = NULL;
  }
  if (NULL != daemon_handle_v4)
  {
    MHD_stop_daemon (daemon_handle_v4);
    daemon_handle_v4 = NULL;
  }
  if (NULL != daemon_handle_v6)
  {
    MHD_stop_daemon (daemon_handle_v6);
    daemon_handle_v6 = NULL;
  }
  if (NULL != response)
  {
    MHD_destroy_response (response);
    response = NULL;
  }
  if (NULL != notify)
  {
    GNUNET_PEERINFO_notify_cancel (notify);
    notify = NULL;
  }
  if (NULL != builder)
  {
    if (NULL != builder->pitr)
    {
      GNUNET_PEERINFO_iterate_cancel (builder->pitr);
      builder->pitr = NULL;
    }
    GNUNET_free_non_null (builder->data);
    GNUNET_free (builder);
    builder = NULL;
  }
  if (NULL != peerinfo)
  {
    GNUNET_PEERINFO_disconnect (peerinfo);
    peerinfo = NULL;
  }
  if (NULL != advertisements)
  {
    GNUNET_break (0 ==
                  GNUNET_CONTAINER_multipeermap_size (advertisements));
    GNUNET_CONTAINER_multipeermap_destroy (advertisements);
    advertisements = NULL;
  }
  cfg = NULL;
  stats = NULL;
  core = NULL;
}