Ejemplo n.º 1
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)
}
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;
}
Ejemplo n.º 3
0
/**
 * Get one of the results for a particular key in the datastore.
 *
 * @param cls closure
 * @param offset offset of the result (modulo num-results);
 *               specific ordering does not matter for the offset
 * @param key maybe NULL (to match all entries)
 * @param vhash hash of the value, maybe NULL (to
 *        match all values that have the right key).
 *        Note that for DBlocks there is no difference
 *        betwen key and vhash, but for other blocks
 *        there may be!
 * @param type entries of which type are relevant?
 *     Use 0 for any type.
 * @param proc function to call on each matching value;
 *        will be called with NULL if nothing matches
 * @param proc_cls closure for proc
 */
static void
heap_plugin_get_key (void *cls, uint64_t offset,
		     const struct GNUNET_HashCode *key,
		     const struct GNUNET_HashCode *vhash,
		     enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc,
		     void *proc_cls)
{
  struct Plugin *plugin = cls;
  struct GetContext gc;

  gc.plugin = plugin;
  gc.offset = 0;
  gc.vhash = vhash;
  gc.type = type;
  gc.proc = proc;
  gc.proc_cls = proc_cls;
  if (NULL == key)
  {
    GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue,
					   &count_iterator,
					   &gc);
    if (0 == gc.offset)
    {
      proc (proc_cls, 
	    NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
      return;
    }
    gc.offset = offset % gc.offset;
    GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue,
					   &get_iterator,
					   &gc);
  }
  else
  {
    GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue,
						key,
						&count_iterator, 
						&gc);
    if (0 == gc.offset)
    {
      proc (proc_cls, 
	    NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0);
      return;
    }
    gc.offset = offset % gc.offset;
    GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue,
						key,
						&get_iterator,
						&gc);
  }
}
/**
 * Find a ValidationEntry entry for the given neighbour that matches
 * the given address and transport.  If none exists, create one (but
 * without starting any validation).
 *
 * @param public_key public key of the peer, NULL for unknown
 * @param address address to find
 * @return validation entry matching the given specifications, NULL
 *         if we don't have an existing entry and no public key was given
 */
static struct ValidationEntry *
find_validation_entry (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
                       *public_key, const struct GNUNET_HELLO_Address *address)
{
  struct ValidationEntryMatchContext vemc;
  struct ValidationEntry *ve;

  vemc.ve = NULL;
  vemc.address = address;
  GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
                                              &address->peer.hashPubKey,
                                              &validation_entry_match, &vemc);
  if (NULL != (ve = vemc.ve))
    return ve;
  if (public_key == NULL)
    return NULL;
  ve = GNUNET_malloc (sizeof (struct ValidationEntry));
  ve->in_use = GNUNET_SYSERR; /* not defined */
  ve->last_line_set_to_no  = 0;
  ve->last_line_set_to_yes  = 0;
  ve->address = GNUNET_HELLO_address_copy (address);
  ve->public_key = *public_key;
  ve->pid = address->peer;
  ve->latency = GNUNET_TIME_UNIT_FOREVER_REL;
  ve->challenge =
      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
  ve->timeout_task =
      GNUNET_SCHEDULER_add_delayed (UNVALIDATED_PING_KEEPALIVE,
                                    &timeout_hello_validation, ve);
  GNUNET_CONTAINER_multihashmap_put (validation_map, &address->peer.hashPubKey,
                                     ve,
                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  ve->expecting_pong = GNUNET_NO;
  return ve;
}
/**
 * Handle a reply (route to origin).  Only forwards the reply back to
 * other peers waiting for it.  Does not do local caching or
 * forwarding to local clients.  Essentially calls
 * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching
 * request recently.
 *
 * @param type type of the block
 * @param expiration_time when does the content expire
 * @param key key for the content
 * @param put_path_length number of entries in put_path
 * @param put_path peers the original PUT traversed (if tracked)
 * @param get_path_length number of entries in put_path
 * @param get_path peers this reply has traversed so far (if tracked)
 * @param data payload of the reply
 * @param data_size number of bytes in data
 */
void
GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
                     struct GNUNET_TIME_Absolute expiration_time,
                     const struct GNUNET_HashCode * key, unsigned int put_path_length,
                     const struct GNUNET_PeerIdentity *put_path,
                     unsigned int get_path_length,
                     const struct GNUNET_PeerIdentity *get_path,
                     const void *data, size_t data_size)
{
  struct ProcessContext pc;

  pc.type = type;
  pc.expiration_time = expiration_time;
  pc.put_path_length = put_path_length;
  pc.put_path = put_path;
  pc.get_path_length = get_path_length;
  pc.get_path = get_path;
  pc.data = data;
  pc.data_size = data_size;
  if (NULL == data)
  {
    /* Some apps might have an 'empty' reply as a valid reply; however,
       'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL'
       reply as request-validation (but we need response-validation).
       So we set 'data' to a 0-byte non-NULL value just to be sure */
    GNUNET_break (0 == data_size);
    data_size = 0;
    pc.data = ""; /* something not null */
  }
  GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc);
}
void
GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
                       const char *plugin_name, const void *plugin_addr,
                       size_t plugin_addr_len, uint32_t session_id)
{
  struct ATS_Address *aa;
  struct ATS_Address *old;

  if (GNUNET_NO == running)
    return;

  /* Get existing address */
  old = lookup_address (peer, plugin_name, plugin_addr, plugin_addr_len,
                       session_id, NULL, 0);
  if (old == NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tried to destroy unknown address for peer `%s' `%s' session id %u\n",
                GNUNET_i2s (peer), plugin_name, session_id);
    return;
  }


  GNUNET_break (0 < strlen (plugin_name));
  aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id);

  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
                                              &destroy_by_session_id, aa);

  free_address (aa);
}
void
GAS_addresses_handle_backoff_reset (const struct GNUNET_PeerIdentity *peer)
{
  GNUNET_break (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (addresses,
                                              &peer->hashPubKey,
                                              &reset_address_it,
                                              NULL));
}
Ejemplo n.º 8
0
/**
 * We have received a KSK result.  Check how it fits in with the
 * overall query and notify the client accordingly.
 *
 * @param sc context for the overall query
 * @param ent entry for the specific keyword
 * @param uri the URI that was found
 * @param meta metadata associated with the URI
 *        under the @a ent keyword
 */
static void
process_ksk_result (struct GNUNET_FS_SearchContext *sc,
                    struct SearchRequestEntry *ent,
                    const struct GNUNET_FS_Uri *uri,
                    const struct GNUNET_CONTAINER_MetaData *meta)
{
  struct GNUNET_HashCode key;
  struct GNUNET_FS_SearchResult *sr;
  struct GetResultContext grc;
  int is_new;
  unsigned int koff;

  /* check if new */
  GNUNET_assert (NULL != sc);
  GNUNET_FS_uri_to_key (uri, &key);
  if (GNUNET_SYSERR ==
      GNUNET_CONTAINER_multihashmap_get_multiple (ent->results, &key,
                                                  &test_result_present,
                                                  (void *) uri))
    return;                     /* duplicate result */
  /* try to find search result in master map */
  grc.sr = NULL;
  grc.uri = uri;
  GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, &key,
                                              &get_result_present, &grc);
  sr = grc.sr;
  is_new = (NULL == sr) || (sr->mandatory_missing > 0);
  if (NULL == sr)
  {
    sr = GNUNET_new (struct GNUNET_FS_SearchResult);
    sr->h = sc->h;
    sr->sc = sc;
    sr->anonymity = sc->anonymity;
    sr->uri = GNUNET_FS_uri_dup (uri);
    sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
    sr->mandatory_missing = sc->mandatory_count;
    sr->key = key;
    sr->keyword_bitmap = GNUNET_malloc ((sc->uri->data.ksk.keywordCount + 7) / 8); /* round up, count bits */
    GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &key, sr,
                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  }
/**
 * Call the given function for each address for the given target.
 * Can either give a snapshot (synchronous API) or be continuous.
 *
 * @param target peer information is requested for
 * @param cb function to call; will not be called after this function returns
 * @param cb_cls closure for 'cb'
 */
void
GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target,
                              GST_ValidationAddressCallback cb, void *cb_cls)
{
  struct IteratorContext ic;

  ic.cb = cb;
  ic.cb_cls = cb_cls;
  GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
                                              &target->hashPubKey,
                                              &iterate_addresses, &ic);
}
/**
 * Find an existing equivalent address record.
 * Compares by peer identity and network address AND by session ID
 * (one of the two must match).
 *
 * @param peer peer to lookup addresses for
 * @param addr existing address record
 * @return existing address record, NULL for none
 */
struct ATS_Address *
find_exact_address (const struct GNUNET_PeerIdentity *peer,
              const struct ATS_Address *addr)
{
  struct CompareAddressContext cac;

  cac.exact_address = NULL;
  cac.search = addr;
  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
                                              &compare_address_session_it, &cac);
  return cac.exact_address;
}
Ejemplo n.º 11
0
static void
iter_hashcodes (struct IBF_Key key,
                GNUNET_CONTAINER_HashMapIterator iter,
                void *cls)
{
  struct GNUNET_HashCode replicated;

  ibf_hashcode_from_key (key, &replicated);
  GNUNET_CONTAINER_multihashmap_get_multiple (key_to_hashcode,
                                              &replicated,
                                              iter, cls);
}
/**
 * Handler for "GET result seen" messages from the client.
 *
 * @param cls closure for the service
 * @param client the client we received this message from
 * @param message the actual message received
 */
static void
handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client,
				  const struct GNUNET_MessageHeader *message)
{
  const struct GNUNET_DHT_ClientGetResultSeenMessage *seen;
  uint16_t size;
  unsigned int hash_count;
  unsigned int old_count;
  const struct GNUNET_HashCode *hc;
  struct FindByUniqueIdContext fui_ctx;
  struct ClientQueryRecord *cqr;

  size = ntohs (message->size);
  if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message;
  hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode);
  if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  hc = (const struct GNUNET_HashCode*) &seen[1];
  fui_ctx.unique_id = seen->unique_id;
  fui_ctx.cqr = NULL;
  GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
					      &seen->key,
					      &find_by_unique_id,
					      &fui_ctx);
  if (NULL == (cqr = fui_ctx.cqr))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  /* finally, update 'seen' list */
  old_count = cqr->seen_replies_count;
  GNUNET_array_grow (cqr->seen_replies,
		     cqr->seen_replies_count,
		     cqr->seen_replies_count + hash_count);
  memcpy (&cqr->seen_replies[old_count],
	  hc,
	  sizeof (struct GNUNET_HashCode) * hash_count);
}
/**
 * Handle GET-message.
 *
 * @param cls closure
 * @param client identification of the client
 * @param message the actual message
 */
static void
handle_get (void *cls, struct GNUNET_SERVER_Client *client,
            const struct GNUNET_MessageHeader *message)
{
  const struct ListPeerMessage *lpm;
  struct GNUNET_SERVER_TransmitContext *tc;

  lpm = (const struct ListPeerMessage *) message;
  GNUNET_break (0 == ntohl (lpm->reserved));
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n",
              "GET", GNUNET_i2s (&lpm->peer));
  tc = GNUNET_SERVER_transmit_context_create (client);
  GNUNET_CONTAINER_multihashmap_get_multiple (hostmap, &lpm->peer.hashPubKey,
                                              &add_to_tc, tc);
  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
                                              GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
}
void
GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
                       const char *plugin_name, const void *plugin_addr,
                       size_t plugin_addr_len, uint32_t session_id)
{
  struct ATS_Address *aa;

  if (GNUNET_NO == running)
    return;

  GNUNET_break (0 < strlen (plugin_name));
  aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id);

  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
                                              &destroy_by_session_id, aa);

  free_address (aa);
}
/**
 * Add a new entry to our routing table.
 *
 * @param sender peer that originated the request
 * @param type type of the block
 * @param options options for processing
 * @param key key for the content
 * @param xquery extended query
 * @param xquery_size number of bytes in xquery
 * @param reply_bf bloomfilter to filter duplicates
 * @param reply_bf_mutator mutator for reply_bf
*/
void
GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
                 enum GNUNET_BLOCK_Type type,
                 enum GNUNET_DHT_RouteOption options,
                 const struct GNUNET_HashCode * key, const void *xquery,
                 size_t xquery_size,
                 const struct GNUNET_CONTAINER_BloomFilter *reply_bf,
                 uint32_t reply_bf_mutator)
{
  struct RecentRequest *recent_req;

  while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT)
    expire_oldest_entry ();
  GNUNET_STATISTICS_update (GDS_stats,
                            gettext_noop ("# Entries added to routing table"),
                            1, GNUNET_NO);
  recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size);
  recent_req->peer = *sender;
  recent_req->key = *key;
  recent_req->reply_bf = GNUNET_CONTAINER_bloomfilter_copy (reply_bf);
  recent_req->type = type;
  recent_req->options = options;
  recent_req->xquery = &recent_req[1];
  memcpy (&recent_req[1], xquery, xquery_size);
  recent_req->xquery_size = xquery_size;
  recent_req->reply_bf_mutator = reply_bf_mutator;
  if (GNUNET_SYSERR ==
      GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key,
						  &try_combine_recent, recent_req))
  {
    GNUNET_STATISTICS_update (GDS_stats,
                              gettext_noop
                              ("# DHT requests combined"),
                              1, GNUNET_NO);
    return;
  }
  recent_req->heap_node =
      GNUNET_CONTAINER_heap_insert (recent_heap, recent_req,
                                    GNUNET_TIME_absolute_get ().abs_value);
  GNUNET_CONTAINER_multihashmap_put (recent_map, key, recent_req,
                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);


}
/**
 * Return all peers currently known to ATS
 *
 * @param peer the respective peer
 * @param pi_it the iterator to call for every peer
 * @param pi_it_cls the closure for the iterator
 */
void
GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer, GNUNET_ATS_PeerInfo_Iterator pi_it, void *pi_it_cls)
{
  struct PeerInfoIteratorContext pi_ctx;
  struct GNUNET_BANDWIDTH_Value32NBO zero_bw;
  GNUNET_assert (NULL != peer);
  GNUNET_assert (NULL != addresses);
  if (NULL == pi_it)
    return; /* does not make sense without callback */

  zero_bw = GNUNET_BANDWIDTH_value_init (0);
  pi_ctx.it = pi_it;
  pi_ctx.it_cls = pi_it_cls;

  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, &peerinfo_it, &pi_ctx);

  if (NULL != pi_it)
    pi_it (pi_it_cls, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, zero_bw, zero_bw);

}
/**
 * Handler for any generic DHT stop messages, calls the appropriate handler
 * depending on message type (if processed locally)
 *
 * @param cls closure for the service
 * @param client the client we received this message from
 * @param message the actual message received
 *
 */
static void
handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client,
                           const struct GNUNET_MessageHeader *message)
{
  const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg =
      (const struct GNUNET_DHT_ClientGetStopMessage *) message;
  struct RemoveByUniqueIdContext ctx;

  GNUNET_STATISTICS_update (GDS_stats,
                            gettext_noop
                            ("# GET STOP requests received from clients"), 1,
                            GNUNET_NO);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received GET STOP request for %s from local client %p\n",
       client, GNUNET_h2s (&dht_stop_msg->key));
  ctx.client = find_active_client (client);
  ctx.unique_id = dht_stop_msg->unique_id;
  GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key,
                                              &remove_by_unique_id, &ctx);
  GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
/**
 * Find an existing equivalent address record.
 * Compares by peer identity and network address OR by session ID
 * (one of the two must match).
 *
 * @param peer peer to lookup addresses for
 * @param addr existing address record
 * @return existing address record, NULL for none
 */
struct ATS_Address *
find_address (const struct GNUNET_PeerIdentity *peer,
              const struct ATS_Address *addr)
{
  struct CompareAddressContext cac;

  cac.exact_address = NULL;
  cac.base_address = NULL;
  cac.search = addr;
  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
                                              &compare_address_it, &cac);

/*
  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
              "exact address: %s           base address: %s\n",
              (cac.exact_address != NULL) ? "YES" : "NO",
              (cac.base_address != NULL) ? "YES" : "NO");
*/
  if (cac.exact_address == NULL)
    return cac.base_address;
  return cac.exact_address;
}
static void 
request_address_simple (const struct GNUNET_PeerIdentity *peer)
{
  struct ATS_Address *aa;
  aa = NULL;

  /* Get address with: stick to current address, lower distance, lower latency */
  GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
                                              &find_address_it, &aa);
  if (aa == NULL)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
    return;
  }

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
              "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer));

  if (aa->active == GNUNET_NO)
  {
    aa->active = GNUNET_YES;
    active_addr_count++;
    if (ats_mode == SIMPLE)
    {
      recalculate_assigned_bw ();
    }
  }
  else
  {
    /* just to be sure... */
    GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, aa->addr,
                                                aa->addr_len, aa->session_id,
                                                aa->ats, aa->ats_count,
                                                aa->assigned_bw_out,
                                                aa->assigned_bw_in);
  }
}
Ejemplo n.º 20
0
/**
 * Handler for port open requests.
 *
 * @param cls Identification of the client.
 * @param pmsg The actual message.
 */
static void
handle_port_open (void *cls,
                  const struct GNUNET_CADET_PortMessage *pmsg)
{
  struct CadetClient *c = cls;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Open port %s requested by client %u\n",
       GNUNET_h2s (&pmsg->port),
       c->id);
  if (NULL == c->ports)
    c->ports = GNUNET_CONTAINER_multihashmap_create (4,
                                                     GNUNET_NO);
  if (GNUNET_OK !=
      GNUNET_CONTAINER_multihashmap_put (c->ports,
                                         &pmsg->port,
                                         c,
                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  {
    GNUNET_break (0);
    GNUNET_SERVICE_client_drop (c->client);
    return;
  }
  /* store in global hashmap */
  /* FIXME only allow one client to have the port open,
   *       have a backup hashmap with waiting clients */
  GNUNET_CONTAINER_multihashmap_put (open_ports,
                                     &pmsg->port,
                                     c,
                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
                                              &pmsg->port,
                                              &bind_loose_channel,
                                              c);
  GNUNET_SERVICE_client_continue (c->client);
}
/**
 * Handle a reply we've received from another peer.  If the reply
 * matches any of our pending queries, forward it to the respective
 * client(s).
 *
 * @param expiration when will the reply expire
 * @param key the query this reply is for
 * @param get_path_length number of peers in @a get_path
 * @param get_path path the reply took on get
 * @param put_path_length number of peers in @a put_path
 * @param put_path path the reply took on put
 * @param type type of the reply
 * @param data_size number of bytes in @a data
 * @param data application payload data
 */
void
GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
                          const struct GNUNET_HashCode *key,
                          unsigned int get_path_length,
                          const struct GNUNET_PeerIdentity *get_path,
                          unsigned int put_path_length,
                          const struct GNUNET_PeerIdentity *put_path,
                          enum GNUNET_BLOCK_Type type, size_t data_size,
                          const void *data)
{
  struct ForwardReplyContext frc;
  struct PendingMessage *pm;
  struct GNUNET_DHT_ClientResultMessage *reply;
  struct GNUNET_PeerIdentity *paths;
  size_t msize;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "reply for key %s\n",
       GNUNET_h2s (key));

  if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key))
  {
    GNUNET_STATISTICS_update (GDS_stats,
                              gettext_noop
                              ("# REPLIES ignored for CLIENTS (no match)"), 1,
                              GNUNET_NO);
    return;                     /* no matching request, fast exit! */
  }
  msize =
      sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size +
      (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
  if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Could not pass reply to client, message too big!\n"));
    return;
  }
  pm = GNUNET_malloc (msize + sizeof (struct PendingMessage));
  reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1];
  pm->msg = &reply->header;
  reply->header.size = htons ((uint16_t) msize);
  reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
  reply->type = htonl (type);
  reply->get_path_length = htonl (get_path_length);
  reply->put_path_length = htonl (put_path_length);
  reply->unique_id = 0;         /* filled in later */
  reply->expiration = GNUNET_TIME_absolute_hton (expiration);
  reply->key = *key;
  paths = (struct GNUNET_PeerIdentity *) &reply[1];
  memcpy (paths, put_path,
          sizeof (struct GNUNET_PeerIdentity) * put_path_length);
  memcpy (&paths[put_path_length], get_path,
          sizeof (struct GNUNET_PeerIdentity) * get_path_length);
  memcpy (&paths[get_path_length + put_path_length], data, data_size);
  frc.do_copy = GNUNET_NO;
  frc.pm = pm;
  frc.data = data;
  frc.data_size = data_size;
  frc.type = type;
  GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply,
                                              &frc);
  if (GNUNET_NO == frc.do_copy)
  {
    /* did not match any of the requests, free! */
    GNUNET_STATISTICS_update (GDS_stats,
                              gettext_noop
                              ("# REPLIES ignored for CLIENTS (no match)"), 1,
                              GNUNET_NO);
    GNUNET_free (pm);
  }
}
Ejemplo n.º 22
0
/**
 * Handler for messages received from the DHT service
 * a demultiplexer which handles numerous message types
 *
 * @param cls the `struct GNUNET_DHT_Handle`
 * @param msg the incoming message
 */
static void
service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_DHT_Handle *handle = cls;
  const struct GNUNET_DHT_ClientResultMessage *dht_msg;
  uint16_t msize;
  int ret;


  if (NULL == msg)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Error receiving data from DHT service, reconnecting\n");
    do_disconnect (handle);
    return;
  }
  GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle,
                         GNUNET_TIME_UNIT_FOREVER_REL);
  ret = GNUNET_SYSERR;
  msize = ntohs (msg->size);
  switch (ntohs (msg->type))
  {
  case GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET:
    if (msize < sizeof (struct GNUNET_DHT_MonitorGetMessage))
    {
      GNUNET_break (0);
      break;
    }
    ret = process_monitor_get_message(handle,
				      (const struct GNUNET_DHT_MonitorGetMessage *) msg);
    break;
  case GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP:
    if (msize < sizeof (struct GNUNET_DHT_MonitorGetRespMessage))
    {
      GNUNET_break (0);
      break;
    }
    ret = process_monitor_get_resp_message(handle,
					   (const struct GNUNET_DHT_MonitorGetRespMessage *) msg);
    break;
  case GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT:
    if (msize < sizeof (struct GNUNET_DHT_MonitorPutMessage))
    {
      GNUNET_break (0);
      break;
    }
    ret = process_monitor_put_message(handle,
				      (const struct GNUNET_DHT_MonitorPutMessage *) msg);
    break;
  case GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT_RESP:
    /* Not implemented yet */
    GNUNET_break(0);
    break;
  case GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT:
    if (ntohs (msg->size) < sizeof (struct GNUNET_DHT_ClientResultMessage))
    {
      GNUNET_break (0);
      break;
    }
    dht_msg = (const struct GNUNET_DHT_ClientResultMessage *) msg;
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Received reply for `%s' from DHT service %p\n",
         GNUNET_h2s (&dht_msg->key), handle);
    GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_requests,
						&dht_msg->key,
						&process_reply,
						(void *) dht_msg);
    ret = GNUNET_OK;
    break;
  case GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK:
    if (ntohs (msg->size) != sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage))
    {
      GNUNET_break (0);
      break;
    }
    ret = process_put_confirmation_message (handle,
					    (const struct GNUNET_DHT_ClientPutConfirmationMessage*) msg);
    break;
#if ENABLE_MALICIOUS
    case GNUNET_MESSAGE_TYPE_DHT_CLIENT_ACT_MALICIOUS_OK:
       if(msize != sizeof (struct GNUNET_DHT_ClientActMaliciousConfirmationMessage))
       {
         GNUNET_break (0);
         break;
       }
       ret = process_act_malicious_confirmation_message (handle,
					    (const struct GNUNET_DHT_ClientActMaliciousConfirmationMessage*) msg);
      break;
#endif
  default:
    GNUNET_break(0);
    LOG (GNUNET_ERROR_TYPE_WARNING,
         "Unknown DHT message type: %hu (%hu) size: %hu\n",
         ntohs (msg->type), msg->type, msize);
    break;
  }
  if (GNUNET_OK != ret)
  {
    GNUNET_break (0);
    do_disconnect (handle);
    return;
  }
}
/**
 * Functions with this signature are called whenever a
 * complete reply is received.
 *
 * Do not call GNUNET_SERVER_mst_destroy in callback
 *
 * @param cls closure with the 'struct StreamHandle'
 * @param client identification of the client, NULL
 * @param message the actual message
 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
 */
static int
reply_cb (void *cls,
	  void *client,
	  const struct GNUNET_MessageHeader *message)
{
  struct StreamHandle *sh = cls;
  const struct StreamReplyMessage *srm;
  struct HandleReplyClosure hrc;
  uint16_t msize;
  enum GNUNET_BLOCK_Type type;
  struct GNUNET_HashCode query;

  msize = ntohs (message->size);
  switch (ntohs (message->type))
  {
  case GNUNET_MESSAGE_TYPE_FS_STREAM_REPLY:
    if (sizeof (struct StreamReplyMessage) > msize)
    {
      GNUNET_break_op (0);
      reset_stream_async (sh);
      return GNUNET_SYSERR;
    }
    srm = (const struct StreamReplyMessage *) message;
    msize -= sizeof (struct StreamReplyMessage);
    type = (enum GNUNET_BLOCK_Type) ntohl (srm->type);
    if (GNUNET_YES !=
	GNUNET_BLOCK_get_key (GSF_block_ctx,
			      type,
			      &srm[1], msize, &query))
    {
      GNUNET_break_op (0); 
      reset_stream_async (sh);
      return GNUNET_SYSERR;
    }
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
		"Received reply `%s' via stream\n",
		GNUNET_h2s (&query));
    GNUNET_STATISTICS_update (GSF_stats,
			      gettext_noop ("# replies received via stream"), 1,
			      GNUNET_NO);
    hrc.data = &srm[1];
    hrc.data_size = msize;
    hrc.expiration = GNUNET_TIME_absolute_ntoh (srm->expiration);
    hrc.type = type;
    hrc.found = GNUNET_NO;
    GNUNET_CONTAINER_multihashmap_get_multiple (sh->waiting_map,
						&query,
						&handle_reply,
						&hrc);
    if (GNUNET_NO == hrc.found)
    {
      GNUNET_STATISTICS_update (GSF_stats,
				gettext_noop ("# replies received via stream dropped"), 1,
				GNUNET_NO);
      return GNUNET_OK;
    }
    return GNUNET_OK;
  default:
    GNUNET_break_op (0);
    reset_stream_async (sh);
    return GNUNET_SYSERR;
  }
}
Ejemplo n.º 24
0
/**
 * Jump to the next edge, with the longest matching token.
 *
 * @param block Block found in the DHT.
 * @param size Size of the block.
 * @param ctx Context of the search.
 */
static void
regex_next_edge (const struct RegexBlock *block,
                 size_t size,
                 struct RegexSearchContext *ctx)
{
  struct RegexSearchContext *new_ctx;
  struct REGEX_INTERNAL_Search *info = ctx->info;
  struct GNUNET_DHT_GetHandle *get_h;
  struct GNUNET_HashCode *hash;
  const char *rest;
  int result;

  LOG (GNUNET_ERROR_TYPE_DEBUG, "Next edge\n");
  /* Find the longest match for the current string position,
   * among tokens in the given block */
  ctx->longest_match = 0;
  result = REGEX_BLOCK_iterate (block, size,
                                &regex_edge_iterator, ctx);
  GNUNET_break (GNUNET_OK == result);

  /* Did anything match? */
  if (0 == ctx->longest_match)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "no match in block\n");
    return;
  }

  hash = &ctx->hash;
  new_ctx = GNUNET_new (struct RegexSearchContext);
  new_ctx->info = info;
  new_ctx->position = ctx->position + ctx->longest_match;
  GNUNET_array_append (info->contexts, info->n_contexts, new_ctx);

  /* Check whether we already have a DHT GET running for it */
  if (GNUNET_YES ==
      GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash))
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
	 "GET for %s running, END\n",
         GNUNET_h2s (hash));
    GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results,
                                                hash,
                                                &regex_result_iterator,
                                                new_ctx);
    return; /* We are already looking for it */
  }

  GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed",
                            1, GNUNET_NO);

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Following edges at %s for offset %u in `%s'\n",
       GNUNET_h2s (hash),
       (unsigned int) ctx->position,
       info->description);
  rest = &new_ctx->info->description[new_ctx->position];
  get_h =
      GNUNET_DHT_get_start (info->dht,    /* handle */
                            GNUNET_BLOCK_TYPE_REGEX, /* type */
                            hash,     /* key to search */
                            DHT_REPLICATION, /* replication level */
                            DHT_OPT,
                            rest, /* xquery */
                            strlen (rest) + 1,     /* xquery bits */
                            &dht_get_string_handler, new_ctx);
  if (GNUNET_OK !=
      GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles,
                                        hash,
                                        get_h,
                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
  {
    GNUNET_break (0);
    return;
  }
}