static void key_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { unsigned int i; struct IteratorContext *ctx = cls; char *out_str; char *state_id = GNUNET_strdup (GNUNET_h2s (key)); GNUNET_assert (NULL != proof); if (GNUNET_YES == ctx->should_save_graph) { if (GNUNET_YES == accepting) GNUNET_asprintf (&out_str, "\"%s\" [shape=doublecircle]\n", state_id); else GNUNET_asprintf (&out_str, "\"%s\" [shape=circle]\n", state_id); fwrite (out_str, strlen (out_str), 1, ctx->graph_filep); GNUNET_free (out_str); for (i = 0; i < num_edges; i++) { transition_counter++; GNUNET_asprintf (&out_str, "\"%s\" -> \"%s\" [label = \"%s (%s)\"]\n", state_id, GNUNET_h2s (&edges[i].destination), edges[i].label, proof); fwrite (out_str, strlen (out_str), 1, ctx->graph_filep); GNUNET_free (out_str); } } else { for (i = 0; i < num_edges; i++) transition_counter++; } for (i = 0; i < ctx->string_count; i++) { if (0 == strcmp (proof, ctx->strings[i])) ctx->match_count++; } if (GNUNET_OK != REGEX_BLOCK_check_proof (proof, strlen (proof), key)) { ctx->error++; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Proof check failed: proof: %s key: %s\n", proof, state_id); } GNUNET_free (state_id); }
/** * Process a given reply that might match the given * request. * * @param cls the 'struct GNUNET_DHT_ClientResultMessage' * @param key query of the request * @param value the 'struct GNUNET_DHT_RouteHandle' of a request matching the same key * @return GNUNET_YES to continue to iterate over all results, * GNUNET_NO if the reply is malformed */ static int process_reply (void *cls, const GNUNET_HashCode * key, void *value) { const struct GNUNET_DHT_ClientResultMessage *dht_msg = cls; struct GNUNET_DHT_GetHandle *get_handle = value; const struct GNUNET_PeerIdentity *put_path; const struct GNUNET_PeerIdentity *get_path; uint32_t put_path_length; uint32_t get_path_length; size_t data_length; size_t msize; size_t meta_length; const void *data; if (dht_msg->unique_id != get_handle->unique_id) { /* UID mismatch */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key), dht_msg->unique_id, get_handle->unique_id); return GNUNET_YES; } msize = ntohs (dht_msg->header.size); put_path_length = ntohl (dht_msg->put_path_length); get_path_length = ntohl (dht_msg->get_path_length); meta_length = sizeof (struct GNUNET_DHT_ClientResultMessage) + sizeof (struct GNUNET_PeerIdentity) * (get_path_length + put_path_length); if ((msize < meta_length) || (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return GNUNET_NO; } data_length = msize - meta_length; LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving %u byte reply for %s to application\n", (unsigned int) data_length, GNUNET_h2s (key)); put_path = (const struct GNUNET_PeerIdentity *) &dht_msg[1]; get_path = &put_path[put_path_length]; data = &get_path[get_path_length]; get_handle->iter (get_handle->iter_cls, GNUNET_TIME_absolute_ntoh (dht_msg->expiration), key, get_path, get_path_length, put_path, put_path_length, ntohl (dht_msg->type), data_length, data); return GNUNET_YES; }
/** * Get a result for a particular key from the datastore. The processor * will only be called once. * * @param h handle to the datastore * @param offset offset of the result (modulo num-results); set to * a random 64-bit value initially; then increment by * one each time; detect that all results have been found by uid * being again the first uid ever returned. * @param key maybe NULL (to match all entries) * @param type desired type, 0 for any * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param proc function to call on each matching value; * will be called once with a NULL value at the end * @param proc_cls closure for proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_key (struct GNUNET_DATASTORE_Handle *h, uint64_t offset, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct GetMessage *gm; union QueueContext qc; GNUNET_assert (NULL != proc); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to look for data of type %u under key `%s'\n", (unsigned int) type, GNUNET_h2s (key)); qc.rc.proc = proc; qc.rc.proc_cls = proc_cls; qe = make_queue_entry (h, sizeof (struct GetMessage), queue_priority, max_queue_size, timeout, &process_result_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not queue request for `%s'\n", GNUNET_h2s (key)); return NULL; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (h->stats, gettext_noop ("# GET requests executed"), 1, GNUNET_NO); #endif gm = (struct GetMessage *) &qe[1]; gm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_GET); gm->type = htonl (type); gm->offset = GNUNET_htonll (offset); if (key != NULL) { gm->header.size = htons (sizeof (struct GetMessage)); gm->key = *key; } else { gm->header.size = htons (sizeof (struct GetMessage) - sizeof (struct GNUNET_HashCode)); } process_queue (h); return qe; }
/** * Store content in DHT. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_dht_put_content (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct PutOperator *po = cls; po->dht_qe = NULL; if (key == NULL) { po->zero_anonymity_count_estimate = po->current_offset - 1; po->current_offset = 0; po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); return; } po->zero_anonymity_count_estimate = GNUNET_MAX (po->current_offset, po->zero_anonymity_count_estimate); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrieved block `%s' of type %u for DHT PUT\n", GNUNET_h2s (key), type); po->dht_put = GNUNET_DHT_put (GSF_dht, key, DEFAULT_PUT_REPLICATION, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data, expiration, GNUNET_TIME_UNIT_FOREVER_REL, &delay_dht_put_blocks, po); }
/** * Handler for port close requests. * * @param cls Identification of the client. * @param pmsg The actual message. */ static void handle_port_close (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 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->ports, &pmsg->port, c)) { GNUNET_break (0); GNUNET_SERVICE_client_drop (c->client); return; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (open_ports, &pmsg->port, c)); GNUNET_SERVICE_client_continue (c->client); }
/** * We've paired up a client session with an incoming CADET request. * Initiate set intersection work. * * @param s client session to start intersection for */ static void start_intersection (struct BobServiceSession *s) { struct GNUNET_HashCode set_sid; GNUNET_CRYPTO_hash (&s->session_id, sizeof (struct GNUNET_HashCode), &set_sid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got session with key %s and %u elements, starting intersection.\n", GNUNET_h2s (&s->session_id), (unsigned int) s->total); s->intersection_op = GNUNET_SET_prepare (&s->cadet->peer, &set_sid, NULL, GNUNET_SET_RESULT_REMOVED, &cb_intersection_element_removed, s); if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set)) { GNUNET_break (0); s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; prepare_client_end_notification (s); return; } GNUNET_SET_destroy (s->intersection_set); s->intersection_set = NULL; }
/** * Function called whenever a channel is destroyed. Should clean up * any associated state. * * It must NOT call #GNUNET_CADET_channel_destroy() on the channel. * * @param cls closure (set from #GNUNET_CADET_connect()) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel, void *channel_ctx) { struct CadetIncomingSession *in = channel_ctx; struct BobServiceSession *s; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer disconnected, terminating session %s with peer %s\n", GNUNET_h2s (&in->session_id), GNUNET_i2s (&in->peer)); if (NULL != in->cadet_mq) { GNUNET_MQ_destroy (in->cadet_mq); in->cadet_mq = NULL; } in->channel = NULL; if (NULL != (s = in->s)) { if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status) { s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; prepare_client_end_notification (s); } } destroy_cadet_session (in); }
static void init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server, const struct GNUNET_PeerIdentity *my_identity) { struct TestMessageContext *pos = cls; total_server_connections++; pos->peer2connected = GNUNET_YES; if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */ { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", GNUNET_i2s (my_identity), GNUNET_h2s (&pos->peer1->id.hashPubKey)); if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, TIMEOUT, &pos->peer2->id, sizeof (struct GNUNET_TestMessage), &transmit_ready, pos)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&pos->peer2->id)); transmit_ready_failed++; } else { transmit_ready_scheduled++; } } }
/** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls Closure. * @param channel New handle to the channel. * @param initiator Peer that started the channel. * @param port Port this channel is connected to. * @param options channel option flags * @return Initial channel context for the channel * (can be NULL -- that's not an error). */ static void * incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator, const struct GNUNET_HashCode *port, enum GNUNET_CADET_ChannelOption options) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel from %s to peer %d:%s\n", GNUNET_i2s (initiator), (int) (long) cls, GNUNET_h2s (port)); ok++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); if ((long) cls == peers_requested - 1) incoming_ch = channel; else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Incoming channel for unknown client %lu\n", (long) cls); GNUNET_break(0); } if (NULL != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, (void *) __LINE__); } return NULL; }
/** * An iterator over a set of items stored in the datastore * that deletes until we're happy with respect to our quota. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int quota_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { unsigned long long *need = cls; if (NULL == key) return GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting %llu bytes of low-priority (%u) content `%s' of type %u at %s prior to expiration (still trying to free another %llu bytes)\n", (unsigned long long) (size + GNUNET_DATASTORE_ENTRY_OVERHEAD), (unsigned int) priority, GNUNET_h2s (key), type, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration), GNUNET_YES), *need); if (size + GNUNET_DATASTORE_ENTRY_OVERHEAD > *need) *need = 0; else *need -= size + GNUNET_DATASTORE_ENTRY_OVERHEAD; if (priority > 0) min_expiration = GNUNET_TIME_UNIT_FOREVER_ABS; else min_expiration = expiration; GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes purged (low-priority)"), size, GNUNET_YES); GNUNET_CONTAINER_bloomfilter_remove (filter, key); return GNUNET_NO; }
/** * Notify of all peer1's peers, once peer 2 is found, schedule connect * to peer two for message send. * * @param cls closure * @param peer peer identity this notification is about * @param atsi performance data for the connection * @param atsi_count number of ATS information included */ static void connect_notify_peer2 (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_ATS_Information *atsi, unsigned int atsi_count) { struct TestMessageContext *pos = cls; if (0 == memcmp (&pos->peer1->id, peer, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core connection from `%s' to `%4s' verfied, sending message!\n", GNUNET_i2s (&pos->peer2->id), GNUNET_h2s (&peer->hashPubKey)); if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0, TIMEOUT, &pos->peer2->id, sizeof (struct GNUNET_TestMessage), &transmit_ready, pos)) { /* This probably shouldn't happen, but it does (timing issue?) */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&pos->peer2->id)); transmit_ready_failed++; total_other_expected_messages--; } else { transmit_ready_scheduled++; } } }
/** * Handle a GET request we've received from another peer. * * @param key the query * @param type requested data type * @param xquery extended query * @param xquery_size number of bytes in @a xquery * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL * @param reply_bf_mutator mutation value for @a reply_bf * @return evaluation result for the local replies */ enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_CONTAINER_BloomFilter **reply_bf, uint32_t reply_bf_mutator) { struct GetRequestContext ctx; unsigned int r; if (NULL == datacache) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests given to datacache"), 1, GNUNET_NO); ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID; ctx.key = *key; ctx.xquery = xquery; ctx.xquery_size = xquery_size; ctx.reply_bf = reply_bf; ctx.reply_bf_mutator = reply_bf_mutator; r = GNUNET_DATACACHE_get (datacache, key, type, &datacache_get_iterator, &ctx); LOG (GNUNET_ERROR_TYPE_DEBUG, "DATACACHE GET for key %s completed (%d). %u results found.\n", GNUNET_h2s (key), ctx.eval, r); return ctx.eval; }
/** * Route the given request via the DHT. This includes updating * the bloom filter and retransmission times, building the P2P * message and initiating the routing operation. */ static void transmit_request (struct ClientQueryRecord *cqr) { int32_t reply_bf_mutator; struct GNUNET_CONTAINER_BloomFilter *reply_bf; struct GNUNET_CONTAINER_BloomFilter *peer_bf; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests from clients injected"), 1, GNUNET_NO); reply_bf_mutator = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); reply_bf = GNUNET_BLOCK_construct_bloomfilter (reply_bf_mutator, cqr->seen_replies, cqr->seen_replies_count); peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); LOG (GNUNET_ERROR_TYPE_DEBUG, "Initiating GET for %s, replication %u, already have %u replies\n", GNUNET_h2s(&cqr->key), cqr->replication, cqr->seen_replies_count); GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, 0 /* hop count */ , &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, reply_bf_mutator, peer_bf); GNUNET_CONTAINER_bloomfilter_free (reply_bf); GNUNET_CONTAINER_bloomfilter_free (peer_bf); /* exponential back-off for retries. * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); }
/** * Look for a block by directly contacting a particular peer. * * @param target peer that should have the block * @param query hash to query for the block * @param type desired type for the block * @param proc function to call with result * @param proc_cls closure for 'proc' * @return handle to cancel the operation */ struct GSF_StreamRequest * GSF_stream_query (const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *query, enum GNUNET_BLOCK_Type type, GSF_StreamReplyProcessor proc, void *proc_cls) { struct StreamHandle *sh; struct GSF_StreamRequest *sr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to send query for %s via stream to %s\n", GNUNET_h2s (query), GNUNET_i2s (target)); sh = get_stream (target); sr = GNUNET_malloc (sizeof (struct GSF_StreamRequest)); sr->sh = sh; sr->proc = proc; sr->proc_cls = proc_cls; sr->type = type; sr->query = *query; GNUNET_CONTAINER_DLL_insert (sh->pending_head, sh->pending_tail, sr); if (GNUNET_YES == sh->is_ready) transmit_pending (sh); return sr; }
/** * Encrypt the next block of the file (and call proc and progress * accordingly; or of course "cont" if we have already completed * encoding of the entire file). * * @param te tree encoder to use */ void GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te) { struct ContentHashKey *mychk; const void *pt_block; uint16_t pt_size; char iob[DBLOCK_SIZE]; char enc[DBLOCK_SIZE]; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; unsigned int off; GNUNET_assert (GNUNET_NO == te->in_next); te->in_next = GNUNET_YES; if (te->chk_tree_depth == te->current_depth) { off = CHK_PER_INODE * (te->chk_tree_depth - 1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TE done, reading CHK `%s' from %u\n", GNUNET_h2s (&te->chk_tree[off].query), off); te->uri = GNUNET_new (struct GNUNET_FS_Uri); te->uri->type = GNUNET_FS_URI_CHK; te->uri->data.chk.chk = te->chk_tree[off]; te->uri->data.chk.file_length = GNUNET_htonll (te->size); te->in_next = GNUNET_NO; te->cont (te->cls, NULL); return; }
/** * TEST FUNCTION * Remove after using. */ void GDS_ROUTING_test_print (void) { struct GNUNET_CONTAINER_MultiHashMapIterator *iter; struct RoutingTrail *trail; struct GNUNET_PeerIdentity print_peer; struct GNUNET_HashCode key_ret; int i; struct GNUNET_PeerIdentity my_identity = *GDS_NEIGHBOURS_get_id(); print_peer = my_identity; FPRINTF (stderr,_("\nSUPU ***PRINTING ROUTING TABLE ***** of =%s"),GNUNET_i2s(&print_peer)); iter =GNUNET_CONTAINER_multihashmap_iterator_create (routing_table); for (i = 0; i < GNUNET_CONTAINER_multihashmap_size(routing_table); i++) { if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, &key_ret, (const void **)&trail)) { FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->trail_id = %s"), __FILE__, __func__,__LINE__, GNUNET_h2s(&trail->trail_id)); GNUNET_memcpy (&print_peer, &trail->next_hop, sizeof (struct GNUNET_PeerIdentity)); FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->next_hop = %s"), __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer)); GNUNET_memcpy (&print_peer, &trail->prev_hop, sizeof (struct GNUNET_PeerIdentity)); FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->prev_hop = %s"), __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer)); } } }
/** * Function to process DHT string to regex matching. * Called on each result obtained for the DHT search. * * @param cls Closure (search context). * @param exp When will this value expire. * @param key Key of the result. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. * @param type Type of the result. * @param size Number of bytes in data. * @param data Pointer to the result data. */ static void dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { const struct RegexAcceptBlock *block = data; struct RegexSearchContext *ctx = cls; struct REGEX_INTERNAL_Search *info = ctx->info; LOG (GNUNET_ERROR_TYPE_DEBUG, "Regex result accept for %s (key %s)\n", info->description, GNUNET_h2s(key)); GNUNET_STATISTICS_update (info->stats, "# regex accepting blocks found", 1, GNUNET_NO); GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found", size, GNUNET_NO); info->callback (info->callback_cls, &block->peer, get_path, get_path_length, put_path, put_path_length); }
/** * 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) }
/** * Handler for requests of new channels. * * @param cls Identification of the client. * @param ccm The actual message. */ static void handle_channel_create (void *cls, const struct GNUNET_CADET_ChannelCreateMessage *ccm) { struct CadetClient *c = cls; struct CadetChannel *ch; struct GNUNET_CADET_ClientChannelNumber chid; struct CadetPeer *dst; chid = ccm->channel_id; if (ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) { /* Channel ID not in allowed range. */ GNUNET_break (0); GNUNET_SERVICE_client_drop (c->client); return; } ch = GNUNET_CONTAINER_multihashmap32_get (c->own_channels, ntohl (chid.channel_of_client)); if (NULL != ch) { /* Channel ID already in use. Not allowed. */ GNUNET_break (0); GNUNET_SERVICE_client_drop (c->client); return; } dst = GCP_get (&ccm->peer, GNUNET_YES); /* Create channel */ ch = GCCH_channel_local_new (c, chid, dst, &ccm->port, ntohl (ccm->opt)); if (NULL == ch) { GNUNET_break (0); GNUNET_SERVICE_client_drop (c->client); return; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_put (c->own_channels, ntohl (chid.channel_of_client), ch, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); LOG (GNUNET_ERROR_TYPE_DEBUG, "New channel %s to %s at port %s requested by client %u\n", GCCH_2s (ch), GNUNET_i2s (&ccm->peer), GNUNET_h2s (&ccm->port), c->id); GNUNET_SERVICE_client_continue (c->client); }
/** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about * @param atsi performance data for the connection */ static void connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_ATS_Information *atsi) { struct TestMessageContext *pos = cls; if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity))) { pos->peer1notified = GNUNET_YES; #if VERBOSE > 1 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' notified of connection to peer `%s'\n", GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey)); #endif } else return; if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */ { #if VERBOSE > 1 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n", GNUNET_i2s (&pos->peer2->id), GNUNET_h2s (&pos->peer1->id.hashPubKey)); #endif if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout, &pos->peer2->id, sizeof (struct GNUNET_TestMessage), &transmit_ready, pos)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&pos->peer2->id)); transmit_ready_failed++; } else { transmit_ready_scheduled++; } } }
/** * Print information about the given node and its edges * to stdout. * * @param cls closure, unused. * @param key hash for current state. * @param proof proof for current state. * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void print_edge (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { unsigned int i; printf ("%s: %s, proof: `%s'\n", GNUNET_h2s (key), accepting ? "ACCEPTING" : "", proof); for (i = 0; i < num_edges; i++) printf (" `%s': %s\n", edges[i].label, GNUNET_h2s (&edges[i].destination)); }
/** * Iterate over the results for a particular key * in the datacache. * * @param h handle to the datacache * @param key what to look up * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ unsigned int GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, const GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { GNUNET_STATISTICS_update (h->stats, gettext_noop ("# requests received"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing request for key `%s'\n", GNUNET_h2s (key)); if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key)) { GNUNET_STATISTICS_update (h->stats, gettext_noop ("# requests filtered by bloom filter"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Bloomfilter filters request for key `%s'\n", GNUNET_h2s (key)); return 0; /* can not be present */ } return h->api->get (h->api->cls, key, type, iter, iter_cls); }
/** * Perform an asynchronous GET operation on the DHT identified. See * also #GNUNET_BLOCK_evaluate. * * @param handle handle to the DHT service * @param type expected type of the response object * @param key the key to look up * @param desired_replication_level estimate of how many nearest peers this request should reach * @param options routing options for this message * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param iter function to call on each result * @param iter_cls closure for iter * @return handle to stop the async get */ struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls) { struct GNUNET_DHT_ClientGetMessage *get_msg; struct GNUNET_DHT_GetHandle *get_handle; size_t msize; struct PendingMessage *pending; msize = sizeof (struct GNUNET_DHT_ClientGetMessage) + xquery_size; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (xquery_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending query for %s to DHT %p\n", GNUNET_h2s (key), handle); pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); get_msg = (struct GNUNET_DHT_ClientGetMessage *) &pending[1]; pending->msg = &get_msg->header; pending->handle = handle; pending->free_on_send = GNUNET_NO; get_msg->header.size = htons (msize); get_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET); get_msg->options = htonl ((uint32_t) options); get_msg->desired_replication_level = htonl (desired_replication_level); get_msg->type = htonl (type); get_msg->key = *key; get_msg->unique_id = ++handle->uid_gen; memcpy (&get_msg[1], xquery, xquery_size); GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; get_handle = GNUNET_new (struct GNUNET_DHT_GetHandle); get_handle->key = *key; get_handle->dht_handle = handle; get_handle->iter = iter; get_handle->iter_cls = iter_cls; get_handle->message = pending; get_handle->unique_id = get_msg->unique_id; GNUNET_CONTAINER_multihashmap_put (handle->active_requests, &get_handle->key, get_handle, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); process_pending_messages (handle); return get_handle; }
/** * Iterator over hash map entries that frees all entries * that match the given client and unique ID. * * @param cls unique ID and client to search for in source routes * @param key current key code * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate) */ static int remove_by_unique_id (void *cls, const struct GNUNET_HashCode * key, void *value) { const struct RemoveByUniqueIdContext *ctx = cls; struct ClientQueryRecord *record = value; if (record->unique_id != ctx->unique_id) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s (by unique id)\n", ctx->client->client_handle, GNUNET_h2s (key)); return remove_client_records (ctx->client, key, record); }
/** * Function called by plugins to notify the datacache * about content deletions. * * @param cls closure * @param key key of the content that was deleted * @param size number of bytes that were made available */ static void env_delete_notify (void *cls, const GNUNET_HashCode * key, size_t size) { struct GNUNET_DATACACHE_Handle *h = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Content under key `%s' discarded\n", GNUNET_h2s (key)); GNUNET_assert (h->utilization >= size); h->utilization -= size; GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), -size, GNUNET_NO); }
/** * Store an item in the datastore. If the item is already present, * the priorities are summed up and the higher expiration time and * lower anonymity level is used. * * @param h handle to the datastore * @param rid reservation ID to use (from "reserve"); use 0 if no * prior reservation was made * @param key key for the value * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication how often should the content be replicated to other peers? * @param expiration expiration time for the content * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout timeout for the operation * @param cont continuation to call when done * @param cont_cls closure for cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h, uint32_t rid, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct DataMessage *dm; size_t msize; union QueueContext qc; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to put %u bytes of data under key `%s' for %llu ms\n", size, GNUNET_h2s (key), GNUNET_TIME_absolute_get_remaining (expiration).rel_value); msize = sizeof (struct DataMessage) + size; GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for PUT\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# PUT requests executed"), 1, GNUNET_NO); dm = (struct DataMessage *) &qe[1]; dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_PUT); dm->header.size = htons (msize); dm->rid = htonl (rid); dm->size = htonl ((uint32_t) size); dm->type = htonl (type); dm->priority = htonl (priority); dm->anonymity = htonl (anonymity); dm->replication = htonl (replication); dm->reserved = htonl (0); dm->uid = GNUNET_htonll (0); dm->expiration = GNUNET_TIME_absolute_hton (expiration); dm->key = *key; memcpy (&dm[1], data, size); process_queue (h); return qe; }
/** * Stop async DHT-get. * * @param get_handle handle to the GET operation to stop */ void GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle) { struct GNUNET_DHT_Handle *handle; const struct GNUNET_DHT_ClientGetMessage *get_msg; struct GNUNET_DHT_ClientGetStopMessage *stop_msg; struct PendingMessage *pending; handle = get_handle->message->handle; get_msg = (const struct GNUNET_DHT_ClientGetMessage *) get_handle->message->msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending STOP for %s to DHT via %p\n", GNUNET_h2s (&get_msg->key), handle); /* generate STOP */ pending = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg = (struct GNUNET_DHT_ClientGetStopMessage *) &pending[1]; pending->msg = &stop_msg->header; pending->handle = handle; pending->free_on_send = GNUNET_YES; stop_msg->header.size = htons (sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP); stop_msg->reserved = htonl (0); stop_msg->unique_id = get_msg->unique_id; stop_msg->key = get_msg->key; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; /* remove 'GET' from active status */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->active_requests, &get_handle->key, get_handle)); if (GNUNET_YES == get_handle->message->in_pending_queue) { GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, get_handle->message); get_handle->message->in_pending_queue = GNUNET_NO; } GNUNET_free (get_handle->message); GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_end, 0); GNUNET_free (get_handle); process_pending_messages (handle); }
/** * Function called once the hash computation over an * indexed file has completed. * * @param cls closure, our publishing context * @param res resulting hash, NULL on error */ static void hash_for_index_val (void *cls, const struct GNUNET_HashCode * res) { struct IndexInfo *ii = cls; ii->fhc = NULL; if ((res == NULL) || (0 != memcmp (res, &ii->file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Hash mismatch trying to index file `%s' which has hash `%s'\n"), ii->filename, GNUNET_h2s (res)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wanted `%s'\n", GNUNET_h2s (&ii->file_id)); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); GNUNET_free (ii); return; } signal_index_ok (ii); }
/** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int mysql_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; unsigned int irepl = replication; unsigned int ipriority = priority; unsigned int ianonymity = anonymity; unsigned long long lexpiration = expiration.abs_value_us; unsigned long long lrvalue = (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); unsigned long hashSize; unsigned long hashSize2; unsigned long lsize; struct GNUNET_HashCode vhash; if (size > MAX_DATUM_SIZE) { GNUNET_break (0); return GNUNET_SYSERR; } hashSize = sizeof (struct GNUNET_HashCode); hashSize2 = sizeof (struct GNUNET_HashCode); lsize = size; GNUNET_CRYPTO_hash (data, size, &vhash); if (GNUNET_OK != GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_entry, NULL, MYSQL_TYPE_LONG, &irepl, GNUNET_YES, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONG, &ipriority, GNUNET_YES, MYSQL_TYPE_LONG, &ianonymity, GNUNET_YES, MYSQL_TYPE_LONGLONG, &lexpiration, GNUNET_YES, MYSQL_TYPE_LONGLONG, &lrvalue, GNUNET_YES, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, &vhash, hashSize2, &hashSize2, MYSQL_TYPE_BLOB, data, lsize, &lsize, -1)) return GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Inserted value `%s' with size %u into gn090 table\n", GNUNET_h2s (key), (unsigned int) size); if (size > 0) plugin->env->duc (plugin->env->cls, size); return GNUNET_OK; }
/** * Explicitly remove some content from the database. * The "cont"inuation will be called with status * "GNUNET_OK" if content was removed, "GNUNET_NO" * if no matching entry was found and "GNUNET_SYSERR" * on all other types of errors. * * @param h handle to the datastore * @param key key for the value * @param size number of bytes in data * @param data content stored * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const void *data, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct DataMessage *dm; size_t msize; union QueueContext qc; if (cont == NULL) cont = &drop_status_cont; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to remove %u bytes under key `%s'\n", size, GNUNET_h2s (key)); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; msize = sizeof (struct DataMessage) + size; GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for REMOVE\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# REMOVE requests executed"), 1, GNUNET_NO); dm = (struct DataMessage *) &qe[1]; dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE); dm->header.size = htons (msize); dm->rid = htonl (0); dm->size = htonl (size); dm->type = htonl (0); dm->priority = htonl (0); dm->anonymity = htonl (0); dm->uid = GNUNET_htonll (0); dm->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_ZERO_ABS); dm->key = *key; memcpy (&dm[1], data, size); process_queue (h); return qe; }