X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fregex%2Fregex_internal_dht.c;h=849ba20d0f324a7796c7caa6d30030eacc569295;hb=d72d8e05401ace44b57432463f136bcfe55cee03;hp=0b5d99928bf1241b8224e3bdab1fd657ec651dbd;hpb=5f7a6c8f6816a826a2dd93eadc5039733f7db606;p=oweals%2Fgnunet.git diff --git a/src/regex/regex_internal_dht.c b/src/regex/regex_internal_dht.c index 0b5d99928..849ba20d0 100644 --- a/src/regex/regex_internal_dht.c +++ b/src/regex/regex_internal_dht.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2012 Christian Grothoff (and other contributing authors) + Copyright (C) 2012, 2015 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** * @file src/regex/regex_internal_dht.c @@ -28,21 +28,32 @@ #include "regex_block_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" +#include "gnunet_constants.h" +#include "gnunet_signatures.h" + #define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__) -/* FIXME: OPTION (API, CONFIG) */ +/** + * DHT replication level to use. + */ #define DHT_REPLICATION 5 + +/** + * DHT record lifetime to use. + */ #define DHT_TTL GNUNET_TIME_UNIT_HOURS -#define DEBUG_DHT GNUNET_NO -#if DEBUG_DHT -#define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | GNUNET_DHT_RO_RECORD_ROUTE -#else +/** + * DHT options to set. + */ #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE -#endif -struct REGEX_ITERNAL_Announcement + +/** + * Handle to store cached data about a regex announce. + */ +struct REGEX_INTERNAL_Announcement { /** * DHT handle to use, must be initialized externally. @@ -57,12 +68,12 @@ struct REGEX_ITERNAL_Announcement /** * Automaton representation of the regex (expensive to build). */ - struct REGEX_ITERNAL_Automaton* dfa; + struct REGEX_INTERNAL_Automaton *dfa; /** - * Identity under which to announce the regex. + * Our private key. */ - struct GNUNET_PeerIdentity id; + const struct GNUNET_CRYPTO_EddsaPrivateKey *priv; /** * Optional statistics handle to report usage. Can be NULL. @@ -77,7 +88,7 @@ struct REGEX_ITERNAL_Announcement * @param cls closure. * @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 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. */ @@ -87,138 +98,147 @@ regex_iterator (void *cls, const char *proof, int accepting, unsigned int num_edges, - const struct REGEX_ITERNAL_Edge *edges) + const struct REGEX_BLOCK_Edge *edges) { - struct REGEX_ITERNAL_Announcement *h = cls; + struct REGEX_INTERNAL_Announcement *h = cls; struct RegexBlock *block; - struct RegexEdge *block_edge; size_t size; - size_t len; unsigned int i; - unsigned int offset; - char *aux; - - LOG (GNUNET_ERROR_TYPE_DEBUG, - " regex dht put for state %s\n", - GNUNET_h2s (key)); - LOG (GNUNET_ERROR_TYPE_DEBUG, " proof: %s\n", proof); - LOG (GNUNET_ERROR_TYPE_DEBUG, " num edges: %u\n", num_edges); + LOG (GNUNET_ERROR_TYPE_INFO, + "DHT PUT for state %s with proof `%s' and %u edges:\n", + GNUNET_h2s (key), + proof, + num_edges); + for (i = 0; i < num_edges; i++) + { + LOG (GNUNET_ERROR_TYPE_INFO, + "Edge %u `%s' towards %s\n", + i, + edges[i].label, + GNUNET_h2s (&edges[i].destination)); + } if (GNUNET_YES == accepting) { - struct RegexAccept block; + struct RegexAcceptBlock ab; + + LOG (GNUNET_ERROR_TYPE_INFO, + "State %s is accepting, putting own id\n", + GNUNET_h2s (key)); + size = sizeof (struct RegexAcceptBlock); + ab.purpose.size = ntohl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + + sizeof (struct GNUNET_TIME_AbsoluteNBO) + + sizeof (struct GNUNET_HashCode)); + ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT); + ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION)); + ab.key = *key; + GNUNET_CRYPTO_eddsa_key_get_public (h->priv, + &ab.peer.public_key); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign (h->priv, + &ab.purpose, + &ab.signature)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - " state %s is accepting, putting own id\n", - GNUNET_h2s(key)); - size = sizeof (block); - block.key = *key; - block.id = h->id; GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored", 1, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored", - sizeof (block), GNUNET_NO); + sizeof (struct RegexAcceptBlock), GNUNET_NO); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_BLOCK_TYPE_REGEX_ACCEPT, size, - (char *) &block, + &ab, GNUNET_TIME_relative_to_absolute (DHT_TTL), DHT_TTL, NULL, NULL); } - len = strlen(proof); - size = sizeof (struct RegexBlock) + len; - block = GNUNET_malloc (size); - - block->key = *key; - block->n_proof = htonl (len); - block->n_edges = htonl (num_edges); - block->accepting = htonl (accepting); - - /* Store the proof at the end of the block. */ - aux = (char *) &block[1]; - memcpy (aux, proof, len); - aux = &aux[len]; - - /* Store each edge in a variable length MeshEdge struct at the - * very end of the MeshRegexBlock structure. - */ - for (i = 0; i < num_edges; i++) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, " edge %s towards %s\n", - edges[i].label, GNUNET_h2s(&edges[i].destination)); - - /* aux points at the end of the last block */ - len = strlen (edges[i].label); - size += sizeof (struct RegexEdge) + len; - // Calculate offset FIXME is this ok? use size instead? - offset = aux - (char *) block; - block = GNUNET_realloc (block, size); - aux = &((char *) block)[offset]; - block_edge = (struct RegexEdge *) aux; - block_edge->key = edges[i].destination; - block_edge->n_token = htonl (len); - aux = (char *) &block_edge[1]; - memcpy (aux, edges[i].label, len); - aux = &aux[len]; - } + block = REGEX_BLOCK_create (proof, + num_edges, edges, + accepting, + &size); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT, - GNUNET_BLOCK_TYPE_REGEX, size, - (char *) block, + GNUNET_BLOCK_TYPE_REGEX, + size, block, GNUNET_TIME_relative_to_absolute (DHT_TTL), DHT_TTL, NULL, NULL); - GNUNET_STATISTICS_update (h->stats, "# regex blocks stored", + GNUNET_STATISTICS_update (h->stats, + "# regex blocks stored", 1, GNUNET_NO); - GNUNET_STATISTICS_update (h->stats, "# regex block bytes stored", + GNUNET_STATISTICS_update (h->stats, + "# regex block bytes stored", size, GNUNET_NO); GNUNET_free (block); } -struct REGEX_ITERNAL_Announcement * -REGEX_ITERNAL_announce (struct GNUNET_DHT_Handle *dht, - const struct GNUNET_PeerIdentity *id, - const char *regex, - uint16_t compression, - struct GNUNET_STATISTICS_Handle *stats) +/** + * Announce a regular expression: put all states of the automaton in the DHT. + * Does not free resources, must call #REGEX_INTERNAL_announce_cancel() for that. + * + * @param dht An existing and valid DHT service handle. CANNOT be NULL. + * @param priv our private key, must remain valid until the announcement is cancelled + * @param regex Regular expression to announce. + * @param compression How many characters per edge can we squeeze? + * @param stats Optional statistics handle to report usage. Can be NULL. + * @return Handle to reuse o free cached resources. + * Must be freed by calling #REGEX_INTERNAL_announce_cancel(). + */ +struct REGEX_INTERNAL_Announcement * +REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht, + const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, + const char *regex, + uint16_t compression, + struct GNUNET_STATISTICS_Handle *stats) { - struct REGEX_ITERNAL_Announcement *h; + struct REGEX_INTERNAL_Announcement *h; GNUNET_assert (NULL != dht); - h = GNUNET_malloc (sizeof (struct REGEX_ITERNAL_Announcement)); + h = GNUNET_new (struct REGEX_INTERNAL_Announcement); h->regex = regex; h->dht = dht; h->stats = stats; - h->id = *id; - h->dfa = REGEX_ITERNAL_construct_dfa (regex, - strlen (regex), - compression); - REGEX_ITERNAL_reannounce (h); + h->priv = priv; + h->dfa = REGEX_INTERNAL_construct_dfa (regex, strlen (regex), compression); + REGEX_INTERNAL_reannounce (h); return h; } +/** + * Announce again a regular expression previously announced. + * Does use caching to speed up process. + * + * @param h Handle returned by a previous #REGEX_INTERNAL_announce call(). + */ void -REGEX_ITERNAL_reannounce (struct REGEX_ITERNAL_Announcement *h) +REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h) { GNUNET_assert (NULL != h->dfa); /* make sure to call announce first */ - LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_ITERNAL_reannounce: %.60s\n", h->regex); - LOG (GNUNET_ERROR_TYPE_DEBUG, " full: %s\n", h->regex); - REGEX_ITERNAL_iterate_all_edges (h->dfa, ®ex_iterator, h); + LOG (GNUNET_ERROR_TYPE_INFO, + "REGEX_INTERNAL_reannounce: %s\n", + h->regex); + REGEX_INTERNAL_iterate_reachable_edges (h->dfa, + ®ex_iterator, + h); } +/** + * Clear all cached data used by a regex announce. + * Does not close DHT connection. + * + * @param h Handle returned by a previous #REGEX_INTERNAL_announce() call. + */ void -REGEX_ITERNAL_announce_cancel (struct REGEX_ITERNAL_Announcement *h) +REGEX_INTERNAL_announce_cancel (struct REGEX_INTERNAL_Announcement *h) { - REGEX_ITERNAL_automaton_destroy (h->dfa); + REGEX_INTERNAL_automaton_destroy (h->dfa); GNUNET_free (h); } @@ -232,75 +252,93 @@ REGEX_ITERNAL_announce_cancel (struct REGEX_ITERNAL_Announcement *h) */ struct RegexSearchContext { - /** - * Part of the description already consumed by - * this particular search branch. - */ + /** + * Part of the description already consumed by + * this particular search branch. + */ size_t position; - /** - * Information about the search. - */ - struct REGEX_ITERNAL_Search *info; + /** + * Information about the search. + */ + struct REGEX_INTERNAL_Search *info; - /** - * We just want to look for one edge, the longer the better. - * Keep its length. - */ + /** + * We just want to look for one edge, the longer the better. + * Keep its length. + */ unsigned int longest_match; - /** - * Destination hash of the longest match. - */ + /** + * Destination hash of the longest match. + */ struct GNUNET_HashCode hash; }; +/** + * Type of values in `dht_get_results`. + */ +struct Result +{ + /** + * Number of bytes in data. + */ + size_t size; + + /** + * The raw result data. + */ + const void *data; +}; + + /** * Struct to keep information of searches of services described by a regex * using a user-provided string service description. */ -struct REGEX_ITERNAL_Search +struct REGEX_INTERNAL_Search { - /** - * DHT handle to use, must be initialized externally. - */ + /** + * DHT handle to use, must be initialized externally. + */ struct GNUNET_DHT_Handle *dht; - /** - * Optional statistics handle to report usage. Can be NULL. - */ + /** + * Optional statistics handle to report usage. Can be NULL. + */ struct GNUNET_STATISTICS_Handle *stats; - /** - * User provided description of the searched service. - */ + /** + * User provided description of the searched service. + */ char *description; - /** - * Running DHT GETs. - */ + /** + * Running DHT GETs. + */ struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; - /** - * Results from running DHT GETs. - */ + /** + * Results from running DHT GETs, values are of type + * 'struct Result'. + */ struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; - /** - * Contexts, for each running DHT GET. Free all on end of search. - */ + /** + * Contexts, for each running DHT GET. Free all on end of search. + */ struct RegexSearchContext **contexts; - /** - * Number of contexts (branches/steps in search). - */ + /** + * Number of contexts (branches/steps in search). + */ unsigned int n_contexts; - + /** * @param callback Callback for found peers. */ - REGEX_ITERNAL_Found callback; + REGEX_INTERNAL_Found callback; /** * @param callback_cls Closure for @c callback. @@ -309,15 +347,12 @@ struct REGEX_ITERNAL_Search }; - /** * 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. - * - * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. */ static void regex_next_edge (const struct RegexBlock *block, @@ -342,7 +377,7 @@ regex_next_edge (const struct RegexBlock *block, */ static void dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, @@ -350,30 +385,31 @@ dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { - const struct RegexAccept *block = data; + const struct RegexAcceptBlock *block = data; struct RegexSearchContext *ctx = cls; - struct REGEX_ITERNAL_Search *info = ctx->info; + struct REGEX_INTERNAL_Search *info = ctx->info; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); - LOG (GNUNET_ERROR_TYPE_INFO, " accept for %s (key %s)\n", + 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", + GNUNET_STATISTICS_update (info->stats, + "# regex accepting blocks found", 1, GNUNET_NO); - GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found", + GNUNET_STATISTICS_update (info->stats, + "# regex accepting block bytes found", size, GNUNET_NO); - info->callback (info->callback_cls, - &block->id, + &block->peer, get_path, get_path_length, put_path, put_path_length); } /** - * Find a path to a peer that offers a regex servcie compatible + * Find a path to a peer that offers a regex service compatible * with a given string. - * + * * @param key The key of the accepting state. * @param ctx Context containing info about the string, tunnel, etc. */ @@ -383,8 +419,10 @@ regex_find_path (const struct GNUNET_HashCode *key, { struct GNUNET_DHT_GetHandle *get_h; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n"); - LOG (GNUNET_ERROR_TYPE_INFO, " find accept for %s\n", GNUNET_h2s (key)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Accept state found, now searching for paths to %s\n", + GNUNET_h2s (key), + (unsigned int) ctx->position); get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ key, /* key to search */ @@ -409,9 +447,9 @@ regex_find_path (const struct GNUNET_HashCode *key, * @param exp when will this value expire * @param key key of the result * @param get_path path of the get request (not used) - * @param get_path_length lenght of get_path (not used) + * @param get_path_length length of @a get_path (not used) * @param put_path path of the put request (not used) - * @param put_path_length length of the put_path (not used) + * @param put_path_length length of the @a put_path (not used) * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data @@ -420,7 +458,7 @@ regex_find_path (const struct GNUNET_HashCode *key, */ static void dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, @@ -430,59 +468,32 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, { const struct RegexBlock *block = data; struct RegexSearchContext *ctx = cls; - struct REGEX_ITERNAL_Search *info = ctx->info; - void *copy; + struct REGEX_INTERNAL_Search *info = ctx->info; size_t len; - char *datastore; - -#if DEBUG_DHT - if (NULL != put_path && 0 != put_path_length) - { - datastore = GNUNET_strdup (GNUNET_i2s (&put_path[put_path_length - 1])); - } - else - { - GNUNET_asprintf (&datastore, "?? %u/%u", put_path_length, get_path_length); - } -#else - datastore = GNUNET_strdup ("N/A"); -#endif - - LOG (GNUNET_ERROR_TYPE_INFO, " DHT GET result for %s (%s) at %s\n", - GNUNET_h2s (key), ctx->info->description, datastore); - GNUNET_free (datastore); - - copy = GNUNET_malloc (size); - memcpy (copy, data, size); - GNUNET_break ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, - &((struct RegexBlock *)copy)->key, copy, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) - ); - len = ntohl (block->n_proof); - { - char proof[len + 1]; - - memcpy (proof, &block[1], len); - proof[len] = '\0'; - if (GNUNET_OK != REGEX_ITERNAL_check_proof (proof, key)) - { - GNUNET_break_op (0); - return; - } - } + struct Result *copy; + + LOG (GNUNET_ERROR_TYPE_INFO, + "DHT GET result for %s (%s)\n", + GNUNET_h2s (key), ctx->info->description); + copy = GNUNET_malloc (sizeof (struct Result) + size); + copy->size = size; + copy->data = ©[1]; + memcpy (©[1], block, size); + GNUNET_break (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, + key, copy, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); len = strlen (info->description); if (len == ctx->position) // String processed { - if (GNUNET_YES == ntohl (block->accepting)) + if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block, size)) { regex_find_path (key, ctx); } else { - LOG (GNUNET_ERROR_TYPE_INFO, " block not accepting!\n"); - // FIXME REGEX this block not successful, wait for more? start timeout? + LOG (GNUNET_ERROR_TYPE_INFO, "block not accepting!\n"); + /* FIXME REGEX this block not successful, wait for more? start timeout? */ } return; } @@ -491,35 +502,39 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, /** - * Iterator over found existing mesh regex blocks that match an ongoing search. + * Iterator over found existing cadet regex blocks that match an ongoing search. * * @param cls Closure (current context)- * @param key Current key code (key for cached block). * @param value Value in the hash map (cached RegexBlock). - * @return GNUNET_YES: we should always continue to iterate. + * @return #GNUNET_YES: we should always continue to iterate. */ static int regex_result_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) { - struct RegexBlock *block = value; + struct Result *result = value; + const struct RegexBlock *block = result->data; struct RegexSearchContext *ctx = cls; - if (GNUNET_YES == ntohl(block->accepting) && - ctx->position == strlen (ctx->info->description)) + if ( (GNUNET_YES == + GNUNET_BLOCK_is_accepting (block, result->size)) && + (ctx->position == strlen (ctx->info->description)) ) { - LOG (GNUNET_ERROR_TYPE_INFO, " * Found accepting known block\n"); + LOG (GNUNET_ERROR_TYPE_INFO, + "Found accepting known block\n"); regex_find_path (key, ctx); return GNUNET_YES; // We found an accept state! } - LOG (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", - ctx->position, strlen(ctx->info->description), - ntohl(block->accepting)); - - regex_next_edge (block, SIZE_MAX, ctx); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "* %u, %u, [%u]\n", + ctx->position, + strlen (ctx->info->description), + GNUNET_BLOCK_is_accepting (block, result->size)); + regex_next_edge (block, result->size, ctx); - GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated", + GNUNET_STATISTICS_update (ctx->info->stats, "# regex cadet blocks iterated", 1, GNUNET_NO); return GNUNET_YES; @@ -533,8 +548,7 @@ regex_result_iterator (void *cls, * @param token Token that follows to next state. * @param len Lenght of token. * @param key Hash of next state. - * - * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. + * @return #GNUNET_YES if should keep iterating, #GNUNET_NO otherwise. */ static int regex_edge_iterator (void *cls, @@ -543,43 +557,34 @@ regex_edge_iterator (void *cls, const struct GNUNET_HashCode *key) { struct RegexSearchContext *ctx = cls; - struct REGEX_ITERNAL_Search *info = ctx->info; + struct REGEX_INTERNAL_Search *info = ctx->info; const char *current; size_t current_len; GNUNET_STATISTICS_update (info->stats, "# regex edges iterated", 1, GNUNET_NO); - - LOG (GNUNET_ERROR_TYPE_DEBUG, "* Start of regex edge iterator\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "* descr : %s\n", info->description); - LOG (GNUNET_ERROR_TYPE_DEBUG, "* posit : %u\n", ctx->position); current = &info->description[ctx->position]; - LOG (GNUNET_ERROR_TYPE_DEBUG, "* currt : %s\n", current); current_len = strlen (info->description) - ctx->position; - LOG (GNUNET_ERROR_TYPE_DEBUG, "* ctlen : %u\n", current_len); - LOG (GNUNET_ERROR_TYPE_DEBUG, "* tklen : %u\n", len); - LOG (GNUNET_ERROR_TYPE_DEBUG, "* token : %.*s\n", len, token); - LOG (GNUNET_ERROR_TYPE_DEBUG, "* nextk : %s\n", GNUNET_h2s(key)); if (len > current_len) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token too long, END\n"); - return GNUNET_YES; // Token too long, wont match + LOG (GNUNET_ERROR_TYPE_DEBUG, "Token too long, END\n"); + return GNUNET_YES; } if (0 != strncmp (current, token, len)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token doesn't match, END\n"); - return GNUNET_YES; // Token doesn't match + LOG (GNUNET_ERROR_TYPE_DEBUG, "Token doesn't match, END\n"); + return GNUNET_YES; } if (len > ctx->longest_match) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token is longer, KEEP\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is longer, KEEP\n"); ctx->longest_match = len; ctx->hash = *key; } else { - LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token is not longer, IGNORE\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is not longer, IGNORE\n"); } LOG (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); @@ -593,8 +598,6 @@ regex_edge_iterator (void *cls, * @param block Block found in the DHT. * @param size Size of the block. * @param ctx Context of the search. - * - * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. */ static void regex_next_edge (const struct RegexBlock *block, @@ -602,28 +605,30 @@ regex_next_edge (const struct RegexBlock *block, struct RegexSearchContext *ctx) { struct RegexSearchContext *new_ctx; - struct REGEX_ITERNAL_Search *info = ctx->info; + struct REGEX_INTERNAL_Search *info = ctx->info; struct GNUNET_DHT_GetHandle *get_h; struct GNUNET_HashCode *hash; const char *rest; int result; - /* Find the longest match for the current string position, + 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_ITERNAL_block_iterate (block, size, - ®ex_edge_iterator, ctx); + 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"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "no match in block\n"); return; } hash = &ctx->hash; - new_ctx = GNUNET_malloc (sizeof (struct RegexSearchContext)); + 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); @@ -632,7 +637,8 @@ regex_next_edge (const struct RegexBlock *block, if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "* GET for %s running, END\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, + "GET for %s running, END\n", GNUNET_h2s (hash)); GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, hash, @@ -644,19 +650,20 @@ regex_next_edge (const struct RegexBlock *block, GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed", 1, GNUNET_NO); - /* Start search in DHT */ - LOG (GNUNET_ERROR_TYPE_INFO, " looking for %s\n", GNUNET_h2s (hash)); + 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 = + 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 */ - // FIXME add BLOOMFILTER to exclude filtered peers - strlen(rest) + 1, /* xquery bits */ - // FIXME add BLOOMFILTER SIZE + strlen (rest) + 1, /* xquery bits */ &dht_get_string_handler, new_ctx); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, @@ -670,14 +677,27 @@ regex_next_edge (const struct RegexBlock *block, } -struct REGEX_ITERNAL_Search * -REGEX_ITERNAL_search (struct GNUNET_DHT_Handle *dht, - const char *string, - REGEX_ITERNAL_Found callback, - void *callback_cls, - struct GNUNET_STATISTICS_Handle *stats) +/** + * Search for a peer offering a regex matching certain string in the DHT. + * The search runs until #REGEX_INTERNAL_search_cancel() is called, even if results + * are returned. + * + * @param dht An existing and valid DHT service handle. + * @param string String to match against the regexes in the DHT. + * @param callback Callback for found peers. + * @param callback_cls Closure for @c callback. + * @param stats Optional statistics handle to report usage. Can be NULL. + * @return Handle to stop search and free resources. + * Must be freed by calling #REGEX_INTERNAL_search_cancel(). + */ +struct REGEX_INTERNAL_Search * +REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, + const char *string, + REGEX_INTERNAL_Found callback, + void *callback_cls, + struct GNUNET_STATISTICS_Handle *stats) { - struct REGEX_ITERNAL_Search *h; + struct REGEX_INTERNAL_Search *h; struct GNUNET_DHT_GetHandle *get_h; struct RegexSearchContext *ctx; struct GNUNET_HashCode key; @@ -685,28 +705,32 @@ REGEX_ITERNAL_search (struct GNUNET_DHT_Handle *dht, size_t len; /* Initialize handle */ - LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_ITERNAL_search: %s\n", string); GNUNET_assert (NULL != dht); GNUNET_assert (NULL != callback); - h = GNUNET_malloc (sizeof (struct REGEX_ITERNAL_Search)); + h = GNUNET_new (struct REGEX_INTERNAL_Search); h->dht = dht; h->description = GNUNET_strdup (string); h->callback = callback; h->callback_cls = callback_cls; h->stats = stats; h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); + h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); /* Initialize context */ len = strlen (string); - size = REGEX_ITERNAL_get_first_key (string, len, &key); - ctx = GNUNET_malloc (sizeof (struct RegexSearchContext)); + size = REGEX_INTERNAL_get_first_key (string, len, &key); + LOG (GNUNET_ERROR_TYPE_INFO, + "Initial key for `%s' is %s (based on `%.*s')\n", + string, + GNUNET_h2s (&key), + size, + string); + ctx = GNUNET_new (struct RegexSearchContext); ctx->position = size; ctx->info = h; - GNUNET_array_append (h->contexts, h->n_contexts, ctx); - LOG (GNUNET_ERROR_TYPE_DEBUG, " consumed %u bits out of %u\n", size, len); - LOG (GNUNET_ERROR_TYPE_INFO, " looking for %s\n", GNUNET_h2s (&key)); - + GNUNET_array_append (h->contexts, + h->n_contexts, + ctx); /* Start search in DHT */ get_h = GNUNET_DHT_get_start (h->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX, /* type */ @@ -737,8 +761,8 @@ REGEX_ITERNAL_search (struct GNUNET_DHT_Handle *dht, * @param cls Closure (unused). * @param key Current key code (unused). * @param value Value in the hash map (get handle). - * @return GNUNET_YES if we should continue to iterate, - * GNUNET_NO if not. + * @return #GNUNET_YES if we should continue to iterate, + * #GNUNET_NO if not. */ static int regex_cancel_dht_get (void *cls, @@ -753,21 +777,20 @@ regex_cancel_dht_get (void *cls, /** - * Iterator over hash map entries to free MeshRegexBlocks stored during the + * Iterator over hash map entries to free CadetRegexBlocks stored during the * search for connect_by_string. * * @param cls Closure (unused). * @param key Current key code (unused). - * @param value MeshRegexBlock in the hash map. - * @return GNUNET_YES if we should continue to iterate, - * GNUNET_NO if not. + * @param value CadetRegexBlock in the hash map. + * @return #GNUNET_YES if we should continue to iterate, + * #GNUNET_NO if not. */ static int regex_free_result (void *cls, const struct GNUNET_HashCode * key, void *value) { - GNUNET_free (value); return GNUNET_YES; } @@ -776,37 +799,28 @@ regex_free_result (void *cls, /** * Cancel an ongoing regex search in the DHT and free all resources. * - * @param ctx The search context. + * @param h the search context. */ -static void -regex_cancel_search (struct REGEX_ITERNAL_Search *ctx) +void +REGEX_INTERNAL_search_cancel (struct REGEX_INTERNAL_Search *h) { - GNUNET_free (ctx->description); - GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_handles, + unsigned int i; + + GNUNET_free (h->description); + GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_handles, ®ex_cancel_dht_get, NULL); - GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_results, + GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_results, ®ex_free_result, NULL); - GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_results); - GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_handles); - if (0 < ctx->n_contexts) + GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_results); + GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_handles); + if (0 < h->n_contexts) { - int i; - - for (i = 0; i < ctx->n_contexts; i++) - { - GNUNET_free (ctx->contexts[i]); - } - GNUNET_free (ctx->contexts); + for (i = 0; i < h->n_contexts; i++) + GNUNET_free (h->contexts[i]); + GNUNET_free (h->contexts); } -} - -void -REGEX_ITERNAL_search_cancel (struct REGEX_ITERNAL_Search *h) -{ - regex_cancel_search (h); GNUNET_free (h); } - -/* end of regex_dht.c */ +/* end of regex_internal_dht.c */