/** * 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; }
/** * 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)); }
/** * 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; }
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); } }
/** * 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); } }
/** * 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; } }
/** * 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, ®ex_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, ®ex_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; } }