Exemplo n.º 1
0
/**
 * Remove peer from view
 *
 * @param peer the peer to remove
 *
 * @return GNUNET_OK if view contained peer and removed it successfully
 *         GNUNET_NO if view does not contain peer
 */
int
View_remove_peer (const struct GNUNET_PeerIdentity *peer)
{
    uint32_t *index;
    uint32_t *swap_index;
    uint32_t last_index;

    if (GNUNET_NO == View_contains_peer (peer))
    {
        return GNUNET_NO;
    }
    index = GNUNET_CONTAINER_multipeermap_get (mpm, peer);
    GNUNET_assert (NULL != index);
    last_index = View_size () - 1;
    if (*index < last_index)
    {   /* Fill the 'gap' in the array with the last peer */
        array[*index] = array[last_index];
        GNUNET_assert (GNUNET_YES == View_contains_peer (&array[last_index]));
        swap_index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[last_index]);
        GNUNET_assert (NULL != swap_index);
        *swap_index = *index;
        GNUNET_free (index);
    }
    GNUNET_CONTAINER_multipeermap_remove_all (mpm, peer);
    return GNUNET_OK;
}
struct Node *
get_node (const struct GNUNET_PeerIdentity *id)
{
  struct Node * res;
  struct Node * tmp;

  res = NULL;
  tmp = NULL;
  tmp = GNUNET_CONTAINER_multipeermap_get (nodes_active, id);
  if (res == NULL)
    res = tmp;

  tmp = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, id);
  if (res == NULL)
    res = tmp;
  else
    GNUNET_break (0); /* Multiple instances */

  tmp = GNUNET_CONTAINER_multipeermap_get (nodes_requested, id);
  if (res == NULL)
    res = tmp;
  else
    GNUNET_break (0); /* Multiple instances */

  return res;
}
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);
}
/**
 * Free `struct PreferencePeer` entry in map.
 *
 * @param cls the `struct PreferenceClient` with the map
 * @param key the peer the entry is for
 * @param value the `struct PreferencePeer` entry to free
 * @return #GNUNET_OK (continue to iterate)
 */
static int
free_preference (void *cls,
                 const struct GNUNET_PeerIdentity *key,
                 void *value)
{
  struct PreferenceClient *pc = cls;
  struct PreferencePeer *p = value;
  struct PeerRelative *pr;

  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_remove (pc->peer2pref,
                                                       key,
                                                       p));
  GNUNET_free (p);
  pr = GNUNET_CONTAINER_multipeermap_get (preference_peers,
                                          key);
  GNUNET_assert (NULL != pr);
  GNUNET_assert (pr->num_clients > 0);
  pr->num_clients--;
  if (0 == pr->num_clients)
  {
    free_peer (NULL,
               key,
               pr);
  }
  return GNUNET_OK;
}
/**
 * The owning peer of this path is no longer interested in maintaining
 * it, so the path should be discarded or shortened (in case a
 * previous peer on the path finds the path desirable).
 *
 * @param path the path that is being released
 */
void
GCPP_release (struct CadetPeerPath *path)
{
  struct CadetPeerPathEntry *entry;

  path->hn = NULL;
  entry = &path->entries[path->entries_length - 1];
  while (1)
  {
    /* cut 'off' end of path, verifying it is not in use */
    GNUNET_assert (NULL ==
                   GNUNET_CONTAINER_multipeermap_get (path->connections,
                                                      GCP_get_id (entry->peer)));
    GCP_path_entry_remove (entry->peer,
                           entry,
                           path->entries_length - 1);
    path->entries_length--; /* We don't bother shrinking the 'entries' array,
                               as it's probably not worth it. */
    if (0 == path->entries_length)
      break; /* the end */

    /* see if new peer at the end likes this path any better */
    entry = &path->entries[path->entries_length - 1];
    path->hn = GCP_attach_path (entry->peer,
                                path,
                                path->entries_length);
    if (NULL != path->hn)
      return; /* yep, got attached, we are done. */
  }

  /* nobody wants us, discard the path */
  path_destroy (path);
}
Exemplo n.º 6
0
/**
 * Function called with information about a peers
 *
 * @param cls closure
 * @param peer identity of the peer, NULL for final callback when operation done
 * @param address binary address used to communicate with this peer,
 *  NULL on disconnect or when done
 * @param state current state this peer is in
 * @param state_timeout time out for the current state
 *
 */
static void
process_peer_monitoring_cb (void *cls, const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    enum GNUNET_TRANSPORT_PeerState state,
    struct GNUNET_TIME_Absolute state_timeout)
{
  struct MonitoredPeer *m;

  if (peer == NULL )
  {
    /* done */
    address_resolution_in_progress = GNUNET_NO;
    pic = NULL;
    if (GNUNET_SCHEDULER_NO_TASK != end)
      GNUNET_SCHEDULER_cancel (end);
    end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL );
    return;
  }

  if (GNUNET_SCHEDULER_NO_TASK != op_timeout)
    GNUNET_SCHEDULER_cancel (op_timeout);
  op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout,
      NULL );

  if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer)))
  {
    m = GNUNET_new (struct MonitoredPeer);
    GNUNET_CONTAINER_multipeermap_put (monitored_peers, peer,
        m, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  }
Exemplo n.º 7
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);
}
Exemplo n.º 8
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;
    }
  }
/**
 * Update the total releative preference for a peer by summing
 * up the relative preferences all clients have for this peer.
 *
 * @param id peer id of the peer for which we should do the update
 * @param kind the kind of preference value to update
 * @return the new relative preference
 */
static void
update_relative_values_for_peer (const struct GNUNET_PeerIdentity *id,
				 enum GNUNET_ATS_PreferenceKind kind)
{
  struct PreferenceClient *c_cur;
  struct SumContext sum_ctx;
  struct PeerRelative *rp;

  sum_ctx.f_rel_total = 0.0;
  sum_ctx.kind = kind;
  for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next)
    GNUNET_CONTAINER_multipeermap_get_multiple (c_cur->peer2pref,
                                                id,
                                                &sum_relative_preferences,
                                                &sum_ctx);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Total relative preference for peer `%s' for `%s' is %.3f\n",
       GNUNET_i2s (id),
       GNUNET_ATS_print_preference_type (kind),
       sum_ctx.f_rel_total);
  rp = GNUNET_CONTAINER_multipeermap_get (preference_peers,
                                          id);
  GNUNET_assert (NULL != rp);
  if (rp->f_rel[kind] != sum_ctx.f_rel_total)
  {
    rp->f_rel[kind] = sum_ctx.f_rel_total;
    GAS_plugin_notify_preference_changed (id,
                                          kind,
                                          rp->f_rel[kind]);
  }
}
/**
 * Add a host to the list and notify clients about this event
 *
 * @param identity the identity of the host
 * @return the HostEntry
 */
static struct HostEntry *
add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
{
  struct HostEntry *entry;
  struct ReadHostFileContext r;
  char *fn;

  entry = GNUNET_CONTAINER_multipeermap_get (hostmap, identity);
  if (NULL == entry)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding new peer `%s'\n", GNUNET_i2s (identity));
    GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1,
			      GNUNET_NO);
    entry = GNUNET_new (struct HostEntry);
    entry->identity = *identity;
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CONTAINER_multipeermap_put (hostmap, &entry->identity, entry,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    notify_all (entry);
    fn = get_host_filename (identity);
    if (NULL != fn)
    {
      read_host_file (fn, GNUNET_YES, &r);
      if (NULL != r.hello)
      	update_hello (identity, r.hello);
      if (NULL != r.friend_only_hello)
      	update_hello (identity, r.friend_only_hello);
      GNUNET_free_non_null (r.hello);
      GNUNET_free_non_null (r.friend_only_hello);
      GNUNET_free (fn);
    }
  }
/**
 * Find the entry for the given neighbour.
 *
 * @param peer identity of the neighbour
 * @return NULL if we are not connected, otherwise the
 *         neighbour's entry.
 */
static struct Neighbour *
find_neighbour (const struct GNUNET_PeerIdentity *peer)
{
  if (NULL == neighbours)
    return NULL;
  return GNUNET_CONTAINER_multipeermap_get (neighbours,
                                            peer);
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
/**
 * Ask the core to call @a notify once it is ready to transmit the
 * given number of bytes to the specified @a target.  Must only be
 * called after a connection to the respective peer has been
 * established (and the client has been informed about this).  You may
 * have one request of this type pending for each connected peer at
 * any time.  If a peer disconnects, the application MUST call
 * #GNUNET_CORE_notify_transmit_ready_cancel on the respective
 * transmission request, if one such request is pending.
 *
 * @param handle connection to core service
 * @param cork is corking allowed for this transmission?
 * @param priority how important is the message?
 * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES
 * @param target who should receive the message, never NULL (can be this peer's identity for loopback)
 * @param notify_size how many bytes of buffer space does @a notify want?
 * @param notify function to call when buffer space is available;
 *        will be called with NULL on timeout; clients MUST cancel
 *        all pending transmission requests DURING the disconnect
 *        handler
 * @param notify_cls closure for notify
 * @return non-NULL if the notify callback was queued,
 *         NULL if we can not even queue the request (request already pending);
 *         if NULL is returned, @a notify will NOT be called.
 */
struct GNUNET_CORE_TransmitHandle *
GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
                                   int cork,
                                   enum GNUNET_CORE_Priority priority,
                                   struct GNUNET_TIME_Relative maxdelay,
                                   const struct GNUNET_PeerIdentity *target,
                                   size_t notify_size,
                                   GNUNET_CONNECTION_TransmitReadyNotify notify,
                                   void *notify_cls)
{
  struct PeerRecord *pr;
  struct GNUNET_CORE_TransmitHandle *th;

  if (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
  {
     GNUNET_break (0);
     return NULL;
  }
  GNUNET_assert (NULL != notify);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Asking core for transmission of %u bytes to `%s'\n",
       (unsigned int) notify_size,
       GNUNET_i2s (target));
  pr = GNUNET_CONTAINER_multipeermap_get (handle->peers, target);
  if (NULL == pr)
  {
    /* attempt to send to peer that is not connected */
    GNUNET_break (0);
    return NULL;
  }
  if (NULL != pr->th.peer)
  {
    /* attempting to queue a second request for the same destination */
    GNUNET_break (0);
    return NULL;
  }
  GNUNET_assert (notify_size + sizeof (struct SendMessage) <
                 GNUNET_SERVER_MAX_MESSAGE_SIZE);
  th = &pr->th;
  memset (th, 0, sizeof (struct GNUNET_CORE_TransmitHandle));
  th->peer = pr;
  th->get_message = notify;
  th->get_message_cls = notify_cls;
  th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
  th->priority = priority;
  th->msize = notify_size;
  th->cork = cork;
  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task);
  pr->ntr_task =
    GNUNET_SCHEDULER_add_now (&run_request_next_transmission, pr);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Transmission request added to queue\n");
  return th;
}
Exemplo n.º 14
0
Arquivo: dv_api.c Projeto: tg-x/gnunet
/**
 * Send a message via DV service.
 *
 * @param sh service handle
 * @param target intended recpient
 * @param msg message payload
 * @param cb function to invoke when done
 * @param cb_cls closure for @a cb
 * @return handle to cancel the operation
 */
struct GNUNET_DV_TransmitHandle *
GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh,
		const struct GNUNET_PeerIdentity *target,
		const struct GNUNET_MessageHeader *msg,
		GNUNET_DV_MessageSentCallback cb,
		void *cb_cls)
{
  struct GNUNET_DV_TransmitHandle *th;
  struct GNUNET_DV_SendMessage *sm;
  struct ConnectedPeer *peer;

  if (ntohs (msg->size) + sizeof (struct GNUNET_DV_SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    return NULL;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Asked to send %u bytes of type %u to %s via %p\n",
       (unsigned int) ntohs (msg->size),
       (unsigned int) ntohs (msg->type),
       GNUNET_i2s (target),
       sh->client);
  peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                            target);
  if (NULL == peer)
  {
    GNUNET_break (0);
    return NULL;
  }
  th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) +
		      sizeof (struct GNUNET_DV_SendMessage) +
		      ntohs (msg->size));
  th->sh = sh;
  th->target = peer;
  th->cb = cb;
  th->cb_cls = cb_cls;
  th->msg = (const struct GNUNET_MessageHeader *) &th[1];
  sm = (struct GNUNET_DV_SendMessage *) &th[1];
  sm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND);
  sm->header.size = htons (sizeof (struct GNUNET_DV_SendMessage) +
			   ntohs (msg->size));
  if (0 == sh->uid_gen)
    sh->uid_gen = 1;
  th->uid = sh->uid_gen;
  sm->uid = htonl (sh->uid_gen++);
  /* use memcpy here as 'target' may not be sufficiently aligned */
  memcpy (&sm->target, target, sizeof (struct GNUNET_PeerIdentity));
  memcpy (&sm[1], msg, ntohs (msg->size));
  GNUNET_CONTAINER_DLL_insert_tail (sh->th_head,
                                    sh->th_tail,
                                    th);
  start_transmit (sh);
  return th;
}
/**
 * Method called whenever a given peer disconnects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 */
static void
core_disconnect_handler (void *cls,
			 const struct GNUNET_PeerIdentity * peer)
{
	struct Node *n;
	if (GNUNET_YES == is_me(peer))
		return;

	GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Disconnected from peer %s\n"),
			GNUNET_i2s (peer));

	if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
		cleanup_node (nodes_requested, peer, n);

	if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
		cleanup_node (nodes_active, peer, n);

	if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
		cleanup_node (nodes_inactive, peer, n);
}
/**
 * Find the next hop to send packet to .
 * @return next hop peer id
 */
struct GNUNET_PeerIdentity *
GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer,
                   struct GNUNET_PeerIdentity *destination_peer)
{
  struct RoutingTrail *trail;
  trail = (struct RoutingTrail *)(GNUNET_CONTAINER_multipeermap_get(routing_table,destination_peer));
    
  if(trail == NULL)
      return NULL;
    
  return trail->next_hop;
}
Exemplo n.º 17
0
/**
 * @brief Get the #PeerContext associated with a peer
 *
 * @param peer the peer id
 *
 * @return the #PeerContext
 */
static struct PeerContext *
get_peer_ctx (const struct GNUNET_PeerIdentity *peer)
{
  struct PeerContext *ctx;
  int ret;

  ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
  GNUNET_assert (GNUNET_YES == ret);
  ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
  GNUNET_assert (NULL != ctx);
  return ctx;
}
/**
 * Handler called by CORE when CORE is ready to transmit message
 *
 * @param cls closure with the `const struct GNUNET_PeerIdentity *` of
 *            the peer we are sending to
 * @param size size of buffer to copy message to
 * @param buf buffer to copy message to
 * @return number of bytes copied to @a buf
 */
static size_t
adv_transmit_ready (void *cls,
                    size_t size,
                    void *buf)
{
  const struct GNUNET_PeerIdentity *peer = cls;
  static uint64_t hostlist_adv_count;
  size_t transmission_size;
  size_t uri_size;              /* Including \0 termination! */
  struct GNUNET_MessageHeader header;
  char *cbuf;
  struct GNUNET_CORE_TransmitHandle *th;

  th = GNUNET_CONTAINER_multipeermap_get (advertisements,
                                          peer);
  GNUNET_assert (NULL != th);
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_remove (advertisements,
                                                       peer,
                                                       th));
  if (NULL == buf)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Transmission failed, buffer invalid!\n");
    return 0;
  }
  uri_size = strlen (hostlist_uri) + 1;
  transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
  header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
  header.size = htons (transmission_size);
  GNUNET_assert (size >= transmission_size);
  memcpy (buf,
          &header,
          sizeof (struct GNUNET_MessageHeader));
  cbuf = buf;
  memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)],
          hostlist_uri,
          uri_size);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sent advertisement message: Copied %u bytes into buffer!\n",
              (unsigned int) transmission_size);
  hostlist_adv_count++;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              " # Sent advertisement message: %u\n",
              hostlist_adv_count);
  GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# hostlist advertisements send"), 1,
                            GNUNET_NO);
  return transmission_size;
}
Exemplo n.º 19
0
/**
 * Search for a peer identity. The reference counter is not changed.
 *
 * @param pid identity to find
 * @return the interned identity or 0.
 */
GNUNET_PEER_Id
GNUNET_PEER_search (const struct GNUNET_PeerIdentity *pid)
{
  struct PeerEntry *e;

  if (NULL == pid)
    return 0;
  if (NULL == map)
    return 0;
  e = GNUNET_CONTAINER_multipeermap_get (map, pid);
  if (NULL == e)
    return 0;
  GNUNET_assert (e->rc > 0);
  return e->pid;
}
Exemplo n.º 20
0
/**
 * Clear the custom peer map
 *
 * @param c_peer_map the custom peer map to look in
 *
 * @return size of the map
 */
void
View_clear ()
{
    uint32_t i;
    uint32_t *index;

    for (i = 0; 0 < View_size (); i++)
    {   /* Need to free indices stored at peers */
        GNUNET_assert (GNUNET_YES ==
                       GNUNET_CONTAINER_multipeermap_contains (mpm, &array[i]));
        index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
        GNUNET_assert (NULL != index);
        GNUNET_free (index);
        GNUNET_CONTAINER_multipeermap_remove_all (mpm, &array[i]);
    }
    GNUNET_assert (0 == View_size ());
}
Exemplo n.º 21
0
/**
 * Function that decides if a connection is acceptable or not.
 * If we have a blacklist, only friends are allowed, so the check
 * is rather simple.
 *
 * @param cls closure
 * @param pid peer to approve or disapprove
 * @return #GNUNET_OK if the connection is allowed
 */
static int
blacklist_check (void *cls,
                 const struct GNUNET_PeerIdentity *pid)
{
  struct Peer *pos;

  pos = GNUNET_CONTAINER_multipeermap_get (peers,
                                           pid);
  if ( (NULL != pos) &&
       (GNUNET_YES == pos->is_friend))
    return GNUNET_OK;
  GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# peers blacklisted"),
                            1,
                            GNUNET_NO);
  return GNUNET_SYSERR;
}
Exemplo n.º 22
0
/**
 * Calculate ECC discrete logarithm for small factors.
 *
 * @param edc precalculated values, determine range of factors
 * @param input point on the curve to factor
 * @return `edc->max` if dlog failed, otherwise the factor
 */
int
GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
			gcry_mpi_point_t input)
{
  unsigned int K = ((edc->max + (edc->mem-1)) / edc->mem);
  gcry_mpi_point_t g;
  struct GNUNET_PeerIdentity key;
  gcry_mpi_point_t q;
  unsigned int i;
  int res;
  void *retp;

  g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
  GNUNET_assert (NULL != g);
  q = gcry_mpi_point_new (0);

  res = edc->max;
  for (i=0;i<=edc->max/edc->mem;i++)
  {
    if (0 == i)
      extract_pk (input, edc->ctx, &key);
    else
      extract_pk (q, edc->ctx, &key);
    retp = GNUNET_CONTAINER_multipeermap_get (edc->map,
					      &key);
    if (NULL != retp)
    {
      res = (((long) retp) - edc->max) * K - i;
      /* we continue the loop here to make the implementation
	 "constant-time". If we do not care about this, we could just
	 'break' here and do fewer operations... */
    }
    if (i == edc->max/edc->mem)
      break;
    /* q = q + g */
    if (0 == i)
      gcry_mpi_ec_add (q, input, g, edc->ctx);
    else
      gcry_mpi_ec_add (q, q, g, edc->ctx);
  }
  gcry_mpi_point_release (g);
  gcry_mpi_point_release (q);

  return res;
}
/**
 * Method called whenever a given peer disconnects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 */
static void
disconnect_handler (void *cls,
                    const struct GNUNET_PeerIdentity *peer)
{
  struct GNUNET_CORE_TransmitHandle *th;

  if (! advertising)
    return;
  th = GNUNET_CONTAINER_multipeermap_get (advertisements,
                                          peer);
  if (NULL == th)
    return;
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_remove (advertisements,
                                                       peer,
                                                       th));
  GNUNET_CORE_notify_transmit_ready_cancel (th);
}
Exemplo n.º 24
0
/**
 * This function is called whenever an encrypted HELLO message is
 * received.
 *
 * @param cls closure with the peer identity of the sender
 * @param message the actual HELLO message
 */
static void
handle_hello (void *cls,
	      const struct GNUNET_HELLO_Message *message)
{
  const struct GNUNET_PeerIdentity *other = cls;
  struct Peer *peer;
  struct GNUNET_PeerIdentity pid;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received encrypted HELLO from peer `%s'",
              GNUNET_i2s (other));
  GNUNET_assert (GNUNET_OK ==
		 GNUNET_HELLO_get_id (message,
				      &pid));
  GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# HELLO messages received"),
                            1,
                            GNUNET_NO);
  peer = GNUNET_CONTAINER_multipeermap_get (peers,
					    &pid);
  if (NULL == peer)
  {
    if ( (GNUNET_YES == friends_only) ||
         (friend_count < minimum_friend_count) )
      return;
  }
  else
  {
    if ( (GNUNET_YES != peer->is_friend) &&
         (GNUNET_YES == friends_only) )
      return;
    if ((GNUNET_YES != peer->is_friend) &&
        (friend_count < minimum_friend_count))
      return;
  }
  if (NULL != oh)
    GNUNET_TRANSPORT_offer_hello_cancel (oh);
  oh = GNUNET_TRANSPORT_offer_hello (cfg,
                                     &message->header,
                                     &done_offer_hello,
                                     NULL);
}
Exemplo n.º 25
0
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;
}
/**
 * Handle a request and send a response
 *
 * @param peer the source
 * @param message the message
 */
static void
handle_request (const struct GNUNET_PeerIdentity *peer,
		const struct GNUNET_MessageHeader *message)
{
  struct Node *n;
  struct NodeComCtx *e_ctx;
  const struct Experimentation_Request *rm = (const struct Experimentation_Request *) message;
  const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1];
  unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
  int c1;
  int c2;
  uint32_t ic;
  uint32_t ic_accepted;
  int make_active;

  if (ntohs (message->size) < sizeof (struct Experimentation_Request))
  {
    GNUNET_break (0);
    return;
  }
  ic = ntohl (rm->issuer_count);
  if (ntohs (message->size) !=
      sizeof (struct Experimentation_Request) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
  {
    GNUNET_break (0);
    return;
  }

  make_active = GNUNET_NO;
  if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
  {
    /* Nothing to do */
  }
  else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
  {
    GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n));
    if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
      {
	GNUNET_SCHEDULER_cancel (n->timeout_task);
	n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
      }
    update_stats (nodes_requested);
    make_active = GNUNET_YES;
  }
  else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
  {
    GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n));
    update_stats (nodes_inactive);
    make_active = GNUNET_YES;
  }
  else
  {
    /* Create new node */
    n = GNUNET_new (struct Node);
    n->id = *peer;
    n->capabilities = NONE;
    make_active = GNUNET_YES;
  }

  /* Update node */
  n->capabilities = ntohl (rm->capabilities);

  /* Filter accepted issuer */
  ic_accepted = 0;
  for (c1 = 0; c1 < ic; c1++)
  {
    if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
      ic_accepted ++;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Request from peer `%s' with %u issuers, we accepted %u issuer \n",
	      GNUNET_i2s (peer), ic, ic_accepted);
  GNUNET_free_non_null (n->issuer_id);
  n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
  c2 = 0;
  for (c1 = 0; c1 < ic; c1++)
  {
    if (GNUNET_YES == GED_experiments_issuer_accepted (&rmi[c1]))
    {
      n->issuer_id[c2] = rmi[c1];
      c2 ++;
    }
  }
  n->issuer_count = ic_accepted;

  if (GNUNET_YES == make_active)
    node_make_active (n);

  /* Send response */
  e_ctx = GNUNET_new (struct NodeComCtx);
  e_ctx->n = n;
  e_ctx->e = NULL;
  e_ctx->size = sizeof (struct Experimentation_Response) +
    my_issuer_count * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
  e_ctx->notify = &send_response_cb;
  e_ctx->notify_cls = n;

  GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx);
  schedule_transmisson (e_ctx);
}
Exemplo n.º 27
0
/**
 * Handler for notification messages received from the core.
 *
 * @param cls our `struct GNUNET_CORE_Handle`
 * @param msg the message received from the core service
 */
static void
main_notify_handler (void *cls,
                     const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_CORE_Handle *h = cls;
  const struct InitReplyMessage *m;
  const struct ConnectNotifyMessage *cnm;
  const struct DisconnectNotifyMessage *dnm;
  const struct NotifyTrafficMessage *ntm;
  const struct GNUNET_MessageHeader *em;
  const struct SendMessageReady *smr;
  const struct GNUNET_CORE_MessageHandler *mh;
  GNUNET_CORE_StartupCallback init;
  struct PeerRecord *pr;
  struct GNUNET_CORE_TransmitHandle *th;
  unsigned int hpos;
  int trigger;
  uint16_t msize;
  uint16_t et;
  if (NULL == msg)
  {
    LOG (GNUNET_ERROR_TYPE_INFO,
         _("Client was disconnected from core service, trying to reconnect.\n"));
    reconnect_later (h);
    return;
  }
  msize = ntohs (msg->size);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Processing message of type %u and size %u from core service\n",
       ntohs (msg->type), msize);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY:
    if (ntohs (msg->size) != sizeof (struct InitReplyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    m = (const struct InitReplyMessage *) msg;
    GNUNET_break (0 == ntohl (m->reserved));
    /* start our message processing loop */
    if (GNUNET_YES == h->currently_down)
    {
      h->currently_down = GNUNET_NO;
      trigger_next_request (h, GNUNET_NO);
    }
    h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
    h->me = m->my_identity;
    if (NULL != (init = h->init))
    {
      /* mark so we don't call init on reconnect */
      h->init = NULL;
      LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to core service of peer `%s'.\n",
           GNUNET_i2s (&h->me));
      init (h->cls, &h->me);
    }
    else
    {
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Successfully reconnected to core service.\n");
    }
    /* fake 'connect to self' */
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &h->me);
    GNUNET_assert (NULL == pr);
    pr = GNUNET_new (struct PeerRecord);
    pr->peer = h->me;
    pr->ch = h;
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multipeermap_put (h->peers,
                                                      &h->me, pr,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
    if (NULL != h->connects)
      h->connects (h->cls, &h->me);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
    if (msize < sizeof (struct ConnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    cnm = (const struct ConnectNotifyMessage *) msg;
    if (msize !=
        sizeof (struct ConnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about connection from `%s'.\n",
         GNUNET_i2s (&cnm->peer));
    if (0 == memcmp (&h->me, &cnm->peer, sizeof (struct GNUNET_PeerIdentity)))
    {
      /* connect to self!? */
      GNUNET_break (0);
      return;
    }
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer);
    if (NULL != pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    pr = GNUNET_new (struct PeerRecord);
    pr->peer = cnm->peer;
    pr->ch = h;
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multipeermap_put (h->peers,
                                                      &cnm->peer, pr,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
    if (NULL != h->connects)
      h->connects (h->cls, &cnm->peer);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
    if (msize != sizeof (struct DisconnectNotifyMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    dnm = (const struct DisconnectNotifyMessage *) msg;
    if (0 == memcmp (&h->me, &dnm->peer, sizeof (struct GNUNET_PeerIdentity)))
    {
      /* connection to self!? */
      GNUNET_break (0);
      return;
    }
    GNUNET_break (0 == ntohl (dnm->reserved));
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about disconnect from `%s'.\n",
         GNUNET_i2s (&dnm->peer));
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer);
    if (NULL == pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    trigger = ((pr->prev != NULL) || (pr->next != NULL) ||
               (h->ready_peer_head == pr));
    disconnect_and_free_peer_entry (h, &dnm->peer, pr);
    if (trigger)
      trigger_next_request (h, GNUNET_NO);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
    if (msize < sizeof (struct NotifyTrafficMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    ntm = (const struct NotifyTrafficMessage *) msg;
    if ((msize <
         sizeof (struct NotifyTrafficMessage) +
         sizeof (struct GNUNET_MessageHeader)) )
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    em = (const struct GNUNET_MessageHeader *) &ntm[1];
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received message of type %u and size %u from peer `%4s'\n",
         ntohs (em->type), ntohs (em->size), GNUNET_i2s (&ntm->peer));
    if ((GNUNET_NO == h->inbound_hdr_only) &&
        (msize !=
         ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    et = ntohs (em->type);
    for (hpos = 0; hpos < h->hcnt; hpos++)
    {
      mh = &h->handlers[hpos];
      if (mh->type != et)
        continue;
      if ((mh->expected_size != ntohs (em->size)) && (mh->expected_size != 0))
      {
        LOG (GNUNET_ERROR_TYPE_ERROR,
	     "Unexpected message size %u for message of type %u from peer `%4s'\n",
	     htons (em->size), mh->type, GNUNET_i2s (&ntm->peer));
        GNUNET_break_op (0);
        continue;
      }
      pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer);
      if (NULL == pr)
      {
	GNUNET_break (0);
	reconnect_later (h);
	return;
      }
      if (GNUNET_OK !=
          h->handlers[hpos].callback (h->cls, &ntm->peer, em))
      {
        /* error in processing, do not process other messages! */
        break;
      }
    }
    if (NULL != h->inbound_notify)
      h->inbound_notify (h->cls, &ntm->peer, em);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
    if (msize < sizeof (struct NotifyTrafficMessage))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    ntm = (const struct NotifyTrafficMessage *) msg;
    if ((msize <
         sizeof (struct NotifyTrafficMessage) +
         sizeof (struct GNUNET_MessageHeader)) )
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    em = (const struct GNUNET_MessageHeader *) &ntm[1];
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about transmission to `%s'.\n",
         GNUNET_i2s (&ntm->peer));
    if ((GNUNET_NO == h->outbound_hdr_only) &&
        (msize !=
         ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    if (NULL == h->outbound_notify)
    {
      GNUNET_break (0);
      break;
    }
    h->outbound_notify (h->cls, &ntm->peer, em);
    break;
  case GNUNET_MESSAGE_TYPE_CORE_SEND_READY:
    if (msize != sizeof (struct SendMessageReady))
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    smr = (const struct SendMessageReady *) msg;
    pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer);
    if (NULL == pr)
    {
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received notification about transmission readiness to `%s'.\n",
         GNUNET_i2s (&smr->peer));
    if (NULL == pr->th.peer)
    {
      /* request must have been cancelled between the original request
       * and the response from core, ignore core's readiness */
      break;
    }

    th = &pr->th;
    if (ntohs (smr->smr_id) != th->smr_id)
    {
      /* READY message is for expired or cancelled message,
       * ignore! (we should have already sent another request) */
      break;
    }
    if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr))
    {
      /* we should not already be on the ready list... */
      GNUNET_break (0);
      reconnect_later (h);
      return;
    }
    GNUNET_CONTAINER_DLL_insert (h->ready_peer_head, h->ready_peer_tail, pr);
    trigger_next_request (h, GNUNET_NO);
    break;
  default:
    reconnect_later (h);
    return;
  }
  GNUNET_CLIENT_receive (h->client, &main_notify_handler, h,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}
/**
 * Handle a response
 *
 * @param peer the source
 * @param message the message
 */
static void handle_response (const struct GNUNET_PeerIdentity *peer,
			     const struct GNUNET_MessageHeader *message)
{
  struct Node *n;
  const struct Experimentation_Response *rm = (const struct Experimentation_Response *) message;
  const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1];
  uint32_t ic;
  uint32_t ic_accepted;
  int make_active;
  unsigned int c1;
  unsigned int c2;

  if (ntohs (message->size) < sizeof (struct Experimentation_Response))
    {
      GNUNET_break (0);
      return;
    }
  ic = ntohl (rm->issuer_count);
  if (ntohs (message->size) != sizeof (struct Experimentation_Response) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
  {
    GNUNET_break (0);
    return;
  }

  make_active = GNUNET_NO;
  if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		"Received %s from %s peer `%s'\n",
		"RESPONSE", "active", GNUNET_i2s (peer));
  }
  else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n",
		"RESPONSE", "requested", GNUNET_i2s (peer));
    GNUNET_assert (GNUNET_OK ==  GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n));
    if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
    {
      GNUNET_SCHEDULER_cancel (n->timeout_task);
      n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
    }
    update_stats (nodes_requested);
    make_active = GNUNET_YES;
  }
  else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		"Received %s from peer `%s'\n",
		"RESPONSE", "inactive", GNUNET_i2s (peer));
    GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n));
    update_stats (nodes_inactive);
    make_active = GNUNET_YES;
  }
  else
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n",
		"RESPONSE", "unknown", GNUNET_i2s (peer));
    return;
  }

  /* Update */
  n->capabilities = ntohl (rm->capabilities);

  /* Filter accepted issuer */
  ic_accepted = 0;
  for (c1 = 0; c1 < ic; c1++)
  {
    if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
      ic_accepted ++;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Response from peer `%s' with %u issuers, we accepted %u issuer \n",
	      GNUNET_i2s (peer), ic, ic_accepted);
  GNUNET_free_non_null (n->issuer_id);
  n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_PeerIdentity));
  c2 = 0;
  for (c1 = 0; c1 < ic; c1++)
  {
    if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1]))
    {
      n->issuer_id[c2] = rmi[c1];
      c2 ++;
    }
  }
  n->issuer_count = ic_accepted;

  if (GNUNET_YES == make_active)
    node_make_active (n);
}
Exemplo n.º 29
0
/**
 * Find the session for the given peer.
 *
 * @param peer identity of the peer
 * @return NULL if we are not connected, otherwise the
 *         session handle
 */
static struct Session *
find_session (const struct GNUNET_PeerIdentity *peer)
{
  return GNUNET_CONTAINER_multipeermap_get (sessions, peer);
}
Exemplo n.º 30
0
Arquivo: dv_api.c Projeto: tg-x/gnunet
/**
 * Handles a message sent from the DV service to us.
 * Parse it out and give it to the plugin.
 *
 * @param cls the handle to the DV API
 * @param msg the message that was received
 */
static void
handle_message_receipt (void *cls,
			const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_DV_ServiceHandle *sh = cls;
  const struct GNUNET_DV_ConnectMessage *cm;
  const struct GNUNET_DV_DistanceUpdateMessage *dum;
  const struct GNUNET_DV_DisconnectMessage *dm;
  const struct GNUNET_DV_ReceivedMessage *rm;
  const struct GNUNET_MessageHeader *payload;
  const struct GNUNET_DV_AckMessage *ack;
  struct GNUNET_DV_TransmitHandle *th;
  struct GNUNET_DV_TransmitHandle *tn;
  struct ConnectedPeer *peer;

  if (NULL == msg)
  {
    /* Connection closed */
    reconnect (sh);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received message of type %u with %u bytes from DV service\n",
       (unsigned int) ntohs (msg->type),
       (unsigned int) ntohs (msg->size));
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_DV_CONNECT:
    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ConnectMessage))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    cm = (const struct GNUNET_DV_ConnectMessage *) msg;
    peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                              &cm->peer);
    if (NULL != peer)
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    peer = GNUNET_new (struct ConnectedPeer);
    peer->pid = cm->peer;
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CONTAINER_multipeermap_put (sh->peers,
                                                      &peer->pid,
                                                      peer,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    sh->connect_cb (sh->cls,
		    &cm->peer,
		    ntohl (cm->distance),
                    (enum GNUNET_ATS_Network_Type) ntohl (cm->network));
    break;
  case GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED:
    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DistanceUpdateMessage))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    dum = (const struct GNUNET_DV_DistanceUpdateMessage *) msg;
    sh->distance_cb (sh->cls,
		     &dum->peer,
		     ntohl (dum->distance),
                     (enum GNUNET_ATS_Network_Type) ntohl (dum->network));
    break;
  case GNUNET_MESSAGE_TYPE_DV_DISCONNECT:
    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DisconnectMessage))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    dm = (const struct GNUNET_DV_DisconnectMessage *) msg;
    peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                              &dm->peer);
    if (NULL == peer)
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    tn = sh->th_head;
    while (NULL != (th = tn))
    {
      tn = th->next;
      if (peer == th->target)
      {
        GNUNET_CONTAINER_DLL_remove (sh->th_head,
                                     sh->th_tail,
                                     th);
        th->cb (th->cb_cls, GNUNET_SYSERR);
        GNUNET_free (th);
      }
    }
    cleanup_send_cb (sh, &dm->peer, peer);
    break;
  case GNUNET_MESSAGE_TYPE_DV_RECV:
    if (ntohs (msg->size) < sizeof (struct GNUNET_DV_ReceivedMessage) + sizeof (struct GNUNET_MessageHeader))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    rm = (const struct GNUNET_DV_ReceivedMessage *) msg;
    payload = (const struct GNUNET_MessageHeader *) &rm[1];
    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (payload->size))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    if (NULL ==
        GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                           &rm->sender))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    sh->message_cb (sh->cls,
		    &rm->sender,
		    ntohl (rm->distance),
		    payload);
    break;
  case GNUNET_MESSAGE_TYPE_DV_SEND_ACK:
  case GNUNET_MESSAGE_TYPE_DV_SEND_NACK:
    if (ntohs (msg->size) != sizeof (struct GNUNET_DV_AckMessage))
    {
      GNUNET_break (0);
      reconnect (sh);
      return;
    }
    ack = (const struct GNUNET_DV_AckMessage *) msg;
    peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
                                              &ack->target);
    if (NULL == peer)
      break; /* this happens, just ignore */
    for (th = peer->head; NULL != th; th = th->next)
    {
      if (th->uid != ntohl (ack->uid))
        continue;
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Matched ACK for message to peer %s\n",
           GNUNET_i2s (&ack->target));
      GNUNET_CONTAINER_DLL_remove (peer->head,
                                   peer->tail,
                                   th);
      th->cb (th->cb_cls,
              (ntohs (ack->header.type) == GNUNET_MESSAGE_TYPE_DV_SEND_ACK)
              ? GNUNET_OK
              : GNUNET_SYSERR);
      GNUNET_free (th);
      break;
    }
    break;
  default:
    reconnect (sh);
    break;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received message, continuing receive loop for %p\n",
       sh->client);
  GNUNET_CLIENT_receive (sh->client,
			 &handle_message_receipt, sh,
                         GNUNET_TIME_UNIT_FOREVER_REL);
}