Пример #1
0
/**
 * Do pre-calculation for ECC discrete logarithm for small factors.
 *
 * @param max maximum value the factor can be
 * @param mem memory to use (should be smaller than @a max), must not be zero.
 * @return @a max if dlog failed, otherwise the factor
 */
struct GNUNET_CRYPTO_EccDlogContext *
GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
				unsigned int mem)
{
  struct GNUNET_CRYPTO_EccDlogContext *edc;
  unsigned int K = ((max + (mem-1)) / mem);
  gcry_mpi_point_t g;
  struct GNUNET_PeerIdentity key;
  gcry_mpi_point_t gKi;
  gcry_mpi_t fact;
  gcry_mpi_t n;
  unsigned int i;

  GNUNET_assert (max < INT32_MAX);
  edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext);
  edc->max = max;
  edc->mem = mem;

  edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2,
						   GNUNET_NO);

  GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx,
				       NULL,
				       CURVE));
  g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
  GNUNET_assert (NULL != g);
  fact = gcry_mpi_new (0);
  gKi = gcry_mpi_point_new (0);
  for (i=0;i<=mem;i++)
  {
    gcry_mpi_set_ui (fact, i * K);
    gcry_mpi_ec_mul (gKi, fact, g, edc->ctx);
    extract_pk (gKi, edc->ctx, &key);
    GNUNET_assert (GNUNET_OK ==
		   GNUNET_CONTAINER_multipeermap_put (edc->map,
						      &key,
						      (void*) (long) i + max,
						      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  }
  /* negative values */
  n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
  for (i=1;i<mem;i++)
  {
    gcry_mpi_set_ui (fact, i * K);
    gcry_mpi_sub (fact, n, fact);
    gcry_mpi_ec_mul (gKi, fact, g, edc->ctx);
    extract_pk (gKi, edc->ctx, &key);
    GNUNET_assert (GNUNET_OK ==
		   GNUNET_CONTAINER_multipeermap_put (edc->map,
						      &key,
						      (void*) (long) max - i,
						      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  }
  gcry_mpi_release (fact);
  gcry_mpi_release (n);
  gcry_mpi_point_release (gKi);
  gcry_mpi_point_release (g);
  return edc;
}
/**
 * FIXME: Change the name of variable. 
 * Ensure that everywhere in this file you are using destination as the key.
 * Do we need prev field in routing table?
 * Add a new entry to our routing table.
 * @param source peer
 * @param destintation
 * @param next_hop
 */
void
GDS_ROUTING_add (struct GNUNET_PeerIdentity *source,
                 struct GNUNET_PeerIdentity *dest,
                 struct GNUNET_PeerIdentity *next_hop)
{
  struct RoutingTrail *new_routing_entry;
    
  new_routing_entry = GNUNET_malloc (sizeof (struct RoutingTrail));
  new_routing_entry->source = source;
  new_routing_entry->next_hop = next_hop;
  new_routing_entry->destination = dest;
    
  /* If dest is already present in the routing table, then exit.*/
  if (GNUNET_YES ==
    GNUNET_CONTAINER_multipeermap_contains (routing_table,
                                              dest))
  {
    GNUNET_break (0);
    return;
  }

  GNUNET_assert (GNUNET_OK ==
    GNUNET_CONTAINER_multipeermap_put (routing_table,
                                           dest, new_routing_entry,
                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
Пример #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);
}
/**
 * Send request to peer to start add him to to the set of experimentation nodes
 *
 * @param peer the peer to send to
 */
static void
send_experimentation_request (const struct GNUNET_PeerIdentity *peer)
{
  struct Node *n;
  struct NodeComCtx *e_ctx;
  size_t size;
  size_t c_issuers;

  c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers);
  size = sizeof (struct Experimentation_Request) +
    c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey);
  n = GNUNET_new (struct Node);
  n->id = *peer;
  n->timeout_task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &remove_request, n);
  n->capabilities = NONE;

  e_ctx = GNUNET_new (struct NodeComCtx);
  e_ctx->n = n;
  e_ctx->e = NULL;
  e_ctx->size = size;
  e_ctx->notify = &send_experimentation_request_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);

  GNUNET_assert (GNUNET_OK ==
		 GNUNET_CONTAINER_multipeermap_put (nodes_requested,
						    peer, n,
						    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
  update_stats (nodes_requested);
}
Пример #5
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);
  }
/**
 * 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);
}
/**
 * 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);
    }
  }
/**
 * Notify ATS about a new inbound @a address. The @a address in
 * combination with the @a session must be new, but this function will
 * perform a santiy check.  If the @a address is indeed new, make it
 * available to ATS.
 *
 * @param address the address
 * @param session the session
 * @param prop performance information
 */
void
GST_ats_add_inbound_address (const struct GNUNET_HELLO_Address *address,
                             struct GNUNET_ATS_Session *session,
                             const struct GNUNET_ATS_Properties *prop)
{
  struct GNUNET_ATS_AddressRecord *ar;
  struct AddressInfo *ai;

  if (0 ==
      memcmp (&GST_my_identity,
              &address->peer,
              sizeof (struct GNUNET_PeerIdentity)))
    return; /* our own, ignore! */

  /* Sanity checks for a valid inbound address */
  if (NULL == address->transport_name)
  {
    GNUNET_break(0);
    return;
  }
  GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != prop->scope);
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_HELLO_address_check_option (address,
                                                    GNUNET_HELLO_ADDRESS_INFO_INBOUND));
  GNUNET_assert (NULL != session);
  ai = find_ai (address, session);
  if (NULL != ai)
  {
    /* This should only be called for new sessions, and thus
       we should not already have the address */
    GNUNET_break (0);
    return;
  }
  /* Is indeed new, let's tell ATS */
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Notifying ATS about peer `%s''s new inbound address `%s' session %p in network %s\n",
       GNUNET_i2s (&address->peer),
       GST_plugins_a2s (address),
       session,
       GNUNET_ATS_print_network_type (prop->scope));
  ar = GNUNET_ATS_address_add (GST_ats,
                               address,
                               session,
                               prop);
  GNUNET_assert (NULL != ar);
  ai = GNUNET_new (struct AddressInfo);
  ai->address = GNUNET_HELLO_address_copy (address);
  ai->session = session;
  ai->properties = *prop;
  ai->ar = ar;
  (void) GNUNET_CONTAINER_multipeermap_put (p2a,
                                            &ai->address->peer,
                                            ai,
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  publish_p2a_stat_update ();
}
Пример #9
0
/**
 * Create an address for a peer
 *
 * @param cp index of the peer
 * @param ca index of the address
 * @return the address
 */
static struct ATS_Address *
perf_create_address (int cp, int ca)
{
  struct ATS_Address *a;

  a = create_address (&ph.peers[cp].id,
      "Test 1", "test 1", strlen ("test 1") + 1, 0);
  GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a,
      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  return a;
}
/**
 * Set a specific node as active
 *
 * @param n the node
 */
static void
node_make_active (struct Node *n)
{
  int c1;

  GNUNET_CONTAINER_multipeermap_put (nodes_active,
				     &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  update_stats (nodes_active);
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      _("Added peer `%s' as active node\n"),
	      GNUNET_i2s (&n->id));
  /* Request experiments for this node to start them */
  for (c1 = 0; c1 < n->issuer_count; c1++)
  {
    GED_experiments_get (n, &n->issuer_id[c1], &get_experiments_cb);
  }
}
/**
 * Method called whenever a given peer connects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 */
static void
connect_handler (void *cls,
                 const struct GNUNET_PeerIdentity *peer)
{
  size_t size;
  struct GNUNET_CORE_TransmitHandle *th;

  if (! advertising)
    return;
  if (NULL == hostlist_uri)
    return;
  size = strlen (hostlist_uri) + 1;
  if (size + sizeof (struct GNUNET_MessageHeader) >=
      GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_break (0);
    return;
  }
  size += sizeof (struct GNUNET_MessageHeader);
  if (NULL == core)
  {
    GNUNET_break (0);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Asked CORE to transmit advertisement message with a size of %u bytes to peer `%s'\n",
              size,
              GNUNET_i2s (peer));
  if (NULL ==
      (th = GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES,
                                               GNUNET_CORE_PRIO_BEST_EFFORT,
                                               GNUNET_ADV_TIMEOUT,
                                               peer,
                                               size,
                                               &adv_transmit_ready,
                                               (void *) peer)) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Advertisement message could not be queued by core\n"));
  }
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_put (advertisements,
                                                    peer,
                                                    th,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
Пример #12
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;
}
Пример #13
0
/**
 * @brief Create a new #PeerContext and insert it into the peer map
 *
 * @param peer the peer to create the #PeerContext for
 *
 * @return the #PeerContext
 */
static struct PeerContext *
create_peer_ctx (const struct GNUNET_PeerIdentity *peer)
{
  struct PeerContext *ctx;
  int ret;

  GNUNET_assert (GNUNET_NO == Peers_check_peer_known (peer));

  ctx = GNUNET_new (struct PeerContext);
  ctx->peer_id = *peer;
  ctx->send_channel_flags = GNUNET_new (uint32_t);
  ctx->recv_channel_flags = GNUNET_new (uint32_t);
  ret = GNUNET_CONTAINER_multipeermap_put (peer_map, peer, ctx,
      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  GNUNET_assert (GNUNET_OK == ret);
  return ctx;
}
/**
 * Notify ATS about the new address including the network this address is
 * located in.  The address must NOT be inbound and must be new to ATS.
 *
 * @param address the address
 * @param prop performance information
 */
void
GST_ats_add_address (const struct GNUNET_HELLO_Address *address,
                     const struct GNUNET_ATS_Properties *prop)
{
  struct GNUNET_ATS_AddressRecord *ar;
  struct AddressInfo *ai;

  if (0 ==
      memcmp (&GST_my_identity,
              &address->peer,
              sizeof (struct GNUNET_PeerIdentity)))
    return; /* our own, ignore! */
  /* validadte address */
  if (NULL == address->transport_name)
  {
    GNUNET_break(0);
    return;
  }
  GNUNET_assert (GNUNET_YES !=
                 GNUNET_HELLO_address_check_option (address,
                                                    GNUNET_HELLO_ADDRESS_INFO_INBOUND));
  ai = find_ai_no_session (address);
  GNUNET_assert (NULL == ai);
  GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != prop->scope);

  /* address seems sane, let's tell ATS */
  LOG (GNUNET_ERROR_TYPE_INFO,
       "Notifying ATS about peer %s's new address `%s'\n",
       GNUNET_i2s (&address->peer),
       GST_plugins_a2s (address));
  ar = GNUNET_ATS_address_add (GST_ats,
                               address,
                               NULL,
                               prop);
  GNUNET_assert (NULL != ar);
  ai = GNUNET_new (struct AddressInfo);
  ai->address = GNUNET_HELLO_address_copy (address);
  ai->ar = ar;
  ai->properties = *prop;
  (void) GNUNET_CONTAINER_multipeermap_put (p2a,
                                            &ai->address->peer,
                                            ai,
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  publish_p2a_stat_update ();
}
/**
 * Remove experimentation request due to timeout
 *
 * @param cls the related node
 * @param tc scheduler's task context
 */
static void
remove_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct Node *n = cls;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Removing request for peer %s due to timeout\n",
	      GNUNET_i2s (&n->id));
  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, &n->id))
  {
    GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, &n->id, n));
    update_stats (nodes_requested);
    GNUNET_CONTAINER_multipeermap_put (nodes_inactive, &n->id, n,
				       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
    update_stats (nodes_inactive);
  }
  n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
Пример #16
0
/**
 * Insert peer into the view
 *
 * @param peer the peer to insert
 *
 * @return GNUNET_OK if peer was actually inserted
 *         GNUNET_NO if peer was not inserted
 */
int
View_put (const struct GNUNET_PeerIdentity *peer)
{
    uint32_t *index;

    if ((length <= View_size ()) || /* If array is 'full' */
            (GNUNET_YES == View_contains_peer (peer)))
    {
        return GNUNET_NO;
    }
    else
    {
        index = GNUNET_new (uint32_t);
        *index = (uint32_t) View_size ();
        array[*index] = *peer;
        GNUNET_CONTAINER_multipeermap_put (mpm, peer, index,
                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
        return GNUNET_OK;
    }
}
Пример #17
0
/**
 * Signature of a function called by ATS with the current bandwidth
 * and address preferences as determined by ATS.
 *
 * @param cls closure, should point to "asc-closure"
 * @param peer for which we suggest an address, NULL if ATS connection died
 * @param address suggested address (including peer identity of the peer),
 *             may be NULL to signal disconnect from peer
 * @param session session to use, NULL to establish a new outgoing session
 * @param bandwidth_out assigned outbound bandwidth for the connection,
 *        0 to signal disconnect
 * @param bandwidth_in assigned inbound bandwidth for the connection,
 *        0 to signal disconnect
 */
static void
address_suggest_cb (void *cls,
                    const struct GNUNET_PeerIdentity *peer,
                    const struct GNUNET_HELLO_Address *address,
                    struct GNUNET_ATS_Session *session,
                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
                    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
{
  const char *asc_cls = cls;
  struct AddressSuggestData *asd;

  GNUNET_break (0 == strcmp (asc_cls, "asc-closure"));
  if (NULL == peer)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Connection to ATS died, likely a crash!\n");
    GNUNET_SCHEDULER_shutdown ();
#if 0
    /* This is what we should do if we wanted to continue past
       the ATS crash. */
    GNUNET_CONTAINER_multipeermap_iterate (p2asd,
                                           &free_asd,
                                           NULL);
    GNUNET_CONTAINER_multipeermap_iterate (p2aid,
                                           &free_aid,
                                           NULL);
#endif
    return;
  }

  asd = find_address_suggestion (peer);
  if (NULL == asd)
  {
    asd = GNUNET_new (struct AddressSuggestData);
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multipeermap_put (p2asd,
                                                      peer,
                                                      asd,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  }
/**
 * 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);
}
Пример #19
0
/**
 * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS messages from clients.
 *
 * @param cls unused, NULL
 * @param client client that sent the request
 * @param message the request message
 */
void
GAS_handle_request_address (void *cls,
                            struct GNUNET_SERVER_Client *client,
                            const struct GNUNET_MessageHeader *message)
{
  const struct RequestAddressMessage *msg =
      (const struct RequestAddressMessage *) message;
  struct ConnectionRequest *cr;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received `%s' message\n",
              "GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS");
  /* FIXME: should not ignore "msg->strength" */
  cr = GNUNET_new (struct ConnectionRequest);
  cr->client = client;
  (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
                                            &msg->peer,
                                            cr,
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  GAS_plugin_request_connect_start (&msg->peer);
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
Пример #20
0
/**
 * Method called whenever a peer connects. Sets up the PeerEntry and
 * schedules the initial size info transmission to this peer.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 */
static void *
handle_core_connect (void *cls,
		     const struct GNUNET_PeerIdentity *peer,
		     struct GNUNET_MQ_Handle *mq)
{
  struct NSEPeerEntry *peer_entry;
  uint64_t flags;
  const void *extra;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Peer `%s' connected to us\n",
              GNUNET_i2s (peer));
  /* set our default transmission options */
  extra = GNUNET_CORE_get_mq_options (GNUNET_NO,
				      NSE_PRIORITY,
				      &flags);
  GNUNET_MQ_set_options (mq,
			 flags,
			 extra);
  /* create our peer entry for this peer */
  peer_entry = GNUNET_new (struct NSEPeerEntry);
  peer_entry->id = peer;
  peer_entry->mq = mq;
  GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (peers,
                                                    peer_entry->id,
                                                    peer_entry,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  peer_entry->transmit_task =
      GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1),
                                    &transmit_task_cb,
                                    peer_entry);
  GNUNET_STATISTICS_update (stats,
                            "# peers connected",
                            1,
                            GNUNET_NO);
  return peer_entry;
}
Пример #21
0
/**
 * Create a new entry in the peer list.
 *
 * @param peer identity of the new entry
 * @param hello hello message, can be NULL
 * @param is_friend is the new entry for a friend?
 * @return the new entry
 */
static struct Peer *
make_peer (const struct GNUNET_PeerIdentity *peer,
           const struct GNUNET_HELLO_Message *hello,
           int is_friend)
{
  struct Peer *ret;

  ret = GNUNET_new (struct Peer);
  ret->pid = *peer;
  ret->is_friend = is_friend;
  if (NULL != hello)
  {
    ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
    GNUNET_memcpy (ret->hello,
		   hello,
		   GNUNET_HELLO_size (hello));
  }
  GNUNET_break (GNUNET_OK ==
                GNUNET_CONTAINER_multipeermap_put (peers,
                                                   peer,
                                                   ret,
                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  return ret;
}
Пример #22
0
/**
 * 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);
}
/**
 * Signature of a function that is called with QoS information about an address.
 *
 * @param cls closure
 * @param address the address
 * @param address_active is this address actively used to maintain a connection
 * 				to a peer
 * @param bandwidth_out assigned outbound bandwidth for the connection
 * @param bandwidth_in assigned inbound bandwidth for the connection
 * @param ats performance data for the address (as far as known)
 * @param ats_count number of performance records in 'ats'
 */
static void
addr_info_cb (void *cls,
              const struct GNUNET_HELLO_Address *address,
              int address_active,
              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
              const struct GNUNET_ATS_Information *ats,
              uint32_t ats_count)
{
  static const char *query_insert =
      "INSERT INTO ats_info("
      " id,"
      " val,"
      " timestamp"
      ") VALUES ("
      " ?1,"
      " ?2,"
      " datetime('now')"
      ");";
  struct Entry *entry;
  int latency;
  unsigned int cnt;

  GNUNET_assert (NULL != db);
  if (GNUNET_NO == address_active)
    return;
  for (cnt = 0; cnt < ats_count; cnt++)
  {
    if (GNUNET_ATS_QUALITY_NET_DELAY == ntohl (ats[cnt].type))
      goto insert;
  }
  return;

 insert:
  latency = (int) ntohl (ats[cnt].value);
  entry = NULL;
  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map,
                                                            &address->peer))
  {
    entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer);
    GNUNET_assert (NULL != entry);
    if (latency == entry->latency)
      return;
  }
  if (NULL == stmt_insert)
  {
    if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert,
                                         NULL))
    {
      LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2");
      goto err_shutdown;
    }
  }
  if ( (SQLITE_OK != sqlite3_bind_text (stmt_insert, 1,
                                        GNUNET_i2s (&address->peer), -1,
                                        SQLITE_STATIC)) ||
        (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency)) )
  {
     LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text");
     goto err_shutdown;
  }
  if (SQLITE_DONE != sqlite3_step (stmt_insert))
  {
    LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step");
    goto err_shutdown;
  }
  if (SQLITE_OK != sqlite3_reset (stmt_insert))
  {
    LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert");
    goto err_shutdown;
  }
  if (NULL == entry)
  {
    entry = GNUNET_new (struct Entry);
    entry->id = address->peer;
    GNUNET_CONTAINER_multipeermap_put (map, 
                                       &entry->id, entry,
                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  }
Пример #24
0
/**
 * Search callback function called when a subscribed peer is found.
 *
 * @param cls closure provided in GNUNET_REGEX_search()
 * @param id peer providing a regex that matches the string
 * @param get_path path of the get request
 * @param get_path_length length of @a get_path
 * @param put_path Path of the put request
 * @param put_path_length length of the @a put_path
 */
static void
subscribed_peer_found (void *cls, const struct GNUNET_PeerIdentity *id,
                       const struct GNUNET_PeerIdentity *get_path,
                       unsigned int get_path_length,
                       const struct GNUNET_PeerIdentity *put_path,
                       unsigned int put_path_length)
{
  struct PendingMessage *pm;
  struct RemoteSubscriberInfo *subscriber;
  struct GNUNET_MessageHeader *msg;
  struct RegexSearchContext *context = cls;
  size_t msg_len = ntohs (context->publish_msg->header.size);

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "--------> Found an active subscription from %s\n",
	     GNUNET_i2s (id));

  /*
   * We may have delivered the message to the peer already if it has
   * other matching subscriptions; ignore this search result if that is
   * the case.
   */
  if (GNUNET_CONTAINER_multipeermap_contains (context->subscribers,
                                              id))
    return;

  GNUNET_CONTAINER_multipeermap_put (context->subscribers, id,
    NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  subscriber = GNUNET_CONTAINER_multipeermap_get (remote_subscribers,
                                                  id);

  if (0 == memcmp (id, &my_id, sizeof (struct GNUNET_PeerIdentity)))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "fast tracking PUBLISH message to local subscribers\n");

    deliver_incoming_publish (context->publish_msg, context);
    return;
  }

  msg = GNUNET_malloc (msg_len);
  memcpy (msg, context->publish_msg, msg_len);

  pm = GNUNET_new (struct PendingMessage);
  pm->msg = msg;
  pm->context = context;

  if (NULL == subscriber)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
                "creating a new channel to %s\n", GNUNET_i2s(id));

    subscriber = GNUNET_new (struct RemoteSubscriberInfo);

    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);
  }
/**
 * Signature of a function that is called with QoS information about an address.
 *
 * @param cls closure
 * @param address the address
 * @param address_active #GNUNET_YES if this address is actively used
 *        to maintain a connection to a peer;
 *        #GNUNET_NO if the address is not actively used;
 *        #GNUNET_SYSERR if this address is no longer available for ATS
 * @param bandwidth_out assigned outbound bandwidth for the connection
 * @param bandwidth_in assigned inbound bandwidth for the connection
 * @param prop performance data for the address (as far as known)
 */
static void
addr_info_cb (void *cls,
              const struct GNUNET_HELLO_Address *address,
              int address_active,
              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
              struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
              const struct GNUNET_ATS_Properties *prop)
{
  static const char *query_insert =
      "INSERT INTO ats_info("
      " id,"
      " val,"
      " timestamp"
      ") VALUES ("
      " ?1,"
      " ?2,"
      " datetime('now')"
      ");";
  struct Entry *entry;
  int latency; /* FIXME: type!? */

  if (NULL == address)
  {
    /* ATS service temporarily disconnected */
    return;
  }

  GNUNET_assert (NULL != db);
  if (GNUNET_YES != address_active)
    return;
  latency = (int) prop->delay.rel_value_us;
  entry = NULL;
  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map,
                                                            &address->peer))
  {
    entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer);
    GNUNET_assert (NULL != entry);
    if (latency == entry->latency)
      return;
  }
  if (NULL == stmt_insert)
  {
    if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert,
                                         NULL))
    {
      LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2");
      goto err_shutdown;
    }
  }
  if ( (SQLITE_OK != sqlite3_bind_text (stmt_insert, 1,
                                        GNUNET_i2s (&address->peer), -1,
                                        SQLITE_STATIC)) ||
        (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency)) )
  {
     LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text");
     goto err_shutdown;
  }
  if (SQLITE_DONE != sqlite3_step (stmt_insert))
  {
    LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step");
    goto err_shutdown;
  }
  if (SQLITE_OK != sqlite3_reset (stmt_insert))
  {
    LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert");
    goto err_shutdown;
  }
  if (NULL == entry)
  {
    entry = GNUNET_new (struct Entry);
    entry->id = address->peer;
    GNUNET_CONTAINER_multipeermap_put (map,
                                       &entry->id, entry,
                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  }
Пример #26
0
/**
 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
 *
 * @param cls unused
 * @param client new client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
 * @param message the `struct SendMessageRequest` (presumably)
 */
static void
handle_client_send_request (void *cls,
                            struct GNUNET_SERVER_Client *client,
                            const struct GNUNET_MessageHeader *message)
{
  const struct SendMessageRequest *req;
  struct GSC_Client *c;
  struct GSC_ClientActiveRequest *car;
  int is_loopback;

  req = (const struct SendMessageRequest *) message;
  c = find_client (client);
  if (NULL == c)
  {
    /* client did not send INIT first! */
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client,
                                GNUNET_SYSERR);
    return;
  }
  if (NULL == c->requests)
    c->requests = GNUNET_CONTAINER_multipeermap_create (16,
                                                        GNUNET_NO);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Client asked for transmission to `%s'\n",
              GNUNET_i2s (&req->peer));
  is_loopback =
      (0 ==
       memcmp (&req->peer,
               &GSC_my_identity,
               sizeof (struct GNUNET_PeerIdentity)));
  if ((! is_loopback) &&
      (GNUNET_YES !=
       GNUNET_CONTAINER_multipeermap_contains (c->connectmap,
                                               &req->peer)))
  {
    /* neighbour must have disconnected since request was issued,
     * ignore (client will realize it once it processes the
     * disconnect notification) */
    GNUNET_STATISTICS_update (GSC_stats,
                              gettext_noop
                              ("# send requests dropped (disconnected)"), 1,
                              GNUNET_NO);
    GNUNET_SERVER_receive_done (client,
                                GNUNET_OK);
    return;
  }

  car = GNUNET_CONTAINER_multipeermap_get (c->requests,
                                           &req->peer);
  if (NULL == car)
  {
    /* create new entry */
    car = GNUNET_new (struct GSC_ClientActiveRequest);
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CONTAINER_multipeermap_put (c->requests,
                                                      &req->peer,
                                                      car,
                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
    car->client_handle = c;
  }
Пример #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);
}
/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls, char *const *args, const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
    char *dbfile;
    struct WhiteListRow *wl_head;
    struct WhiteListRow *wl_entry;
    struct GNUNET_PeerIdentity identity;
    struct GNUNET_ATS_Properties prop;
    struct GNUNET_TIME_Relative delay;
    unsigned long long pid;
    unsigned int nrows;
    int ret;

    if (GNUNET_OK !=
            GNUNET_CONFIGURATION_get_value_number (c, "TESTBED",
                    "PEERID", &pid))
    {
        GNUNET_break (0);
        return;
    }
    if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED-UNDERLAY",
            "DBFILE",
            &dbfile))
    {
        GNUNET_break (0);
        return;
    }
    if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL)))
    {
        if (NULL != db)
        {
            LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
            GNUNET_break (SQLITE_OK == sqlite3_close (db));
        }
        else
            LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
        GNUNET_free (dbfile);
        return;
    }
    DEBUG ("Opened database %s\n", dbfile);
    GNUNET_free (dbfile);
    dbfile = NULL;
    wl_head = NULL;
    if (GNUNET_OK != load_keys (c))
        goto close_db;

    transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL);
    if (NULL == transport)
    {
        GNUNET_break (0);
        return;
    }
    /* read and process whitelist */
    nrows = 0;
    wl_head = NULL;
    nrows = db_read_whitelist (db, pid, &wl_head);
    if ((GNUNET_SYSERR == nrows) || (0 == nrows))
    {
        GNUNET_TRANSPORT_disconnect (transport);
        goto close_db;
    }
    map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO);
    while (NULL != (wl_entry = wl_head))
    {
        wl_head = wl_entry->next;
        delay.rel_value_us = wl_entry->latency;
        memset (&prop, 0, sizeof (prop));
        GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity));
        GNUNET_break (GNUNET_OK ==
                      GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity,
                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
        DEBUG ("Setting %u ms latency to peer `%s'\n",
               wl_entry->latency,
               GNUNET_i2s (&identity));
        GNUNET_TRANSPORT_set_traffic_metric (transport,
                                             &identity,
                                             &prop,
                                             delay,
                                             delay);
        GNUNET_free (wl_entry);
    }
    bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL);
    shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                    &do_shutdown, NULL);

close_db:
    GNUNET_break (SQLITE_OK == sqlite3_close (db));
    return;
}
Пример #29
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;
}
Пример #30
0
/**
 * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request.
 *
 * @param cls unused
 * @param client new client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
 * @param message the `struct InitMessage` (presumably)
 */
static void
handle_client_init (void *cls,
                    struct GNUNET_SERVER_Client *client,
                    const struct GNUNET_MessageHeader *message)
{
  const struct InitMessage *im;
  struct InitReplyMessage irm;
  struct GSC_Client *c;
  uint16_t msize;
  const uint16_t *types;
  uint16_t *wtypes;
  unsigned int i;

  /* check that we don't have an entry already */
  c = find_client (client);
  if (NULL != c)
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  msize = ntohs (message->size);
  if (msize < sizeof (struct InitMessage))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  GNUNET_SERVER_notification_context_add (notifier, client);
  im = (const struct InitMessage *) message;
  types = (const uint16_t *) &im[1];
  msize -= sizeof (struct InitMessage);
  c = GNUNET_malloc (sizeof (struct GSC_Client) + msize);
  c->client_handle = client;
  c->tcnt = msize / sizeof (uint16_t);
  c->options = ntohl (im->options);
  all_client_options |= c->options;
  c->types = (const uint16_t *) &c[1];
  c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO);
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_put (c->connectmap,
                                                    &GSC_my_identity,
                                                    NULL,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  wtypes = (uint16_t *) & c[1];
  for (i = 0; i < c->tcnt; i++)
    wtypes[i] = ntohs (types[i]);
  GSC_TYPEMAP_add (wtypes, c->tcnt);
  GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Client connecting to core service is interested in %u message types\n",
              (unsigned int) c->tcnt);
  /* send init reply message */
  irm.header.size = htons (sizeof (struct InitReplyMessage));
  irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
  irm.reserved = htonl (0);
  irm.my_identity = GSC_my_identity;
  send_to_client (c, &irm.header, GNUNET_NO);
  GSC_SESSIONS_notify_client_about_sessions (c);
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
}