From 15a8471c0edc4134f57c19884c033a63f49a04dd Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 2 Jul 2013 14:38:54 +0000 Subject: -implementing regex test --- src/regex/Makefile.am | 13 ++- src/regex/gnunet-service-regex.c | 15 ++- src/regex/perf-regex.c | 64 +++++------ src/regex/regex_api.c | 16 +-- src/regex/regex_block_lib.c | 14 ++- src/regex/regex_block_lib.h | 4 +- src/regex/regex_internal.c | 36 +++---- src/regex/regex_internal_dht.c | 227 ++++++++++++++++++++------------------- src/regex/test_regex_api.c | 130 ++++++++++++++++++++++ 9 files changed, 336 insertions(+), 183 deletions(-) create mode 100644 src/regex/test_regex_api.c diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am index b09413565..ba3b8f78d 100644 --- a/src/regex/Makefile.am +++ b/src/regex/Makefile.am @@ -165,7 +165,8 @@ check_PROGRAMS = \ test_regex_eval_api \ test_regex_iterate_api \ test_regex_proofs \ - test_regex_graph_api + test_regex_graph_api \ + test_regex_api if ENABLE_TEST_RUN TESTS = $(check_PROGRAMS) @@ -180,6 +181,13 @@ test_regex_eval_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la +test_regex_api_SOURCES = \ + test_regex_api.c +test_regex_api_LDADD = -lm \ + $(top_builddir)/src/regex/libgnunetregex.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/util/libgnunetutil.la + test_regex_iterate_api_SOURCES = \ test_regex_iterate_api.c test_regex_iterate_api_LDADD = -lm \ @@ -208,4 +216,5 @@ test_regex_graph_api_LDADD = -lm \ EXTRA_DIST = \ - regex_simulation_profiler_test.conf + regex_simulation_profiler_test.conf \ + test_regex_api_data.conf diff --git a/src/regex/gnunet-service-regex.c b/src/regex/gnunet-service-regex.c index 96a6b82b1..e44d11b7d 100644 --- a/src/regex/gnunet-service-regex.c +++ b/src/regex/gnunet-service-regex.c @@ -212,8 +212,18 @@ handle_announce (void *cls, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } + ce = GNUNET_new (struct ClientEntry); ce->client = client; + ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); + ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, + &reannounce, + ce); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting to announce regex `%s' every %s\n", + regex, + GNUNET_STRINGS_relative_time_to_string (ce->frequency, + GNUNET_NO)); ce->ah = REGEX_INTERNAL_announce (dht, my_private_key, regex, @@ -222,14 +232,11 @@ handle_announce (void *cls, if (NULL == ce->ah) { GNUNET_break (0); + GNUNET_SCHEDULER_cancel (ce->refresh_task); GNUNET_free (ce); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); - ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, - &reannounce, - ce); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); diff --git a/src/regex/perf-regex.c b/src/regex/perf-regex.c index bf19a2bff..c2ec7441e 100644 --- a/src/regex/perf-regex.c +++ b/src/regex/perf-regex.c @@ -29,18 +29,12 @@ #include "regex_internal_lib.h" #include "regex_test_lib.h" -static const char *exe; - -static void -usage(void) -{ - fprintf (stderr, "Usage: %s REGEX_FILE COMPRESSION\n", exe); -} /** - * Iterator callback function. + * Print information about the given node and its edges + * to stdout. * - * @param cls closure. + * @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. @@ -48,28 +42,25 @@ usage(void) * @param edges edges leaving current state. */ static void -iter (void *cls, - const struct GNUNET_HashCode *key, - const char *proof, - int accepting, - unsigned int num_edges, - const struct REGEX_BLOCK_Edge *edges) +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\n", GNUNET_h2s (key), accepting ? "ACCEPTING" : ""); - printf (" proof: %s\n", proof); + 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)); - } + printf (" `%s': %s\n", + edges[i].label, + GNUNET_h2s (&edges[i].destination)); } -static void -print_dfa (struct REGEX_INTERNAL_Automaton* dfa) -{ - REGEX_INTERNAL_iterate_all_edges (dfa, iter, NULL); -} /** * The main function of the regex performace test. @@ -92,30 +83,33 @@ main (int argc, char *const *argv) long size; GNUNET_log_setup ("perf-regex", "DEBUG", NULL); - exe = argv[0]; if (3 != argc) { - usage(); + fprintf (stderr, + "Usage: %s REGEX_FILE COMPRESSION\n", + argv[0]); return 1; } regexes = REGEX_TEST_read_from_file (argv[1]); - if (NULL == regexes) { - usage(); + fprintf (stderr, + "Failed to read regexes from `%s'\n", + argv[1]); return 2; } - buffer = REGEX_TEST_combine (regexes); + compression = atoi (argv[2]); + buffer = REGEX_TEST_combine (regexes); GNUNET_asprintf (®ex, "GNVPN-0001-PAD(%s)(0|1)*", buffer); size = strlen (regex); - fprintf (stderr, "Combined regex (%ld bytes):\n%s\n", size, regex); - // return 0; - - compression = atoi (argv[2]); + fprintf (stderr, + "Combined regex (%ld bytes):\n%s\n", + size, + regex); dfa = REGEX_INTERNAL_construct_dfa (regex, size, compression); - print_dfa (dfa); + REGEX_INTERNAL_iterate_all_edges (dfa, &print_edge, NULL); REGEX_INTERNAL_automaton_destroy (dfa); GNUNET_free (buffer); REGEX_TEST_free_from_file (regexes); diff --git a/src/regex/regex_api.c b/src/regex/regex_api.c index fdfd05058..d51bd4c21 100644 --- a/src/regex/regex_api.c +++ b/src/regex/regex_api.c @@ -18,7 +18,7 @@ Boston, MA 02111-1307, USA. */ /** - * @file include/gnunet_regex_service.h + * @file regex/regex_api.c * @brief access regex service to advertise capabilities via regex and discover * respective peers using matching strings * @author Maximilian Szengel @@ -188,7 +188,7 @@ struct GNUNET_REGEX_Search /** * Search message to transmit to the service. */ - struct SearchMessage msg; + struct SearchMessage *msg; }; @@ -216,7 +216,7 @@ retry_search (struct GNUNET_REGEX_Search *s) GNUNET_assert (NULL != s->client); GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (s->client, - &s->msg.header, + &s->msg->header, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &handle_search_response, @@ -300,16 +300,17 @@ GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t slen; slen = strlen (string) + 1; - s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen); + s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Search)); s->cfg = cfg; s->client = GNUNET_CLIENT_connect ("regex", cfg); if (NULL == s->client) return NULL; s->callback = callback; s->callback_cls = callback_cls; - s->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); - s->msg.header.size = htons (sizeof (struct SearchMessage) + slen); - memcpy (&s[1], string, slen); + s->msg = GNUNET_malloc (sizeof (struct SearchMessage) + slen); + s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); + s->msg->header.size = htons (sizeof (struct SearchMessage) + slen); + memcpy (&s->msg[1], string, slen); retry_search (s); return s; } @@ -324,6 +325,7 @@ void GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) { GNUNET_CLIENT_disconnect (s->client); + GNUNET_free (s->msg); GNUNET_free (s); } diff --git a/src/regex/regex_block_lib.c b/src/regex/regex_block_lib.c index 7fcb1a7f1..7b273e6d8 100644 --- a/src/regex/regex_block_lib.c +++ b/src/regex/regex_block_lib.c @@ -96,11 +96,18 @@ GNUNET_NETWORK_STRUCT_END * Test if this block is marked as being an accept state. * * @param block block to test + * @param size number of bytes in block * @return GNUNET_YES if the block is accepting, GNUNET_NO if not */ int -GNUNET_BLOCK_is_accepting (const struct RegexBlock *block) +GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, + size_t size) { + if (size < sizeof (struct RegexBlock)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } return ntohs (block->is_accepting); } @@ -316,7 +323,7 @@ REGEX_BLOCK_iterate (const struct RegexBlock *block, destinations = (const struct GNUNET_HashCode *) &block[1]; edges = (const struct EdgeInfo *) &destinations[num_destinations]; aux = (const char *) &edges[num_edges]; - total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges + sizeof (struct EdgeInfo) + len; + total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges * sizeof (struct EdgeInfo) + len; if (size < total) { GNUNET_break_op (0); @@ -326,6 +333,9 @@ REGEX_BLOCK_iterate (const struct RegexBlock *block, total += ntohs (edges[n].token_length); if (size != total) { + fprintf (stderr, "Expected %u, got %u\n", + (unsigned int) size, + (unsigned int) total); GNUNET_break_op (0); return GNUNET_SYSERR; } diff --git a/src/regex/regex_block_lib.h b/src/regex/regex_block_lib.h index 7c48bbefd..80c2ea2af 100644 --- a/src/regex/regex_block_lib.h +++ b/src/regex/regex_block_lib.h @@ -156,10 +156,12 @@ REGEX_BLOCK_get_key (const struct RegexBlock *block, * Test if this block is marked as being an accept state. * * @param block block to test + * @param size number of bytes in block * @return GNUNET_YES if the block is accepting, GNUNET_NO if not */ int -GNUNET_BLOCK_is_accepting (const struct RegexBlock *block); +GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, + size_t block_len); /** diff --git a/src/regex/regex_internal.c b/src/regex/regex_internal.c index 4ad27c441..a1fab7694 100644 --- a/src/regex/regex_internal.c +++ b/src/regex/regex_internal.c @@ -2132,7 +2132,7 @@ struct REGEX_INTERNAL_Strided_Context * @param start start state for the depth-first traversal of the graph. * @param s current state in the depth-first traversal */ -void +static void dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, struct REGEX_INTERNAL_State *start, struct REGEX_INTERNAL_State *s) @@ -2182,7 +2182,7 @@ dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, * @param count not used. * @param s current state. */ -void +static void dfa_add_multi_strides (void *cls, const unsigned int count, struct REGEX_INTERNAL_State *s) { @@ -2653,7 +2653,6 @@ nfa_add_question_op (struct REGEX_INTERNAL_Context *ctx) struct REGEX_INTERNAL_State *end; a = ctx->stack_tail; - if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -3035,7 +3034,6 @@ REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, REGEX_INTERNAL_context_init (&ctx); /* Create NFA */ - // fprintf (stderr, "N"); nfa = REGEX_INTERNAL_construct_nfa (regex, len); if (NULL == nfa) @@ -3057,12 +3055,10 @@ REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, dfa->start = dfa_state_create (&ctx, &nfa_start_eps_cls); automaton_add_state (dfa, dfa->start); - // fprintf (stderr, "D"); construct_dfa_states (&ctx, nfa, dfa, dfa->start); REGEX_INTERNAL_automaton_destroy (nfa); /* Minimize DFA */ - // fprintf (stderr, "M"); if (GNUNET_OK != dfa_minimize (&ctx, dfa)) { REGEX_INTERNAL_automaton_destroy (dfa); @@ -3310,18 +3306,17 @@ size_t REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, struct GNUNET_HashCode * key) { - unsigned int size; + size_t size; size = string_len < GNUNET_REGEX_INITIAL_BYTES ? string_len : GNUNET_REGEX_INITIAL_BYTES; - if (NULL == input_string) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Given input string was NULL!\n"); return 0; } - GNUNET_CRYPTO_hash (input_string, size, key); return size; @@ -3351,7 +3346,6 @@ iterate_initial_edge (const unsigned int min_len, const unsigned int max_len, struct REGEX_BLOCK_Edge edge[1]; struct GNUNET_HashCode hash; struct GNUNET_HashCode hash_new; - unsigned int cur_len; if (NULL != consumed_string) @@ -3442,19 +3436,19 @@ REGEX_INTERNAL_iterate_all_edges (struct REGEX_INTERNAL_Automaton *a, unsigned int num_edges; num_edges = state_get_edges (s, edges); - - if ((NULL != s->proof && 0 < strlen (s->proof)) || s->accepting) - iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges, - edges); - + if ( ( (NULL != s->proof) && + (0 < strlen (s->proof)) ) || s->accepting) + iterator (iterator_cls, &s->hash, s->proof, + s->accepting, + num_edges, edges); s->marked = GNUNET_NO; } - iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES, GNUNET_REGEX_INITIAL_BYTES, - NULL, a->start, iterator, iterator_cls); + iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES, + GNUNET_REGEX_INITIAL_BYTES, + NULL, a->start, + iterator, iterator_cls); } - - -/* end of regex.c */ +/* end of regex_internal.c */ diff --git a/src/regex/regex_internal_dht.c b/src/regex/regex_internal_dht.c index 15f53e953..317c6ef48 100644 --- a/src/regex/regex_internal_dht.c +++ b/src/regex/regex_internal_dht.c @@ -34,16 +34,9 @@ #define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__) -/* FIXME: OPTION (API, CONFIG) */ #define DHT_REPLICATION 5 #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 #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE -#endif /** @@ -113,9 +106,9 @@ regex_iterator (void *cls, "State %s is accepting, putting own id\n", GNUNET_h2s(key)); size = sizeof (struct RegexAcceptBlock); - ab.purpose.size = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + - sizeof (struct GNUNET_TIME_AbsoluteNBO) + - sizeof (struct GNUNET_HashCode); + 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; @@ -191,8 +184,8 @@ REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht, h->stats = stats; h->priv = priv; h->dfa = REGEX_INTERNAL_construct_dfa (regex, - strlen (regex), - compression); + strlen (regex), + compression); REGEX_INTERNAL_reannounce (h); return h; } @@ -208,13 +201,14 @@ void 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_INTERNAL_reannounce: %.60s\n", h->regex); - LOG (GNUNET_ERROR_TYPE_DEBUG, " full: %s\n", h->regex); - REGEX_INTERNAL_iterate_all_edges (h->dfa, ®ex_iterator, h); + LOG (GNUNET_ERROR_TYPE_INFO, + "REGEX_INTERNAL_reannounce: %s\n", + h->regex); + REGEX_INTERNAL_iterate_all_edges (h->dfa, + ®ex_iterator, h); } - /** * Clear all cached data used by a regex announce. * Does not close DHT connection. @@ -262,45 +256,63 @@ struct RegexSearchContext }; +/** + * 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_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; /** @@ -315,15 +327,12 @@ struct REGEX_INTERNAL_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, @@ -361,13 +370,15 @@ dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, struct REGEX_INTERNAL_Search *info = ctx->info; struct GNUNET_PeerIdentity pid; - 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); GNUNET_CRYPTO_hash (&block->public_key, sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded), @@ -392,8 +403,9 @@ 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, + "regex finds path for %s\n", + GNUNET_h2s (key)); get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ key, /* key to search */ @@ -440,40 +452,24 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct RegexBlock *block = data; struct RegexSearchContext *ctx = cls; struct REGEX_INTERNAL_Search *info = ctx->info; - void *copy; 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, block, size); - GNUNET_break ( - GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, - key, copy, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) - ); + 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 == GNUNET_BLOCK_is_accepting (block)) + if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block, size)) { regex_find_path (key, ctx); } @@ -501,22 +497,25 @@ 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 == - GNUNET_BLOCK_is_accepting (block)) && + 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), - GNUNET_BLOCK_is_accepting (block)); - - 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", 1, GNUNET_NO); @@ -548,37 +547,28 @@ regex_edge_iterator (void *cls, 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"); @@ -592,8 +582,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, @@ -611,13 +599,14 @@ regex_next_edge (const struct RegexBlock *block, * among tokens in the given block */ ctx->longest_match = 0; result = REGEX_BLOCK_iterate (block, size, - ®ex_edge_iterator, ctx); + ®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; } @@ -631,7 +620,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, @@ -643,8 +633,9 @@ 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_INFO, + "looking for %s\n", + GNUNET_h2s (hash)); rest = &new_ctx->info->description[new_ctx->position]; get_h = GNUNET_DHT_get_start (info->dht, /* handle */ @@ -653,9 +644,7 @@ regex_next_edge (const struct RegexBlock *block, 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, @@ -669,6 +658,20 @@ regex_next_edge (const struct RegexBlock *block, } +/** + * 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, @@ -703,8 +706,10 @@ REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, 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)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "consumed %u bits out of %u, now looking for %s\n", + size, len, + GNUNET_h2s (&key)); /* Start search in DHT */ get_h = GNUNET_DHT_get_start (h->dht, /* handle */ diff --git a/src/regex/test_regex_api.c b/src/regex/test_regex_api.c new file mode 100644 index 000000000..81627e6e4 --- /dev/null +++ b/src/regex/test_regex_api.c @@ -0,0 +1,130 @@ +/* + This file is part of GNUnet. + (C) 2013 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 + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + 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. +*/ +/** + * @file regex/test_regex_api.c + * @brief base test case for regex api (and DHT functions) + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_lib.h" +#include "gnunet_regex_service.h" + + +/** + * How long until we really give up on a particular testcase portion? + */ +#define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) + +/** + * How long until we give up on any particular operation (and retry)? + */ +#define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) + + +static struct GNUNET_REGEX_Announcement *a; + +static struct GNUNET_REGEX_Search *s; + +static int ok = 1; + +static GNUNET_SCHEDULER_TaskIdentifier die_task; + + +static void +end (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_REGEX_announce_cancel (a); + a = NULL; + GNUNET_REGEX_search_cancel (s); + s = NULL; + ok = 0; +} + + +static void +end_badly () +{ + die_task = GNUNET_SCHEDULER_NO_TASK; + FPRINTF (stderr, "%s", "Testcase failed (timeout).\n"); + GNUNET_REGEX_announce_cancel (a); + a = NULL; + GNUNET_REGEX_search_cancel (s); + s = NULL; + ok = 1; +} + + +/** + * Search callback function, invoked for every result that was found. + * + * @param cls Closure provided in GNUNET_REGEX_search. + * @param id Peer providing a regex that matches the string. + * @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. + */ +static void +found_cb (void *cls, + const struct GNUNET_PeerIdentity *id, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length) +{ + GNUNET_SCHEDULER_cancel (die_task); + die_task = + GNUNET_SCHEDULER_add_now (&end, NULL); +} + + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + die_task = + GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, + &end_badly, NULL); + a = GNUNET_REGEX_announce (cfg, + "my long prefix - hello world(0|1)*", + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + 5), + 1); + s = GNUNET_REGEX_search (cfg, + "my long prefix - hello world0101", + &found_cb, NULL); +} + + +int +main (int argc, char *argv[]) +{ + if (0 != GNUNET_TESTING_peer_run ("test-regex-api", + "test_regex_api_data.conf", + &run, NULL)) + return 1; + return ok; +} + +/* end of test_regex_api.c */ -- cgit v1.2.3