Пример #1
0
/**
 * Find the first peer whom to send a packet to go down this path
 *
 * @param t The tunnel tree to use
 * @param peer The peerinfo of the peer we are trying to reach
 *
 * @return peerinfo of the peer who is the first hop in the tunnel
 *         NULL on error
 * 
 * FIXME use PEER_Id
 */
struct GNUNET_PeerIdentity *
tree_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer)
{
  struct GNUNET_PeerIdentity id;
  struct GNUNET_PeerIdentity *r;

  GNUNET_PEER_resolve (peer, &id);
  r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
  if (NULL == r)
  {
    struct MeshTunnelTreeNode *n;

    n = tree_find_peer (t, peer);
    if (NULL != t->me && NULL != n)
    {
      tree_node_update_first_hops (t, n, NULL);
      r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
      GNUNET_assert (NULL != r);
    }
    else
    {
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  "Tree structure inconsistent! me: %p, n: %p", t->me, n);
      GNUNET_break (0);
    }
  }

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

  if (err_msg != NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                _("Error in communication with PEERINFO service: %s\n"),
                err_msg);
    GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
    peerinfo_notify = GNUNET_PEERINFO_notify (cfg, &process_peer, NULL);
    return;
  }
  GNUNET_assert (peer != NULL);
  if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
    return;                     /* that's me! */
  if (hello == NULL)
  {
    /* free existing HELLO, if any */
    pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
    if (NULL != pos)
    {
      GNUNET_free_non_null (pos->hello);
      pos->hello = NULL;
      if (pos->filter != NULL)
      {
        GNUNET_CONTAINER_bloomfilter_free (pos->filter);
        pos->filter = NULL;
      }
      if ((GNUNET_NO == pos->is_connected) && (GNUNET_NO == pos->is_friend) &&
          (0 ==
           GNUNET_TIME_absolute_get_remaining (pos->
                                               greylisted_until).rel_value))
        free_peer (NULL, &pos->pid.hashPubKey, pos);
    }
    return;
  }
  consider_for_advertising (hello);
  pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
  if (pos == NULL)
    pos = make_peer (peer, hello, GNUNET_NO);
  GNUNET_assert (NULL != pos);
  if (GNUNET_YES == pos->is_connected)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already connected to peer `%s'\n",
                GNUNET_i2s (peer));
    return;
  }
  if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value > 0)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already tried peer `%s' recently\n",
                GNUNET_i2s (peer));
    return;                     /* peer still greylisted */
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering connecting to peer `%s'\n",
              GNUNET_i2s (peer));
  schedule_attempt_connect (pos);
}
static int
testMap (int i)
{
  struct GNUNET_CONTAINER_MultiHashMap *m;
  GNUNET_HashCode k1;
  GNUNET_HashCode k2;
  const char *ret;
  int j;

  CHECK (NULL != (m = GNUNET_CONTAINER_multihashmap_create (i)));
  memset (&k1, 0, sizeof (k1));
  memset (&k2, 1, sizeof (k2));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k1));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k2));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (m, &k1, NULL));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (m, &k2, NULL));
  CHECK (NULL == GNUNET_CONTAINER_multihashmap_get (m, &k1));
  CHECK (NULL == GNUNET_CONTAINER_multihashmap_get (m, &k2));
  CHECK (0 == GNUNET_CONTAINER_multihashmap_remove_all (m, &k1));
  CHECK (0 == GNUNET_CONTAINER_multihashmap_size (m));
  CHECK (0 == GNUNET_CONTAINER_multihashmap_iterate (m, NULL, NULL));
  CHECK (0 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k1, NULL, NULL));

  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multihashmap_put (m, &k1, "v1",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
  CHECK (1 == GNUNET_CONTAINER_multihashmap_size (m));
  ret = GNUNET_CONTAINER_multihashmap_get (m, &k1);
  GNUNET_assert (ret != NULL);
  CHECK (0 == strcmp ("v1", ret));
  CHECK (GNUNET_NO ==
         GNUNET_CONTAINER_multihashmap_put (m, &k1, "v1",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
  CHECK (1 == GNUNET_CONTAINER_multihashmap_size (m));
  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multihashmap_put (m, &k1, "v2",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  CHECK (GNUNET_OK ==
         GNUNET_CONTAINER_multihashmap_put (m, &k1, "v3",
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  CHECK (3 == GNUNET_CONTAINER_multihashmap_size (m));
  CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (m, &k1, "v3"));
  CHECK (2 == GNUNET_CONTAINER_multihashmap_size (m));
  CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (m, &k1));
  CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k2));
  CHECK (2 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k1, NULL, NULL));
  CHECK (0 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k2, NULL, NULL));
  CHECK (2 == GNUNET_CONTAINER_multihashmap_iterate (m, NULL, NULL));
  CHECK (2 == GNUNET_CONTAINER_multihashmap_remove_all (m, &k1));
  for (j = 0; j < 1024; j++)
    CHECK (GNUNET_OK ==
           GNUNET_CONTAINER_multihashmap_put (m, &k1, "v2",
                                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  GNUNET_CONTAINER_multihashmap_destroy (m);
  return 0;
}
Пример #4
0
/**
 * Get the next hop for trail corresponding to trail_id
 *
 * @param trail_id Trail id to be searched.
 * @return Next_hop if found
 *         NULL If next hop not found.
 */
const struct GNUNET_PeerIdentity *
GDS_ROUTING_get_next_hop (const struct GNUNET_HashCode *trail_id,
                          enum GDS_ROUTING_trail_direction trail_direction)
{
  struct RoutingTrail *trail;

  trail = GNUNET_CONTAINER_multihashmap_get (routing_table,
					     trail_id);
  if (NULL == trail)
  {
    /* If a friend got disconnected and we removed all the entry from the
     routing table, then trail will be deleted and my identity will not know
     and when it tries to reach to that finger it fails. thats why
     assertion always fails in*/
    return NULL;
  }
  switch (trail_direction)
  {
    case GDS_ROUTING_SRC_TO_DEST:
      return &trail->next_hop;
    case GDS_ROUTING_DEST_TO_SRC:
      return &trail->prev_hop;
  }
  return NULL;
}
/**
 * Reserve the given amount of incoming bandwidth (in bytes) from the
 * given peer.  If a reservation is not possible right now, return how
 * long the client should wait before trying again.
 *
 * @param peer peer to reserve bandwidth from
 * @param amount number of bytes to reserve
 * @return 0 if the reservation was successful, FOREVER if the
 *         peer is not connected, otherwise the time to wait
 *         until the reservation might succeed
 */
struct GNUNET_TIME_Relative
GAS_reservations_reserve (const struct GNUNET_PeerIdentity *peer,
                          int32_t amount)
{
  struct GNUNET_BANDWIDTH_Tracker *tracker;
  struct GNUNET_TIME_Relative ret;

  tracker = GNUNET_CONTAINER_multihashmap_get (trackers, &peer->hashPubKey);
  if (NULL == tracker)
    return GNUNET_TIME_UNIT_ZERO;       /* not connected, satisfy now */
  if (amount >= 0)
  {
    ret = GNUNET_BANDWIDTH_tracker_get_delay (tracker, amount);
    if (ret.rel_value > 0)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Delay to satisfy reservation for %d bytes is %llu ms\n",
                  (int) amount, (unsigned long long) ret.rel_value);
      return ret;
    }
  }
  (void) GNUNET_BANDWIDTH_tracker_consume (tracker, amount);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reserved %d bytes\n", (int) amount);
  return GNUNET_TIME_UNIT_ZERO;
}
/**
 * Set the amount of bandwidth the other peer could currently transmit
 * to us (as far as we know) to the given value.
 *
 * @param peer identity of the peer
 * @param bandwidth_in currently available bandwidth from that peer to
 *        this peer (estimate)
 */
void
GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer,
                                struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
{
  struct GNUNET_BANDWIDTH_Tracker *tracker;

  tracker = GNUNET_CONTAINER_multihashmap_get (trackers, &peer->hashPubKey);
  if (0 == ntohl (bandwidth_in.value__))
  {
    if (NULL == tracker)
      return;
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multihashmap_remove (trackers,
                                                         &peer->hashPubKey,
                                                         tracker));
    GNUNET_free (tracker);
    return;
  }
  if (NULL == tracker)
  {
    tracker = GNUNET_malloc (sizeof (struct GNUNET_BANDWIDTH_Tracker));
    GNUNET_BANDWIDTH_tracker_init (tracker, bandwidth_in,
                                   MAX_BANDWIDTH_CARRY_S);
    GNUNET_CONTAINER_multihashmap_put (trackers, &peer->hashPubKey, tracker,
                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
    return;
  }
  GNUNET_BANDWIDTH_tracker_update_quota (tracker, bandwidth_in);
}
Пример #7
0
/**
 * Function called on each meta data item.  Increments the
 * respective counter.
 *
 * @param cls the container multihashmap to update
 * @param plugin_name name of the plugin that produced this value;
 *        special values can be used (i.e. '&lt;zlib&gt;' for zlib being
 *        used in the main libextractor library and yielding
 *        meta data).
 * @param type libextractor-type describing the meta data
 * @param format basic format information about data
 * @param data_mime_type mime-type of data (not of the original file);
 *        can be NULL (if mime-type is not known)
 * @param data actual meta-data found
 * @param data_len number of bytes in data
 * @return GNUNET_OK to continue extracting / iterating
 */
static int
add_to_meta_counter (void *cls, const char *plugin_name,
		     enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format,
		     const char *data_mime_type, const char *data, size_t data_len)
{
  struct GNUNET_CONTAINER_MultiHashMap *map = cls;
  GNUNET_HashCode key;
  struct MetaCounter *cnt;

  GNUNET_CRYPTO_hash (data, data_len, &key);
  cnt = GNUNET_CONTAINER_multihashmap_get (map, &key);
  if (cnt == NULL)
  {
    cnt = GNUNET_malloc (sizeof (struct MetaCounter));
    cnt->data = data;
    cnt->data_size = data_len;
    cnt->plugin_name = plugin_name;
    cnt->type = type;
    cnt->format = format;
    cnt->data_mime_type = data_mime_type;
    GNUNET_assert (GNUNET_OK ==
		   GNUNET_CONTAINER_multihashmap_put (map,
						      &key, cnt,
						      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  }
  cnt->count++;
  return 0;
}
Пример #8
0
/**
 * When a watch record is received
 *
 * @param cls a `struct GNUNET_PEERSTORE_Handle *`
 * @param msg message received, NULL on timeout or fatal error
 */
static void
handle_watch_result (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_PEERSTORE_Handle *h = cls;
  struct GNUNET_PEERSTORE_Record *record;
  struct GNUNET_HashCode keyhash;
  struct GNUNET_PEERSTORE_WatchContext *wc;

  if (NULL == msg)
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _
         ("Problem receiving a watch response, no way to determine which request.\n"));
    reconnect (h);
    return;
  }
  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a watch record from service.\n");
  record = PEERSTORE_parse_record_message (msg);
  PEERSTORE_hash_key (record->sub_system, record->peer, record->key, &keyhash);
  // FIXME: what if there are multiple watches for the same key?
  wc = GNUNET_CONTAINER_multihashmap_get (h->watches, &keyhash);
  if (NULL == wc)
  {
    LOG (GNUNET_ERROR_TYPE_ERROR,
         _("Received a watch result for a non existing watch.\n"));
    PEERSTORE_destroy_record (record);
    reconnect (h);
    return;
  }
  if (NULL != wc->callback)
    wc->callback (wc->callback_cls, record, NULL);
  PEERSTORE_destroy_record (record);
}
Пример #9
0
/**
 * Recusively mark peer and children as disconnected, notify client
 *
 * @param tree Tree this node belongs to
 * @param parent Node to be clean, potentially with children
 * @param cb Callback to use to notify about disconnected peers.
 * @param cbcls Closure for cb.
 */
static void
tree_mark_peers_disconnected (struct MeshTunnelTree *tree,
                              struct MeshTunnelTreeNode *parent,
                              MeshTreeCallback cb, void *cbcls)
{
  struct GNUNET_PeerIdentity *pi;
  struct GNUNET_PeerIdentity id;
  struct MeshTunnelTreeNode *n;

  for (n = parent->children_head; NULL != n; n = n->next)
  {
    tree_mark_peers_disconnected (tree, n, cb, cbcls);
  }
  if (MESH_PEER_READY == parent->status)
  {
    if (NULL != cb)
      cb (cbcls, parent->peer);
    parent->status = MESH_PEER_RECONNECTING;
  }

  /* Remove and free info about first hop */
  GNUNET_PEER_resolve (parent->peer, &id);
  pi = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
  GNUNET_CONTAINER_multihashmap_remove_all (tree->first_hops, &id.hashPubKey);
  if (NULL != pi)
    GNUNET_free (pi);
}
/**
 * We've validated the hash of the file we're about to index.  Signal
 * success to the client and update our internal data structures.
 *
 * @param ii the index info entry for the request
 */
static void
signal_index_ok (struct IndexInfo *ii)
{
  struct IndexInfo *ir;
  if (GNUNET_SYSERR ==
      GNUNET_CONTAINER_multihashmap_put (ifm, &ii->file_id,
                                         ii,
                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  {
    ir = GNUNET_CONTAINER_multihashmap_get (ifm,
					    &ii->file_id);
    GNUNET_assert (NULL != ir);
    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                _
                ("Index request received for file `%s' is already indexed as `%s'.  Permitting anyway.\n"),
                ii->filename,
		ir->filename);           
    GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0,
                                                GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
    GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES);
    GNUNET_free (ii);
    return;
  }
  GNUNET_CONTAINER_DLL_insert (indexed_files_head,
			       indexed_files_tail,
			       ii);
  write_index_list ();
  GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0,
                                              GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
  GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES);
  ii->tc = NULL;
}
Пример #11
0
/**
 * Create a new query plan entry.
 *
 * @param cp peer with the entry
 * @param pr request with the entry
 */
void
GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr)
{
  const struct GNUNET_PeerIdentity *id;
  struct PeerPlan *pp;
  struct GSF_PendingRequestData *prd;
  struct GSF_RequestPlan *rp;
  struct GSF_PendingRequestPlanBijection *bi;
  struct MergeContext mpc;

  GNUNET_assert (NULL != cp);
  id = GSF_connected_peer_get_identity2_ (cp);
  pp = GNUNET_CONTAINER_multihashmap_get (plans, &id->hashPubKey);
  if (NULL == pp)
  {
    pp = GNUNET_malloc (sizeof (struct PeerPlan));
    pp->plan_map = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
    pp->priority_heap =
        GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
    pp->delay_heap =
        GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
    pp->cp = cp;
    GNUNET_CONTAINER_multihashmap_put (plans, 
				       &id->hashPubKey, pp,
                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  }
  mpc.merged = GNUNET_NO;
  mpc.pr = pr;
  GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map,
                                              &GSF_pending_request_get_data_
                                              (pr)->query, &merge_pr, &mpc); // 8 MB in 'merge_pr'
  if (GNUNET_NO != mpc.merged)
    return;
  GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map,
                                              &GSF_pending_request_get_data_
                                              (pr)->query, &merge_pr, &mpc);
  if (GNUNET_NO != mpc.merged)
    return;
  plan_count++;
  GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query plan entries"), 1,
                            GNUNET_NO);
  prd = GSF_pending_request_get_data_ (pr);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Planning transmission of query `%s' to peer `%s'\n",
              GNUNET_h2s (&prd->query), GNUNET_i2s (id));
  rp = GNUNET_malloc (sizeof (struct GSF_RequestPlan)); // 8 MB
  bi = GNUNET_malloc (sizeof (struct GSF_PendingRequestPlanBijection));
  bi->rp = rp;
  bi->pr = pr;
  GNUNET_CONTAINER_MDLL_insert (PR, prd->pr_head, prd->pr_tail, bi);
  GNUNET_CONTAINER_MDLL_insert (PE, rp->pe_head, rp->pe_tail, bi);
  rp->pp = pp;
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_put (pp->plan_map,
                                                    get_rp_key (rp), rp,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); // 8 MB
  plan (pp, rp); // +5 MB (plan/heap-insert)
}
/**
 * We've gotten a HELLO from another peer.  Consider it for
 * advertising.
 *
 * @param hello the HELLO we got
 */
static void
consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
{
  int have_address;
  struct GNUNET_PeerIdentity pid;
  struct GNUNET_TIME_Absolute dt;
  struct GNUNET_HELLO_Message *nh;
  struct Peer *peer;
  uint16_t size;

  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
  {
    GNUNET_break (0);
    return;
  }
  if (0 == memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
    return;                     /* that's me! */
  have_address = GNUNET_NO;
  GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &address_iterator,
                                  &have_address);
  if (GNUNET_NO == have_address)
    return;                     /* no point in advertising this one... */
  peer = GNUNET_CONTAINER_multihashmap_get (peers, &pid.hashPubKey);
  if (NULL == peer)
  {
    peer = make_peer (&pid, hello, GNUNET_NO);
  }
  else if (peer->hello != NULL)
  {
    dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ());
    if (dt.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
      return;                   /* nothing new here */
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Found `%s' from peer `%s' for advertising\n", "HELLO",
              GNUNET_i2s (&pid));
  if (peer->hello != NULL)
  {
    nh = GNUNET_HELLO_merge (peer->hello, hello);
    GNUNET_free (peer->hello);
    peer->hello = nh;
  }
  else
  {
    size = GNUNET_HELLO_size (hello);
    peer->hello = GNUNET_malloc (size);
    memcpy (peer->hello, hello, size);
  }
  if (peer->filter != NULL)
    GNUNET_CONTAINER_bloomfilter_free (peer->filter);
  setup_filter (peer);
  /* since we have a new HELLO to pick from, re-schedule all
   * HELLO requests that are not bound by the HELLO send rate! */
  GNUNET_CONTAINER_multihashmap_iterate (peers, &reschedule_hellos, peer);
}
Пример #13
0
/**
 * Recusively update the info about what is the first hop to reach the node
 *
 * @param tree Tree this nodes belongs to.
 * @param parent ID from node form which to start updating.
 * @param hop If known, ID of the first hop.
 *            If not known, NULL to find out and pass on children.
 */
static void
tree_node_update_first_hops (struct MeshTunnelTree *tree,
                             struct MeshTunnelTreeNode *parent,
                             struct GNUNET_PeerIdentity *hop)
{
  struct GNUNET_PeerIdentity pi;
  struct GNUNET_PeerIdentity *copy;
  struct GNUNET_PeerIdentity id;
  struct MeshTunnelTreeNode *n;

#if MESH_TREE_DEBUG
  GNUNET_PEER_resolve (parent->peer, &id);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   Finding first hop for %s.\n",
              GNUNET_i2s (&id));
#endif
  if (NULL == hop)
  {
    struct MeshTunnelTreeNode *aux;
    struct MeshTunnelTreeNode *old;

    aux = old = parent;
    while (aux != tree->me)
    {
#if MESH_TREE_DEBUG
      GNUNET_PEER_resolve (aux->peer, &id);
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   ... checking %s.\n",
                  GNUNET_i2s (&id));
#endif
      old = aux;
      aux = aux->parent;
      GNUNET_assert (NULL != aux);
    }
#if MESH_TREE_DEBUG
    GNUNET_PEER_resolve (old->peer, &id);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree:   It's %s!\n",
                GNUNET_i2s (&id));
#endif
    hop = &pi;
    GNUNET_PEER_resolve (old->peer, hop);
  }
  GNUNET_PEER_resolve (parent->peer, &id);
  copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
  if (NULL == copy)
    copy = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
  *copy = *hop;

  (void) GNUNET_CONTAINER_multihashmap_put (tree->first_hops, &id.hashPubKey,
                                            copy,
                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);

  for (n = parent->children_head; NULL != n; n = n->next)
  {
    tree_node_update_first_hops (tree, n, hop);
  }
}
/**
 * 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 disapproave
 * @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_multihashmap_get (peers, &pid->hashPubKey);
  if ((pos != NULL) && (pos->is_friend == GNUNET_YES))
    return GNUNET_OK;
  GNUNET_STATISTICS_update (stats, gettext_noop ("# peers blacklisted"), 1,
                            GNUNET_NO);
  return GNUNET_SYSERR;
}
/**
 * Obtain statistics and/or change preferences for the given peer.
 *
 * @param h core handle
 * @param peer identifies the peer
 * @param amount reserve N bytes for receiving, negative
 *                amounts can be used to undo a (recent) reservation;
 * @param preference increase incoming traffic share preference by this amount;
 *                in the absence of "amount" reservations, we use this
 *                preference value to assign proportional bandwidth shares
 *                to all connected peers
 * @param info function to call with the resulting configuration information
 * @param info_cls closure for info
 * @return NULL on error
 */
struct GNUNET_ATS_InformationRequestContext *
GNUNET_ATS_peer_change_preference (struct GNUNET_ATS_SchedulingHandle *h,
                                   const struct GNUNET_PeerIdentity *peer,
                                   int32_t amount, uint64_t preference,
                                   GNUNET_ATS_PeerConfigurationInfoCallback
                                   info, void *info_cls)
{
  struct GNUNET_ATS_InformationRequestContext *irc;
  struct PeerRecord *pr;
  struct RequestInfoMessage *rim;
  struct ControlMessage *cm;

  pr = GNUNET_CONTAINER_multihashmap_get (h->peers, &peer->hashPubKey);
  if (NULL == pr)
  {
    /* attempt to change preference on peer that is not connected */
    GNUNET_assert (0);
    return NULL;
  }
  if (pr->pcic != NULL)
  {
    /* second change before first one is done */
    GNUNET_break (0);
    return NULL;
  }
  irc = GNUNET_malloc (sizeof (struct GNUNET_ATS_InformationRequestContext));
  irc->h = h;
  irc->pr = pr;
  cm = GNUNET_malloc (sizeof (struct ControlMessage) +
                      sizeof (struct RequestInfoMessage));
  cm->cont = &change_preference_send_continuation;
  cm->cont_cls = irc;
  irc->cm = cm;
  rim = (struct RequestInfoMessage *) &cm[1];
  rim->header.size = htons (sizeof (struct RequestInfoMessage));
  rim->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_REQUEST_INFO);
  rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++);
  rim->reserved = htonl (0);
  rim->reserve_inbound = htonl (amount);
  rim->preference_change = GNUNET_htonll (preference);
  rim->peer = *peer;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Queueing CHANGE PREFERENCE request for peer `%s' with RIM %u\n",
              GNUNET_i2s (peer), (unsigned int) pr->rim_id);
  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
                                    h->control_pending_tail, cm);
  pr->pcic = info;
  pr->pcic_cls = info_cls;
  pr->pcic_ptr = irc;           /* for free'ing irc */
  if (NULL != h->client)
    trigger_next_request (h, GNUNET_NO);
  return irc;
}
Пример #16
0
/**
 * Update the next hop of the trail. Call made by trail compression where
 * if you are source of the trail and now you have a new first friend, then
 * you should update the trail.
 * @param trail_id
 * @return #GNUNET_OK success
 *         #GNUNET_SYSERR in case no matching entry found in routing table.
 */
int
GDS_ROUTING_update_trail_next_hop (const struct GNUNET_HashCode *trail_id,
                                   const struct GNUNET_PeerIdentity *next_hop)
{
  struct RoutingTrail *trail;

  trail = GNUNET_CONTAINER_multihashmap_get (routing_table,
					     trail_id);
  if (NULL == trail)
    return GNUNET_SYSERR;
  trail->next_hop = *next_hop;
  return GNUNET_OK;
}
/**
 * Parses a sensor reading message struct
 *
 * @param msg message header received
 * @param sensors multihashmap of loaded sensors
 * @return sensor reading struct or NULL if error
 */
static struct ClientSensorReading *
parse_reading_message (const struct GNUNET_MessageHeader *msg,
                       struct GNUNET_CONTAINER_MultiHashMap *sensors)
{
  uint16_t msg_size;
  uint16_t value_size;
  struct GNUNET_SENSOR_ValueMessage *vm;
  struct GNUNET_SENSOR_SensorInfo *sensor;
  struct ClientSensorReading *reading;

  msg_size = ntohs (msg->size);
  if (msg_size < sizeof (struct GNUNET_SENSOR_ValueMessage))
  {
    GNUNET_break_op (0);
    return NULL;
  }
  vm = (struct GNUNET_SENSOR_ValueMessage *) msg;
  value_size = ntohs (vm->value_size);
  if ((sizeof (struct GNUNET_SENSOR_ValueMessage) + value_size) != msg_size)
  {
    GNUNET_break_op (0);
    return NULL;
  }
  sensor = GNUNET_CONTAINER_multihashmap_get (sensors, &vm->sensorname_hash);
  if (NULL == sensor)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Unknown sensor name in reading message.\n");
    return NULL;
  }
  if ((sensor->version_minor != ntohs (vm->sensorversion_minor)) ||
      (sensor->version_major != ntohs (vm->sensorversion_major)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Sensor version mismatch in reading message.\n");
    return NULL;
  }
  if (0 == strcmp (sensor->expected_datatype, "numeric") &&
      sizeof (double) != value_size)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Invalid value size for a numerical sensor.\n");
    return NULL;
  }
  reading = GNUNET_new (struct ClientSensorReading);
  reading->sensor = sensor;
  reading->timestamp = vm->timestamp;
  reading->value_size = value_size;
  reading->value = GNUNET_memdup (&vm[1], value_size);
  return reading;
}
/**
 * Called with any anomaly report received from a peer.
 *
 * Each time the function must call #GNUNET_CADET_receive_done on the channel
 * in order to receive the next message. This doesn't need to be immediate:
 * can be delayed if some processing is done on the message.
 *
 * @param cls Closure (set from #GNUNET_CADET_connect).
 * @param channel Connection to the other end.
 * @param channel_ctx Place to store local state associated with the channel.
 * @param message The actual message.
 * @return #GNUNET_OK to keep the channel open,
 *         #GNUNET_SYSERR to close it (signal serious error).
 */
static int
handle_anomaly_report (void *cls, struct GNUNET_CADET_Channel *channel,
                       void **channel_ctx,
                       const struct GNUNET_MessageHeader *message)
{
  struct ClientPeerContext *cp = *channel_ctx;
  struct GNUNET_SENSOR_crypto_pow_block *report_block;
  struct GNUNET_SENSOR_AnomalyReportMessage *anomaly_msg;
  struct GNUNET_SENSOR_SensorInfo *sensor;
  struct GNUNET_SENSOR_DashboardAnomalyEntry *anomaly_entry;
  struct GNUNET_TIME_Absolute expiry;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received an anomaly report message from peer `%s'.\n",
              GNUNET_i2s (&cp->peerid));
  report_block = (struct GNUNET_SENSOR_crypto_pow_block *) &message[1];
  if (sizeof (struct GNUNET_SENSOR_AnomalyReportMessage) !=
      GNUNET_SENSOR_crypto_verify_pow_sign (report_block, pow_matching_bits,
                                            &cp->peerid.public_key,
                                            (void **) &anomaly_msg))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Received invalid anomaly report from peer `%s'.\n",
                GNUNET_i2s (&cp->peerid));
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  sensor =
      GNUNET_CONTAINER_multihashmap_get (sensors,
                                         &anomaly_msg->sensorname_hash);
  if (NULL == sensor)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  anomaly_entry = GNUNET_new (struct GNUNET_SENSOR_DashboardAnomalyEntry);
  anomaly_entry->anomalous = ntohs (anomaly_msg->anomalous);
  anomaly_entry->anomalous_neighbors = anomaly_msg->anomalous_neighbors;
  expiry =
      (GNUNET_YES ==
       anomaly_entry->anomalous) ? GNUNET_TIME_UNIT_FOREVER_ABS :
      GNUNET_TIME_absolute_get ();
  GNUNET_PEERSTORE_store (peerstore, anomalies_subsystem, &cp->peerid,
                          sensor->name, anomaly_entry,
                          sizeof (struct GNUNET_SENSOR_DashboardAnomalyEntry),
                          expiry, GNUNET_PEERSTORE_STOREOPTION_REPLACE, NULL,
                          NULL);
  GNUNET_free (anomaly_entry);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
/**
 * Method called whenever a peer disconnects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 */
static void
disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer)
{
  struct Peer *pos;

  if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
    return;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core told us that we disconnected from `%s'\n",
              GNUNET_i2s (peer));
  pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
  if (NULL == pos)
  {
    GNUNET_break (0);
    return;
  }
  if (pos->is_connected != GNUNET_YES)
  {
    GNUNET_break (0);
    return;
  }
  pos->is_connected = GNUNET_NO;
  connection_count--;
  if (NULL != pos->hello_req)
  {
    GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
    pos->hello_req = NULL;
  }
  if (GNUNET_SCHEDULER_NO_TASK != pos->hello_delay_task)
  {
    GNUNET_SCHEDULER_cancel (pos->hello_delay_task);
    pos->hello_delay_task = GNUNET_SCHEDULER_NO_TASK;
  }
  GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"),
                         connection_count, GNUNET_NO);
  if (pos->is_friend)
  {
    friend_count--;
    GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"),
                           friend_count, GNUNET_NO);
  }
  if (((connection_count < target_connection_count) ||
       (friend_count < minimum_friend_count)) &&
      (GNUNET_SCHEDULER_NO_TASK == add_task))
    add_task = GNUNET_SCHEDULER_add_now (&add_peer_task, NULL);
  if ((friend_count < minimum_friend_count) && (blacklist == NULL))
    blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL);
}
Пример #20
0
/**
 * Ask the core to call "notify" once it is ready to transmit the
 * given number of bytes to the specified "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?
 * @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 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, "notify" will NOT be called.
 */
struct GNUNET_CORE_TransmitHandle *
GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, int cork,
                                   uint32_t 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;

  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_multihashmap_get (handle->peers, &target->hashPubKey);
  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;
}
Пример #21
0
/**
 * Get the block for a particular zone and label in the
 * datastore.  Will return at most one result to the iterator.
 *
 * @param cls closure (internal context for the plugin)
 * @param query hash of public key derived from the zone and the label
 * @param iter function to call with the result
 * @param iter_cls closure for @a iter
 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
 */
static int
namecache_lookup_block (void *cls,
                        const struct GNUNET_HashCode *query,
                        GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls)
{
  struct Plugin *plugin = cls;
  const struct GNUNET_GNSRECORD_Block *block;

  block = GNUNET_CONTAINER_multihashmap_get (plugin->hm, query);
  if (NULL == block)
    return GNUNET_NO;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Found block under derived key `%s'\n",
              GNUNET_h2s_full (query));
  iter (iter_cls, block);
  return GNUNET_YES;
}
Пример #22
0
/**
 * Remove keywords above the threshold.
 *
 * @param cls the 'struct TrimContext' with the pos to remove the keywords from
 * @param keyword the keyword to check
 * @param is_mandatory ignored
 * @return always GNUNET_OK
 */
static int
remove_high_frequency_keywords (void *cls, const char *keyword, int is_mandatory)
{
  struct TrimContext *tc = cls;
  struct KeywordCounter *counter;
  GNUNET_HashCode hc;
  size_t klen;

  klen = strlen (keyword) + 1;
  GNUNET_CRYPTO_hash (keyword, klen - 1, &hc);
  counter = GNUNET_CONTAINER_multihashmap_get (tc->keywordcounter, &hc);
  GNUNET_assert (NULL != counter);
  if (counter->count < tc->move_threshold)
    return GNUNET_OK;
  GNUNET_FS_uri_ksk_remove_keyword (tc->pos->ksk_uri,
				    counter->value);
  return GNUNET_OK;
}
/**
 * Bind a host address (hello) to a hostId.
 *
 * @param peer the peer for which this is a hello
 * @param hello the verified (!) hello message
 */
static void
bind_address (const struct GNUNET_PeerIdentity *peer,
              const struct GNUNET_HELLO_Message *hello)
{
  char *fn;
  struct HostEntry *host;
  struct GNUNET_HELLO_Message *mrg;
  struct GNUNET_TIME_Absolute delta;

  add_host_to_known_hosts (peer);
  host = GNUNET_CONTAINER_multihashmap_get (hostmap, &peer->hashPubKey);
  GNUNET_assert (host != NULL);
  if (host->hello == NULL)
  {
    host->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
    memcpy (host->hello, hello, GNUNET_HELLO_size (hello));
  }
  else
  {
    mrg = GNUNET_HELLO_merge (host->hello, hello);
    delta = GNUNET_HELLO_equals (mrg, host->hello, GNUNET_TIME_absolute_get ());
    if (delta.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
    {
      GNUNET_free (mrg);
      return;
    }
    GNUNET_free (host->hello);
    host->hello = mrg;
  }
  fn = get_host_filename (peer);
  if (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn))
  {
    if (GNUNET_SYSERR ==
        GNUNET_DISK_fn_write (fn, host->hello, GNUNET_HELLO_size (host->hello),
                              GNUNET_DISK_PERM_USER_READ |
                              GNUNET_DISK_PERM_USER_WRITE |
                              GNUNET_DISK_PERM_GROUP_READ |
                              GNUNET_DISK_PERM_OTHER_READ))
      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);

  }
  GNUNET_free (fn);
  notify_all (host);
}
static void
exec_pcp (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_ATS_InformationRequestContext *irc = cls;
  int32_t want_reserv;
  int32_t got_reserv;
  struct GNUNET_TIME_Relative rdelay;
  struct AllocationRecord *ar;

  rdelay = GNUNET_TIME_UNIT_ZERO;
  want_reserv = irc->amount;
  ar = GNUNET_CONTAINER_multihashmap_get (irc->h->peers, &irc->peer.hashPubKey);
  if (NULL == ar)
  {
    /* attempt to change preference on peer that is not connected */
    /* FIXME: this can happen if the 'service' didn't yet tell us about
     * a new connection, fake it! */
    irc->info (irc->info_cls, &irc->peer, want_reserv, rdelay);
    GNUNET_free (irc);
    return;
  }
  if (want_reserv < 0)
  {
    got_reserv = want_reserv;
  }
  else if (want_reserv > 0)
  {
    rdelay =
        GNUNET_BANDWIDTH_tracker_get_delay (&ar->available_recv_window,
                                            want_reserv);
    if (rdelay.rel_value == 0)
      got_reserv = want_reserv;
    else
      got_reserv = 0;           /* all or nothing */
  }
  else
    got_reserv = 0;
  GNUNET_BANDWIDTH_tracker_consume (&ar->available_recv_window, got_reserv);

  irc->info (irc->info_cls, &irc->peer, got_reserv, rdelay);
  GNUNET_free (irc);
}
/**
 * Add a host to the list.
 *
 * @param identity the identity of the host
 */
static void
add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
{
  struct HostEntry *entry;
  char *fn;

  entry = GNUNET_CONTAINER_multihashmap_get (hostmap, &identity->hashPubKey);
  if (entry != NULL)
    return;
  GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1,
                            GNUNET_NO);
  entry = GNUNET_malloc (sizeof (struct HostEntry));
  entry->identity = *identity;
  GNUNET_CONTAINER_multihashmap_put (hostmap, &identity->hashPubKey, entry,
                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  fn = get_host_filename (identity);
  entry->hello = read_host_file (fn);
  GNUNET_free (fn);
  notify_all (entry);
}
Пример #26
0
/**
 * Remove trail with trail_id
 * @param trail_id Trail id to be removed
 * @return #GNUNET_YES success
 *         #GNUNET_NO if entry not found.
 */
int
GDS_ROUTING_remove_trail (const struct GNUNET_HashCode *remove_trail_id)
{
  struct RoutingTrail *remove_entry;

  remove_entry = GNUNET_CONTAINER_multihashmap_get (routing_table,
						    remove_trail_id);
  if (NULL == remove_entry)
    return GNUNET_NO;

  if (GNUNET_YES ==
      GNUNET_CONTAINER_multihashmap_remove (routing_table,
					    remove_trail_id,
					    remove_entry))
  {
    GNUNET_free (remove_entry);
    return GNUNET_YES;
  }
  return GNUNET_NO;
}
/**
 * Method called whenever a peer connects.
 *
 * @param cls closure
 * @param peer peer identity this notification is about
 * @param atsi performance data
 * @param atsi_count number of records in 'atsi'
 */
static void
connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_ATS_Information *atsi,
                unsigned int atsi_count)
{
  struct Peer *pos;

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

  connection_count++;
  GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"),
                         connection_count, GNUNET_NO);
  pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
  if (NULL == pos)
  {
    pos = make_peer (peer, NULL, GNUNET_NO);
    GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
  }
  else
  {
    GNUNET_assert (GNUNET_NO == pos->is_connected);
    pos->greylisted_until.abs_value = 0;        /* remove greylisting */
  }
  pos->is_connected = GNUNET_YES;
  pos->connect_attempts = 0;    /* re-set back-off factor */
  if (pos->is_friend)
  {
    if ((friend_count == minimum_friend_count - 1) &&
        (GNUNET_YES != friends_only))
      whitelist_peers ();
    friend_count++;
    GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"),
                           friend_count, GNUNET_NO);
  }
  reschedule_hellos (NULL, &peer->hashPubKey, pos);
}
/**
 * This function is called whenever an encrypted HELLO message is
 * received.
 *
 * @param cls closure
 * @param other the other peer involved (sender or receiver, NULL
 *        for loopback messages where we are both sender and receiver)
 * @param message the actual HELLO message
 * @param atsi performance data
 * @param atsi_count number of records in 'atsi'
 * @return GNUNET_OK to keep the connection open,
 *         GNUNET_SYSERR to close it (signal serious error)
 */
static int
handle_encrypted_hello (void *cls, const struct GNUNET_PeerIdentity *other,
                        const struct GNUNET_MessageHeader *message,
                        const struct GNUNET_ATS_Information *atsi,
                        unsigned int atsi_count)
{
  struct Peer *peer;
  struct GNUNET_PeerIdentity pid;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received encrypted `%s' from peer `%s'",
              "HELLO", GNUNET_i2s (other));
  if (GNUNET_OK !=
      GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) message, &pid))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages received"),
                            1, GNUNET_NO);
  peer = GNUNET_CONTAINER_multihashmap_get (peers, &pid.hashPubKey);
  if (NULL == peer)
  {
    if ((GNUNET_YES == friends_only) || (friend_count < minimum_friend_count))
      return GNUNET_OK;
  }
  else
  {
    if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only))
      return GNUNET_OK;
    if ((GNUNET_YES != peer->is_friend) &&
        (friend_count < minimum_friend_count))
      return GNUNET_OK;
  }
  if (transport != NULL)
    GNUNET_TRANSPORT_offer_hello (transport, message, NULL, NULL);
  return GNUNET_OK;
}
Пример #29
0
/**
 * Add the given keyword to the keyword statistics tracker.
 *
 * @param cls the multihashmap we store the keyword counters in
 * @param keyword the keyword to count
 * @param is_mandatory ignored
 * @return always GNUNET_OK
 */
static int
add_to_keyword_counter (void *cls, const char *keyword, int is_mandatory)
{
  struct GNUNET_CONTAINER_MultiHashMap *mcm = cls;
  struct KeywordCounter *cnt;
  GNUNET_HashCode hc;
  size_t klen;

  klen = strlen (keyword) + 1;
  GNUNET_CRYPTO_hash (keyword, klen - 1, &hc);
  cnt = GNUNET_CONTAINER_multihashmap_get (mcm, &hc);
  if (cnt == NULL)
  {
    cnt = GNUNET_malloc (sizeof (struct KeywordCounter) + klen);
    cnt->value = (const char *) &cnt[1];
    memcpy (&cnt[1], keyword, klen);
    GNUNET_assert (GNUNET_OK ==
		   GNUNET_CONTAINER_multihashmap_put (mcm, 
						      &hc, cnt,
						      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  }
  cnt->count++;
  return GNUNET_OK;
}
/**
 * Get (or create) a stream to talk to the given peer.
 *
 * @param target peer we want to communicate with
 */
static struct StreamHandle *
get_stream (const struct GNUNET_PeerIdentity *target)
{
  struct StreamHandle *sh;

  sh = GNUNET_CONTAINER_multihashmap_get (stream_map,
					  &target->hashPubKey);
  if (NULL != sh)
  {
    if (GNUNET_SCHEDULER_NO_TASK != sh->timeout_task)
    {
      GNUNET_SCHEDULER_cancel (sh->timeout_task);
      sh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
    }
    return sh;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "Creating stream to %s\n",
	      GNUNET_i2s (target));
  sh = GNUNET_malloc (sizeof (struct StreamHandle));
  sh->mst = GNUNET_SERVER_mst_create (&reply_cb,
				      sh);
  sh->waiting_map = GNUNET_CONTAINER_multihashmap_create (512, GNUNET_YES);
  sh->target = *target;
  sh->stream = GNUNET_STREAM_open (GSF_cfg,
				   &sh->target,
				   GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER,
				   &stream_ready_cb, sh,
				   GNUNET_STREAM_OPTION_END);
  GNUNET_assert (GNUNET_OK ==
		 GNUNET_CONTAINER_multihashmap_put (stream_map,
						    &sh->target.hashPubKey,
						    sh,
						    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  return sh;
}