Esempio n. 1
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);
}
Esempio n. 2
0
/**
 * Client is done with ATS scheduling, release resources.
 *
 * @param sh handle to release
 */
void
GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
{
  struct GNUNET_ATS_AddressRecord *ar;
  unsigned int i;

  if (NULL != sh->mq)
  {
    GNUNET_MQ_destroy (sh->mq);
    sh->mq = NULL;
  }
  if (NULL != sh->client)
  {
    GNUNET_CLIENT_disconnect (sh->client);
    sh->client = NULL;
  }
  if (NULL != sh->task)
  {
    GNUNET_SCHEDULER_cancel (sh->task);
    sh->task = NULL;
  }
  for (i=0;i<sh->session_array_size;i++)
  {
    if (NULL != (ar = sh->session_array[i]))
    {
      GNUNET_HELLO_address_free (ar->address);
      GNUNET_free (ar);
      sh->session_array[i] = NULL;
    }
  }
  GNUNET_array_grow (sh->session_array,
                     sh->session_array_size,
                     0);
  GNUNET_free (sh);
}
Esempio n. 3
0
/**
 * Create a host to run peers and controllers on.
 *
 * @param id global host ID assigned to the host; 0 is
 *        reserved to always mean 'localhost'
 * @param hostname name of the host, use "NULL" for localhost
 * @param username username to use for the login; may be NULL
 * @param cfg the configuration to use as a template while starting a controller
 *          on this host.  Operation queue sizes specific to a host are also
 *          read from this configuration handle
 * @param port port number to use for ssh; use 0 to let ssh decide
 * @return handle to the host, NULL on error
 */
struct GNUNET_TESTBED_Host *
GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname,
                                    const char *username,
                                    const struct GNUNET_CONFIGURATION_Handle
                                    *cfg,
                                    uint16_t port)
{
  struct GNUNET_TESTBED_Host *host;
  unsigned int new_size;

  if ((id < host_list_size) && (NULL != host_list[id]))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id);
    return NULL;
  }
  host = GNUNET_new (struct GNUNET_TESTBED_Host);
  host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL;
  host->username = (NULL != username) ? GNUNET_strdup (username) : NULL;
  host->id = id;
  host->port = (0 == port) ? 22 : port;
  host->cfg = GNUNET_CONFIGURATION_dup (cfg);
  host->opq_parallel_overlay_connect_operations =
      GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE,
                                              UINT_MAX);
  new_size = host_list_size;
  while (id >= new_size)
    new_size += HOST_LIST_GROW_STEP;
  if (new_size != host_list_size)
    GNUNET_array_grow (host_list, host_list_size, new_size);
  GNUNET_assert (id < host_list_size);
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding host with id: %u\n", host->id);
  host_list[id] = host;
  return host;
}
Esempio n. 4
0
/**
 * Intern an peer identity.  If the identity is already known, its
 * reference counter will be increased by one.
 *
 * @param pid identity to intern
 * @return the interned identity.
 */
GNUNET_PEER_Id
GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid)
{
  GNUNET_PEER_Id ret;
  struct PeerEntry *e;
  unsigned int i;

  if (NULL == pid)
    return 0;
  if (NULL == map)
    map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
  e = GNUNET_CONTAINER_multipeermap_get (map, pid);
  if (NULL != e)
  {
    GNUNET_assert (e->rc > 0);
    e->rc++;
    return e->pid;
  }
  ret = free_list_start;
  if (ret == size)
  {
    GNUNET_array_grow (table, size, size + 16);
    for (i = ret; i < size; i++)
    {
      table[i] = GNUNET_new (struct PeerEntry);
      table[i]->pid = i + 1;
    }
  }
/**
 * Delete the given value, removing it from the plugin's data
 * structures.
 *
 * @param plugin the plugin
 * @param value value to delete
 */
static void
delete_value (struct Plugin *plugin,
	      struct Value *value)
{
  GNUNET_assert (GNUNET_YES ==
		 GNUNET_CONTAINER_multihashmap_remove (plugin->keyvalue,
						       &value->key,
						       value));
  GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->expire_heap));
  GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->replication_heap));
  if (0 == value->anonymity)
  {
    struct ZeroAnonByType *zabt;

    for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next)
      if (zabt->type == value->type)
	break;
    GNUNET_assert (NULL != zabt);
    zabt->array[value->zero_anon_offset] = zabt->array[--zabt->array_pos];
    zabt->array[value->zero_anon_offset]->zero_anon_offset = value->zero_anon_offset;
    if (0 == zabt->array_pos)
    {
      GNUNET_array_grow (zabt->array,
			 zabt->array_size,
			 0);
      GNUNET_CONTAINER_DLL_remove (plugin->zero_head,
				   plugin->zero_tail,
				   zabt);
      GNUNET_free (zabt);
    }
  }
  plugin->size -= value->size;
  GNUNET_free (value);
}
/**
 * Store an item in the datastore.
 *
 * @param cls closure
 * @param key key for the item
 * @param size number of bytes in data
 * @param data content stored
 * @param type type of the content
 * @param priority priority of the content
 * @param anonymity anonymity-level for the content
 * @param replication replication-level for the content
 * @param expiration expiration time for the content
 * @param msg set to error message
 * @return GNUNET_OK on success
 */
static int
heap_plugin_put (void *cls, 
		 const struct GNUNET_HashCode * key, 
		 uint32_t size,
		 const void *data, 
		 enum GNUNET_BLOCK_Type type,
		 uint32_t priority, uint32_t anonymity,
		 uint32_t replication,
		 struct GNUNET_TIME_Absolute expiration, char **msg)
{
  struct Plugin *plugin = cls;
  struct Value *value;

  value = GNUNET_malloc (sizeof (struct Value) + size);
  value->key = *key;
  value->data = &value[1];
  value->expire_heap = GNUNET_CONTAINER_heap_insert (plugin->by_expiration,
						     value,
						     expiration.abs_value);
  value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication,
							  value,
							  replication);
  value->expiration = expiration;
  if (0 == anonymity)
  {
    struct ZeroAnonByType *zabt;

    for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next)
      if (zabt->type == type)
	break;
    if (NULL == zabt)
    {
      zabt = GNUNET_malloc (sizeof (struct ZeroAnonByType));
      zabt->type = type;
      GNUNET_CONTAINER_DLL_insert (plugin->zero_head,
				   plugin->zero_tail,
				   zabt);
    }
    if (zabt->array_size == zabt->array_pos)
    {
      GNUNET_array_grow (zabt->array,
			 zabt->array_size,
			 zabt->array_size * 2 + 4);
    }
    value->zero_anon_offset = zabt->array_pos;
    zabt->array[zabt->array_pos++] = value;
  }
  value->size = size;
  value->priority = priority;
  value->anonymity = anonymity;
  value->replication = replication;
  value->type = type;
  memcpy (&value[1], data, size);
  GNUNET_CONTAINER_multihashmap_put (plugin->keyvalue,
				     &value->key,
				     value,
				     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  plugin->size += size;
  return GNUNET_OK;
}
Esempio n. 7
0
/**
 * @brief Set the peer flag to living and
 *        call the pending operations on this peer.
 *
 * Also adds peer to #valid_peers.
 *
 * @param peer_ctx the #PeerContext of the peer to set live
 */
static void
set_peer_live (struct PeerContext *peer_ctx)
{
  struct GNUNET_PeerIdentity *peer;
  unsigned int i;

  peer = &peer_ctx->peer_id;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "Peer %s is live and valid, calling %i pending operations on it\n",
      GNUNET_i2s (peer),
      peer_ctx->num_pending_ops);

  if (NULL != peer_ctx->liveliness_check_pending)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Removing pending liveliness check for peer %s\n",
         GNUNET_i2s (&peer_ctx->peer_id));
    // TODO wait until cadet sets mq->cancel_impl
    //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
    GNUNET_free (peer_ctx->liveliness_check_pending);
    peer_ctx->liveliness_check_pending = NULL;
  }

  (void) add_valid_peer (peer);
  set_peer_flag (peer_ctx, Peers_ONLINE);

  /* Call pending operations */
  for (i = 0; i < peer_ctx->num_pending_ops; i++)
  {
    peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
  }
  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
}
Esempio n. 8
0
/**
 * Destroy connection with the service.  This will automatically
 * cancel any pending "receive" request (however, the handler will
 * *NOT* be called, not even with a NULL message).  Any pending
 * transmission request will also be cancelled UNLESS the callback for
 * the transmission request has already been called, in which case the
 * transmission 'finish_pending_write' argument determines whether or
 * not the write is guaranteed to complete before the socket is fully
 * destroyed (unless, of course, there is an error with the server in
 * which case the message may still be lost).
 *
 * @param client handle to the service connection
 */
void
GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client)
{
  if (GNUNET_YES == client->in_receive)
  {
    GNUNET_CONNECTION_receive_cancel (client->connection);
    client->in_receive = GNUNET_NO;
  }
  if (NULL != client->th)
  {
    GNUNET_CLIENT_notify_transmit_ready_cancel (client->th);
    client->th = NULL;
  }
  if (NULL != client->connection)
  {
    GNUNET_CONNECTION_destroy (client->connection);
    client->connection = NULL;
  }
  if (GNUNET_SCHEDULER_NO_TASK != client->receive_task)
  {
    GNUNET_SCHEDULER_cancel (client->receive_task);
    client->receive_task = GNUNET_SCHEDULER_NO_TASK;
  }
  if (NULL != client->tag)
  {
    GNUNET_free (client->tag);
    client->tag = NULL;
  }
  client->receiver_handler = NULL;
  GNUNET_array_grow (client->received_buf, client->received_size, 0);
  GNUNET_free (client->service_name);
  GNUNET_free (client);
}
Esempio n. 9
0
/**
 * Destructor that frees the KSK cache.
 */
void __attribute__ ((destructor)) GNUNET_CRYPTO_ksk_fini ()
{
  unsigned int i;

  for (i = 0; i < cacheSize; i++)
  {
    GNUNET_free (cache[i]->pke);
    GNUNET_free (cache[i]);
  }
  GNUNET_array_grow (cache, cacheSize, 0);
}
Esempio n. 10
0
/**
 * Callback function for data received from the network.  Note that
 * both "available" and "errCode" would be 0 if the read simply timed out.
 *
 * @param cls closure
 * @param buf pointer to received data
 * @param available number of bytes availabe in "buf",
 *        possibly 0 (on errors)
 * @param addr address of the sender
 * @param addrlen size of addr
 * @param errCode value of errno (on errors receiving)
 */
static void
receive_helper (void *cls, const void *buf, size_t available,
                const struct sockaddr *addr, socklen_t addrlen, int errCode)
{
  struct GNUNET_CLIENT_Connection *client = cls;
  struct GNUNET_TIME_Relative remaining;
  GNUNET_CLIENT_MessageHandler receive_handler;
  void *receive_handler_cls;

  GNUNET_assert (GNUNET_NO == client->msg_complete);
  GNUNET_assert (GNUNET_YES == client->in_receive);
  client->in_receive = GNUNET_NO;
  if ((0 == available) || (NULL == client->connection) || (0 != errCode))
  {
    /* signal timeout! */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n",
         (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL",
         STRERROR (errCode));
    if (NULL != (receive_handler = client->receiver_handler))
    {
      receive_handler_cls = client->receiver_handler_cls;
      client->receiver_handler = NULL;
      receive_handler (receive_handler_cls, NULL);
    }
    return;
  }
  /* FIXME: optimize for common fast case where buf contains the
   * entire message and we need no copying... */

  /* slow path: append to array */
  if (client->received_size < client->received_pos + available)
    GNUNET_array_grow (client->received_buf, client->received_size,
                       client->received_pos + available);
  memcpy (&client->received_buf[client->received_pos], buf, available);
  client->received_pos += available;
  check_complete (client);
  /* check for timeout */
  remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout);
  if (0 == remaining.rel_value)
  {
    /* signal timeout! */
    if (NULL != client->receiver_handler)
      client->receiver_handler (client->receiver_handler_cls, NULL);
    return;
  }
  /* back to receive -- either for more data or to call callback! */
  GNUNET_CLIENT_receive (client, client->receiver_handler,
                         client->receiver_handler_cls, remaining);
}
Esempio n. 11
0
/**
 * Stop async DHT-get.
 *
 * @param get_handle handle to the GET operation to stop
 */
void
GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle)
{
  struct GNUNET_DHT_Handle *handle;
  const struct GNUNET_DHT_ClientGetMessage *get_msg;
  struct GNUNET_DHT_ClientGetStopMessage *stop_msg;
  struct PendingMessage *pending;

  handle = get_handle->message->handle;
  get_msg =
      (const struct GNUNET_DHT_ClientGetMessage *) get_handle->message->msg;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Sending STOP for %s to DHT via %p\n",
       GNUNET_h2s (&get_msg->key), handle);
  /* generate STOP */
  pending =
      GNUNET_malloc (sizeof (struct PendingMessage) +
                     sizeof (struct GNUNET_DHT_ClientGetStopMessage));
  stop_msg = (struct GNUNET_DHT_ClientGetStopMessage *) &pending[1];
  pending->msg = &stop_msg->header;
  pending->handle = handle;
  pending->free_on_send = GNUNET_YES;
  stop_msg->header.size =
      htons (sizeof (struct GNUNET_DHT_ClientGetStopMessage));
  stop_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP);
  stop_msg->reserved = htonl (0);
  stop_msg->unique_id = get_msg->unique_id;
  stop_msg->key = get_msg->key;
  GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
                               pending);
  pending->in_pending_queue = GNUNET_YES;

  /* remove 'GET' from active status */
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (handle->active_requests,
                                                       &get_handle->key,
                                                       get_handle));
  if (GNUNET_YES == get_handle->message->in_pending_queue)
  {
    GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail,
                                 get_handle->message);
    get_handle->message->in_pending_queue = GNUNET_NO;
  }
  GNUNET_free (get_handle->message);
  GNUNET_array_grow (get_handle->seen_results,
		     get_handle->seen_results_end,
		     0);
  GNUNET_free (get_handle);
  process_pending_messages (handle);
}
/**
 * Handler for "GET result seen" messages from the client.
 *
 * @param cls closure for the service
 * @param client the client we received this message from
 * @param message the actual message received
 */
static void
handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client,
				  const struct GNUNET_MessageHeader *message)
{
  const struct GNUNET_DHT_ClientGetResultSeenMessage *seen;
  uint16_t size;
  unsigned int hash_count;
  unsigned int old_count;
  const struct GNUNET_HashCode *hc;
  struct FindByUniqueIdContext fui_ctx;
  struct ClientQueryRecord *cqr;

  size = ntohs (message->size);
  if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message;
  hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode);
  if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  hc = (const struct GNUNET_HashCode*) &seen[1];
  fui_ctx.unique_id = seen->unique_id;
  fui_ctx.cqr = NULL;
  GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
					      &seen->key,
					      &find_by_unique_id,
					      &fui_ctx);
  if (NULL == (cqr = fui_ctx.cqr))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  /* finally, update 'seen' list */
  old_count = cqr->seen_replies_count;
  GNUNET_array_grow (cqr->seen_replies,
		     cqr->seen_replies_count,
		     cqr->seen_replies_count + hash_count);
  memcpy (&cqr->seen_replies[old_count],
	  hc,
	  sizeof (struct GNUNET_HashCode) * hash_count);
}
Esempio n. 13
0
/**
 * Initialize the ATS subsystem.
 *
 * @param cfg configuration to use
 * @param suggest_cb notification to call whenever the suggestation changed
 * @param suggest_cb_cls closure for @a suggest_cb
 * @return ats context
 */
struct GNUNET_ATS_SchedulingHandle *
GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
                            GNUNET_ATS_AddressSuggestionCallback suggest_cb,
                            void *suggest_cb_cls)
{
  struct GNUNET_ATS_SchedulingHandle *sh;

  sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle);
  sh->cfg = cfg;
  sh->suggest_cb = suggest_cb;
  sh->suggest_cb_cls = suggest_cb_cls;
  GNUNET_array_grow (sh->session_array,
                     sh->session_array_size,
                     4);
  reconnect (sh);
  return sh;
}
Esempio n. 14
0
/**
 * Deterministically (!) create a hostkey using only the
 * given HashCode as input to the PRNG.
 *
 * @param hc hash code to generate the key from
 * @return corresponding private key; must not be freed!
 */
struct GNUNET_CRYPTO_RsaPrivateKey *
GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode * hc)
{
  struct KBlockKeyCacheLine *line;
  unsigned int i;

  for (i = 0; i < cacheSize; i++)  
    if (0 == memcmp (hc, &cache[i]->hc, sizeof (struct GNUNET_HashCode)))
      return GNUNET_CRYPTO_rsa_decode_key ((const char*) cache[i]->pke,
					   ntohs (cache[i]->pke->len));  
  line = GNUNET_malloc (sizeof (struct KBlockKeyCacheLine));
  line->hc = *hc;
  line->pke = makeKblockKeyInternal (hc);
  GNUNET_array_grow (cache, cacheSize, cacheSize + 1);
  cache[cacheSize - 1] = line;
  return GNUNET_CRYPTO_rsa_decode_key ((const char*) line->pke,
				       ntohs (line->pke->len));
}
Esempio n. 15
0
/**
 * Tell the DHT not to return any of the following known results
 * to this client.
 *
 * @param get_handle get operation for which results should be filtered
 * @param num_results number of results to be blocked that are
 *        provided in this call (size of the @a results array)
 * @param results array of hash codes over the 'data' of the results
 *        to be blocked
 */
void
GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle,
				     unsigned int num_results,
				     const struct GNUNET_HashCode *results)
{
  unsigned int needed;

  needed = get_handle->seen_results_end + num_results;
  if (needed > get_handle->seen_results_size)
    GNUNET_array_grow (get_handle->seen_results,
		       get_handle->seen_results_size,
		       needed);
  memcpy (&get_handle->seen_results[get_handle->seen_results_end],
	  results,
	  num_results * sizeof (struct GNUNET_HashCode));
  get_handle->seen_results_end += num_results;
  queue_filter_messages (get_handle);
  process_pending_messages (get_handle->dht_handle);
}
/**
 * Iterator over hash map entries that frees all entries
 * associated with the given client.
 *
 * @param cls client to search for in source routes
 * @param key current key code (ignored)
 * @param value value in the hash map, a ClientQueryRecord
 * @return #GNUNET_YES (we should continue to iterate)
 */
static int
remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value)
{
  struct ClientList *client = cls;
  struct ClientQueryRecord *record = value;

  if (record->client != client)
    return GNUNET_YES;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Removing client %p's record for key %s\n", client,
              GNUNET_h2s (key));
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (forward_map, key,
                                                       record));
  if (NULL != record->hnode)
    GNUNET_CONTAINER_heap_remove_node (record->hnode);
  GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0);
  GNUNET_free (record);
  return GNUNET_YES;
}
/**
 * Extend path @a path by the @a num_peers from the @a peers
 * array, assuming the owners past the current owner want it.
 *
 * @param path path to extend
 * @param peers list of peers beyond the end of @a path
 * @param num_peers length of the @a peers array
 */
static void
extend_path (struct CadetPeerPath *path,
             struct CadetPeer **peers,
             unsigned int num_peers)
{
  unsigned int old_len = path->entries_length;
  struct GNUNET_CONTAINER_HeapNode *hn;
  int i;

  /* If we extend an existing path, detach it from the
     old owner and re-attach to the new one */
  hn = NULL;
  for (i=num_peers-1;i>=0;i--)
  {
    /* FIXME: note that path->desirability is used, but not yet updated here! */
    hn = GCP_attach_path (peers[i],
                          path,
                          old_len + (unsigned int) i);
    if (NULL != hn)
      break;
  }
  if (NULL == hn)
    return; /* none of the peers is interested in this path */
  GCP_detach_path (path->entries[old_len-1].peer,
                   path,
                   path->hn);
  path->hn = hn;
  GNUNET_array_grow (path->entries,
                     path->entries_length,
                     old_len + i);
  for (;i >= 0;i--)
  {
    struct CadetPeerPathEntry *entry = &path->entries[old_len + i];

    entry->peer = peers[i];
    entry->path = path;
    GCP_path_entry_add (entry->peer,
                        entry,
                        old_len + i);
  }
}
Esempio n. 18
0
/**
 * Get an available session ID.
 *
 * @param sh our handle
 * @return an unused slot, but never NOT_FOUND (0)
 */
static uint32_t
find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh)
{
  static uint32_t off;
  uint32_t i;

  i = 0;
  while ( ( (NOT_FOUND == off) ||
            (NULL != sh->session_array[off % sh->session_array_size]) ) &&
          (i < sh->session_array_size) )
  {
    off++;
    i++;
  }
  if ( (NOT_FOUND != off % sh->session_array_size) &&
       (NULL == sh->session_array[off % sh->session_array_size]) )
    return off;
  i = sh->session_array_size;
  GNUNET_array_grow (sh->session_array,
                     sh->session_array_size,
                     sh->session_array_size * 2);
  return i;
}
/**
 * Callback that processes each of the known HELLOs for the
 * hostlist response construction.
 *
 * @param cls closure, NULL
 * @param peer id of the peer, NULL for last call
 * @param hello hello message for the peer (can be NULL)
 * @param err_msg message
 */
static void
host_processor (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_HELLO_Message *hello,
                const char *err_msg)
{
  size_t old;
  size_t s;
  int has_addr;

  if (NULL != err_msg)
  {
    GNUNET_assert (NULL == peer);
    builder->pitr = NULL;
    GNUNET_free_non_null (builder->data);
    GNUNET_free (builder);
    builder = NULL;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                _("Error in communication with PEERINFO service: %s\n"),
                err_msg);
    return;
  }
  if (NULL == peer)
  {
    builder->pitr = NULL;
    finish_response ();
    return;
  }
  if (NULL == hello)
    return;
  has_addr = GNUNET_NO;
  GNUNET_HELLO_iterate_addresses (hello,
                                  GNUNET_NO,
                                  &check_has_addr,
                                  &has_addr);
  if (GNUNET_NO == has_addr)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "HELLO for peer `%4s' has no address, not suitable for hostlist!\n",
                GNUNET_i2s (peer));
    GNUNET_STATISTICS_update (stats,
                              gettext_noop
                              ("HELLOs without addresses encountered (ignored)"),
                              1, GNUNET_NO);
    return;
  }
  old = builder->size;
  s = GNUNET_HELLO_size (hello);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
              (unsigned int) s,
              "HELLO",
              GNUNET_i2s (peer));
  if ( (old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
       (old + s >= MAX_BYTES_PER_HOSTLISTS) )
  {
    /* too large, skip! */
    GNUNET_STATISTICS_update (stats,
                              gettext_noop
                              ("bytes not included in hostlist (size limit)"),
                              s, GNUNET_NO);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Adding peer `%s' to hostlist (%u bytes)\n",
              GNUNET_i2s (peer),
              (unsigned int) s);
  GNUNET_array_grow (builder->data,
                     builder->size,
                     old + s);
  memcpy (&builder->data[old],
          hello,
          s);
}
Esempio n. 20
0
/**
 * Process a given reply that might match the given
 * request.
 *
 * @param cls the `struct GNUNET_DHT_ClientResultMessage`
 * @param key query of the request
 * @param value the `struct GNUNET_DHT_RouteHandle` of a request matching the same key
 * @return #GNUNET_YES to continue to iterate over all results,
 *         #GNUNET_NO if the reply is malformed or we found a matching request
 */
static int
process_reply (void *cls,
	       const struct GNUNET_HashCode *key,
	       void *value)
{
  const struct GNUNET_DHT_ClientResultMessage *dht_msg = cls;
  struct GNUNET_DHT_GetHandle *get_handle = value;
  const struct GNUNET_PeerIdentity *put_path;
  const struct GNUNET_PeerIdentity *get_path;
  struct GNUNET_HashCode hc;
  uint32_t put_path_length;
  uint32_t get_path_length;
  size_t data_length;
  size_t msize;
  size_t meta_length;
  const void *data;

  if (dht_msg->unique_id != get_handle->unique_id)
  {
    /* UID mismatch */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key),
         dht_msg->unique_id, get_handle->unique_id);
    return GNUNET_YES;
  }
  msize = ntohs (dht_msg->header.size);
  put_path_length = ntohl (dht_msg->put_path_length);
  get_path_length = ntohl (dht_msg->get_path_length);
  meta_length =
      sizeof (struct GNUNET_DHT_ClientResultMessage) +
      sizeof (struct GNUNET_PeerIdentity) * (get_path_length + put_path_length);
  if ((msize < meta_length) ||
      (get_path_length >
       GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) ||
      (put_path_length >
       GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
  {
    GNUNET_break (0);
    return GNUNET_NO;
  }
  data_length = msize - meta_length;
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving %u byte reply for %s to application\n",
       (unsigned int) data_length, GNUNET_h2s (key));
  put_path = (const struct GNUNET_PeerIdentity *) &dht_msg[1];
  get_path = &put_path[put_path_length];
  data = &get_path[get_path_length];
  /* remember that we've seen this result */
  GNUNET_CRYPTO_hash (data, data_length, &hc);
  if (get_handle->seen_results_size == get_handle->seen_results_end)
    GNUNET_array_grow (get_handle->seen_results,
		       get_handle->seen_results_size,
		       get_handle->seen_results_size * 2 + 1);
  GNUNET_assert (get_handle->seen_results_end == get_handle->seen_results_transmission_offset);
  get_handle->seen_results[get_handle->seen_results_end++] = hc;
  /* no need to block it explicitly, service already knows about it! */
  get_handle->seen_results_transmission_offset++;
  get_handle->iter (get_handle->iter_cls,
                    GNUNET_TIME_absolute_ntoh (dht_msg->expiration), key,
                    get_path, get_path_length, put_path, put_path_length,
                    ntohl (dht_msg->type), data_length, data);
  return GNUNET_NO;
}
/**
 * Actually start the process for the given service.
 *
 * @param sl identifies service to start
 */
static void
start_process (struct ServiceList *sl)
{
  char *loprefix;
  char *options;
  char *optpos;
  char *optend;
  const char *next;
  int use_debug;
  char b;
  char *val;
  struct ServiceListeningInfo *sli;
  SOCKTYPE *lsocks;
  unsigned int ls;

  /* calculate listen socket list */
  lsocks = NULL;
  ls = 0;
  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
    {
      GNUNET_array_append (lsocks, ls,
			   GNUNET_NETWORK_get_fd (sli->listen_socket));
      if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK)
	{
	  GNUNET_SCHEDULER_cancel (sli->accept_task);
	  sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
	}
    }
#if WINDOWS
  GNUNET_array_append (lsocks, ls, INVALID_SOCKET);
#else
  GNUNET_array_append (lsocks, ls, -1);
#endif

  /* obtain configuration */
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX",
					     &loprefix))
    loprefix = GNUNET_strdup (prefix_command);
  if (GNUNET_OK !=
      GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS",
					     &options))
    {
      options = GNUNET_strdup (final_option);
      if (NULL == strstr (options, "%"))
	{
	  /* replace '{}' with service name */
	  while (NULL != (optpos = strstr (options, "{}")))
	    {
	      optpos[0] = '%';
	      optpos[1] = 's';
	      GNUNET_asprintf (&optpos, options, sl->name);
	      GNUNET_free (options);
	      options = optpos;
	    }
	  /* replace '$PATH' with value associated with "PATH" */
	  while (NULL != (optpos = strstr (options, "$")))
	    {
	      optend = optpos + 1;
	      while (isupper ((unsigned char) *optend))
		optend++;
	      b = *optend;
	      if ('\0' == b)
		next = "";
	      else
		next = optend + 1;
	      *optend = '\0';
	      if (GNUNET_OK !=
		  GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
							 optpos + 1, &val))
		val = GNUNET_strdup ("");
	      *optpos = '\0';
	      GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next);
	      GNUNET_free (options);
	      GNUNET_free (val);
	      options = optpos;
	    }
	}
    }
  use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");

  /* actually start process */
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Starting service `%s' using binary `%s' and configuration `%s'\n",
	      sl->name, sl->binary, sl->config);
  GNUNET_assert (NULL == sl->proc);
  if (GNUNET_YES == use_debug)
    sl->proc =
      do_start_process (sl->pipe_control,
			lsocks, loprefix, sl->binary, "-c", sl->config, "-L",
			"DEBUG", options, NULL);
  else
    sl->proc =
      do_start_process (sl->pipe_control,
			lsocks, loprefix, sl->binary, "-c", sl->config,
			options, NULL);
  if (sl->proc == NULL)
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"),
		sl->name);
  else
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"),
		sl->name);
  /* clean up */
  GNUNET_free (loprefix);
  GNUNET_free (options);
  GNUNET_array_grow (lsocks, ls, 0);
}
Esempio n. 22
0
/**
 * @brief Remove peer
 *
 * @param peer the peer to clean
 * @return #GNUNET_YES if peer was removed
 *         #GNUNET_NO  otherwise
 */
int
Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
{
  struct PeerContext *peer_ctx;

  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
  {
    return GNUNET_NO;
  }

  peer_ctx = get_peer_ctx (peer);
  set_peer_flag (peer_ctx, Peers_TO_DESTROY);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Going to remove peer %s\n",
       GNUNET_i2s (&peer_ctx->peer_id));
  Peers_unset_peer_flag (peer, Peers_ONLINE);

  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
  while (NULL != peer_ctx->pending_messages_head)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Removing unsent %s\n",
        peer_ctx->pending_messages_head->type);
    remove_pending_message (peer_ctx->pending_messages_head);
  }
  /* If we are still waiting for notification whether this peer is live
   * cancel the according task */
  if (NULL != peer_ctx->liveliness_check_pending)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
         "Removing pending liveliness check for peer %s\n",
         GNUNET_i2s (&peer_ctx->peer_id));
    // TODO wait until cadet sets mq->cancel_impl
    //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
    GNUNET_free (peer_ctx->liveliness_check_pending);
    peer_ctx->liveliness_check_pending = NULL;
  }
  if (NULL != peer_ctx->send_channel)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Destroying send channel\n");
    GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
    peer_ctx->send_channel = NULL;
  }
  if (NULL != peer_ctx->recv_channel)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Destroying recv channel\n");
    GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
    peer_ctx->recv_channel = NULL;
  }
  if (NULL != peer_ctx->mq)
  {
    GNUNET_MQ_destroy (peer_ctx->mq);
    peer_ctx->mq = NULL;
  }

  GNUNET_free (peer_ctx->send_channel_flags);
  GNUNET_free (peer_ctx->recv_channel_flags);

  if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
  }
  GNUNET_free (peer_ctx);
  return GNUNET_YES;
}
Esempio n. 23
0
static int
check ()
{
#define MAX_TESTVAL 1024
  char *ptrs[MAX_TESTVAL];
  int i;
  int j;
  int k;
  unsigned int ui;

  /* GNUNET_malloc/GNUNET_free test */
  k = 352;                      /* random start value */
  for (i = 1; i < MAX_TESTVAL; i++)
  {
    ptrs[i] = GNUNET_malloc (i);
    for (j = 0; j < i; j++)
      ptrs[i][j] = k++;
  }

  for (i = MAX_TESTVAL - 1; i >= 1; i--)
  {
    for (j = i - 1; j >= 0; j--)
      if (ptrs[i][j] != (char) --k)
        return 1;
    GNUNET_free (ptrs[i]);
  }

  /* GNUNET_free_non_null test */
  GNUNET_free_non_null (NULL);
  GNUNET_free_non_null (GNUNET_malloc (4));

  /* GNUNET_strdup tests */
  ptrs[0] = GNUNET_strdup ("bar");
  if (0 != strcmp (ptrs[0], "bar"))
    return 3;
  /* now realloc */
  ptrs[0] = GNUNET_realloc (ptrs[0], 12);
  strcpy (ptrs[0], "Hello World");

  GNUNET_free (ptrs[0]);
  GNUNET_asprintf (&ptrs[0], "%s %s", "Hello", "World");
  GNUNET_assert (strlen (ptrs[0]) == 11);
  GNUNET_free (ptrs[0]);

  /* GNUNET_array_grow tests */
  ptrs[0] = NULL;
  ui = 0;
  GNUNET_array_grow (ptrs[0], ui, 42);
  if (ui != 42)
    return 4;
  GNUNET_array_grow (ptrs[0], ui, 22);
  if (ui != 22)
    return 5;
  for (j = 0; j < 22; j++)
    ptrs[0][j] = j;
  GNUNET_array_grow (ptrs[0], ui, 32);
  for (j = 0; j < 22; j++)
    if (ptrs[0][j] != j)
      return 6;
  for (j = 22; j < 32; j++)
    if (ptrs[0][j] != 0)
      return 7;
  GNUNET_array_grow (ptrs[0], ui, 0);
  if (i != 0)
    return 8;
  if (ptrs[0] != NULL)
    return 9;


  return 0;
}
Esempio n. 24
0
/**
 * Grow or shrink the size of the sampler.
 *
 * @param sampler the sampler to resize.
 * @param new_size the new size of the sampler
 */
static void
sampler_resize (struct RPS_Sampler *sampler, unsigned int new_size)
{
  unsigned int old_size;
  uint32_t i;

  // TODO check min and max size

  old_size = sampler->sampler_size;

  if (old_size > new_size)
  { /* Shrinking */

    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Shrinking sampler %d -> %d\n",
         old_size,
         new_size);

    to_file (sampler->file_name,
         "Shrinking sampler %d -> %d",
         old_size,
         new_size);

    for (i = new_size ; i < old_size ; i++)
    {
      to_file (sampler->file_name,
               "-%" PRIu32 ": %s",
               i,
               sampler->sampler_elements[i]->file_name);
    }

    GNUNET_array_grow (sampler->sampler_elements,
                       sampler->sampler_size,
                       new_size);
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "sampler->sampler_elements now points to %p\n",
         sampler->sampler_elements);

  }
  else if (old_size < new_size)
  { /* Growing */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Growing sampler %d -> %d\n",
         old_size,
         new_size);

    to_file (sampler->file_name,
         "Growing sampler %d -> %d",
         old_size,
         new_size);

    GNUNET_array_grow (sampler->sampler_elements,
        sampler->sampler_size,
        new_size);

    for (i = old_size ; i < new_size ; i++)
    { /* Add new sampler elements */
      sampler->sampler_elements[i] = RPS_sampler_elem_create ();

      to_file (sampler->file_name,
               "+%" PRIu32 ": %s",
               i,
               sampler->sampler_elements[i]->file_name);
    }
  }
  else
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG, "Size remains the same -- nothing to do\n");
    return;
  }

  GNUNET_assert (sampler->sampler_size == new_size);
}