/** * Handler for PUT messages. * * @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_put (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientPutMessage *dht_msg; struct GNUNET_CONTAINER_BloomFilter *peer_bf; uint16_t size; struct PendingMessage *pm; struct GNUNET_DHT_ClientPutConfirmationMessage *conf; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests received from clients"), 1, GNUNET_NO); dht_msg = (const struct GNUNET_DHT_ClientPutMessage *) message; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "XDHT CLIENT-PUT %s @ %u\n", GNUNET_h2s (&dht_msg->key), getpid ()); /* give to local clients */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling local PUT of %u-bytes for query %s\n", size - sizeof (struct GNUNET_DHT_ClientPutMessage), GNUNET_h2s (&dht_msg->key)); GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* store locally */ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* route to other peers */ peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), ntohl (dht_msg->options), ntohl (dht_msg->desired_replication_level), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 0 /* hop count */ , peer_bf, &dht_msg->key, 0, NULL, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GDS_CLIENTS_process_put (ntohl (dht_msg->options), ntohl (dht_msg->type), 0, ntohl (dht_msg->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GNUNET_CONTAINER_bloomfilter_free (peer_bf); pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK); conf->reserved = htonl (0); conf->unique_id = dht_msg->unique_id; pm->msg = &conf->header; add_pending_message (find_active_client (client), pm); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Iterator for local get request results, * * @param cls closure for iterator, a DatacacheGetContext * @param exp when does this value expire? * @param key the key this data is stored under * @param size the size of the data identified by key * @param data the actual data * @param type the type of the data * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @return GNUNET_OK to continue iteration, anything else * to stop iteration. */ static int datacache_get_iterator (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path) { struct GetRequestContext *ctx = cls; enum GNUNET_BLOCK_EvaluationResult eval; eval = GNUNET_BLOCK_evaluate (GDS_block_context, type, key, ctx->reply_bf, ctx->reply_bf_mutator, ctx->xquery, ctx->xquery_size, data, size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found reply for query %s in datacache, evaluation result is %d\n", GNUNET_h2s (key), (int) eval); ctx->eval = eval; switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_LAST: case GNUNET_BLOCK_EVALUATION_OK_MORE: /* forward to local clients */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Good RESULTS found in datacache"), 1, GNUNET_NO); GDS_CLIENTS_handle_reply (exp, key, 0, NULL, put_path_length, put_path, type, size, data); /* forward to other peers */ GDS_ROUTING_process (type, exp, key, put_path_length, put_path, 0, NULL, data, size); break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Invalid RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Irrelevant RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); break; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break_op (0); return GNUNET_SYSERR; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Unsupported RESULTS found in datacache"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in local response!\n"), type); break; } return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK; }