aboutsummaryrefslogtreecommitdiff
path: root/src/regex
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-07-02 14:38:54 +0000
committerChristian Grothoff <christian@grothoff.org>2013-07-02 14:38:54 +0000
commit15a8471c0edc4134f57c19884c033a63f49a04dd (patch)
tree4465bb0b1198f1869163706e6cfeeaba5ff3fabf /src/regex
parent2a453cf6aec60af36f655bd053847ab15ff7ae8f (diff)
downloadgnunet-15a8471c0edc4134f57c19884c033a63f49a04dd.tar.gz
gnunet-15a8471c0edc4134f57c19884c033a63f49a04dd.zip
-implementing regex test
Diffstat (limited to 'src/regex')
-rw-r--r--src/regex/Makefile.am13
-rw-r--r--src/regex/gnunet-service-regex.c15
-rw-r--r--src/regex/perf-regex.c64
-rw-r--r--src/regex/regex_api.c16
-rw-r--r--src/regex/regex_block_lib.c14
-rw-r--r--src/regex/regex_block_lib.h4
-rw-r--r--src/regex/regex_internal.c36
-rw-r--r--src/regex/regex_internal_dht.c227
-rw-r--r--src/regex/test_regex_api.c130
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
170if ENABLE_TEST_RUN 171if 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
184test_regex_api_SOURCES = \
185 test_regex_api.c
186test_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
183test_regex_iterate_api_SOURCES = \ 191test_regex_iterate_api_SOURCES = \
184 test_regex_iterate_api.c 192 test_regex_iterate_api.c
185test_regex_iterate_api_LDADD = -lm \ 193test_regex_iterate_api_LDADD = -lm \
@@ -208,4 +216,5 @@ test_regex_graph_api_LDADD = -lm \
208 216
209 217
210EXTRA_DIST = \ 218EXTRA_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
32static const char *exe;
33
34static void
35usage(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 */
50static void 44static void
51iter (void *cls, 45print_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
68static void
69print_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 (&regex, "GNVPN-0001-PAD(%s)(0|1)*", buffer); 104 GNUNET_asprintf (&regex, "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
324GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) 325GNUNET_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 */
101int 102int
102GNUNET_BLOCK_is_accepting (const struct RegexBlock *block) 103GNUNET_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 */
161int 162int
162GNUNET_BLOCK_is_accepting (const struct RegexBlock *block); 163GNUNET_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 */
2135void 2135static void
2136dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, 2136dfa_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 */
2185void 2185static void
2186dfa_add_multi_strides (void *cls, const unsigned int count, 2186dfa_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
3310REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, 3306REGEX_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
208REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h) 201REGEX_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, &regex_iterator, h); 206 h->regex);
207 REGEX_INTERNAL_iterate_all_edges (h->dfa,
208 &regex_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 */
262struct 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 */
269struct REGEX_INTERNAL_Search 280struct 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 */
328static void 337static void
329regex_next_edge (const struct RegexBlock *block, 338regex_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 = &copy[1];
453 else 464 memcpy (&copy[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 */
598static void 586static void
599regex_next_edge (const struct RegexBlock *block, 587regex_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 &regex_edge_iterator, ctx); 602 &regex_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 */
672struct REGEX_INTERNAL_Search * 675struct REGEX_INTERNAL_Search *
673REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, 676REGEX_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
42static struct GNUNET_REGEX_Announcement *a;
43
44static struct GNUNET_REGEX_Search *s;
45
46static int ok = 1;
47
48static GNUNET_SCHEDULER_TaskIdentifier die_task;
49
50
51static void
52end (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
64static void
65end_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 */
87static void
88found_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
101static void
102run (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
120int
121main (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 */