From: Christian Grothoff Date: Tue, 27 Sep 2011 08:12:07 +0000 (+0000) Subject: hxing X-Git-Tag: initial-import-from-subversion-38251~16950 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e83f3d39b93b4a1aa721c6de33a9c1f04c82896d;p=oweals%2Fgnunet.git hxing --- diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c index 425411b75..48d9d72a6 100644 --- a/src/dht/gnunet-service-dht_neighbours.c +++ b/src/dht/gnunet-service-dht_neighbours.c @@ -1053,7 +1053,8 @@ GDS_NEIGHBOURS_handle_reply (const GNUNET_PeerIdentity *target, msize = data_size + sizeof (struct PeerResultMessage) + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); if ( (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || - (get_path_length + put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || + (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || + (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (data_size > GNUNET_SERVER_MAX_MESSAGE_SIZE) ) { GNUNET_break (0); @@ -1439,19 +1440,69 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TRANSPORT_ATS_Information *atsi) { - // FIXME! - // 1) validate result format - // 2) append 'peer' to put path - // 3) forward to local clients - // 4) p2p routing - const struct GNUNET_DHT_P2PRouteResultMessage *incoming = - (const struct GNUNET_DHT_P2PRouteResultMessage *) message; - struct GNUNET_MessageHeader *enc_msg = - (struct GNUNET_MessageHeader *) &incoming[1]; - struct DHT_MessageContext msg_ctx; - - - + const struct PeerResultMessage *prm; + const struct GNUNET_PeerIdentity *put_path; + const struct GNUNET_PeerIdentity *get_path; + const void *data; + uint32_t get_path_length; + uint32_t put_path_length; + uint16_t msize; + size_t data_size; + enum GNUNET_BLOCK_Type type; + + /* parse and validate message */ + msize = ntohs (message->size); + if (msize < sizeof (struct PeerResultMessage)) + { + GNUNET_break_op (0); + return GNUNET_YES; + } + prm = (struct PeerResultMessage *) message; + put_path_length = ntohl (prm->put_path_length); + get_path_length = ntohl (prm->get_path_length); + if ( (msize < sizeof (struct PeerResultMessage) + + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)) || + (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_op (0); + return GNUNET_YES; + } + put_path = (const struct GNUNET_PeerIdentity*) &prm[1]; + get_path = &put_path[put_path_length]; + type = ntohl (prm->type); + data = (const void*) &get_path[get_path_length]; + data_size = msize - (sizeof (struct PeerResultMessage) + + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)); + /* append 'peer' to 'get_path' */ + { + struct GNUNET_PeerIdentity xget_path[get_path_length+1]; + + memcpy (xget_path, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); + xget_path[get_path_length] = *peer; + + /* forward to local clients */ + GDS_CLIENT_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration), + &prm->key, + get_path_length + 1, + xget_path, + put_path_length, + put_path, + type, + data_size, + data); + + /* forward to other peers */ + GDS_ROUTING_process (type, + GNUNET_TIME_absolute_ntoh (prm->expiration), + &prm->key, + put_path_length, + put_path, + get_path_length + 1, + xget_path, + data, + data_size); + } return GNUNET_YES; } diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c index 535a63267..1d43cfd3d 100644 --- a/src/dht/gnunet-service-dht_routing.c +++ b/src/dht/gnunet-service-dht_routing.c @@ -45,6 +45,11 @@ struct RecentRequest */ struct GNUNET_PeerIdentity peer; + /** + * Key of this request. + */ + GNUNET_HashCode key; + /** * Position of this node in the min heap. */ @@ -55,12 +60,6 @@ struct RecentRequest */ struct GNUNET_CONTAINER_BloomFilter *reply_bf; - /** - * Timestamp of this request, for ordering - * the min heap. - */ - struct GNUNET_TIME_Absolute timestamp; - /** * Type of the requested block. */ @@ -82,11 +81,6 @@ struct RecentRequest */ uint32_t reply_bf_mutator; - /** - * Key of this request. - */ - GNUNET_HashCode key; - }; @@ -101,6 +95,118 @@ static struct GNUNET_CONTAINER_Heap *recent_heap; static struct GNUNET_CONTAINER_MultiHashMap *recent_map; +/** + * Closure for the 'process' function. + */ +struct ProcessContext +{ + /** + * Path of the original PUT + */ + const struct GNUNET_PeerIdentity *put_path; + + /** + * Path of the reply. + */ + const struct GNUNET_PeerIdentity *get_path; + + /** + * Payload of the reply. + */ + const void *data; + + /** + * Expiration time of the result. + */ + GNUNET_TIME_Absolute expiration_time; + + /** + * Number of entries in 'put_path'. + */ + unsigned int put_path_length; + + /** + * Number of entries in 'get_path'. + */ + unsigned int get_path_length; + + /** + * Number of bytes in 'data'. + */ + size_t data_size; + + /** + * Type of the reply. + */ + enum GNUNET_BLOCK_Type type; + +}; + + +/** + * Forward the result to the given peer if it matches the request. + * + * @param cls the 'struct ProcessContext' with the result + * @param key the query + * @param value the 'struct RecentRequest' with the request + * @return GNUNET_OK (continue to iterate), + * GNUNET_SYSERR if the result is malformed or type unsupported + */ +static int +process (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct ProcessContext *pc = cls; + struct RecentRequest *rr = value; + enum GNUNET_BLOCK_EvaluationResult eval; + + if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) && + (rr->type != pc->type) ) + return GNUNET_OK; /* type missmatch */ + eval = GNUNET_BLOCK_evaluate (block_context, + pc->type, + key, + &rr->reply_bf, + rr->reply_bf_mutator, + rr->xquery, + rr->xquery_size, + pc->data, + pc->data_size); + switch (eval) + { + case GNUNET_BLOCK_EVALUATION_OK_MORE: + case GNUNET_BLOCK_EVALUATION_OK_LAST: + GDS_NEIGHBOURS_handle_reply (&rr->target, + pc->type, + pc->expiration_time, + key, + pc->put_path_length, + pc->put_path, + pc->get_path_length, + pc->get_path, + pc->data, + pc->data_size); + break; + case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: + return GNUNET_OK; + case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: + GNUNET_break_op (0); + return GNUNET_SYSERR; + case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: + case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: + GNUNET_break (0); + return GNUNET_OK; + case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: + return GNUNET_SYSERR; + default: + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + /** * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or @@ -123,12 +229,26 @@ GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, GNUNET_TIME_Absolute expiration_time, const GNUNET_HashCode *key, unsigned int put_path_length, - struct GNUNET_PeerIdentity *put_path, + const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, - struct GNUNET_PeerIdentity *get_path, + 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; + GNUNET_CONTAINER_multihashmap_iterate (recent_map, + key, + &process, + &pc); } @@ -152,24 +272,33 @@ GDS_ROUTING_add (const GNUNET_PeerIdentity *sender, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator) { - if (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) + struct RecentRequest *recent_req; + + while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) { recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); GNUNET_assert (recent_req != NULL); - GNUNET_SCHEDULER_cancel (recent_req->remove_task); GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node); GNUNET_CONTAINER_bloomfilter_free (recent_req->bloom); GNUNET_free (recent_req); } - recent_req = GNUNET_malloc (sizeof (struct RecentRequest)); - recent_req->uid = msg_ctx->unique_id; - memcpy (&recent_req->key, &msg_ctx->key, sizeof (GNUNET_HashCode)); + recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size); + recent_req->peer = *sender; + recent_req->key = *key; recent_req->heap_node = GNUNET_CONTAINER_heap_insert (recent_heap, recent_req, GNUNET_TIME_absolute_get ().abs_value); - recent_req->bloom = - GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K); + recent_req->reply_bf = + GNUNET_CONTAINER_bloomfilter_copy (reply_bf); + recent_req->type = type; + recent_req->xquery = &recent_req[1]; + recent_req->xquery_size = xquery_size; + recent_req->reply_bf_mutator = reply_bf_mutator; + GNUNET_CONTAINER_multihashmap_put (recent_map, + key, + recent_req, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } @@ -194,6 +323,8 @@ GDS_ROUTING_init () void GDS_ROUTING_done () { + struct RecentRequest *recent_req; + while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) { recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); @@ -202,6 +333,7 @@ GDS_ROUTING_done () GNUNET_CONTAINER_bloomfilter_free (recent_req->bloom); GNUNET_free (recent_req); } + GNUNET_assert (0 == GNUNET_CONTAINER_heap_size (recent_heap)); GNUNET_CONTAINER_heap_destroy (recent_heap); recent_heap = NULL; GNUNET_CONTAINER_multihashmap_destroy (recent_map); diff --git a/src/dht/gnunet-service-dht_routing.h b/src/dht/gnunet-service-dht_routing.h index 3ddfcc66e..3dbae1ee7 100644 --- a/src/dht/gnunet-service-dht_routing.h +++ b/src/dht/gnunet-service-dht_routing.h @@ -49,9 +49,9 @@ GDS_ROUTING_process (uint32_t type, GNUNET_TIME_Absolute expiration_time, const GNUNET_HashCode *key, unsigned int put_path_length, - struct GNUNET_PeerIdentity *put_path, + const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, - struct GNUNET_PeerIdentity *get_path, + const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size);