diff options
-rw-r--r-- | src/regex/Makefile.am | 13 | ||||
-rw-r--r-- | src/regex/gnunet-service-regex.c | 15 | ||||
-rw-r--r-- | src/regex/perf-regex.c | 64 | ||||
-rw-r--r-- | src/regex/regex_api.c | 16 | ||||
-rw-r--r-- | src/regex/regex_block_lib.c | 14 | ||||
-rw-r--r-- | src/regex/regex_block_lib.h | 4 | ||||
-rw-r--r-- | src/regex/regex_internal.c | 36 | ||||
-rw-r--r-- | src/regex/regex_internal_dht.c | 227 | ||||
-rw-r--r-- | src/regex/test_regex_api.c | 130 |
9 files changed, 336 insertions, 183 deletions
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 = \ | |||
165 | test_regex_eval_api \ | 165 | test_regex_eval_api \ |
166 | test_regex_iterate_api \ | 166 | test_regex_iterate_api \ |
167 | test_regex_proofs \ | 167 | test_regex_proofs \ |
168 | test_regex_graph_api | 168 | test_regex_graph_api \ |
169 | test_regex_api | ||
169 | 170 | ||
170 | if ENABLE_TEST_RUN | 171 | if ENABLE_TEST_RUN |
171 | TESTS = $(check_PROGRAMS) | 172 | TESTS = $(check_PROGRAMS) |
@@ -180,6 +181,13 @@ test_regex_eval_api_LDADD = -lm \ | |||
180 | $(top_builddir)/src/regex/libgnunetregexblock.la \ | 181 | $(top_builddir)/src/regex/libgnunetregexblock.la \ |
181 | $(top_builddir)/src/util/libgnunetutil.la | 182 | $(top_builddir)/src/util/libgnunetutil.la |
182 | 183 | ||
184 | test_regex_api_SOURCES = \ | ||
185 | test_regex_api.c | ||
186 | test_regex_api_LDADD = -lm \ | ||
187 | $(top_builddir)/src/regex/libgnunetregex.la \ | ||
188 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
189 | $(top_builddir)/src/util/libgnunetutil.la | ||
190 | |||
183 | test_regex_iterate_api_SOURCES = \ | 191 | test_regex_iterate_api_SOURCES = \ |
184 | test_regex_iterate_api.c | 192 | test_regex_iterate_api.c |
185 | test_regex_iterate_api_LDADD = -lm \ | 193 | test_regex_iterate_api_LDADD = -lm \ |
@@ -208,4 +216,5 @@ test_regex_graph_api_LDADD = -lm \ | |||
208 | 216 | ||
209 | 217 | ||
210 | EXTRA_DIST = \ | 218 | EXTRA_DIST = \ |
211 | regex_simulation_profiler_test.conf | 219 | regex_simulation_profiler_test.conf \ |
220 | 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, | |||
212 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 212 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
213 | return; | 213 | return; |
214 | } | 214 | } |
215 | |||
215 | ce = GNUNET_new (struct ClientEntry); | 216 | ce = GNUNET_new (struct ClientEntry); |
216 | ce->client = client; | 217 | ce->client = client; |
218 | ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); | ||
219 | ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, | ||
220 | &reannounce, | ||
221 | ce); | ||
222 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
223 | "Starting to announce regex `%s' every %s\n", | ||
224 | regex, | ||
225 | GNUNET_STRINGS_relative_time_to_string (ce->frequency, | ||
226 | GNUNET_NO)); | ||
217 | ce->ah = REGEX_INTERNAL_announce (dht, | 227 | ce->ah = REGEX_INTERNAL_announce (dht, |
218 | my_private_key, | 228 | my_private_key, |
219 | regex, | 229 | regex, |
@@ -222,14 +232,11 @@ handle_announce (void *cls, | |||
222 | if (NULL == ce->ah) | 232 | if (NULL == ce->ah) |
223 | { | 233 | { |
224 | GNUNET_break (0); | 234 | GNUNET_break (0); |
235 | GNUNET_SCHEDULER_cancel (ce->refresh_task); | ||
225 | GNUNET_free (ce); | 236 | GNUNET_free (ce); |
226 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 237 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
227 | return; | 238 | return; |
228 | } | 239 | } |
229 | ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); | ||
230 | ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, | ||
231 | &reannounce, | ||
232 | ce); | ||
233 | GNUNET_CONTAINER_DLL_insert (client_head, | 240 | GNUNET_CONTAINER_DLL_insert (client_head, |
234 | client_tail, | 241 | client_tail, |
235 | ce); | 242 | 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 @@ | |||
29 | #include "regex_internal_lib.h" | 29 | #include "regex_internal_lib.h" |
30 | #include "regex_test_lib.h" | 30 | #include "regex_test_lib.h" |
31 | 31 | ||
32 | static const char *exe; | ||
33 | |||
34 | static void | ||
35 | usage(void) | ||
36 | { | ||
37 | fprintf (stderr, "Usage: %s REGEX_FILE COMPRESSION\n", exe); | ||
38 | } | ||
39 | 32 | ||
40 | /** | 33 | /** |
41 | * Iterator callback function. | 34 | * Print information about the given node and its edges |
35 | * to stdout. | ||
42 | * | 36 | * |
43 | * @param cls closure. | 37 | * @param cls closure, unused. |
44 | * @param key hash for current state. | 38 | * @param key hash for current state. |
45 | * @param proof proof for current state. | 39 | * @param proof proof for current state. |
46 | * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. | 40 | * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. |
@@ -48,28 +42,25 @@ usage(void) | |||
48 | * @param edges edges leaving current state. | 42 | * @param edges edges leaving current state. |
49 | */ | 43 | */ |
50 | static void | 44 | static void |
51 | iter (void *cls, | 45 | print_edge (void *cls, |
52 | const struct GNUNET_HashCode *key, | 46 | const struct GNUNET_HashCode *key, |
53 | const char *proof, | 47 | const char *proof, |
54 | int accepting, | 48 | int accepting, |
55 | unsigned int num_edges, | 49 | unsigned int num_edges, |
56 | const struct REGEX_BLOCK_Edge *edges) | 50 | const struct REGEX_BLOCK_Edge *edges) |
57 | { | 51 | { |
58 | unsigned int i; | 52 | unsigned int i; |
59 | 53 | ||
60 | printf ("%s: %s\n", GNUNET_h2s (key), accepting ? "ACCEPTING" : ""); | 54 | printf ("%s: %s, proof: `%s'\n", |
61 | printf (" proof: %s\n", proof); | 55 | GNUNET_h2s (key), |
56 | accepting ? "ACCEPTING" : "", | ||
57 | proof); | ||
62 | for (i = 0; i < num_edges; i++) | 58 | for (i = 0; i < num_edges; i++) |
63 | { | 59 | printf (" `%s': %s\n", |
64 | printf (" %s: %s\n", edges[i].label, GNUNET_h2s (&edges[i].destination)); | 60 | edges[i].label, |
65 | } | 61 | GNUNET_h2s (&edges[i].destination)); |
66 | } | 62 | } |
67 | 63 | ||
68 | static void | ||
69 | print_dfa (struct REGEX_INTERNAL_Automaton* dfa) | ||
70 | { | ||
71 | REGEX_INTERNAL_iterate_all_edges (dfa, iter, NULL); | ||
72 | } | ||
73 | 64 | ||
74 | /** | 65 | /** |
75 | * The main function of the regex performace test. | 66 | * The main function of the regex performace test. |
@@ -92,30 +83,33 @@ main (int argc, char *const *argv) | |||
92 | long size; | 83 | long size; |
93 | 84 | ||
94 | GNUNET_log_setup ("perf-regex", "DEBUG", NULL); | 85 | GNUNET_log_setup ("perf-regex", "DEBUG", NULL); |
95 | exe = argv[0]; | ||
96 | if (3 != argc) | 86 | if (3 != argc) |
97 | { | 87 | { |
98 | usage(); | 88 | fprintf (stderr, |
89 | "Usage: %s REGEX_FILE COMPRESSION\n", | ||
90 | argv[0]); | ||
99 | return 1; | 91 | return 1; |
100 | } | 92 | } |
101 | regexes = REGEX_TEST_read_from_file (argv[1]); | 93 | regexes = REGEX_TEST_read_from_file (argv[1]); |
102 | |||
103 | if (NULL == regexes) | 94 | if (NULL == regexes) |
104 | { | 95 | { |
105 | usage(); | 96 | fprintf (stderr, |
97 | "Failed to read regexes from `%s'\n", | ||
98 | argv[1]); | ||
106 | return 2; | 99 | return 2; |
107 | } | 100 | } |
108 | buffer = REGEX_TEST_combine (regexes); | 101 | compression = atoi (argv[2]); |
109 | 102 | ||
103 | buffer = REGEX_TEST_combine (regexes); | ||
110 | GNUNET_asprintf (®ex, "GNVPN-0001-PAD(%s)(0|1)*", buffer); | 104 | GNUNET_asprintf (®ex, "GNVPN-0001-PAD(%s)(0|1)*", buffer); |
111 | size = strlen (regex); | 105 | size = strlen (regex); |
112 | 106 | ||
113 | fprintf (stderr, "Combined regex (%ld bytes):\n%s\n", size, regex); | 107 | fprintf (stderr, |
114 | // return 0; | 108 | "Combined regex (%ld bytes):\n%s\n", |
115 | 109 | size, | |
116 | compression = atoi (argv[2]); | 110 | regex); |
117 | dfa = REGEX_INTERNAL_construct_dfa (regex, size, compression); | 111 | dfa = REGEX_INTERNAL_construct_dfa (regex, size, compression); |
118 | print_dfa (dfa); | 112 | REGEX_INTERNAL_iterate_all_edges (dfa, &print_edge, NULL); |
119 | REGEX_INTERNAL_automaton_destroy (dfa); | 113 | REGEX_INTERNAL_automaton_destroy (dfa); |
120 | GNUNET_free (buffer); | 114 | GNUNET_free (buffer); |
121 | REGEX_TEST_free_from_file (regexes); | 115 | 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 @@ | |||
18 | Boston, MA 02111-1307, USA. | 18 | Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file include/gnunet_regex_service.h | 21 | * @file regex/regex_api.c |
22 | * @brief access regex service to advertise capabilities via regex and discover | 22 | * @brief access regex service to advertise capabilities via regex and discover |
23 | * respective peers using matching strings | 23 | * respective peers using matching strings |
24 | * @author Maximilian Szengel | 24 | * @author Maximilian Szengel |
@@ -188,7 +188,7 @@ struct GNUNET_REGEX_Search | |||
188 | /** | 188 | /** |
189 | * Search message to transmit to the service. | 189 | * Search message to transmit to the service. |
190 | */ | 190 | */ |
191 | struct SearchMessage msg; | 191 | struct SearchMessage *msg; |
192 | }; | 192 | }; |
193 | 193 | ||
194 | 194 | ||
@@ -216,7 +216,7 @@ retry_search (struct GNUNET_REGEX_Search *s) | |||
216 | GNUNET_assert (NULL != s->client); | 216 | GNUNET_assert (NULL != s->client); |
217 | GNUNET_assert (GNUNET_OK == | 217 | GNUNET_assert (GNUNET_OK == |
218 | GNUNET_CLIENT_transmit_and_get_response (s->client, | 218 | GNUNET_CLIENT_transmit_and_get_response (s->client, |
219 | &s->msg.header, | 219 | &s->msg->header, |
220 | GNUNET_TIME_UNIT_FOREVER_REL, | 220 | GNUNET_TIME_UNIT_FOREVER_REL, |
221 | GNUNET_YES, | 221 | GNUNET_YES, |
222 | &handle_search_response, | 222 | &handle_search_response, |
@@ -300,16 +300,17 @@ GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
300 | size_t slen; | 300 | size_t slen; |
301 | 301 | ||
302 | slen = strlen (string) + 1; | 302 | slen = strlen (string) + 1; |
303 | s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen); | 303 | s = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Search)); |
304 | s->cfg = cfg; | 304 | s->cfg = cfg; |
305 | s->client = GNUNET_CLIENT_connect ("regex", cfg); | 305 | s->client = GNUNET_CLIENT_connect ("regex", cfg); |
306 | if (NULL == s->client) | 306 | if (NULL == s->client) |
307 | return NULL; | 307 | return NULL; |
308 | s->callback = callback; | 308 | s->callback = callback; |
309 | s->callback_cls = callback_cls; | 309 | s->callback_cls = callback_cls; |
310 | s->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); | 310 | s->msg = GNUNET_malloc (sizeof (struct SearchMessage) + slen); |
311 | s->msg.header.size = htons (sizeof (struct SearchMessage) + slen); | 311 | s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); |
312 | memcpy (&s[1], string, slen); | 312 | s->msg->header.size = htons (sizeof (struct SearchMessage) + slen); |
313 | memcpy (&s->msg[1], string, slen); | ||
313 | retry_search (s); | 314 | retry_search (s); |
314 | return s; | 315 | return s; |
315 | } | 316 | } |
@@ -324,6 +325,7 @@ void | |||
324 | GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) | 325 | GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) |
325 | { | 326 | { |
326 | GNUNET_CLIENT_disconnect (s->client); | 327 | GNUNET_CLIENT_disconnect (s->client); |
328 | GNUNET_free (s->msg); | ||
327 | GNUNET_free (s); | 329 | GNUNET_free (s); |
328 | } | 330 | } |
329 | 331 | ||
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 | |||
96 | * Test if this block is marked as being an accept state. | 96 | * Test if this block is marked as being an accept state. |
97 | * | 97 | * |
98 | * @param block block to test | 98 | * @param block block to test |
99 | * @param size number of bytes in block | ||
99 | * @return GNUNET_YES if the block is accepting, GNUNET_NO if not | 100 | * @return GNUNET_YES if the block is accepting, GNUNET_NO if not |
100 | */ | 101 | */ |
101 | int | 102 | int |
102 | GNUNET_BLOCK_is_accepting (const struct RegexBlock *block) | 103 | GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, |
104 | size_t size) | ||
103 | { | 105 | { |
106 | if (size < sizeof (struct RegexBlock)) | ||
107 | { | ||
108 | GNUNET_break_op (0); | ||
109 | return GNUNET_SYSERR; | ||
110 | } | ||
104 | return ntohs (block->is_accepting); | 111 | return ntohs (block->is_accepting); |
105 | } | 112 | } |
106 | 113 | ||
@@ -316,7 +323,7 @@ REGEX_BLOCK_iterate (const struct RegexBlock *block, | |||
316 | destinations = (const struct GNUNET_HashCode *) &block[1]; | 323 | destinations = (const struct GNUNET_HashCode *) &block[1]; |
317 | edges = (const struct EdgeInfo *) &destinations[num_destinations]; | 324 | edges = (const struct EdgeInfo *) &destinations[num_destinations]; |
318 | aux = (const char *) &edges[num_edges]; | 325 | aux = (const char *) &edges[num_edges]; |
319 | total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges + sizeof (struct EdgeInfo) + len; | 326 | total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges * sizeof (struct EdgeInfo) + len; |
320 | if (size < total) | 327 | if (size < total) |
321 | { | 328 | { |
322 | GNUNET_break_op (0); | 329 | GNUNET_break_op (0); |
@@ -326,6 +333,9 @@ REGEX_BLOCK_iterate (const struct RegexBlock *block, | |||
326 | total += ntohs (edges[n].token_length); | 333 | total += ntohs (edges[n].token_length); |
327 | if (size != total) | 334 | if (size != total) |
328 | { | 335 | { |
336 | fprintf (stderr, "Expected %u, got %u\n", | ||
337 | (unsigned int) size, | ||
338 | (unsigned int) total); | ||
329 | GNUNET_break_op (0); | 339 | GNUNET_break_op (0); |
330 | return GNUNET_SYSERR; | 340 | return GNUNET_SYSERR; |
331 | } | 341 | } |
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, | |||
156 | * Test if this block is marked as being an accept state. | 156 | * Test if this block is marked as being an accept state. |
157 | * | 157 | * |
158 | * @param block block to test | 158 | * @param block block to test |
159 | * @param size number of bytes in block | ||
159 | * @return GNUNET_YES if the block is accepting, GNUNET_NO if not | 160 | * @return GNUNET_YES if the block is accepting, GNUNET_NO if not |
160 | */ | 161 | */ |
161 | int | 162 | int |
162 | GNUNET_BLOCK_is_accepting (const struct RegexBlock *block); | 163 | GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, |
164 | size_t block_len); | ||
163 | 165 | ||
164 | 166 | ||
165 | /** | 167 | /** |
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 | |||
2132 | * @param start start state for the depth-first traversal of the graph. | 2132 | * @param start start state for the depth-first traversal of the graph. |
2133 | * @param s current state in the depth-first traversal | 2133 | * @param s current state in the depth-first traversal |
2134 | */ | 2134 | */ |
2135 | void | 2135 | static void |
2136 | dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, | 2136 | dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, |
2137 | struct REGEX_INTERNAL_State *start, | 2137 | struct REGEX_INTERNAL_State *start, |
2138 | struct REGEX_INTERNAL_State *s) | 2138 | struct REGEX_INTERNAL_State *s) |
@@ -2182,7 +2182,7 @@ dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, | |||
2182 | * @param count not used. | 2182 | * @param count not used. |
2183 | * @param s current state. | 2183 | * @param s current state. |
2184 | */ | 2184 | */ |
2185 | void | 2185 | static void |
2186 | dfa_add_multi_strides (void *cls, const unsigned int count, | 2186 | dfa_add_multi_strides (void *cls, const unsigned int count, |
2187 | struct REGEX_INTERNAL_State *s) | 2187 | struct REGEX_INTERNAL_State *s) |
2188 | { | 2188 | { |
@@ -2653,7 +2653,6 @@ nfa_add_question_op (struct REGEX_INTERNAL_Context *ctx) | |||
2653 | struct REGEX_INTERNAL_State *end; | 2653 | struct REGEX_INTERNAL_State *end; |
2654 | 2654 | ||
2655 | a = ctx->stack_tail; | 2655 | a = ctx->stack_tail; |
2656 | |||
2657 | if (NULL == a) | 2656 | if (NULL == a) |
2658 | { | 2657 | { |
2659 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2658 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
@@ -3035,7 +3034,6 @@ REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, | |||
3035 | REGEX_INTERNAL_context_init (&ctx); | 3034 | REGEX_INTERNAL_context_init (&ctx); |
3036 | 3035 | ||
3037 | /* Create NFA */ | 3036 | /* Create NFA */ |
3038 | // fprintf (stderr, "N"); | ||
3039 | nfa = REGEX_INTERNAL_construct_nfa (regex, len); | 3037 | nfa = REGEX_INTERNAL_construct_nfa (regex, len); |
3040 | 3038 | ||
3041 | if (NULL == nfa) | 3039 | if (NULL == nfa) |
@@ -3057,12 +3055,10 @@ REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, | |||
3057 | dfa->start = dfa_state_create (&ctx, &nfa_start_eps_cls); | 3055 | dfa->start = dfa_state_create (&ctx, &nfa_start_eps_cls); |
3058 | automaton_add_state (dfa, dfa->start); | 3056 | automaton_add_state (dfa, dfa->start); |
3059 | 3057 | ||
3060 | // fprintf (stderr, "D"); | ||
3061 | construct_dfa_states (&ctx, nfa, dfa, dfa->start); | 3058 | construct_dfa_states (&ctx, nfa, dfa, dfa->start); |
3062 | REGEX_INTERNAL_automaton_destroy (nfa); | 3059 | REGEX_INTERNAL_automaton_destroy (nfa); |
3063 | 3060 | ||
3064 | /* Minimize DFA */ | 3061 | /* Minimize DFA */ |
3065 | // fprintf (stderr, "M"); | ||
3066 | if (GNUNET_OK != dfa_minimize (&ctx, dfa)) | 3062 | if (GNUNET_OK != dfa_minimize (&ctx, dfa)) |
3067 | { | 3063 | { |
3068 | REGEX_INTERNAL_automaton_destroy (dfa); | 3064 | REGEX_INTERNAL_automaton_destroy (dfa); |
@@ -3310,18 +3306,17 @@ size_t | |||
3310 | REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, | 3306 | REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, |
3311 | struct GNUNET_HashCode * key) | 3307 | struct GNUNET_HashCode * key) |
3312 | { | 3308 | { |
3313 | unsigned int size; | 3309 | size_t size; |
3314 | 3310 | ||
3315 | size = | 3311 | size = |
3316 | string_len < | 3312 | string_len < |
3317 | GNUNET_REGEX_INITIAL_BYTES ? string_len : GNUNET_REGEX_INITIAL_BYTES; | 3313 | GNUNET_REGEX_INITIAL_BYTES ? string_len : GNUNET_REGEX_INITIAL_BYTES; |
3318 | |||
3319 | if (NULL == input_string) | 3314 | if (NULL == input_string) |
3320 | { | 3315 | { |
3321 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n"); | 3316 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
3317 | "Given input string was NULL!\n"); | ||
3322 | return 0; | 3318 | return 0; |
3323 | } | 3319 | } |
3324 | |||
3325 | GNUNET_CRYPTO_hash (input_string, size, key); | 3320 | GNUNET_CRYPTO_hash (input_string, size, key); |
3326 | 3321 | ||
3327 | return size; | 3322 | return size; |
@@ -3351,7 +3346,6 @@ iterate_initial_edge (const unsigned int min_len, const unsigned int max_len, | |||
3351 | struct REGEX_BLOCK_Edge edge[1]; | 3346 | struct REGEX_BLOCK_Edge edge[1]; |
3352 | struct GNUNET_HashCode hash; | 3347 | struct GNUNET_HashCode hash; |
3353 | struct GNUNET_HashCode hash_new; | 3348 | struct GNUNET_HashCode hash_new; |
3354 | |||
3355 | unsigned int cur_len; | 3349 | unsigned int cur_len; |
3356 | 3350 | ||
3357 | if (NULL != consumed_string) | 3351 | if (NULL != consumed_string) |
@@ -3442,19 +3436,19 @@ REGEX_INTERNAL_iterate_all_edges (struct REGEX_INTERNAL_Automaton *a, | |||
3442 | unsigned int num_edges; | 3436 | unsigned int num_edges; |
3443 | 3437 | ||
3444 | num_edges = state_get_edges (s, edges); | 3438 | num_edges = state_get_edges (s, edges); |
3445 | 3439 | if ( ( (NULL != s->proof) && | |
3446 | if ((NULL != s->proof && 0 < strlen (s->proof)) || s->accepting) | 3440 | (0 < strlen (s->proof)) ) || s->accepting) |
3447 | iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges, | 3441 | iterator (iterator_cls, &s->hash, s->proof, |
3448 | edges); | 3442 | s->accepting, |
3449 | 3443 | num_edges, edges); | |
3450 | s->marked = GNUNET_NO; | 3444 | s->marked = GNUNET_NO; |
3451 | } | 3445 | } |
3452 | 3446 | ||
3453 | iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES, GNUNET_REGEX_INITIAL_BYTES, | 3447 | iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES, |
3454 | NULL, a->start, iterator, iterator_cls); | 3448 | GNUNET_REGEX_INITIAL_BYTES, |
3449 | NULL, a->start, | ||
3450 | iterator, iterator_cls); | ||
3455 | } | 3451 | } |
3456 | 3452 | ||
3457 | 3453 | ||
3458 | 3454 | /* end of regex_internal.c */ | |
3459 | |||
3460 | /* end of regex.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 @@ | |||
34 | 34 | ||
35 | #define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__) | 35 | #define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__) |
36 | 36 | ||
37 | /* FIXME: OPTION (API, CONFIG) */ | ||
38 | #define DHT_REPLICATION 5 | 37 | #define DHT_REPLICATION 5 |
39 | #define DHT_TTL GNUNET_TIME_UNIT_HOURS | 38 | #define DHT_TTL GNUNET_TIME_UNIT_HOURS |
40 | #define DEBUG_DHT GNUNET_NO | ||
41 | |||
42 | #if DEBUG_DHT | ||
43 | #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | GNUNET_DHT_RO_RECORD_ROUTE | ||
44 | #else | ||
45 | #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | 39 | #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE |
46 | #endif | ||
47 | 40 | ||
48 | 41 | ||
49 | /** | 42 | /** |
@@ -113,9 +106,9 @@ regex_iterator (void *cls, | |||
113 | "State %s is accepting, putting own id\n", | 106 | "State %s is accepting, putting own id\n", |
114 | GNUNET_h2s(key)); | 107 | GNUNET_h2s(key)); |
115 | size = sizeof (struct RegexAcceptBlock); | 108 | size = sizeof (struct RegexAcceptBlock); |
116 | ab.purpose.size = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | 109 | ab.purpose.size = ntohl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + |
117 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | 110 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + |
118 | sizeof (struct GNUNET_HashCode); | 111 | sizeof (struct GNUNET_HashCode)); |
119 | ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT); | 112 | ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT); |
120 | ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION)); | 113 | ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION)); |
121 | ab.key = *key; | 114 | ab.key = *key; |
@@ -191,8 +184,8 @@ REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht, | |||
191 | h->stats = stats; | 184 | h->stats = stats; |
192 | h->priv = priv; | 185 | h->priv = priv; |
193 | h->dfa = REGEX_INTERNAL_construct_dfa (regex, | 186 | h->dfa = REGEX_INTERNAL_construct_dfa (regex, |
194 | strlen (regex), | 187 | strlen (regex), |
195 | compression); | 188 | compression); |
196 | REGEX_INTERNAL_reannounce (h); | 189 | REGEX_INTERNAL_reannounce (h); |
197 | return h; | 190 | return h; |
198 | } | 191 | } |
@@ -208,13 +201,14 @@ void | |||
208 | REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h) | 201 | REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h) |
209 | { | 202 | { |
210 | GNUNET_assert (NULL != h->dfa); /* make sure to call announce first */ | 203 | GNUNET_assert (NULL != h->dfa); /* make sure to call announce first */ |
211 | LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_INTERNAL_reannounce: %.60s\n", h->regex); | 204 | LOG (GNUNET_ERROR_TYPE_INFO, |
212 | LOG (GNUNET_ERROR_TYPE_DEBUG, " full: %s\n", h->regex); | 205 | "REGEX_INTERNAL_reannounce: %s\n", |
213 | REGEX_INTERNAL_iterate_all_edges (h->dfa, ®ex_iterator, h); | 206 | h->regex); |
207 | REGEX_INTERNAL_iterate_all_edges (h->dfa, | ||
208 | ®ex_iterator, h); | ||
214 | } | 209 | } |
215 | 210 | ||
216 | 211 | ||
217 | |||
218 | /** | 212 | /** |
219 | * Clear all cached data used by a regex announce. | 213 | * Clear all cached data used by a regex announce. |
220 | * Does not close DHT connection. | 214 | * Does not close DHT connection. |
@@ -263,44 +257,62 @@ struct RegexSearchContext | |||
263 | 257 | ||
264 | 258 | ||
265 | /** | 259 | /** |
260 | * Type of values in 'dht_get_results'. | ||
261 | */ | ||
262 | struct Result | ||
263 | { | ||
264 | /** | ||
265 | * Number of bytes in data. | ||
266 | */ | ||
267 | size_t size; | ||
268 | |||
269 | /** | ||
270 | * The raw result data. | ||
271 | */ | ||
272 | const void *data; | ||
273 | }; | ||
274 | |||
275 | |||
276 | /** | ||
266 | * Struct to keep information of searches of services described by a regex | 277 | * Struct to keep information of searches of services described by a regex |
267 | * using a user-provided string service description. | 278 | * using a user-provided string service description. |
268 | */ | 279 | */ |
269 | struct REGEX_INTERNAL_Search | 280 | struct REGEX_INTERNAL_Search |
270 | { | 281 | { |
271 | /** | 282 | /** |
272 | * DHT handle to use, must be initialized externally. | 283 | * DHT handle to use, must be initialized externally. |
273 | */ | 284 | */ |
274 | struct GNUNET_DHT_Handle *dht; | 285 | struct GNUNET_DHT_Handle *dht; |
275 | 286 | ||
276 | /** | 287 | /** |
277 | * Optional statistics handle to report usage. Can be NULL. | 288 | * Optional statistics handle to report usage. Can be NULL. |
278 | */ | 289 | */ |
279 | struct GNUNET_STATISTICS_Handle *stats; | 290 | struct GNUNET_STATISTICS_Handle *stats; |
280 | 291 | ||
281 | /** | 292 | /** |
282 | * User provided description of the searched service. | 293 | * User provided description of the searched service. |
283 | */ | 294 | */ |
284 | char *description; | 295 | char *description; |
285 | 296 | ||
286 | /** | 297 | /** |
287 | * Running DHT GETs. | 298 | * Running DHT GETs. |
288 | */ | 299 | */ |
289 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; | 300 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; |
290 | 301 | ||
291 | /** | 302 | /** |
292 | * Results from running DHT GETs. | 303 | * Results from running DHT GETs, values are of type |
293 | */ | 304 | * 'struct Result'. |
305 | */ | ||
294 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; | 306 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; |
295 | 307 | ||
296 | /** | 308 | /** |
297 | * Contexts, for each running DHT GET. Free all on end of search. | 309 | * Contexts, for each running DHT GET. Free all on end of search. |
298 | */ | 310 | */ |
299 | struct RegexSearchContext **contexts; | 311 | struct RegexSearchContext **contexts; |
300 | 312 | ||
301 | /** | 313 | /** |
302 | * Number of contexts (branches/steps in search). | 314 | * Number of contexts (branches/steps in search). |
303 | */ | 315 | */ |
304 | unsigned int n_contexts; | 316 | unsigned int n_contexts; |
305 | 317 | ||
306 | /** | 318 | /** |
@@ -315,15 +327,12 @@ struct REGEX_INTERNAL_Search | |||
315 | }; | 327 | }; |
316 | 328 | ||
317 | 329 | ||
318 | |||
319 | /** | 330 | /** |
320 | * Jump to the next edge, with the longest matching token. | 331 | * Jump to the next edge, with the longest matching token. |
321 | * | 332 | * |
322 | * @param block Block found in the DHT. | 333 | * @param block Block found in the DHT. |
323 | * @param size Size of the block. | 334 | * @param size Size of the block. |
324 | * @param ctx Context of the search. | 335 | * @param ctx Context of the search. |
325 | * | ||
326 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
327 | */ | 336 | */ |
328 | static void | 337 | static void |
329 | regex_next_edge (const struct RegexBlock *block, | 338 | regex_next_edge (const struct RegexBlock *block, |
@@ -361,13 +370,15 @@ dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
361 | struct REGEX_INTERNAL_Search *info = ctx->info; | 370 | struct REGEX_INTERNAL_Search *info = ctx->info; |
362 | struct GNUNET_PeerIdentity pid; | 371 | struct GNUNET_PeerIdentity pid; |
363 | 372 | ||
364 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | 373 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
365 | LOG (GNUNET_ERROR_TYPE_INFO, " accept for %s (key %s)\n", | 374 | "Regex result accept for %s (key %s)\n", |
366 | info->description, GNUNET_h2s(key)); | 375 | info->description, GNUNET_h2s(key)); |
367 | 376 | ||
368 | GNUNET_STATISTICS_update (info->stats, "# regex accepting blocks found", | 377 | GNUNET_STATISTICS_update (info->stats, |
378 | "# regex accepting blocks found", | ||
369 | 1, GNUNET_NO); | 379 | 1, GNUNET_NO); |
370 | GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found", | 380 | GNUNET_STATISTICS_update (info->stats, |
381 | "# regex accepting block bytes found", | ||
371 | size, GNUNET_NO); | 382 | size, GNUNET_NO); |
372 | GNUNET_CRYPTO_hash (&block->public_key, | 383 | GNUNET_CRYPTO_hash (&block->public_key, |
373 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded), | 384 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded), |
@@ -392,8 +403,9 @@ regex_find_path (const struct GNUNET_HashCode *key, | |||
392 | { | 403 | { |
393 | struct GNUNET_DHT_GetHandle *get_h; | 404 | struct GNUNET_DHT_GetHandle *get_h; |
394 | 405 | ||
395 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n"); | 406 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
396 | LOG (GNUNET_ERROR_TYPE_INFO, " find accept for %s\n", GNUNET_h2s (key)); | 407 | "regex finds path for %s\n", |
408 | GNUNET_h2s (key)); | ||
397 | get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ | 409 | get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ |
398 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ | 410 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ |
399 | key, /* key to search */ | 411 | key, /* key to search */ |
@@ -440,40 +452,24 @@ dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
440 | const struct RegexBlock *block = data; | 452 | const struct RegexBlock *block = data; |
441 | struct RegexSearchContext *ctx = cls; | 453 | struct RegexSearchContext *ctx = cls; |
442 | struct REGEX_INTERNAL_Search *info = ctx->info; | 454 | struct REGEX_INTERNAL_Search *info = ctx->info; |
443 | void *copy; | ||
444 | size_t len; | 455 | size_t len; |
445 | char *datastore; | 456 | struct Result *copy; |
446 | 457 | ||
447 | #if DEBUG_DHT | 458 | LOG (GNUNET_ERROR_TYPE_INFO, |
448 | if ( (NULL != put_path) && | 459 | "DHT GET result for %s (%s)\n", |
449 | (0 != put_path_length) ) | 460 | GNUNET_h2s (key), ctx->info->description); |
450 | { | 461 | copy = GNUNET_malloc (sizeof (struct Result) + size); |
451 | datastore = GNUNET_strdup (GNUNET_i2s (&put_path[put_path_length - 1])); | 462 | copy->size = size; |
452 | } | 463 | copy->data = ©[1]; |
453 | else | 464 | memcpy (©[1], block, size); |
454 | { | 465 | GNUNET_break (GNUNET_OK == |
455 | GNUNET_asprintf (&datastore, "?? %u/%u", put_path_length, get_path_length); | 466 | GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, |
456 | } | 467 | key, copy, |
457 | #else | 468 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); |
458 | datastore = GNUNET_strdup ("N/A"); | ||
459 | #endif | ||
460 | |||
461 | LOG (GNUNET_ERROR_TYPE_INFO, " DHT GET result for %s (%s) at %s\n", | ||
462 | GNUNET_h2s (key), ctx->info->description, datastore); | ||
463 | GNUNET_free (datastore); | ||
464 | |||
465 | copy = GNUNET_malloc (size); | ||
466 | memcpy (copy, block, size); | ||
467 | GNUNET_break ( | ||
468 | GNUNET_OK == | ||
469 | GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, | ||
470 | key, copy, | ||
471 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) | ||
472 | ); | ||
473 | len = strlen (info->description); | 469 | len = strlen (info->description); |
474 | if (len == ctx->position) // String processed | 470 | if (len == ctx->position) // String processed |
475 | { | 471 | { |
476 | if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block)) | 472 | if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block, size)) |
477 | { | 473 | { |
478 | regex_find_path (key, ctx); | 474 | regex_find_path (key, ctx); |
479 | } | 475 | } |
@@ -501,22 +497,25 @@ regex_result_iterator (void *cls, | |||
501 | const struct GNUNET_HashCode * key, | 497 | const struct GNUNET_HashCode * key, |
502 | void *value) | 498 | void *value) |
503 | { | 499 | { |
504 | struct RegexBlock *block = value; | 500 | struct Result *result = value; |
501 | const struct RegexBlock *block = result->data; | ||
505 | struct RegexSearchContext *ctx = cls; | 502 | struct RegexSearchContext *ctx = cls; |
506 | 503 | ||
507 | if ( (GNUNET_YES == | 504 | if ( (GNUNET_YES == |
508 | GNUNET_BLOCK_is_accepting (block)) && | 505 | GNUNET_BLOCK_is_accepting (block, result->size)) && |
509 | (ctx->position == strlen (ctx->info->description)) ) | 506 | (ctx->position == strlen (ctx->info->description)) ) |
510 | { | 507 | { |
511 | LOG (GNUNET_ERROR_TYPE_INFO, " * Found accepting known block\n"); | 508 | LOG (GNUNET_ERROR_TYPE_INFO, |
509 | "Found accepting known block\n"); | ||
512 | regex_find_path (key, ctx); | 510 | regex_find_path (key, ctx); |
513 | return GNUNET_YES; // We found an accept state! | 511 | return GNUNET_YES; // We found an accept state! |
514 | } | 512 | } |
515 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", | 513 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
516 | ctx->position, strlen(ctx->info->description), | 514 | "* %u, %u, [%u]\n", |
517 | GNUNET_BLOCK_is_accepting (block)); | 515 | ctx->position, |
518 | 516 | strlen (ctx->info->description), | |
519 | regex_next_edge (block, SIZE_MAX, ctx); | 517 | GNUNET_BLOCK_is_accepting (block, result->size)); |
518 | regex_next_edge (block, result->size, ctx); | ||
520 | 519 | ||
521 | GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated", | 520 | GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated", |
522 | 1, GNUNET_NO); | 521 | 1, GNUNET_NO); |
@@ -548,37 +547,28 @@ regex_edge_iterator (void *cls, | |||
548 | 547 | ||
549 | GNUNET_STATISTICS_update (info->stats, "# regex edges iterated", | 548 | GNUNET_STATISTICS_update (info->stats, "# regex edges iterated", |
550 | 1, GNUNET_NO); | 549 | 1, GNUNET_NO); |
551 | |||
552 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* Start of regex edge iterator\n"); | ||
553 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* descr : %s\n", info->description); | ||
554 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* posit : %u\n", ctx->position); | ||
555 | current = &info->description[ctx->position]; | 550 | current = &info->description[ctx->position]; |
556 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* currt : %s\n", current); | ||
557 | current_len = strlen (info->description) - ctx->position; | 551 | current_len = strlen (info->description) - ctx->position; |
558 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* ctlen : %u\n", current_len); | ||
559 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* tklen : %u\n", len); | ||
560 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* token : %.*s\n", len, token); | ||
561 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* nextk : %s\n", GNUNET_h2s(key)); | ||
562 | if (len > current_len) | 552 | if (len > current_len) |
563 | { | 553 | { |
564 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token too long, END\n"); | 554 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Token too long, END\n"); |
565 | return GNUNET_YES; // Token too long, wont match | 555 | return GNUNET_YES; |
566 | } | 556 | } |
567 | if (0 != strncmp (current, token, len)) | 557 | if (0 != strncmp (current, token, len)) |
568 | { | 558 | { |
569 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token doesn't match, END\n"); | 559 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Token doesn't match, END\n"); |
570 | return GNUNET_YES; // Token doesn't match | 560 | return GNUNET_YES; |
571 | } | 561 | } |
572 | 562 | ||
573 | if (len > ctx->longest_match) | 563 | if (len > ctx->longest_match) |
574 | { | 564 | { |
575 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token is longer, KEEP\n"); | 565 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is longer, KEEP\n"); |
576 | ctx->longest_match = len; | 566 | ctx->longest_match = len; |
577 | ctx->hash = *key; | 567 | ctx->hash = *key; |
578 | } | 568 | } |
579 | else | 569 | else |
580 | { | 570 | { |
581 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* Token is not longer, IGNORE\n"); | 571 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is not longer, IGNORE\n"); |
582 | } | 572 | } |
583 | 573 | ||
584 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); | 574 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); |
@@ -592,8 +582,6 @@ regex_edge_iterator (void *cls, | |||
592 | * @param block Block found in the DHT. | 582 | * @param block Block found in the DHT. |
593 | * @param size Size of the block. | 583 | * @param size Size of the block. |
594 | * @param ctx Context of the search. | 584 | * @param ctx Context of the search. |
595 | * | ||
596 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
597 | */ | 585 | */ |
598 | static void | 586 | static void |
599 | regex_next_edge (const struct RegexBlock *block, | 587 | regex_next_edge (const struct RegexBlock *block, |
@@ -611,13 +599,14 @@ regex_next_edge (const struct RegexBlock *block, | |||
611 | * among tokens in the given block */ | 599 | * among tokens in the given block */ |
612 | ctx->longest_match = 0; | 600 | ctx->longest_match = 0; |
613 | result = REGEX_BLOCK_iterate (block, size, | 601 | result = REGEX_BLOCK_iterate (block, size, |
614 | ®ex_edge_iterator, ctx); | 602 | ®ex_edge_iterator, ctx); |
615 | GNUNET_break (GNUNET_OK == result); | 603 | GNUNET_break (GNUNET_OK == result); |
616 | 604 | ||
617 | /* Did anything match? */ | 605 | /* Did anything match? */ |
618 | if (0 == ctx->longest_match) | 606 | if (0 == ctx->longest_match) |
619 | { | 607 | { |
620 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no match in block\n"); | 608 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
609 | "no match in block\n"); | ||
621 | return; | 610 | return; |
622 | } | 611 | } |
623 | 612 | ||
@@ -631,7 +620,8 @@ regex_next_edge (const struct RegexBlock *block, | |||
631 | if (GNUNET_YES == | 620 | if (GNUNET_YES == |
632 | GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash)) | 621 | GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash)) |
633 | { | 622 | { |
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, "* GET for %s running, END\n", | 623 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
624 | "GET for %s running, END\n", | ||
635 | GNUNET_h2s (hash)); | 625 | GNUNET_h2s (hash)); |
636 | GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, | 626 | GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, |
637 | hash, | 627 | hash, |
@@ -643,8 +633,9 @@ regex_next_edge (const struct RegexBlock *block, | |||
643 | GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed", | 633 | GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed", |
644 | 1, GNUNET_NO); | 634 | 1, GNUNET_NO); |
645 | 635 | ||
646 | /* Start search in DHT */ | 636 | LOG (GNUNET_ERROR_TYPE_INFO, |
647 | LOG (GNUNET_ERROR_TYPE_INFO, " looking for %s\n", GNUNET_h2s (hash)); | 637 | "looking for %s\n", |
638 | GNUNET_h2s (hash)); | ||
648 | rest = &new_ctx->info->description[new_ctx->position]; | 639 | rest = &new_ctx->info->description[new_ctx->position]; |
649 | get_h = | 640 | get_h = |
650 | GNUNET_DHT_get_start (info->dht, /* handle */ | 641 | GNUNET_DHT_get_start (info->dht, /* handle */ |
@@ -653,9 +644,7 @@ regex_next_edge (const struct RegexBlock *block, | |||
653 | DHT_REPLICATION, /* replication level */ | 644 | DHT_REPLICATION, /* replication level */ |
654 | DHT_OPT, | 645 | DHT_OPT, |
655 | rest, /* xquery */ | 646 | rest, /* xquery */ |
656 | // FIXME add BLOOMFILTER to exclude filtered peers | 647 | strlen (rest) + 1, /* xquery bits */ |
657 | strlen(rest) + 1, /* xquery bits */ | ||
658 | // FIXME add BLOOMFILTER SIZE | ||
659 | &dht_get_string_handler, new_ctx); | 648 | &dht_get_string_handler, new_ctx); |
660 | if (GNUNET_OK != | 649 | if (GNUNET_OK != |
661 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | 650 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, |
@@ -669,6 +658,20 @@ regex_next_edge (const struct RegexBlock *block, | |||
669 | } | 658 | } |
670 | 659 | ||
671 | 660 | ||
661 | /** | ||
662 | * Search for a peer offering a regex matching certain string in the DHT. | ||
663 | * The search runs until REGEX_INTERNAL_search_cancel is called, even if results | ||
664 | * are returned. | ||
665 | * | ||
666 | * @param dht An existing and valid DHT service handle. | ||
667 | * @param string String to match against the regexes in the DHT. | ||
668 | * @param callback Callback for found peers. | ||
669 | * @param callback_cls Closure for @c callback. | ||
670 | * @param stats Optional statistics handle to report usage. Can be NULL. | ||
671 | * | ||
672 | * @return Handle to stop search and free resources. | ||
673 | * Must be freed by calling REGEX_INTERNAL_search_cancel. | ||
674 | */ | ||
672 | struct REGEX_INTERNAL_Search * | 675 | struct REGEX_INTERNAL_Search * |
673 | REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, | 676 | REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, |
674 | const char *string, | 677 | const char *string, |
@@ -703,8 +706,10 @@ REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, | |||
703 | ctx->position = size; | 706 | ctx->position = size; |
704 | ctx->info = h; | 707 | ctx->info = h; |
705 | GNUNET_array_append (h->contexts, h->n_contexts, ctx); | 708 | GNUNET_array_append (h->contexts, h->n_contexts, ctx); |
706 | LOG (GNUNET_ERROR_TYPE_DEBUG, " consumed %u bits out of %u\n", size, len); | 709 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
707 | LOG (GNUNET_ERROR_TYPE_INFO, " looking for %s\n", GNUNET_h2s (&key)); | 710 | "consumed %u bits out of %u, now looking for %s\n", |
711 | size, len, | ||
712 | GNUNET_h2s (&key)); | ||
708 | 713 | ||
709 | /* Start search in DHT */ | 714 | /* Start search in DHT */ |
710 | get_h = GNUNET_DHT_get_start (h->dht, /* handle */ | 715 | 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 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file regex/test_regex_api.c | ||
22 | * @brief base test case for regex api (and DHT functions) | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_testing_lib.h" | ||
28 | #include "gnunet_regex_service.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * How long until we really give up on a particular testcase portion? | ||
33 | */ | ||
34 | #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) | ||
35 | |||
36 | /** | ||
37 | * How long until we give up on any particular operation (and retry)? | ||
38 | */ | ||
39 | #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) | ||
40 | |||
41 | |||
42 | static struct GNUNET_REGEX_Announcement *a; | ||
43 | |||
44 | static struct GNUNET_REGEX_Search *s; | ||
45 | |||
46 | static int ok = 1; | ||
47 | |||
48 | static GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
49 | |||
50 | |||
51 | static void | ||
52 | end (void *cls, | ||
53 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
54 | { | ||
55 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
56 | GNUNET_REGEX_announce_cancel (a); | ||
57 | a = NULL; | ||
58 | GNUNET_REGEX_search_cancel (s); | ||
59 | s = NULL; | ||
60 | ok = 0; | ||
61 | } | ||
62 | |||
63 | |||
64 | static void | ||
65 | end_badly () | ||
66 | { | ||
67 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
68 | FPRINTF (stderr, "%s", "Testcase failed (timeout).\n"); | ||
69 | GNUNET_REGEX_announce_cancel (a); | ||
70 | a = NULL; | ||
71 | GNUNET_REGEX_search_cancel (s); | ||
72 | s = NULL; | ||
73 | ok = 1; | ||
74 | } | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Search callback function, invoked for every result that was found. | ||
79 | * | ||
80 | * @param cls Closure provided in GNUNET_REGEX_search. | ||
81 | * @param id Peer providing a regex that matches the string. | ||
82 | * @param get_path Path of the get request. | ||
83 | * @param get_path_length Lenght of get_path. | ||
84 | * @param put_path Path of the put request. | ||
85 | * @param put_path_length Length of the put_path. | ||
86 | */ | ||
87 | static void | ||
88 | found_cb (void *cls, | ||
89 | const struct GNUNET_PeerIdentity *id, | ||
90 | const struct GNUNET_PeerIdentity *get_path, | ||
91 | unsigned int get_path_length, | ||
92 | const struct GNUNET_PeerIdentity *put_path, | ||
93 | unsigned int put_path_length) | ||
94 | { | ||
95 | GNUNET_SCHEDULER_cancel (die_task); | ||
96 | die_task = | ||
97 | GNUNET_SCHEDULER_add_now (&end, NULL); | ||
98 | } | ||
99 | |||
100 | |||
101 | static void | ||
102 | run (void *cls, | ||
103 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
104 | struct GNUNET_TESTING_Peer *peer) | ||
105 | { | ||
106 | die_task = | ||
107 | GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, | ||
108 | &end_badly, NULL); | ||
109 | a = GNUNET_REGEX_announce (cfg, | ||
110 | "my long prefix - hello world(0|1)*", | ||
111 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
112 | 5), | ||
113 | 1); | ||
114 | s = GNUNET_REGEX_search (cfg, | ||
115 | "my long prefix - hello world0101", | ||
116 | &found_cb, NULL); | ||
117 | } | ||
118 | |||
119 | |||
120 | int | ||
121 | main (int argc, char *argv[]) | ||
122 | { | ||
123 | if (0 != GNUNET_TESTING_peer_run ("test-regex-api", | ||
124 | "test_regex_api_data.conf", | ||
125 | &run, NULL)) | ||
126 | return 1; | ||
127 | return ok; | ||
128 | } | ||
129 | |||
130 | /* end of test_regex_api.c */ | ||