diff options
author | Bart Polot <bart@net.in.tum.de> | 2013-01-17 17:09:37 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2013-01-17 17:09:37 +0000 |
commit | 47cb85c43071a16ec899e7f8fb45b3eec39895ec (patch) | |
tree | 4b3ec6dd6eb72488826053d0ce9fc45d26df3df6 /src | |
parent | 37a8306064f1fe08c1471c46a3cd913cd22f8a60 (diff) | |
download | gnunet-47cb85c43071a16ec899e7f8fb45b3eec39895ec.tar.gz gnunet-47cb85c43071a16ec899e7f8fb45b3eec39895ec.zip |
Move regex DHT integration from mesh to regex
Diffstat (limited to 'src')
-rw-r--r-- | src/include/block_regex.h (renamed from src/include/block_mesh.h) | 53 | ||||
-rw-r--r-- | src/include/gnunet_block_lib.h | 4 | ||||
-rw-r--r-- | src/include/gnunet_regex_lib.h | 101 | ||||
-rw-r--r-- | src/mesh/Makefile.am | 19 | ||||
-rw-r--r-- | src/mesh/gnunet-service-mesh-new.c | 2147 | ||||
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 1026 | ||||
-rw-r--r-- | src/mesh/plugin_block_mesh.c | 91 | ||||
-rw-r--r-- | src/regex/Makefile.am | 42 | ||||
-rw-r--r-- | src/regex/plugin_block_regex.c | 221 | ||||
-rw-r--r-- | src/regex/regex.c | 3 | ||||
-rw-r--r-- | src/regex/regex_block_lib.c (renamed from src/mesh/mesh_block_lib.c) | 42 | ||||
-rw-r--r-- | src/regex/regex_block_lib.h (renamed from src/mesh/mesh_block_lib.h) | 36 | ||||
-rw-r--r-- | src/regex/regex_dht.c | 754 |
13 files changed, 2487 insertions, 2052 deletions
diff --git a/src/include/block_mesh.h b/src/include/block_regex.h index f051e6666..282c626a2 100644 --- a/src/include/block_mesh.h +++ b/src/include/block_regex.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2012,2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -19,37 +19,30 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file include/block_mesh.h | 22 | * @file include/block_regex.h |
23 | * @brief fs block formats (shared between fs and block) | 23 | * @brief regex block formats |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | */ | 25 | */ |
26 | #ifndef BLOCK_MESH_H | 26 | #ifndef BLOCK_REGEX_H |
27 | #define BLOCK_MESH_H | 27 | #define BLOCK_REGEX_H |
28 | |||
29 | #ifdef __cplusplus | ||
30 | extern "C" | ||
31 | { | ||
32 | #if 0 | ||
33 | /* keep Emacsens' auto-indent happy */ | ||
34 | } | ||
35 | #endif | ||
36 | #endif | ||
28 | 37 | ||
29 | #include "gnunet_util_lib.h" | 38 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_mesh_service.h" | ||
31 | #include <stdint.h> | 39 | #include <stdint.h> |
32 | 40 | ||
33 | /** | ||
34 | * @brief peer block (announce peer + type) | ||
35 | */ | ||
36 | struct PBlock | ||
37 | { | ||
38 | /** | ||
39 | * Identity of the peer | ||
40 | */ | ||
41 | struct GNUNET_PeerIdentity id; | ||
42 | |||
43 | /** | ||
44 | * Type of service offered | ||
45 | */ | ||
46 | GNUNET_MESH_ApplicationType type; | ||
47 | }; | ||
48 | 41 | ||
49 | /** | 42 | /** |
50 | * @brief A MeshRegexBlock contains one or more of this struct in the payload. | 43 | * @brief A RegexBlock contains one or more of this struct in the payload. |
51 | */ | 44 | */ |
52 | struct MeshRegexEdge | 45 | struct RegexEdge |
53 | { | 46 | { |
54 | /** | 47 | /** |
55 | * Destination of this edge. | 48 | * Destination of this edge. |
@@ -67,7 +60,7 @@ struct MeshRegexEdge | |||
67 | /** | 60 | /** |
68 | * @brief Block to announce a regex state. | 61 | * @brief Block to announce a regex state. |
69 | */ | 62 | */ |
70 | struct MeshRegexBlock | 63 | struct RegexBlock |
71 | { | 64 | { |
72 | /** | 65 | /** |
73 | * The key of the state. | 66 | * The key of the state. |
@@ -90,13 +83,13 @@ struct MeshRegexBlock | |||
90 | int accepting; | 83 | int accepting; |
91 | 84 | ||
92 | /* char proof[n_proof] */ | 85 | /* char proof[n_proof] */ |
93 | /* struct MeshEdge edges[n_edges] */ | 86 | /* struct RegexEdge edges[n_edges] */ |
94 | }; | 87 | }; |
95 | 88 | ||
96 | /** | 89 | /** |
97 | * @brief Block to announce a peer accepting a state. | 90 | * @brief Block to announce a peer accepting a state. |
98 | */ | 91 | */ |
99 | struct MeshRegexAccept | 92 | struct RegexAccept |
100 | { | 93 | { |
101 | /** | 94 | /** |
102 | * The key of the state. | 95 | * The key of the state. |
@@ -116,4 +109,12 @@ struct MeshRegexAccept | |||
116 | struct GNUNET_PeerIdentity id; | 109 | struct GNUNET_PeerIdentity id; |
117 | 110 | ||
118 | }; | 111 | }; |
112 | |||
113 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
114 | { | ||
115 | #endif | ||
116 | #ifdef __cplusplus | ||
117 | } | ||
118 | #endif | ||
119 | |||
119 | #endif \ No newline at end of file | 120 | #endif \ No newline at end of file |
diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h index cd4b2a0ac..002d5c11b 100644 --- a/src/include/gnunet_block_lib.h +++ b/src/include/gnunet_block_lib.h | |||
@@ -113,12 +113,12 @@ enum GNUNET_BLOCK_Type | |||
113 | /** | 113 | /** |
114 | * Block to store a mesh regex state | 114 | * Block to store a mesh regex state |
115 | */ | 115 | */ |
116 | GNUNET_BLOCK_TYPE_MESH_REGEX = 22, | 116 | GNUNET_BLOCK_TYPE_REGEX = 22, |
117 | 117 | ||
118 | /** | 118 | /** |
119 | * Block to store a mesh regex accepting state | 119 | * Block to store a mesh regex accepting state |
120 | */ | 120 | */ |
121 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT = 23 | 121 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT = 23 |
122 | }; | 122 | }; |
123 | 123 | ||
124 | 124 | ||
diff --git a/src/include/gnunet_regex_lib.h b/src/include/gnunet_regex_lib.h index 105ccee54..ebeb9e50c 100644 --- a/src/include/gnunet_regex_lib.h +++ b/src/include/gnunet_regex_lib.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #define GNUNET_REGEX_LIB_H | 28 | #define GNUNET_REGEX_LIB_H |
29 | 29 | ||
30 | #include "gnunet_util_lib.h" | 30 | #include "gnunet_util_lib.h" |
31 | #include "gnunet_dht_service.h" | ||
32 | #include "gnunet_statistics_service.h" | ||
31 | 33 | ||
32 | #ifdef __cplusplus | 34 | #ifdef __cplusplus |
33 | extern "C" | 35 | extern "C" |
@@ -250,6 +252,105 @@ GNUNET_REGEX_ipv6toregex (const struct in6_addr *ipv6, | |||
250 | 252 | ||
251 | 253 | ||
252 | 254 | ||
255 | /** | ||
256 | * Handle to store cached data about a regex announce. | ||
257 | */ | ||
258 | struct GNUNET_REGEX_announce_handle; | ||
259 | |||
260 | /** | ||
261 | * Handle to store data about a regex search. | ||
262 | */ | ||
263 | struct GNUNET_REGEX_search_handle; | ||
264 | |||
265 | /** | ||
266 | * Announce a regular expression: put all states of the automaton in the DHT. | ||
267 | * Does not free resources, must call GNUNET_REGEX_announce_cancel for that. | ||
268 | * | ||
269 | * @param dht An existing and valid DHT service handle. | ||
270 | * @param id ID to announce as provider of regex. Own ID in most cases. | ||
271 | * @param regex Regular expression to announce. | ||
272 | * @param compression How many characters per edge can we squeeze? | ||
273 | * @param stats Optional statistics handle to report usage. Can be NULL. | ||
274 | * | ||
275 | * @return Handle to reuse o free cached resources. | ||
276 | * Must be freed by calling GNUNET_REGEX_announce_cancel. | ||
277 | */ | ||
278 | struct GNUNET_REGEX_announce_handle * | ||
279 | GNUNET_REGEX_announce (struct GNUNET_DHT_Handle *dht, | ||
280 | struct GNUNET_PeerIdentity *id, | ||
281 | const char *regex, | ||
282 | uint16_t compression, | ||
283 | struct GNUNET_STATISTICS_Handle *stats); | ||
284 | |||
285 | /** | ||
286 | * Announce again a regular expression previously announced. | ||
287 | * Does use caching to speed up process. | ||
288 | * | ||
289 | * @param h Handle returned by a previous GNUNET_REGEX_announce call. | ||
290 | */ | ||
291 | void | ||
292 | GNUNET_REGEX_reannounce (struct GNUNET_REGEX_announce_handle *h); | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Clear all cached data used by a regex announce. | ||
297 | * Does not close DHT connection. | ||
298 | * | ||
299 | * @param h Handle returned by a previous GNUNET_REGEX_announce call. | ||
300 | */ | ||
301 | void | ||
302 | GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_announce_handle *h); | ||
303 | |||
304 | |||
305 | /** | ||
306 | * Search callback function. | ||
307 | * | ||
308 | * @param cls Closure provided in GNUNET_REGEX_search. | ||
309 | * @param id Peer providing a regex that matches the string. | ||
310 | * @param get_path Path of the get request. | ||
311 | * @param get_path_length Lenght of get_path. | ||
312 | * @param put_path Path of the put request. | ||
313 | * @param put_path_length Length of the put_path. | ||
314 | */ | ||
315 | typedef void (*GNUNET_REGEX_Found)(void *cls, | ||
316 | const struct GNUNET_PeerIdentity *id, | ||
317 | const struct GNUNET_PeerIdentity *get_path, | ||
318 | unsigned int get_path_length, | ||
319 | const struct GNUNET_PeerIdentity *put_path, | ||
320 | unsigned int put_path_length); | ||
321 | |||
322 | |||
323 | /** | ||
324 | * Search for a peer offering a regex matching certain string in the DHT. | ||
325 | * The search runs until GNUNET_REGEX_search_cancel is called, even if results | ||
326 | * are returned. | ||
327 | * | ||
328 | * @param dht An existing and valid DHT service handle. | ||
329 | * @param string String to match against the regexes in the DHT. | ||
330 | * @param callback Callback for found peers. | ||
331 | * @param callback_cls Closure for @c callback. | ||
332 | * @param stats Optional statistics handle to report usage. Can be NULL. | ||
333 | * | ||
334 | * @return Handle to stop search and free resources. | ||
335 | * Must be freed by calling GNUNET_REGEX_search_cancel. | ||
336 | */ | ||
337 | struct GNUNET_REGEX_search_handle * | ||
338 | GNUNET_REGEX_search (struct GNUNET_DHT_Handle *dht, | ||
339 | const char *string, | ||
340 | GNUNET_REGEX_Found callback, | ||
341 | void *callback_cls, | ||
342 | struct GNUNET_STATISTICS_Handle *stats); | ||
343 | |||
344 | /** | ||
345 | * Stop search and free all data used by a GNUNET_REGEX_search call. | ||
346 | * Does not close DHT connection. | ||
347 | * | ||
348 | * @param h Handle returned by a previous GNUNET_REGEX_search call. | ||
349 | */ | ||
350 | void | ||
351 | GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_search_handle *h); | ||
352 | |||
353 | |||
253 | #if 0 /* keep Emacsens' auto-indent happy */ | 354 | #if 0 /* keep Emacsens' auto-indent happy */ |
254 | { | 355 | { |
255 | #endif | 356 | #endif |
diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am index 41f8c0444..5db9868ab 100644 --- a/src/mesh/Makefile.am +++ b/src/mesh/Makefile.am | |||
@@ -27,8 +27,7 @@ bin_PROGRAMS = \ | |||
27 | gnunet-mesh | 27 | gnunet-mesh |
28 | 28 | ||
29 | lib_LTLIBRARIES = \ | 29 | lib_LTLIBRARIES = \ |
30 | libgnunetmesh.la \ | 30 | libgnunetmesh.la |
31 | libgnunetmeshblock.la | ||
32 | 31 | ||
33 | plugin_LTLIBRARIES = \ | 32 | plugin_LTLIBRARIES = \ |
34 | libgnunet_plugin_block_mesh.la | 33 | libgnunet_plugin_block_mesh.la |
@@ -36,13 +35,11 @@ plugin_LTLIBRARIES = \ | |||
36 | libgnunet_plugin_block_mesh_la_SOURCES = \ | 35 | libgnunet_plugin_block_mesh_la_SOURCES = \ |
37 | plugin_block_mesh.c | 36 | plugin_block_mesh.c |
38 | libgnunet_plugin_block_mesh_la_LIBADD = \ | 37 | libgnunet_plugin_block_mesh_la_LIBADD = \ |
39 | $(top_builddir)/src/mesh/libgnunetmeshblock.la \ | ||
40 | $(top_builddir)/src/block/libgnunetblock.la \ | 38 | $(top_builddir)/src/block/libgnunetblock.la \ |
41 | $(top_builddir)/src/util/libgnunetutil.la | 39 | $(top_builddir)/src/util/libgnunetutil.la |
42 | libgnunet_plugin_block_mesh_la_LDFLAGS = \ | 40 | libgnunet_plugin_block_mesh_la_LDFLAGS = \ |
43 | $(GN_PLUGIN_LDFLAGS) | 41 | $(GN_PLUGIN_LDFLAGS) |
44 | libgnunet_plugin_block_mesh_la_DEPENDENCIES = \ | 42 | libgnunet_plugin_block_mesh_la_DEPENDENCIES = \ |
45 | libgnunetmeshblock.la \ | ||
46 | $(top_builddir)/src/block/libgnunetblock.la \ | 43 | $(top_builddir)/src/block/libgnunetblock.la \ |
47 | $(top_builddir)/src/util/libgnunetutil.la | 44 | $(top_builddir)/src/util/libgnunetutil.la |
48 | 45 | ||
@@ -56,16 +53,6 @@ libgnunetmesh_la_LDFLAGS = \ | |||
56 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 53 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
57 | -version-info 2:0:1 | 54 | -version-info 2:0:1 |
58 | 55 | ||
59 | libgnunetmeshblock_la_SOURCES = \ | ||
60 | mesh_block_lib.c mesh_block_lib.h | ||
61 | libgnunetmeshblock_la_LIBADD = \ | ||
62 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
63 | $(XLIB) \ | ||
64 | $(LTLIBINTL) | ||
65 | libgnunetmeshblock_la_LDFLAGS = \ | ||
66 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
67 | -version-info 2:0:0 | ||
68 | |||
69 | gnunet_service_mesh_SOURCES = \ | 56 | gnunet_service_mesh_SOURCES = \ |
70 | gnunet-service-mesh.c \ | 57 | gnunet-service-mesh.c \ |
71 | mesh_tunnel_tree.c mesh_tunnel_tree.h \ | 58 | mesh_tunnel_tree.c mesh_tunnel_tree.h \ |
@@ -77,7 +64,6 @@ gnunet_service_mesh_LDADD = \ | |||
77 | $(top_builddir)/src/dht/libgnunetdht.la \ | 64 | $(top_builddir)/src/dht/libgnunetdht.la \ |
78 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 65 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
79 | $(top_builddir)/src/block/libgnunetblock.la \ | 66 | $(top_builddir)/src/block/libgnunetblock.la \ |
80 | $(top_builddir)/src/mesh/libgnunetmeshblock.la \ | ||
81 | $(top_builddir)/src/regex/libgnunetregex.la | 67 | $(top_builddir)/src/regex/libgnunetregex.la |
82 | gnunet_service_mesh_DEPENDENCIES = \ | 68 | gnunet_service_mesh_DEPENDENCIES = \ |
83 | $(top_builddir)/src/util/libgnunetutil.la \ | 69 | $(top_builddir)/src/util/libgnunetutil.la \ |
@@ -85,7 +71,6 @@ gnunet_service_mesh_DEPENDENCIES = \ | |||
85 | $(top_builddir)/src/dht/libgnunetdht.la \ | 71 | $(top_builddir)/src/dht/libgnunetdht.la \ |
86 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 72 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
87 | $(top_builddir)/src/block/libgnunetblock.la \ | 73 | $(top_builddir)/src/block/libgnunetblock.la \ |
88 | libgnunetmeshblock.la \ | ||
89 | $(top_builddir)/src/regex/libgnunetregex.la | 74 | $(top_builddir)/src/regex/libgnunetregex.la |
90 | if LINUX | 75 | if LINUX |
91 | gnunet_service_mesh_LDFLAGS = -lrt | 76 | gnunet_service_mesh_LDFLAGS = -lrt |
@@ -110,7 +95,6 @@ gnunet_service_mesh_new_LDADD = \ | |||
110 | $(top_builddir)/src/dht/libgnunetdht.la \ | 95 | $(top_builddir)/src/dht/libgnunetdht.la \ |
111 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 96 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
112 | $(top_builddir)/src/block/libgnunetblock.la \ | 97 | $(top_builddir)/src/block/libgnunetblock.la \ |
113 | $(top_builddir)/src/mesh/libgnunetmeshblock.la \ | ||
114 | $(top_builddir)/src/regex/libgnunetregex.la | 98 | $(top_builddir)/src/regex/libgnunetregex.la |
115 | gnunet_service_mesh_new_DEPENDENCIES = \ | 99 | gnunet_service_mesh_new_DEPENDENCIES = \ |
116 | $(top_builddir)/src/util/libgnunetutil.la \ | 100 | $(top_builddir)/src/util/libgnunetutil.la \ |
@@ -118,7 +102,6 @@ gnunet_service_mesh_new_DEPENDENCIES = \ | |||
118 | $(top_builddir)/src/dht/libgnunetdht.la \ | 102 | $(top_builddir)/src/dht/libgnunetdht.la \ |
119 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 103 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
120 | $(top_builddir)/src/block/libgnunetblock.la \ | 104 | $(top_builddir)/src/block/libgnunetblock.la \ |
121 | libgnunetmeshblock.la \ | ||
122 | $(top_builddir)/src/regex/libgnunetregex.la | 105 | $(top_builddir)/src/regex/libgnunetregex.la |
123 | if LINUX | 106 | if LINUX |
124 | gnunet_service_mesh_new_LDFLAGS = -lrt | 107 | gnunet_service_mesh_new_LDFLAGS = -lrt |
diff --git a/src/mesh/gnunet-service-mesh-new.c b/src/mesh/gnunet-service-mesh-new.c index 2e8b094bd..82bfc5e8d 100644 --- a/src/mesh/gnunet-service-mesh-new.c +++ b/src/mesh/gnunet-service-mesh-new.c | |||
@@ -35,7 +35,6 @@ | |||
35 | * - MAIN FUNCTIONS (main & run) | 35 | * - MAIN FUNCTIONS (main & run) |
36 | * | 36 | * |
37 | * TODO: | 37 | * TODO: |
38 | * - Backport r24764, r24767. | ||
39 | * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message! | 38 | * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message! |
40 | * - partial disconnect reporting -- same as error reporting? | 39 | * - partial disconnect reporting -- same as error reporting? |
41 | * - add ping message | 40 | * - add ping message |
@@ -51,7 +50,6 @@ | |||
51 | #include "mesh_protocol.h" | 50 | #include "mesh_protocol.h" |
52 | #include "mesh_tunnel_tree.h" | 51 | #include "mesh_tunnel_tree.h" |
53 | #include "block_mesh.h" | 52 | #include "block_mesh.h" |
54 | #include "mesh_block_lib.h" | ||
55 | #include "gnunet_dht_service.h" | 53 | #include "gnunet_dht_service.h" |
56 | #include "gnunet_statistics_service.h" | 54 | #include "gnunet_statistics_service.h" |
57 | #include "gnunet_regex_lib.h" | 55 | #include "gnunet_regex_lib.h" |
@@ -62,6 +60,10 @@ | |||
62 | #define MESH_DEBUG_CONNECTION GNUNET_NO | 60 | #define MESH_DEBUG_CONNECTION GNUNET_NO |
63 | #define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO | 61 | #define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO |
64 | 62 | ||
63 | #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ | ||
64 | GNUNET_TIME_UNIT_MINUTES,\ | ||
65 | 10) | ||
66 | |||
65 | #if MESH_DEBUG_CONNECTION | 67 | #if MESH_DEBUG_CONNECTION |
66 | #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) | 68 | #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) |
67 | #else | 69 | #else |
@@ -185,8 +187,65 @@ struct MeshRegexDescriptor | |||
185 | * How many characters per edge can we squeeze? | 187 | * How many characters per edge can we squeeze? |
186 | */ | 188 | */ |
187 | uint16_t compression; | 189 | uint16_t compression; |
190 | |||
191 | /** | ||
192 | * Handle to announce the regex. | ||
193 | */ | ||
194 | struct GNUNET_REGEX_announce_handle *h; | ||
188 | }; | 195 | }; |
189 | 196 | ||
197 | |||
198 | /** | ||
199 | * Struct to keep information of searches of services described by a regex | ||
200 | * using a user-provided string service description. | ||
201 | */ | ||
202 | struct MeshRegexSearchInfo | ||
203 | { | ||
204 | /** | ||
205 | * Which tunnel is this for | ||
206 | */ | ||
207 | struct MeshTunnel *t; | ||
208 | |||
209 | /** | ||
210 | * User provided description of the searched service. | ||
211 | */ | ||
212 | char *description; | ||
213 | |||
214 | /** | ||
215 | * Regex search handle. | ||
216 | */ | ||
217 | struct GNUNET_REGEX_search_handle *search_handle; | ||
218 | |||
219 | /** | ||
220 | * Peer that is connecting via connect_by_string. When connected, free ctx. | ||
221 | */ | ||
222 | GNUNET_PEER_Id peer; | ||
223 | |||
224 | /** | ||
225 | * Other peers that are found but not yet being connected to. | ||
226 | */ | ||
227 | GNUNET_PEER_Id *peers; | ||
228 | |||
229 | /** | ||
230 | * Number of elements in peers. | ||
231 | */ | ||
232 | unsigned int n_peers; | ||
233 | |||
234 | /** | ||
235 | * Next peer to try to connect to. | ||
236 | */ | ||
237 | unsigned int i_peer; | ||
238 | |||
239 | /** | ||
240 | * Timeout for a connect attempt. | ||
241 | * When reached, try to connect to a different peer, if any. If not, | ||
242 | * try the same peer again. | ||
243 | */ | ||
244 | GNUNET_SCHEDULER_TaskIdentifier timeout; | ||
245 | |||
246 | }; | ||
247 | |||
248 | |||
190 | /** | 249 | /** |
191 | * Struct containing all info possibly needed to build a package when called | 250 | * Struct containing all info possibly needed to build a package when called |
192 | * back by core. | 251 | * back by core. |
@@ -352,13 +411,18 @@ struct MeshTunnel | |||
352 | */ | 411 | */ |
353 | uint32_t bck_pid; | 412 | uint32_t bck_pid; |
354 | 413 | ||
355 | /** | 414 | /** |
356 | * SKIP value for this tunnel. | 415 | * SKIP value for this tunnel. |
357 | */ | 416 | */ |
358 | uint32_t skip; | 417 | uint32_t skip; |
359 | 418 | ||
360 | /** | 419 | /** |
361 | * MeshTunnelFlowControlInfo of all children, indexed by GNUNET_PEER_Id. | 420 | * Force sending ACK? Flag to allow duplicate ACK on POLL. |
421 | */ | ||
422 | int force_ack; | ||
423 | |||
424 | /** | ||
425 | * MeshTunnelChildInfo of all children, indexed by GNUNET_PEER_Id. | ||
362 | * Contains the Flow Control info: FWD ACK value received, | 426 | * Contains the Flow Control info: FWD ACK value received, |
363 | * last BCK ACK sent, PID and SKIP values. | 427 | * last BCK ACK sent, PID and SKIP values. |
364 | */ | 428 | */ |
@@ -434,7 +498,7 @@ struct MeshTunnel | |||
434 | /** | 498 | /** |
435 | * Flow control info for each client. | 499 | * Flow control info for each client. |
436 | */ | 500 | */ |
437 | struct MeshTunnelFlowControlInfo *clients_fc; | 501 | struct MeshTunnelClientInfo *clients_fc; |
438 | 502 | ||
439 | /** | 503 | /** |
440 | * Number of elements in clients/clients_fc | 504 | * Number of elements in clients/clients_fc |
@@ -482,9 +546,9 @@ struct MeshTunnel | |||
482 | struct GNUNET_DHT_GetHandle *dht_get_type; | 546 | struct GNUNET_DHT_GetHandle *dht_get_type; |
483 | 547 | ||
484 | /** | 548 | /** |
485 | * Initial context of the regex search for a connect_by_string | 549 | * Handle for the regex search for a connect_by_string |
486 | */ | 550 | */ |
487 | struct MeshRegexSearchContext *regex_ctx; | 551 | struct MeshRegexSearchInfo *regex_search; |
488 | 552 | ||
489 | /** | 553 | /** |
490 | * Task to keep the used paths alive | 554 | * Task to keep the used paths alive |
@@ -505,24 +569,28 @@ struct MeshTunnel | |||
505 | * when the queue is empty. | 569 | * when the queue is empty. |
506 | */ | 570 | */ |
507 | int destroy; | 571 | int destroy; |
572 | |||
573 | /** | ||
574 | * Total messages pending for this tunnels, payload or not. | ||
575 | */ | ||
576 | unsigned int pending_messages; | ||
577 | |||
578 | /** | ||
579 | * If the tunnel is empty, destoy it. | ||
580 | */ | ||
581 | GNUNET_SCHEDULER_TaskIdentifier delayed_destroy; | ||
508 | }; | 582 | }; |
509 | 583 | ||
510 | 584 | ||
511 | /** | 585 | /** |
512 | * Flow control info about a node in a tunnel. The node can be a local client | 586 | * Info about a child node in a tunnel, needed to perform flow control. |
513 | * or a remote peer. | ||
514 | */ | 587 | */ |
515 | struct MeshTunnelFlowControlInfo | 588 | struct MeshTunnelChildInfo |
516 | { | 589 | { |
517 | /** | 590 | /** |
518 | * Peer info of the node, NULL if local client. | 591 | * ID of the child node. |
519 | */ | 592 | */ |
520 | struct MeshPeerInfo *peer; | 593 | GNUNET_PEER_Id id; |
521 | |||
522 | /** | ||
523 | * Client info of the node, NULL if remote peer. | ||
524 | */ | ||
525 | struct MeshClient *client; | ||
526 | 594 | ||
527 | /** | 595 | /** |
528 | * SKIP value. | 596 | * SKIP value. |
@@ -530,28 +598,28 @@ struct MeshTunnelFlowControlInfo | |||
530 | uint32_t skip; | 598 | uint32_t skip; |
531 | 599 | ||
532 | /** | 600 | /** |
533 | * Last PID sent. | 601 | * Last sent PID. |
534 | */ | 602 | */ |
535 | uint32_t fwd_pid; | 603 | uint32_t fwd_pid; |
536 | 604 | ||
537 | /** | 605 | /** |
538 | * Last PID received. | 606 | * Last received PID. |
539 | */ | 607 | */ |
540 | uint32_t bck_pid; | 608 | uint32_t bck_pid; |
541 | 609 | ||
542 | /** | 610 | /** |
543 | * Maximum PID they allowed us to send (FWD ACK received). | 611 | * Maximum PID allowed (FWD ACK received). |
544 | */ | 612 | */ |
545 | uint32_t fwd_ack; | 613 | uint32_t fwd_ack; |
546 | 614 | ||
547 | /** | 615 | /** |
548 | * Maximum PID we allowed them to send (BCK ACK sent). | 616 | * Last ACK sent to that child (BCK ACK). |
549 | */ | 617 | */ |
550 | uint32_t bck_ack; | 618 | uint32_t bck_ack; |
551 | 619 | ||
552 | /** | 620 | /** |
553 | * Circular buffer pointing to MeshPeerQueue elements for all | 621 | * Circular buffer pointing to MeshPeerQueue elements for all |
554 | * payload traffic going to this node. | 622 | * payload traffic going to this child. |
555 | * Size determined by the tunnel queue size (@c t->fwd_queue_max). | 623 | * Size determined by the tunnel queue size (@c t->fwd_queue_max). |
556 | */ | 624 | */ |
557 | struct MeshPeerQueue **send_buffer; | 625 | struct MeshPeerQueue **send_buffer; |
@@ -574,10 +642,43 @@ struct MeshTunnelFlowControlInfo | |||
574 | /** | 642 | /** |
575 | * Task to poll peer in case of a stall. | 643 | * Task to poll peer in case of a stall. |
576 | */ | 644 | */ |
577 | GNUNET_SCHEDULER_TaskIdentifier fc_poll; | 645 | GNUNET_SCHEDULER_TaskIdentifier fc_poll; |
646 | |||
647 | /** | ||
648 | * Time to use for next polling call. | ||
649 | */ | ||
650 | struct GNUNET_TIME_Relative fc_poll_time; | ||
651 | }; | ||
652 | |||
653 | |||
654 | /** | ||
655 | * Info about a leaf client of a tunnel, needed to perform flow control. | ||
656 | */ | ||
657 | struct MeshTunnelClientInfo | ||
658 | { | ||
659 | /** | ||
660 | * PID of the last packet sent to the client (FWD). | ||
661 | */ | ||
662 | uint32_t fwd_pid; | ||
663 | |||
664 | /** | ||
665 | * PID of the last packet received from the client (BCK). | ||
666 | */ | ||
667 | uint32_t bck_pid; | ||
668 | |||
669 | /** | ||
670 | * Maximum PID allowed (FWD ACK received). | ||
671 | */ | ||
672 | uint32_t fwd_ack; | ||
673 | |||
674 | /** | ||
675 | * Last ACK sent to that child (BCK ACK). | ||
676 | */ | ||
677 | uint32_t bck_ack; | ||
578 | }; | 678 | }; |
579 | 679 | ||
580 | 680 | ||
681 | |||
581 | /** | 682 | /** |
582 | * Info collected during iteration of child nodes in order to get the ACK value | 683 | * Info collected during iteration of child nodes in order to get the ACK value |
583 | * for a tunnel. | 684 | * for a tunnel. |
@@ -698,107 +799,13 @@ struct MeshClient | |||
698 | */ | 799 | */ |
699 | GNUNET_SCHEDULER_TaskIdentifier regex_announce_task; | 800 | GNUNET_SCHEDULER_TaskIdentifier regex_announce_task; |
700 | 801 | ||
701 | }; | ||
702 | |||
703 | |||
704 | /** | ||
705 | * Struct to keep information of searches of services described by a regex | ||
706 | * using a user-provided string service description. | ||
707 | */ | ||
708 | struct MeshRegexSearchInfo | ||
709 | { | ||
710 | /** | 802 | /** |
711 | * Which tunnel is this for | 803 | * Tmp store for partially retrieved regex. |
712 | */ | ||
713 | struct MeshTunnel *t; | ||
714 | |||
715 | /** | ||
716 | * User provided description of the searched service. | ||
717 | */ | ||
718 | char *description; | ||
719 | |||
720 | /** | ||
721 | * Part of the description already consumed by the search. | ||
722 | */ | 804 | */ |
723 | size_t position; | 805 | char *partial_regex; |
724 | |||
725 | /** | ||
726 | * Running DHT GETs. | ||
727 | */ | ||
728 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; | ||
729 | |||
730 | /** | ||
731 | * Results from running DHT GETs. | ||
732 | */ | ||
733 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; | ||
734 | |||
735 | /** | ||
736 | * Contexts, for each running DHT GET. Free all on end of search. | ||
737 | */ | ||
738 | struct MeshRegexSearchContext **contexts; | ||
739 | |||
740 | /** | ||
741 | * Number of contexts (branches/steps in search). | ||
742 | */ | ||
743 | unsigned int n_contexts; | ||
744 | |||
745 | /** | ||
746 | * Peer that is connecting via connect_by_string. When connected, free ctx. | ||
747 | */ | ||
748 | GNUNET_PEER_Id peer; | ||
749 | |||
750 | /** | ||
751 | * Other peers that are found but not yet being connected to. | ||
752 | */ | ||
753 | GNUNET_PEER_Id *peers; | ||
754 | |||
755 | /** | ||
756 | * Number of elements in peers. | ||
757 | */ | ||
758 | unsigned int n_peers; | ||
759 | |||
760 | /** | ||
761 | * Next peer to try to connect to. | ||
762 | */ | ||
763 | unsigned int i_peer; | ||
764 | |||
765 | /** | ||
766 | * Timeout for a connect attempt. | ||
767 | * When reached, try to connect to a different peer, if any. If not, | ||
768 | * try the same peer again. | ||
769 | */ | ||
770 | GNUNET_SCHEDULER_TaskIdentifier timeout; | ||
771 | 806 | ||
772 | }; | 807 | }; |
773 | 808 | ||
774 | /** | ||
775 | * Struct to keep state of running searches that have consumed a part of | ||
776 | * the inital string. | ||
777 | */ | ||
778 | struct MeshRegexSearchContext | ||
779 | { | ||
780 | /** | ||
781 | * Part of the description already consumed by | ||
782 | * this particular search branch. | ||
783 | */ | ||
784 | size_t position; | ||
785 | |||
786 | /** | ||
787 | * Information about the search. | ||
788 | */ | ||
789 | struct MeshRegexSearchInfo *info; | ||
790 | |||
791 | /** | ||
792 | * We just want to look for one edge, the longer the better. | ||
793 | * Keep its length. | ||
794 | */ | ||
795 | unsigned int longest_match; | ||
796 | |||
797 | /** | ||
798 | * Destination hash of the longest match. | ||
799 | */ | ||
800 | struct GNUNET_HashCode hash; | ||
801 | }; | ||
802 | 809 | ||
803 | /******************************************************************************/ | 810 | /******************************************************************************/ |
804 | /************************ DEBUG FUNCTIONS ****************************/ | 811 | /************************ DEBUG FUNCTIONS ****************************/ |
@@ -878,6 +885,11 @@ static unsigned long long max_tunnels; | |||
878 | */ | 885 | */ |
879 | static unsigned long long max_msgs_queue; | 886 | static unsigned long long max_msgs_queue; |
880 | 887 | ||
888 | /** | ||
889 | * How many peers do we want to remember? | ||
890 | */ | ||
891 | static unsigned long long max_peers; | ||
892 | |||
881 | 893 | ||
882 | /*************************** Static global variables **************************/ | 894 | /*************************** Static global variables **************************/ |
883 | 895 | ||
@@ -1030,56 +1042,15 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1030 | 1042 | ||
1031 | 1043 | ||
1032 | /** | 1044 | /** |
1033 | * Function to process DHT string to regex matching. | 1045 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one |
1034 | * Called on each result obtained for the DHT search. | 1046 | * and insert it in the appropiate structures if the peer is not known yet. |
1035 | * | ||
1036 | * @param cls closure (search context) | ||
1037 | * @param exp when will this value expire | ||
1038 | * @param key key of the result | ||
1039 | * @param get_path path of the get request (not used) | ||
1040 | * @param get_path_length lenght of get_path (not used) | ||
1041 | * @param put_path path of the put request (not used) | ||
1042 | * @param put_path_length length of the put_path (not used) | ||
1043 | * @param type type of the result | ||
1044 | * @param size number of bytes in data | ||
1045 | * @param data pointer to the result data | ||
1046 | * | 1047 | * |
1047 | * TODO: re-issue the request after certain time? cancel after X results? | 1048 | * @param peer Full identity of the peer. |
1048 | */ | ||
1049 | static void | ||
1050 | dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
1051 | const struct GNUNET_HashCode * key, | ||
1052 | const struct GNUNET_PeerIdentity *get_path, | ||
1053 | unsigned int get_path_length, | ||
1054 | const struct GNUNET_PeerIdentity *put_path, | ||
1055 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
1056 | size_t size, const void *data); | ||
1057 | |||
1058 | |||
1059 | /** | ||
1060 | * Function to process DHT string to regex matching. | ||
1061 | * Called on each result obtained for the DHT search. | ||
1062 | * | 1049 | * |
1063 | * @param cls closure (search context) | 1050 | * @return Existing or newly created peer info. |
1064 | * @param exp when will this value expire | ||
1065 | * @param key key of the result | ||
1066 | * @param get_path path of the get request (not used) | ||
1067 | * @param get_path_length lenght of get_path (not used) | ||
1068 | * @param put_path path of the put request (not used) | ||
1069 | * @param put_path_length length of the put_path (not used) | ||
1070 | * @param type type of the result | ||
1071 | * @param size number of bytes in data | ||
1072 | * @param data pointer to the result data | ||
1073 | */ | 1051 | */ |
1074 | static void | 1052 | static struct MeshPeerInfo * |
1075 | dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 1053 | peer_info_get (const struct GNUNET_PeerIdentity *peer); |
1076 | const struct GNUNET_HashCode * key, | ||
1077 | const struct GNUNET_PeerIdentity *get_path, | ||
1078 | unsigned int get_path_length, | ||
1079 | const struct GNUNET_PeerIdentity *put_path, | ||
1080 | unsigned int put_path_length, | ||
1081 | enum GNUNET_BLOCK_Type type, | ||
1082 | size_t size, const void *data); | ||
1083 | 1054 | ||
1084 | 1055 | ||
1085 | /** | 1056 | /** |
@@ -1108,6 +1079,29 @@ peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t); | |||
1108 | 1079 | ||
1109 | 1080 | ||
1110 | /** | 1081 | /** |
1082 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
1083 | * to obtain a local peer -> destination path and interning the peer ids. | ||
1084 | * | ||
1085 | * @return Newly allocated and created path | ||
1086 | */ | ||
1087 | static struct MeshPeerPath * | ||
1088 | path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | ||
1089 | unsigned int get_path_length, | ||
1090 | const struct GNUNET_PeerIdentity *put_path, | ||
1091 | unsigned int put_path_length); | ||
1092 | |||
1093 | |||
1094 | /** | ||
1095 | * Adds a path to the peer_infos of all the peers in the path | ||
1096 | * | ||
1097 | * @param p Path to process. | ||
1098 | * @param confirmed Whether we know if the path works or not. | ||
1099 | */ | ||
1100 | static void | ||
1101 | path_add_to_peers (struct MeshPeerPath *p, int confirmed); | ||
1102 | |||
1103 | |||
1104 | /** | ||
1111 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | 1105 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all |
1112 | * needed rescources. | 1106 | * needed rescources. |
1113 | * If peer already exists, reevaluate shortest path and change if different. | 1107 | * If peer already exists, reevaluate shortest path and change if different. |
@@ -1141,7 +1135,7 @@ tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer); | |||
1141 | * @return tunnel handler, NULL if doesn't exist. | 1135 | * @return tunnel handler, NULL if doesn't exist. |
1142 | */ | 1136 | */ |
1143 | static struct MeshTunnel * | 1137 | static struct MeshTunnel * |
1144 | tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid); | 1138 | tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid); |
1145 | 1139 | ||
1146 | 1140 | ||
1147 | /** | 1141 | /** |
@@ -1192,33 +1186,6 @@ tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c); | |||
1192 | 1186 | ||
1193 | 1187 | ||
1194 | /** | 1188 | /** |
1195 | * Jump to the next edge, with the longest matching token. | ||
1196 | * | ||
1197 | * @param block Block found in the DHT. | ||
1198 | * @param size Size of the block. | ||
1199 | * @param ctx Context of the search. | ||
1200 | * | ||
1201 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1202 | */ | ||
1203 | static void | ||
1204 | regex_next_edge (const struct MeshRegexBlock *block, | ||
1205 | size_t size, | ||
1206 | struct MeshRegexSearchContext *ctx); | ||
1207 | |||
1208 | |||
1209 | /** | ||
1210 | * Find a path to a peer that offers a regex servcie compatible | ||
1211 | * with a given string. | ||
1212 | * | ||
1213 | * @param key The key of the accepting state. | ||
1214 | * @param ctx Context containing info about the string, tunnel, etc. | ||
1215 | */ | ||
1216 | static void | ||
1217 | regex_find_path (const struct GNUNET_HashCode *key, | ||
1218 | struct MeshRegexSearchContext *ctx); | ||
1219 | |||
1220 | |||
1221 | /** | ||
1222 | * @brief Queue and pass message to core when possible. | 1189 | * @brief Queue and pass message to core when possible. |
1223 | * | 1190 | * |
1224 | * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status | 1191 | * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status |
@@ -1279,383 +1246,23 @@ static size_t | |||
1279 | queue_send (void *cls, size_t size, void *buf); | 1246 | queue_send (void *cls, size_t size, void *buf); |
1280 | 1247 | ||
1281 | /******************************************************************************/ | 1248 | /******************************************************************************/ |
1282 | /************************ ITERATORS ****************************/ | 1249 | /************************ REGEX INTEGRATION ****************************/ |
1283 | /******************************************************************************/ | 1250 | /******************************************************************************/ |
1284 | 1251 | ||
1285 | /** | 1252 | /** |
1286 | * Iterator over found existing mesh regex blocks that match an ongoing search. | 1253 | * Cancel a mesh regex search and free resources. |
1287 | * | ||
1288 | * @param cls closure | ||
1289 | * @param key current key code | ||
1290 | * @param value value in the hash map | ||
1291 | * @return GNUNET_YES if we should continue to iterate, | ||
1292 | * GNUNET_NO if not. | ||
1293 | */ | ||
1294 | static int | ||
1295 | regex_result_iterator (void *cls, | ||
1296 | const struct GNUNET_HashCode * key, | ||
1297 | void *value) | ||
1298 | { | ||
1299 | struct MeshRegexBlock *block = value; | ||
1300 | struct MeshRegexSearchContext *ctx = cls; | ||
1301 | |||
1302 | if (GNUNET_YES == ntohl(block->accepting) && | ||
1303 | ctx->position == strlen (ctx->info->description)) | ||
1304 | { | ||
1305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Found accepting known block\n"); | ||
1306 | regex_find_path (key, ctx); | ||
1307 | return GNUNET_YES; // We found an accept state! | ||
1308 | } | ||
1309 | else | ||
1310 | { | ||
1311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", | ||
1312 | ctx->position, strlen(ctx->info->description), | ||
1313 | ntohl(block->accepting)); | ||
1314 | |||
1315 | } | ||
1316 | regex_next_edge(block, SIZE_MAX, ctx); | ||
1317 | |||
1318 | GNUNET_STATISTICS_update (stats, "# regex mesh blocks iterated", 1, GNUNET_NO); | ||
1319 | |||
1320 | return GNUNET_YES; | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Iterator over edges in a regex block retrieved from the DHT. | ||
1326 | * | ||
1327 | * @param cls Closure (context of the search). | ||
1328 | * @param token Token that follows to next state. | ||
1329 | * @param len Lenght of token. | ||
1330 | * @param key Hash of next state. | ||
1331 | * | ||
1332 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1333 | */ | ||
1334 | static int | ||
1335 | regex_edge_iterator (void *cls, | ||
1336 | const char *token, | ||
1337 | size_t len, | ||
1338 | const struct GNUNET_HashCode *key) | ||
1339 | { | ||
1340 | struct MeshRegexSearchContext *ctx = cls; | ||
1341 | struct MeshRegexSearchInfo *info = ctx->info; | ||
1342 | char *current; | ||
1343 | size_t current_len; | ||
1344 | |||
1345 | GNUNET_STATISTICS_update (stats, "# regex edges iterated", 1, GNUNET_NO); | ||
1346 | |||
1347 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Start of regex edge iterator\n"); | ||
1348 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* descr : %s\n", info->description); | ||
1349 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* posit : %u\n", ctx->position); | ||
1350 | current = &info->description[ctx->position]; | ||
1351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* currt : %s\n", current); | ||
1352 | current_len = strlen (info->description) - ctx->position; | ||
1353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* ctlen : %u\n", current_len); | ||
1354 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* tklen : %u\n", len); | ||
1355 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* tk[0] : %c\n", token[0]); | ||
1356 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* nextk : %s\n", GNUNET_h2s(key)); | ||
1357 | if (len > current_len) | ||
1358 | { | ||
1359 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token too long, END\n"); | ||
1360 | return GNUNET_YES; // Token too long, wont match | ||
1361 | } | ||
1362 | if (0 != strncmp (current, token, len)) | ||
1363 | { | ||
1364 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token doesn't match, END\n"); | ||
1365 | return GNUNET_YES; // Token doesn't match | ||
1366 | } | ||
1367 | |||
1368 | if (len > ctx->longest_match) | ||
1369 | { | ||
1370 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is longer, KEEP\n"); | ||
1371 | ctx->longest_match = len; | ||
1372 | ctx->hash = *key; | ||
1373 | } | ||
1374 | else | ||
1375 | { | ||
1376 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is not longer, IGNORE\n"); | ||
1377 | } | ||
1378 | |||
1379 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); | ||
1380 | return GNUNET_YES; | ||
1381 | } | ||
1382 | |||
1383 | |||
1384 | /** | ||
1385 | * Jump to the next edge, with the longest matching token. | ||
1386 | * | ||
1387 | * @param block Block found in the DHT. | ||
1388 | * @param size Size of the block. | ||
1389 | * @param ctx Context of the search. | ||
1390 | * | ||
1391 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1392 | */ | 1254 | */ |
1393 | static void | 1255 | static void |
1394 | regex_next_edge (const struct MeshRegexBlock *block, | 1256 | regex_cancel_search (struct MeshRegexSearchInfo *regex_search) |
1395 | size_t size, | ||
1396 | struct MeshRegexSearchContext *ctx) | ||
1397 | { | 1257 | { |
1398 | struct MeshRegexSearchContext *new_ctx; | 1258 | GNUNET_REGEX_search_cancel (regex_search->search_handle); |
1399 | struct MeshRegexSearchInfo *info = ctx->info; | 1259 | if (0 < regex_search->n_peers) |
1400 | struct GNUNET_DHT_GetHandle *get_h; | 1260 | GNUNET_free (regex_search->peers); |
1401 | 1261 | if (GNUNET_SCHEDULER_NO_TASK != regex_search->timeout) | |
1402 | int result; | ||
1403 | |||
1404 | /* Find the longest match for the current string position, | ||
1405 | * among tokens in the given block */ | ||
1406 | ctx->longest_match = 0; | ||
1407 | result = GNUNET_MESH_regex_block_iterate (block, size, | ||
1408 | ®ex_edge_iterator, ctx); | ||
1409 | GNUNET_break (GNUNET_OK == result || SIZE_MAX == size); | ||
1410 | |||
1411 | /* Did anything match? */ | ||
1412 | if (0 == ctx->longest_match) | ||
1413 | return; | ||
1414 | |||
1415 | new_ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext)); | ||
1416 | new_ctx->info = info; | ||
1417 | new_ctx->position = ctx->position + ctx->longest_match; | ||
1418 | GNUNET_array_append (info->contexts, info->n_contexts, new_ctx); | ||
1419 | |||
1420 | /* Check whether we already have a DHT GET running for it */ | ||
1421 | if (GNUNET_YES == | ||
1422 | GNUNET_CONTAINER_multihashmap_contains(info->dht_get_handles, &ctx->hash)) | ||
1423 | { | ||
1424 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* GET running, END\n"); | ||
1425 | GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, | ||
1426 | &ctx->hash, | ||
1427 | ®ex_result_iterator, | ||
1428 | new_ctx); | ||
1429 | return; // We are already looking for it | ||
1430 | } | ||
1431 | |||
1432 | GNUNET_STATISTICS_update (stats, "# regex nodes traversed", 1, GNUNET_NO); | ||
1433 | |||
1434 | /* Start search in DHT */ | ||
1435 | get_h = | ||
1436 | GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
1437 | GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */ | ||
1438 | &ctx->hash, /* key to search */ | ||
1439 | dht_replication_level, /* replication level */ | ||
1440 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
1441 | NULL, /* xquery */ // FIXME BLOOMFILTER | ||
1442 | 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE | ||
1443 | &dht_get_string_handler, new_ctx); | ||
1444 | if (GNUNET_OK != | ||
1445 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | ||
1446 | &ctx->hash, | ||
1447 | get_h, | ||
1448 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
1449 | { | 1262 | { |
1450 | GNUNET_break (0); | 1263 | GNUNET_SCHEDULER_cancel(regex_search->timeout); |
1451 | return; | ||
1452 | } | 1264 | } |
1453 | } | 1265 | GNUNET_free (regex_search); |
1454 | |||
1455 | |||
1456 | /** | ||
1457 | * Iterator over hash map entries to cancel DHT GET requests after a | ||
1458 | * successful connect_by_string. | ||
1459 | * | ||
1460 | * @param cls Closure (unused). | ||
1461 | * @param key Current key code (unused). | ||
1462 | * @param value Value in the hash map (get handle). | ||
1463 | * @return GNUNET_YES if we should continue to iterate, | ||
1464 | * GNUNET_NO if not. | ||
1465 | */ | ||
1466 | static int | ||
1467 | regex_cancel_dht_get (void *cls, | ||
1468 | const struct GNUNET_HashCode * key, | ||
1469 | void *value) | ||
1470 | { | ||
1471 | struct GNUNET_DHT_GetHandle *h = value; | ||
1472 | |||
1473 | GNUNET_DHT_get_stop (h); | ||
1474 | return GNUNET_YES; | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * Iterator over hash map entries to free MeshRegexBlocks stored during the | ||
1480 | * search for connect_by_string. | ||
1481 | * | ||
1482 | * @param cls Closure (unused). | ||
1483 | * @param key Current key code (unused). | ||
1484 | * @param value MeshRegexBlock in the hash map. | ||
1485 | * @return GNUNET_YES if we should continue to iterate, | ||
1486 | * GNUNET_NO if not. | ||
1487 | */ | ||
1488 | static int | ||
1489 | regex_free_result (void *cls, | ||
1490 | const struct GNUNET_HashCode * key, | ||
1491 | void *value) | ||
1492 | { | ||
1493 | |||
1494 | GNUNET_free (value); | ||
1495 | return GNUNET_YES; | ||
1496 | } | ||
1497 | |||
1498 | |||
1499 | /** | ||
1500 | * Regex callback iterator to store own service description in the DHT. | ||
1501 | * | ||
1502 | * @param cls closure. | ||
1503 | * @param key hash for current state. | ||
1504 | * @param proof proof for current state. | ||
1505 | * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. | ||
1506 | * @param num_edges number of edges leaving current state. | ||
1507 | * @param edges edges leaving current state. | ||
1508 | */ | ||
1509 | void | ||
1510 | regex_iterator (void *cls, | ||
1511 | const struct GNUNET_HashCode *key, | ||
1512 | const char *proof, | ||
1513 | int accepting, | ||
1514 | unsigned int num_edges, | ||
1515 | const struct GNUNET_REGEX_Edge *edges) | ||
1516 | { | ||
1517 | struct MeshRegexBlock *block; | ||
1518 | struct MeshRegexEdge *block_edge; | ||
1519 | enum GNUNET_DHT_RouteOption opt; | ||
1520 | size_t size; | ||
1521 | size_t len; | ||
1522 | unsigned int i; | ||
1523 | unsigned int offset; | ||
1524 | char *aux; | ||
1525 | |||
1526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1527 | " regex dht put for state %s\n", | ||
1528 | GNUNET_h2s(key)); | ||
1529 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1530 | " proof: %s\n", | ||
1531 | proof); | ||
1532 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1533 | " num edges: %u\n", | ||
1534 | num_edges); | ||
1535 | |||
1536 | opt = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE; | ||
1537 | if (GNUNET_YES == accepting) | ||
1538 | { | ||
1539 | struct MeshRegexAccept block; | ||
1540 | |||
1541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1542 | " state %s is accepting, putting own id\n", | ||
1543 | GNUNET_h2s(key)); | ||
1544 | size = sizeof (block); | ||
1545 | block.key = *key; | ||
1546 | block.id = my_full_id; | ||
1547 | (void) | ||
1548 | GNUNET_DHT_put(dht_handle, key, | ||
1549 | dht_replication_level, | ||
1550 | opt | GNUNET_DHT_RO_RECORD_ROUTE, | ||
1551 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, | ||
1552 | size, | ||
1553 | (char *) &block, | ||
1554 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
1555 | app_announce_time), | ||
1556 | app_announce_time, | ||
1557 | NULL, NULL); | ||
1558 | } | ||
1559 | len = strlen(proof); | ||
1560 | size = sizeof (struct MeshRegexBlock) + len; | ||
1561 | block = GNUNET_malloc (size); | ||
1562 | |||
1563 | block->key = *key; | ||
1564 | block->n_proof = htonl (len); | ||
1565 | block->n_edges = htonl (num_edges); | ||
1566 | block->accepting = htonl (accepting); | ||
1567 | |||
1568 | /* Store the proof at the end of the block. */ | ||
1569 | aux = (char *) &block[1]; | ||
1570 | memcpy (aux, proof, len); | ||
1571 | aux = &aux[len]; | ||
1572 | |||
1573 | /* Store each edge in a variable length MeshEdge struct at the | ||
1574 | * very end of the MeshRegexBlock structure. | ||
1575 | */ | ||
1576 | for (i = 0; i < num_edges; i++) | ||
1577 | { | ||
1578 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1579 | " edge %s towards %s\n", | ||
1580 | edges[i].label, | ||
1581 | GNUNET_h2s(&edges[i].destination)); | ||
1582 | |||
1583 | /* aux points at the end of the last block */ | ||
1584 | len = strlen (edges[i].label); | ||
1585 | size += sizeof (struct MeshRegexEdge) + len; | ||
1586 | // Calculate offset FIXME is this ok? use size instead? | ||
1587 | offset = aux - (char *) block; | ||
1588 | block = GNUNET_realloc (block, size); | ||
1589 | aux = &((char *) block)[offset]; | ||
1590 | block_edge = (struct MeshRegexEdge *) aux; | ||
1591 | block_edge->key = edges[i].destination; | ||
1592 | block_edge->n_token = htonl (len); | ||
1593 | aux = (char *) &block_edge[1]; | ||
1594 | memcpy (aux, edges[i].label, len); | ||
1595 | aux = &aux[len]; | ||
1596 | } | ||
1597 | (void) | ||
1598 | GNUNET_DHT_put(dht_handle, key, | ||
1599 | dht_replication_level, | ||
1600 | opt, | ||
1601 | GNUNET_BLOCK_TYPE_MESH_REGEX, size, | ||
1602 | (char *) block, | ||
1603 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
1604 | app_announce_time), | ||
1605 | app_announce_time, | ||
1606 | NULL, NULL); | ||
1607 | GNUNET_free (block); | ||
1608 | } | ||
1609 | |||
1610 | |||
1611 | /** | ||
1612 | * Store the regular expression describing a local service into the DHT. | ||
1613 | * | ||
1614 | * @param regex The regular expresion. | ||
1615 | */ | ||
1616 | static void | ||
1617 | regex_put (const struct MeshRegexDescriptor *regex) | ||
1618 | { | ||
1619 | struct GNUNET_REGEX_Automaton *dfa; | ||
1620 | |||
1621 | DEBUG_DHT (" regex_put (%s) start\n", regex->regex); | ||
1622 | dfa = GNUNET_REGEX_construct_dfa (regex->regex, | ||
1623 | strlen(regex->regex), | ||
1624 | regex->compression); | ||
1625 | GNUNET_REGEX_iterate_all_edges (dfa, ®ex_iterator, NULL); | ||
1626 | GNUNET_REGEX_automaton_destroy (dfa); | ||
1627 | DEBUG_DHT (" regex_put (%s) end\n", regex); | ||
1628 | |||
1629 | } | ||
1630 | |||
1631 | /** | ||
1632 | * Find a path to a peer that offers a regex servcie compatible | ||
1633 | * with a given string. | ||
1634 | * | ||
1635 | * @param key The key of the accepting state. | ||
1636 | * @param ctx Context containing info about the string, tunnel, etc. | ||
1637 | */ | ||
1638 | static void | ||
1639 | regex_find_path (const struct GNUNET_HashCode *key, | ||
1640 | struct MeshRegexSearchContext *ctx) | ||
1641 | { | ||
1642 | struct GNUNET_DHT_GetHandle *get_h; | ||
1643 | |||
1644 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n"); | ||
1645 | get_h = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
1646 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, /* type */ | ||
1647 | key, /* key to search */ | ||
1648 | dht_replication_level, /* replication level */ | ||
1649 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | | ||
1650 | GNUNET_DHT_RO_RECORD_ROUTE, | ||
1651 | NULL, /* xquery */ // FIXME BLOOMFILTER | ||
1652 | 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE | ||
1653 | &dht_get_string_accept_handler, ctx); | ||
1654 | GNUNET_break (GNUNET_OK == | ||
1655 | GNUNET_CONTAINER_multihashmap_put(ctx->info->dht_get_handles, | ||
1656 | key, | ||
1657 | get_h, | ||
1658 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
1659 | } | 1266 | } |
1660 | 1267 | ||
1661 | 1268 | ||
@@ -1679,6 +1286,7 @@ regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1679 | info->timeout = GNUNET_SCHEDULER_NO_TASK; | 1286 | info->timeout = GNUNET_SCHEDULER_NO_TASK; |
1680 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 1287 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
1681 | { | 1288 | { |
1289 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " due to shutdown\n"); | ||
1682 | return; | 1290 | return; |
1683 | } | 1291 | } |
1684 | 1292 | ||
@@ -1712,37 +1320,109 @@ regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1712 | 1320 | ||
1713 | 1321 | ||
1714 | /** | 1322 | /** |
1715 | * Cancel an ongoing regex search in the DHT and free all resources. | 1323 | * Function to process DHT string to regex matching. |
1324 | * Called on each result obtained for the DHT search. | ||
1716 | * | 1325 | * |
1717 | * @param ctx The search context. | 1326 | * @param cls Closure provided in GNUNET_REGEX_search. |
1327 | * @param id Peer providing a regex that matches the string. | ||
1328 | * @param get_path Path of the get request. | ||
1329 | * @param get_path_length Lenght of get_path. | ||
1330 | * @param put_path Path of the put request. | ||
1331 | * @param put_path_length Length of the put_path. | ||
1718 | */ | 1332 | */ |
1719 | static void | 1333 | static void |
1720 | regex_cancel_search(struct MeshRegexSearchContext *ctx) | 1334 | regex_found_handler (void *cls, |
1335 | const struct GNUNET_PeerIdentity *id, | ||
1336 | const struct GNUNET_PeerIdentity *get_path, | ||
1337 | unsigned int get_path_length, | ||
1338 | const struct GNUNET_PeerIdentity *put_path, | ||
1339 | unsigned int put_path_length) | ||
1721 | { | 1340 | { |
1722 | struct MeshRegexSearchInfo *info = ctx->info; | 1341 | struct MeshRegexSearchInfo *info = cls; |
1723 | int i; | 1342 | struct MeshPeerPath *p; |
1343 | struct MeshPeerInfo *peer_info; | ||
1344 | |||
1345 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | ||
1346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", info->description); | ||
1347 | |||
1348 | peer_info = peer_info_get (id); | ||
1349 | p = path_build_from_dht (get_path, get_path_length, | ||
1350 | put_path, put_path_length); | ||
1351 | path_add_to_peers (p, GNUNET_NO); | ||
1352 | path_destroy(p); | ||
1724 | 1353 | ||
1725 | GNUNET_free (info->description); | 1354 | tunnel_add_peer (info->t, peer_info); |
1726 | GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_handles, | 1355 | peer_info_connect (peer_info, info->t); |
1727 | ®ex_cancel_dht_get, NULL); | 1356 | if (0 == info->peer) |
1728 | GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_results, | ||
1729 | ®ex_free_result, NULL); | ||
1730 | GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_results); | ||
1731 | GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_handles); | ||
1732 | info->t->regex_ctx = NULL; | ||
1733 | for (i = 0; i < info->n_contexts; i++) | ||
1734 | { | 1357 | { |
1735 | GNUNET_free (info->contexts[i]); | 1358 | info->peer = peer_info->id; |
1736 | } | 1359 | } |
1737 | if (0 < info->n_contexts) | 1360 | else |
1738 | GNUNET_free (info->contexts); | 1361 | { |
1739 | if (0 < info->n_peers) | 1362 | GNUNET_array_append (info->peers, info->n_peers, peer_info->id); |
1740 | GNUNET_free (info->peers); | 1363 | } |
1364 | |||
1741 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout) | 1365 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout) |
1366 | return; | ||
1367 | |||
1368 | info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, | ||
1369 | ®ex_connect_timeout, | ||
1370 | info); | ||
1371 | |||
1372 | return; | ||
1373 | } | ||
1374 | |||
1375 | |||
1376 | /** | ||
1377 | * Store the regular expression describing a local service into the DHT. | ||
1378 | * | ||
1379 | * @param regex The regular expresion. | ||
1380 | */ | ||
1381 | static void | ||
1382 | regex_put (struct MeshRegexDescriptor *regex) | ||
1383 | { | ||
1384 | DEBUG_DHT (" regex_put (%s) start\n", regex->regex); | ||
1385 | if (NULL == regex->h) | ||
1742 | { | 1386 | { |
1743 | GNUNET_SCHEDULER_cancel(info->timeout); | 1387 | DEBUG_DHT (" first put, creating DFA\n"); |
1388 | regex->h = GNUNET_REGEX_announce (dht_handle, | ||
1389 | &my_full_id, | ||
1390 | regex->regex, | ||
1391 | regex->compression, | ||
1392 | stats); | ||
1744 | } | 1393 | } |
1745 | GNUNET_free (info); | 1394 | else |
1395 | { | ||
1396 | DEBUG_DHT (" not first put, using cached data\n"); | ||
1397 | GNUNET_REGEX_reannounce (regex->h); | ||
1398 | } | ||
1399 | DEBUG_DHT (" regex_put (%s) end\n", regex->regex); | ||
1400 | } | ||
1401 | |||
1402 | |||
1403 | /** | ||
1404 | * Periodically announce what applications are provided by local clients | ||
1405 | * (by regex) | ||
1406 | * | ||
1407 | * @param cls closure | ||
1408 | * @param tc task context | ||
1409 | */ | ||
1410 | static void | ||
1411 | regex_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1412 | { | ||
1413 | struct MeshClient *c = cls; | ||
1414 | unsigned int i; | ||
1415 | |||
1416 | c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK; | ||
1417 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1418 | return; | ||
1419 | DEBUG_DHT ("Starting PUT for regex\n"); | ||
1420 | for (i = 0; i < c->n_regex; i++) | ||
1421 | regex_put (&c->regexes[i]); | ||
1422 | c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time, | ||
1423 | ®ex_announce, | ||
1424 | cls); | ||
1425 | DEBUG_DHT ("Finished PUT for regex\n"); | ||
1746 | } | 1426 | } |
1747 | 1427 | ||
1748 | 1428 | ||
@@ -1779,55 +1459,20 @@ announce_application (void *cls, const struct GNUNET_HashCode * key, void *value | |||
1779 | 1459 | ||
1780 | GNUNET_break (NULL != | 1460 | GNUNET_break (NULL != |
1781 | GNUNET_DHT_put (dht_handle, key, | 1461 | GNUNET_DHT_put (dht_handle, key, |
1782 | dht_replication_level, | 1462 | dht_replication_level, |
1783 | GNUNET_DHT_RO_RECORD_ROUTE | | 1463 | GNUNET_DHT_RO_RECORD_ROUTE | |
1784 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | 1464 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, |
1785 | GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, | 1465 | GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, |
1786 | sizeof (block), | 1466 | sizeof (block), |
1787 | (const char *) &block, | 1467 | (const char *) &block, |
1788 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | 1468 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: this should be an option */ |
1789 | app_announce_time), | 1469 | app_announce_time, NULL, NULL)); |
1790 | app_announce_time, NULL, NULL)); | ||
1791 | return GNUNET_OK; | 1470 | return GNUNET_OK; |
1792 | } | 1471 | } |
1793 | 1472 | ||
1794 | 1473 | ||
1795 | /** | 1474 | /** |
1796 | * Periodically announce what applications are provided by local clients | 1475 | * Periodically announce what applications are provided by local clients |
1797 | * (by regex) | ||
1798 | * | ||
1799 | * @param cls closure | ||
1800 | * @param tc task context | ||
1801 | */ | ||
1802 | static void | ||
1803 | announce_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1804 | { | ||
1805 | struct MeshClient *c = cls; | ||
1806 | unsigned int i; | ||
1807 | |||
1808 | c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK; | ||
1809 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1810 | { | ||
1811 | return; | ||
1812 | } | ||
1813 | |||
1814 | DEBUG_DHT ("Starting PUT for regex\n"); | ||
1815 | |||
1816 | for (i = 0; i < c->n_regex; i++) | ||
1817 | { | ||
1818 | regex_put (&c->regexes[i]); | ||
1819 | } | ||
1820 | c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time, | ||
1821 | &announce_regex, | ||
1822 | cls); | ||
1823 | DEBUG_DHT ("Finished PUT for regex\n"); | ||
1824 | |||
1825 | return; | ||
1826 | } | ||
1827 | |||
1828 | |||
1829 | /** | ||
1830 | * Periodically announce what applications are provided by local clients | ||
1831 | * (by type) | 1476 | * (by type) |
1832 | * | 1477 | * |
1833 | * @param cls closure | 1478 | * @param cls closure |
@@ -1850,8 +1495,6 @@ announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1850 | GNUNET_SCHEDULER_add_delayed (app_announce_time, &announce_applications, | 1495 | GNUNET_SCHEDULER_add_delayed (app_announce_time, &announce_applications, |
1851 | cls); | 1496 | cls); |
1852 | DEBUG_DHT ("Finished PUT for apps\n"); | 1497 | DEBUG_DHT ("Finished PUT for apps\n"); |
1853 | |||
1854 | return; | ||
1855 | } | 1498 | } |
1856 | 1499 | ||
1857 | 1500 | ||
@@ -2073,6 +1716,32 @@ client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t) | |||
2073 | 1716 | ||
2074 | 1717 | ||
2075 | /** | 1718 | /** |
1719 | * Notify the owner of a tunnel that a peer has disconnected. | ||
1720 | * | ||
1721 | * @param c Client (owner of tunnel). | ||
1722 | * @param t Tunnel this message is about. | ||
1723 | * @param peer_id Short ID of the disconnected peer. | ||
1724 | */ | ||
1725 | void | ||
1726 | client_notify_peer_disconnected (struct MeshClient *c, | ||
1727 | struct MeshTunnel *t, | ||
1728 | GNUNET_PEER_Id peer_id) | ||
1729 | { | ||
1730 | struct GNUNET_MESH_PeerControl msg; | ||
1731 | |||
1732 | if (NULL == t->owner || NULL == nc) | ||
1733 | return; | ||
1734 | |||
1735 | msg.header.size = htons (sizeof (msg)); | ||
1736 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); | ||
1737 | msg.tunnel_id = htonl (t->local_tid); | ||
1738 | GNUNET_PEER_resolve (peer_id, &msg.peer); | ||
1739 | GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, | ||
1740 | &msg.header, GNUNET_NO); | ||
1741 | } | ||
1742 | |||
1743 | |||
1744 | /** | ||
2076 | * Send the message to all clients that have subscribed to its type | 1745 | * Send the message to all clients that have subscribed to its type |
2077 | * | 1746 | * |
2078 | * @param msg Pointer to the message itself | 1747 | * @param msg Pointer to the message itself |
@@ -2189,6 +1858,9 @@ send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id) | |||
2189 | { | 1858 | { |
2190 | struct GNUNET_MESH_PeerControl pc; | 1859 | struct GNUNET_MESH_PeerControl pc; |
2191 | 1860 | ||
1861 | if (NULL == t->owner || GNUNET_YES == t->destroy) | ||
1862 | return; | ||
1863 | |||
2192 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); | 1864 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); |
2193 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); | 1865 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); |
2194 | pc.tunnel_id = htonl (t->local_tid); | 1866 | pc.tunnel_id = htonl (t->local_tid); |
@@ -2259,6 +1931,23 @@ send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c) | |||
2259 | 1931 | ||
2260 | 1932 | ||
2261 | /** | 1933 | /** |
1934 | * Iterator over all the peers to remove the oldest not-used entry. | ||
1935 | * | ||
1936 | * @param cls Closure (unsued). | ||
1937 | * @param key ID of the peer. | ||
1938 | * @param value Peer_Info of the peer. | ||
1939 | * | ||
1940 | * FIXME implement | ||
1941 | */ | ||
1942 | static int | ||
1943 | peer_info_timeout (void *cls, | ||
1944 | const struct GNUNET_HashCode *key, | ||
1945 | void *value) | ||
1946 | { | ||
1947 | return GNUNET_YES; | ||
1948 | } | ||
1949 | |||
1950 | /** | ||
2262 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one | 1951 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one |
2263 | * and insert it in the appropiate structures if the peer is not known yet. | 1952 | * and insert it in the appropiate structures if the peer is not known yet. |
2264 | * | 1953 | * |
@@ -2276,10 +1965,17 @@ peer_info_get (const struct GNUNET_PeerIdentity *peer) | |||
2276 | { | 1965 | { |
2277 | peer_info = | 1966 | peer_info = |
2278 | (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo)); | 1967 | (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo)); |
1968 | if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers) | ||
1969 | { | ||
1970 | GNUNET_CONTAINER_multihashmap_iterate (peers, | ||
1971 | &peer_info_timeout, | ||
1972 | NULL); | ||
1973 | } | ||
2279 | GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info, | 1974 | GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info, |
2280 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 1975 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); |
2281 | peer_info->id = GNUNET_PEER_intern (peer); | 1976 | peer_info->id = GNUNET_PEER_intern (peer); |
2282 | } | 1977 | } |
1978 | peer_info->last_contact = GNUNET_TIME_absolute_get(); | ||
2283 | 1979 | ||
2284 | return peer_info; | 1980 | return peer_info; |
2285 | } | 1981 | } |
@@ -2447,6 +2143,9 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message, | |||
2447 | } | 2143 | } |
2448 | #endif | 2144 | #endif |
2449 | GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) | 2145 | GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) |
2146 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2147 | " no direct connection to %s\n", | ||
2148 | GNUNET_i2s (peer)); | ||
2450 | GNUNET_free (info->mesh_data->data); | 2149 | GNUNET_free (info->mesh_data->data); |
2451 | GNUNET_free (info->mesh_data); | 2150 | GNUNET_free (info->mesh_data); |
2452 | GNUNET_free (info); | 2151 | GNUNET_free (info); |
@@ -2932,38 +2631,37 @@ peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info, | |||
2932 | * Function called if the connection to the peer has been stalled for a while, | 2631 | * Function called if the connection to the peer has been stalled for a while, |
2933 | * possibly due to a missed ACK. Poll the peer about its ACK status. | 2632 | * possibly due to a missed ACK. Poll the peer about its ACK status. |
2934 | * | 2633 | * |
2935 | * @param cls Closure (MeshPeerInfo of stalled peer). | 2634 | * @param cls Closure (cinfo). |
2936 | * @param tc TaskContext. | 2635 | * @param tc TaskContext. |
2937 | */ | 2636 | */ |
2938 | static void | 2637 | static void |
2939 | tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 2638 | tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
2940 | { | 2639 | { |
2941 | struct MeshTunnelFlowControlInfo *fcinfo = cls; | 2640 | struct MeshTunnelChildInfo *cinfo = cls; |
2942 | struct GNUNET_MESH_Poll msg; | 2641 | struct GNUNET_MESH_Poll msg; |
2943 | struct GNUNET_PeerIdentity id; | 2642 | struct GNUNET_PeerIdentity id; |
2944 | struct MeshTunnel *t; | 2643 | struct MeshTunnel *t; |
2945 | 2644 | ||
2946 | // FIXME fc include code to poll clients | 2645 | cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; |
2947 | if (NULL == fcinfo->peer) | ||
2948 | return; | ||
2949 | fcinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; | ||
2950 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 2646 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
2951 | { | 2647 | { |
2952 | return; | 2648 | return; |
2953 | } | 2649 | } |
2954 | 2650 | ||
2955 | t = fcinfo->t; | 2651 | t = cinfo->t; |
2956 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); | 2652 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); |
2957 | msg.header.size = htons (sizeof (msg)); | 2653 | msg.header.size = htons (sizeof (msg)); |
2958 | msg.tid = htonl (t->id.tid); | 2654 | msg.tid = htonl (t->id.tid); |
2959 | GNUNET_PEER_resolve (t->id.oid, &msg.oid); | 2655 | GNUNET_PEER_resolve (t->id.oid, &msg.oid); |
2960 | msg.last_ack = htonl (fcinfo->fwd_ack); | 2656 | msg.last_ack = htonl (cinfo->fwd_ack); |
2961 | |||
2962 | GNUNET_PEER_resolve (fcinfo->peer->id, &id); | ||
2963 | send_prebuilt_message (&msg.header, &id, fcinfo->t); | ||
2964 | fcinfo->fc_poll = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, | ||
2965 | &tunnel_poll, fcinfo); | ||
2966 | 2657 | ||
2658 | GNUNET_PEER_resolve (cinfo->id, &id); | ||
2659 | send_prebuilt_message (&msg.header, &id, cinfo->t); | ||
2660 | cinfo->fc_poll_time = GNUNET_TIME_relative_min ( | ||
2661 | MESH_MAX_POLL_TIME, | ||
2662 | GNUNET_TIME_relative_multiply (cinfo->fc_poll_time, 2)); | ||
2663 | cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time, | ||
2664 | &tunnel_poll, cinfo); | ||
2967 | } | 2665 | } |
2968 | 2666 | ||
2969 | 2667 | ||
@@ -3166,7 +2864,7 @@ tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) | |||
3166 | * @return tunnel handler, NULL if doesn't exist | 2864 | * @return tunnel handler, NULL if doesn't exist |
3167 | */ | 2865 | */ |
3168 | static struct MeshTunnel * | 2866 | static struct MeshTunnel * |
3169 | tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) | 2867 | tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) |
3170 | { | 2868 | { |
3171 | return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid); | 2869 | return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid); |
3172 | } | 2870 | } |
@@ -3253,7 +2951,7 @@ tunnel_destroy_child (void *cls, | |||
3253 | const struct GNUNET_HashCode * key, | 2951 | const struct GNUNET_HashCode * key, |
3254 | void *value) | 2952 | void *value) |
3255 | { | 2953 | { |
3256 | struct MeshTunnelFlowControlInfo *cinfo = value; | 2954 | struct MeshTunnelChildInfo *cinfo = value; |
3257 | struct MeshTunnel *t = cls; | 2955 | struct MeshTunnel *t = cls; |
3258 | struct MeshPeerQueue *q; | 2956 | struct MeshPeerQueue *q; |
3259 | unsigned int c; | 2957 | unsigned int c; |
@@ -3271,6 +2969,11 @@ tunnel_destroy_child (void *cls, | |||
3271 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n); | 2969 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n); |
3272 | } | 2970 | } |
3273 | GNUNET_free_non_null (cinfo->send_buffer); | 2971 | GNUNET_free_non_null (cinfo->send_buffer); |
2972 | if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll) | ||
2973 | { | ||
2974 | GNUNET_SCHEDULER_cancel (cinfo->fc_poll); | ||
2975 | cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; | ||
2976 | } | ||
3274 | GNUNET_free (cinfo); | 2977 | GNUNET_free (cinfo); |
3275 | return GNUNET_YES; | 2978 | return GNUNET_YES; |
3276 | } | 2979 | } |
@@ -3290,17 +2993,8 @@ tunnel_notify_client_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id) | |||
3290 | struct MeshPeerInfo *peer; | 2993 | struct MeshPeerInfo *peer; |
3291 | struct MeshPathInfo *path_info; | 2994 | struct MeshPathInfo *path_info; |
3292 | 2995 | ||
3293 | if (NULL != t->owner && NULL != nc) | 2996 | client_notify_peer_disconnected (t->owner, t, peer_id); |
3294 | { | ||
3295 | struct GNUNET_MESH_PeerControl msg; | ||
3296 | 2997 | ||
3297 | msg.header.size = htons (sizeof (msg)); | ||
3298 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); | ||
3299 | msg.tunnel_id = htonl (t->local_tid); | ||
3300 | GNUNET_PEER_resolve (peer_id, &msg.peer); | ||
3301 | GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, | ||
3302 | &msg.header, GNUNET_NO); | ||
3303 | } | ||
3304 | peer = peer_info_get_short (peer_id); | 2998 | peer = peer_info_get_short (peer_id); |
3305 | path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); | 2999 | path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); |
3306 | path_info->peer = peer; | 3000 | path_info->peer = peer; |
@@ -3403,25 +3097,15 @@ tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p, | |||
3403 | static void | 3097 | static void |
3404 | tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) | 3098 | tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) |
3405 | { | 3099 | { |
3406 | struct MeshTunnelFlowControlInfo fcinfo; | 3100 | struct MeshTunnelClientInfo clinfo; |
3407 | 3101 | ||
3408 | GNUNET_array_append (t->clients, t->nclients, c); | 3102 | GNUNET_array_append (t->clients, t->nclients, c); |
3409 | fcinfo.t = t; | 3103 | clinfo.fwd_ack = t->fwd_pid + 1; |
3410 | fcinfo.client = c; | 3104 | clinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1; |
3411 | fcinfo.peer = NULL; | 3105 | clinfo.fwd_pid = t->fwd_pid; |
3412 | fcinfo.fwd_ack = t->fwd_pid + 1; | 3106 | clinfo.bck_pid = (uint32_t) -1; // Expected next: 0 |
3413 | fcinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1; | ||
3414 | fcinfo.fwd_pid = t->fwd_pid; | ||
3415 | fcinfo.bck_pid = (uint32_t) -1; // Expected next: 0 | ||
3416 | fcinfo.fc_poll = GNUNET_SCHEDULER_NO_TASK; | ||
3417 | fcinfo.send_buffer = NULL; | ||
3418 | fcinfo.send_buffer_n = 0; | ||
3419 | fcinfo.send_buffer_start = 0; | ||
3420 | fcinfo.skip = t->fwd_pid; | ||
3421 | // FIXME fc buffering is done by context_notify. Confirm this is OK. | ||
3422 | |||
3423 | t->nclients--; | 3107 | t->nclients--; |
3424 | GNUNET_array_append (t->clients_fc, t->nclients, fcinfo); | 3108 | GNUNET_array_append (t->clients_fc, t->nclients, clinfo); |
3425 | } | 3109 | } |
3426 | 3110 | ||
3427 | 3111 | ||
@@ -3564,7 +3248,8 @@ tunnel_send_multicast (struct MeshTunnel *t, | |||
3564 | " no one to send data to\n"); | 3248 | " no one to send data to\n"); |
3565 | GNUNET_free (mdata->data); | 3249 | GNUNET_free (mdata->data); |
3566 | GNUNET_free (mdata); | 3250 | GNUNET_free (mdata); |
3567 | t->fwd_queue_n--; | 3251 | if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST) |
3252 | t->fwd_queue_n--; | ||
3568 | } | 3253 | } |
3569 | else | 3254 | else |
3570 | { | 3255 | { |
@@ -3582,7 +3267,7 @@ tunnel_send_multicast (struct MeshTunnel *t, | |||
3582 | * | 3267 | * |
3583 | * @param cls Closure (ID of the peer that HAS received the message). | 3268 | * @param cls Closure (ID of the peer that HAS received the message). |
3584 | * @param key ID of the neighbor. | 3269 | * @param key ID of the neighbor. |
3585 | * @param value FLow control information about the neighbor. | 3270 | * @param value Information about the neighbor. |
3586 | * | 3271 | * |
3587 | * @return GNUNET_YES to keep iterating. | 3272 | * @return GNUNET_YES to keep iterating. |
3588 | */ | 3273 | */ |
@@ -3592,14 +3277,14 @@ tunnel_add_skip (void *cls, | |||
3592 | void *value) | 3277 | void *value) |
3593 | { | 3278 | { |
3594 | struct GNUNET_PeerIdentity *neighbor = cls; | 3279 | struct GNUNET_PeerIdentity *neighbor = cls; |
3595 | struct MeshTunnelFlowControlInfo *fcinfo = value; | 3280 | struct MeshTunnelChildInfo *cinfo = value; |
3596 | 3281 | ||
3597 | /* TODO compare only pointers? key == neighbor? */ | 3282 | /* TODO compare only pointers? key == neighbor? */ |
3598 | if (0 == memcmp (&neighbor->hashPubKey, key, sizeof (struct GNUNET_HashCode))) | 3283 | if (0 == memcmp (&neighbor->hashPubKey, key, sizeof (struct GNUNET_HashCode))) |
3599 | { | 3284 | { |
3600 | return GNUNET_YES; | 3285 | return GNUNET_YES; |
3601 | } | 3286 | } |
3602 | fcinfo->skip++; | 3287 | cinfo->skip++; |
3603 | return GNUNET_YES; | 3288 | return GNUNET_YES; |
3604 | } | 3289 | } |
3605 | 3290 | ||
@@ -3607,8 +3292,8 @@ tunnel_add_skip (void *cls, | |||
3607 | /** | 3292 | /** |
3608 | * @brief Get neighbor's Flow Control information. | 3293 | * @brief Get neighbor's Flow Control information. |
3609 | * | 3294 | * |
3610 | * Retrieves the MeshTunnelFlowControlInfo containing Flow Control data about | 3295 | * Retrieves the MeshTunnelChildInfo containing Flow Control data about a direct |
3611 | * a direct descendant of the local node in a certain tunnel. | 3296 | * descendant of the local node in a certain tunnel. |
3612 | * If the info is not yet there (recently created path), creates the data struct | 3297 | * If the info is not yet there (recently created path), creates the data struct |
3613 | * and inserts it into the tunnel info, initialized to the current tunnel ACK | 3298 | * and inserts it into the tunnel info, initialized to the current tunnel ACK |
3614 | * values. | 3299 | * values. |
@@ -3618,41 +3303,44 @@ tunnel_add_skip (void *cls, | |||
3618 | * | 3303 | * |
3619 | * @return Neighbor's Flow Control info. | 3304 | * @return Neighbor's Flow Control info. |
3620 | */ | 3305 | */ |
3621 | static struct MeshTunnelFlowControlInfo * | 3306 | static struct MeshTunnelChildInfo * |
3622 | tunnel_get_neighbor_fc (struct MeshTunnel *t, | 3307 | tunnel_get_neighbor_fc (struct MeshTunnel *t, |
3623 | const struct GNUNET_PeerIdentity *peer) | 3308 | const struct GNUNET_PeerIdentity *peer) |
3624 | { | 3309 | { |
3625 | struct MeshTunnelFlowControlInfo *fcinfo; | 3310 | struct MeshTunnelChildInfo *cinfo; |
3626 | 3311 | ||
3627 | if (NULL == t->children_fc) | 3312 | if (NULL == t->children_fc) |
3628 | return NULL; | 3313 | return NULL; |
3629 | 3314 | ||
3630 | fcinfo = GNUNET_CONTAINER_multihashmap_get (t->children_fc, | 3315 | cinfo = GNUNET_CONTAINER_multihashmap_get (t->children_fc, |
3631 | &peer->hashPubKey); | 3316 | &peer->hashPubKey); |
3632 | if (NULL == fcinfo) | 3317 | if (NULL == cinfo) |
3633 | { | 3318 | { |
3634 | uint32_t delta; | 3319 | uint32_t delta; |
3635 | 3320 | ||
3636 | fcinfo = GNUNET_malloc (sizeof (struct MeshTunnelFlowControlInfo)); | 3321 | cinfo = GNUNET_malloc (sizeof (struct MeshTunnelChildInfo)); |
3637 | fcinfo->peer = peer_info_get(peer); | 3322 | cinfo->id = GNUNET_PEER_intern (peer); |
3638 | fcinfo->skip = t->fwd_pid; | 3323 | cinfo->skip = t->fwd_pid; |
3639 | fcinfo->t = t; | 3324 | cinfo->t = t; |
3640 | 3325 | ||
3641 | delta = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE; | 3326 | delta = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE; |
3642 | fcinfo->fwd_ack = t->fwd_pid + delta; | 3327 | cinfo->fwd_ack = t->fwd_pid + delta; |
3643 | fcinfo->bck_ack = delta; | 3328 | cinfo->bck_ack = delta; |
3644 | fcinfo->bck_pid = -1; | 3329 | cinfo->bck_pid = -1; |
3330 | |||
3331 | cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; | ||
3332 | cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
3645 | 3333 | ||
3646 | fcinfo->send_buffer = | 3334 | cinfo->send_buffer = |
3647 | GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max); | 3335 | GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max); |
3648 | 3336 | ||
3649 | GNUNET_assert (GNUNET_OK == | 3337 | GNUNET_assert (GNUNET_OK == |
3650 | GNUNET_CONTAINER_multihashmap_put (t->children_fc, | 3338 | GNUNET_CONTAINER_multihashmap_put (t->children_fc, |
3651 | &peer->hashPubKey, | 3339 | &peer->hashPubKey, |
3652 | fcinfo, | 3340 | cinfo, |
3653 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | 3341 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); |
3654 | } | 3342 | } |
3655 | return fcinfo; | 3343 | return cinfo; |
3656 | } | 3344 | } |
3657 | 3345 | ||
3658 | 3346 | ||
@@ -3664,7 +3352,7 @@ tunnel_get_neighbor_fc (struct MeshTunnel *t, | |||
3664 | * | 3352 | * |
3665 | * @return ACK value. | 3353 | * @return ACK value. |
3666 | */ | 3354 | */ |
3667 | static struct MeshTunnelFlowControlInfo * | 3355 | static struct MeshTunnelClientInfo * |
3668 | tunnel_get_client_fc (struct MeshTunnel *t, | 3356 | tunnel_get_client_fc (struct MeshTunnel *t, |
3669 | struct MeshClient *c) | 3357 | struct MeshClient *c) |
3670 | { | 3358 | { |
@@ -3677,7 +3365,7 @@ tunnel_get_client_fc (struct MeshTunnel *t, | |||
3677 | return &t->clients_fc[i]; | 3365 | return &t->clients_fc[i]; |
3678 | } | 3366 | } |
3679 | GNUNET_assert (0); | 3367 | GNUNET_assert (0); |
3680 | return NULL; // won't get here. Just to avoid compiler / coverity complaints. | 3368 | return NULL; // avoid compiler / coverity complaints |
3681 | } | 3369 | } |
3682 | 3370 | ||
3683 | 3371 | ||
@@ -3692,14 +3380,14 @@ tunnel_get_child_fwd_ack (void *cls, | |||
3692 | GNUNET_PEER_Id id) | 3380 | GNUNET_PEER_Id id) |
3693 | { | 3381 | { |
3694 | struct GNUNET_PeerIdentity peer_id; | 3382 | struct GNUNET_PeerIdentity peer_id; |
3695 | struct MeshTunnelFlowControlInfo *fcinfo; | 3383 | struct MeshTunnelChildInfo *cinfo; |
3696 | struct MeshTunnelChildIteratorContext *ctx = cls; | 3384 | struct MeshTunnelChildIteratorContext *ctx = cls; |
3697 | struct MeshTunnel *t = ctx->t; | 3385 | struct MeshTunnel *t = ctx->t; |
3698 | uint32_t ack; | 3386 | uint32_t ack; |
3699 | 3387 | ||
3700 | GNUNET_PEER_resolve (id, &peer_id); | 3388 | GNUNET_PEER_resolve (id, &peer_id); |
3701 | fcinfo = tunnel_get_neighbor_fc (t, &peer_id); | 3389 | cinfo = tunnel_get_neighbor_fc (t, &peer_id); |
3702 | ack = fcinfo->fwd_ack; | 3390 | ack = cinfo->fwd_ack; |
3703 | 3391 | ||
3704 | ctx->nchildren++; | 3392 | ctx->nchildren++; |
3705 | if (GNUNET_NO == ctx->init) | 3393 | if (GNUNET_NO == ctx->init) |
@@ -3716,6 +3404,7 @@ tunnel_get_child_fwd_ack (void *cls, | |||
3716 | { | 3404 | { |
3717 | ctx->max_child_ack = ctx->max_child_ack > ack ? ctx->max_child_ack : ack; | 3405 | ctx->max_child_ack = ctx->max_child_ack > ack ? ctx->max_child_ack : ack; |
3718 | } | 3406 | } |
3407 | |||
3719 | } | 3408 | } |
3720 | 3409 | ||
3721 | 3410 | ||
@@ -3857,7 +3546,12 @@ tunnel_get_fwd_ack (struct MeshTunnel *t) | |||
3857 | if (-1LL == child_ack) | 3546 | if (-1LL == child_ack) |
3858 | { | 3547 | { |
3859 | // Node has no children, child_ack AND core buffer are irrelevant. | 3548 | // Node has no children, child_ack AND core buffer are irrelevant. |
3860 | GNUNET_break (-1LL != client_ack); // No children AND no clients? Not good! | 3549 | if (-1LL == client_ack) // No children AND no clients? Not good! |
3550 | { | ||
3551 | GNUNET_STATISTICS_update (stats, "# mesh acks with no target", | ||
3552 | 1, GNUNET_NO); | ||
3553 | |||
3554 | } | ||
3861 | return (uint32_t) client_ack; | 3555 | return (uint32_t) client_ack; |
3862 | } | 3556 | } |
3863 | if (-1LL == client_ack) | 3557 | if (-1LL == client_ack) |
@@ -3993,13 +3687,17 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) | |||
3993 | case GNUNET_MESSAGE_TYPE_MESH_ACK: | 3687 | case GNUNET_MESSAGE_TYPE_MESH_ACK: |
3994 | case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: | 3688 | case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: |
3995 | break; | 3689 | break; |
3690 | case GNUNET_MESSAGE_TYPE_MESH_POLL: | ||
3691 | t->force_ack = GNUNET_YES; | ||
3692 | break; | ||
3996 | default: | 3693 | default: |
3997 | GNUNET_break (0); | 3694 | GNUNET_break (0); |
3998 | } | 3695 | } |
3999 | 3696 | ||
4000 | /* Check if we need no retransmit the ACK */ | 3697 | /* Check if we need to transmit the ACK */ |
4001 | if (t->fwd_queue_max > t->fwd_queue_n * 4 && | 3698 | if (t->fwd_queue_max > t->fwd_queue_n * 4 && |
4002 | GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid)) | 3699 | GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid) && |
3700 | GNUNET_NO == t->force_ack) | ||
4003 | { | 3701 | { |
4004 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n"); | 3702 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n"); |
4005 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3703 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -4015,7 +3713,7 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) | |||
4015 | ack = tunnel_get_fwd_ack (t); | 3713 | ack = tunnel_get_fwd_ack (t); |
4016 | 3714 | ||
4017 | /* If speed_min and not all children have ack'd, dont send yet */ | 3715 | /* If speed_min and not all children have ack'd, dont send yet */ |
4018 | if (ack == t->last_fwd_ack) | 3716 | if (ack == t->last_fwd_ack && GNUNET_NO == t->force_ack) |
4019 | { | 3717 | { |
4020 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n"); | 3718 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n"); |
4021 | return; | 3719 | return; |
@@ -4025,6 +3723,7 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) | |||
4025 | GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); | 3723 | GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); |
4026 | send_ack (t, &id, ack); | 3724 | send_ack (t, &id, ack); |
4027 | debug_fwd_ack++; | 3725 | debug_fwd_ack++; |
3726 | t->force_ack = GNUNET_NO; | ||
4028 | } | 3727 | } |
4029 | 3728 | ||
4030 | 3729 | ||
@@ -4040,27 +3739,25 @@ tunnel_send_child_bck_ack (void *cls, | |||
4040 | GNUNET_PEER_Id id) | 3739 | GNUNET_PEER_Id id) |
4041 | { | 3740 | { |
4042 | struct MeshTunnel *t = cls; | 3741 | struct MeshTunnel *t = cls; |
4043 | struct MeshTunnelFlowControlInfo *fcinfo; | 3742 | struct MeshTunnelChildInfo *cinfo; |
4044 | struct GNUNET_PeerIdentity peer; | 3743 | struct GNUNET_PeerIdentity peer; |
4045 | uint32_t ack; | 3744 | uint32_t ack; |
4046 | 3745 | ||
4047 | GNUNET_PEER_resolve (id, &peer); | 3746 | GNUNET_PEER_resolve (id, &peer); |
4048 | fcinfo = tunnel_get_neighbor_fc (t, &peer); | 3747 | cinfo = tunnel_get_neighbor_fc (t, &peer); |
4049 | ack = fcinfo->bck_pid + t->bck_queue_max - t->bck_queue_n; | 3748 | ack = cinfo->bck_pid + t->bck_queue_max - t->bck_queue_n; |
4050 | |||
4051 | 3749 | ||
4052 | if (fcinfo->bck_ack == ack) | 3750 | if (cinfo->bck_ack == ack && GNUNET_NO == t->force_ack) |
4053 | { | 3751 | { |
4054 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4055 | " Not sending ACK, not needed\n"); | 3753 | " Not sending ACK, not needed\n"); |
4056 | return; | 3754 | return; |
4057 | } | 3755 | } |
4058 | fcinfo->bck_ack = ack; | 3756 | cinfo->bck_ack = ack; |
4059 | 3757 | ||
4060 | fcinfo->bck_ack = fcinfo->bck_pid + t->bck_queue_max - t->bck_queue_n; | ||
4061 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3758 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4062 | " Sending BCK ACK %u (last sent: %u)\n", | 3759 | " Sending BCK ACK %u (last sent: %u)\n", |
4063 | ack, fcinfo->bck_ack); | 3760 | ack, cinfo->bck_ack); |
4064 | send_ack (t, &peer, ack); | 3761 | send_ack (t, &peer, ack); |
4065 | } | 3762 | } |
4066 | 3763 | ||
@@ -4094,11 +3791,11 @@ tunnel_send_clients_bck_ack (struct MeshTunnel *t) | |||
4094 | /* Find client whom to allow to send to origin (with lowest buffer space) */ | 3791 | /* Find client whom to allow to send to origin (with lowest buffer space) */ |
4095 | for (i = 0; i < t->nclients; i++) | 3792 | for (i = 0; i < t->nclients; i++) |
4096 | { | 3793 | { |
4097 | struct MeshTunnelFlowControlInfo *fcinfo; | 3794 | struct MeshTunnelClientInfo *clinfo; |
4098 | unsigned int delta; | 3795 | unsigned int delta; |
4099 | 3796 | ||
4100 | fcinfo = &t->clients_fc[i]; | 3797 | clinfo = &t->clients_fc[i]; |
4101 | delta = fcinfo->bck_ack - fcinfo->bck_pid; | 3798 | delta = clinfo->bck_ack - clinfo->bck_pid; |
4102 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u delta: %u\n", | 3799 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u delta: %u\n", |
4103 | t->clients[i]->id, delta); | 3800 | t->clients[i]->id, delta); |
4104 | 3801 | ||
@@ -4107,13 +3804,13 @@ tunnel_send_clients_bck_ack (struct MeshTunnel *t) | |||
4107 | { | 3804 | { |
4108 | uint32_t ack; | 3805 | uint32_t ack; |
4109 | 3806 | ||
4110 | ack = fcinfo->bck_pid; | 3807 | ack = clinfo->bck_pid; |
4111 | ack += t->nobuffer ? 1 : tunnel_delta; | 3808 | ack += t->nobuffer ? 1 : tunnel_delta; |
4112 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3809 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4113 | " sending ack to client %u: %u\n", | 3810 | " sending ack to client %u: %u\n", |
4114 | t->clients[i]->id, ack); | 3811 | t->clients[i]->id, ack); |
4115 | send_local_ack (t, t->clients[i], ack); | 3812 | send_local_ack (t, t->clients[i], ack); |
4116 | fcinfo->bck_ack = ack; | 3813 | clinfo->bck_ack = ack; |
4117 | } | 3814 | } |
4118 | else | 3815 | else |
4119 | { | 3816 | { |
@@ -4155,7 +3852,9 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) | |||
4155 | break; | 3852 | break; |
4156 | case GNUNET_MESSAGE_TYPE_MESH_ACK: | 3853 | case GNUNET_MESSAGE_TYPE_MESH_ACK: |
4157 | case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: | 3854 | case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: |
3855 | break; | ||
4158 | case GNUNET_MESSAGE_TYPE_MESH_POLL: | 3856 | case GNUNET_MESSAGE_TYPE_MESH_POLL: |
3857 | t->force_ack = GNUNET_YES; | ||
4159 | break; | 3858 | break; |
4160 | default: | 3859 | default: |
4161 | GNUNET_break (0); | 3860 | GNUNET_break (0); |
@@ -4163,6 +3862,7 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) | |||
4163 | 3862 | ||
4164 | tunnel_send_clients_bck_ack (t); | 3863 | tunnel_send_clients_bck_ack (t); |
4165 | tree_iterate_children (t->tree, &tunnel_send_child_bck_ack, t); | 3864 | tree_iterate_children (t->tree, &tunnel_send_child_bck_ack, t); |
3865 | t->force_ack = GNUNET_NO; | ||
4166 | } | 3866 | } |
4167 | 3867 | ||
4168 | 3868 | ||
@@ -4254,17 +3954,37 @@ tunnel_unlock_bck_queue (struct MeshTunnel *t) | |||
4254 | * valid. | 3954 | * valid. |
4255 | * | 3955 | * |
4256 | * @param t The tunnel whose peers to notify. | 3956 | * @param t The tunnel whose peers to notify. |
3957 | * @param parent ID of the parent, in case the tree is already destroyed. | ||
4257 | */ | 3958 | */ |
4258 | static void | 3959 | static void |
4259 | tunnel_send_destroy (struct MeshTunnel *t) | 3960 | tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent) |
4260 | { | 3961 | { |
4261 | struct GNUNET_MESH_TunnelDestroy msg; | 3962 | struct GNUNET_MESH_TunnelDestroy msg; |
3963 | struct GNUNET_PeerIdentity id; | ||
4262 | 3964 | ||
4263 | msg.header.size = htons (sizeof (msg)); | 3965 | msg.header.size = htons (sizeof (msg)); |
4264 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY); | 3966 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY); |
4265 | GNUNET_PEER_resolve (t->id.oid, &msg.oid); | 3967 | GNUNET_PEER_resolve (t->id.oid, &msg.oid); |
4266 | msg.tid = htonl (t->id.tid); | 3968 | msg.tid = htonl (t->id.tid); |
4267 | tunnel_send_multicast (t, &msg.header); | 3969 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
3970 | " sending tunnel destroy for tunnel: %s [%X]\n", | ||
3971 | GNUNET_i2s (&msg.oid), t->id.tid); | ||
3972 | if (tree_count_children(t->tree) > 0) | ||
3973 | { | ||
3974 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending multicast to children\n"); | ||
3975 | tunnel_send_multicast (t, &msg.header); | ||
3976 | } | ||
3977 | if (0 == parent) | ||
3978 | parent = tree_get_predecessor (t->tree); | ||
3979 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", parent); | ||
3980 | if (0 == parent) | ||
3981 | return; | ||
3982 | |||
3983 | GNUNET_PEER_resolve (parent, &id); | ||
3984 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3985 | " sending back to %s\n", | ||
3986 | GNUNET_i2s (&id)); | ||
3987 | send_prebuilt_message (&msg.header, &id, t); | ||
4268 | } | 3988 | } |
4269 | 3989 | ||
4270 | 3990 | ||
@@ -4377,17 +4097,10 @@ tunnel_destroy (struct MeshTunnel *t) | |||
4377 | } | 4097 | } |
4378 | } | 4098 | } |
4379 | 4099 | ||
4380 | if (t->nclients > 0) | 4100 | (void) GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t); |
4381 | { | 4101 | GNUNET_free_non_null (t->clients); |
4382 | if (GNUNET_YES != | 4102 | GNUNET_free_non_null (t->ignore); |
4383 | GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)) | 4103 | GNUNET_free_non_null (t->clients_fc); |
4384 | { | ||
4385 | GNUNET_break (0); | ||
4386 | r = GNUNET_SYSERR; | ||
4387 | } | ||
4388 | GNUNET_free (t->clients); | ||
4389 | GNUNET_free (t->clients_fc); | ||
4390 | } | ||
4391 | 4104 | ||
4392 | if (NULL != t->peers) | 4105 | if (NULL != t->peers) |
4393 | { | 4106 | { |
@@ -4405,8 +4118,8 @@ tunnel_destroy (struct MeshTunnel *t) | |||
4405 | tree_iterate_children (t->tree, &tunnel_cancel_queues, t); | 4118 | tree_iterate_children (t->tree, &tunnel_cancel_queues, t); |
4406 | tree_destroy (t->tree); | 4119 | tree_destroy (t->tree); |
4407 | 4120 | ||
4408 | if (NULL != t->regex_ctx) | 4121 | if (NULL != t->regex_search) |
4409 | regex_cancel_search (t->regex_ctx); | 4122 | GNUNET_REGEX_search_cancel (t->regex_search->search_handle); |
4410 | if (NULL != t->dht_get_type) | 4123 | if (NULL != t->dht_get_type) |
4411 | GNUNET_DHT_get_stop (t->dht_get_type); | 4124 | GNUNET_DHT_get_stop (t->dht_get_type); |
4412 | if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) | 4125 | if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) |
@@ -4420,6 +4133,82 @@ tunnel_destroy (struct MeshTunnel *t) | |||
4420 | return r; | 4133 | return r; |
4421 | } | 4134 | } |
4422 | 4135 | ||
4136 | #define TUNNEL_DESTROY_EMPTY_TIME GNUNET_TIME_UNIT_MILLISECONDS | ||
4137 | |||
4138 | /** | ||
4139 | * Tunnel is empty: destroy it. | ||
4140 | * | ||
4141 | * @param cls Closure (Tunnel). | ||
4142 | * @param tc TaskContext. | ||
4143 | */ | ||
4144 | static void | ||
4145 | tunnel_destroy_empty_delayed (void *cls, | ||
4146 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
4147 | { | ||
4148 | struct MeshTunnel *t = cls; | ||
4149 | |||
4150 | t->delayed_destroy = GNUNET_SCHEDULER_NO_TASK; | ||
4151 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
4152 | return; | ||
4153 | |||
4154 | if (0 != t->nclients || | ||
4155 | 0 != tree_count_children (t->tree)) | ||
4156 | return; | ||
4157 | |||
4158 | #if MESH_DEBUG | ||
4159 | { | ||
4160 | struct GNUNET_PeerIdentity id; | ||
4161 | |||
4162 | GNUNET_PEER_resolve (t->id.oid, &id); | ||
4163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4164 | "executing destruction of empty tunnel %s [%X]\n", | ||
4165 | GNUNET_i2s (&id), t->id.tid); | ||
4166 | } | ||
4167 | #endif | ||
4168 | |||
4169 | tunnel_send_destroy (t, 0); | ||
4170 | if (0 == t->pending_messages) | ||
4171 | tunnel_destroy (t); | ||
4172 | else | ||
4173 | t->destroy = GNUNET_YES; | ||
4174 | } | ||
4175 | |||
4176 | |||
4177 | /** | ||
4178 | * Schedule tunnel destruction if is empty and no new traffic comes in a time. | ||
4179 | * | ||
4180 | * @param t Tunnel to destroy if empty. | ||
4181 | */ | ||
4182 | static void | ||
4183 | tunnel_destroy_empty (struct MeshTunnel *t) | ||
4184 | { | ||
4185 | if (GNUNET_SCHEDULER_NO_TASK != t->delayed_destroy || | ||
4186 | 0 != t->nclients || | ||
4187 | 0 != tree_count_children (t->tree)) | ||
4188 | { | ||
4189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4190 | "%u %u %u\n", | ||
4191 | t->delayed_destroy, t->nclients, tree_count_children(t->tree)); | ||
4192 | return; | ||
4193 | } | ||
4194 | |||
4195 | #if MESH_DEBUG | ||
4196 | { | ||
4197 | struct GNUNET_PeerIdentity id; | ||
4198 | |||
4199 | GNUNET_PEER_resolve (t->id.oid, &id); | ||
4200 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4201 | "scheduling destruction of empty tunnel %s [%X]\n", | ||
4202 | GNUNET_i2s (&id), t->id.tid); | ||
4203 | } | ||
4204 | #endif | ||
4205 | |||
4206 | t->delayed_destroy = | ||
4207 | GNUNET_SCHEDULER_add_delayed (TUNNEL_DESTROY_EMPTY_TIME, | ||
4208 | &tunnel_destroy_empty_delayed, | ||
4209 | t); | ||
4210 | } | ||
4211 | |||
4423 | 4212 | ||
4424 | /** | 4213 | /** |
4425 | * Create a new tunnel | 4214 | * Create a new tunnel |
@@ -4491,6 +4280,19 @@ tunnel_new (GNUNET_PEER_Id owner, | |||
4491 | return t; | 4280 | return t; |
4492 | } | 4281 | } |
4493 | 4282 | ||
4283 | /** | ||
4284 | * Callback when removing children from a tunnel tree. Notify owner. | ||
4285 | * | ||
4286 | * @param cls Closure (tunnel). | ||
4287 | * @param peer_id Short ID of the peer deleted. | ||
4288 | */ | ||
4289 | void | ||
4290 | tunnel_child_removed (void *cls, GNUNET_PEER_Id peer_id) | ||
4291 | { | ||
4292 | struct MeshTunnel *t = cls; | ||
4293 | |||
4294 | client_notify_peer_disconnected (t->owner, t, peer_id); | ||
4295 | } | ||
4494 | 4296 | ||
4495 | /** | 4297 | /** |
4496 | * Removes an explicit path from a tunnel, freeing all intermediate nodes | 4298 | * Removes an explicit path from a tunnel, freeing all intermediate nodes |
@@ -4503,8 +4305,15 @@ tunnel_new (GNUNET_PEER_Id owner, | |||
4503 | static void | 4305 | static void |
4504 | tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer) | 4306 | tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer) |
4505 | { | 4307 | { |
4506 | if (GNUNET_NO == tree_del_peer (t->tree, peer, NULL, NULL)) | 4308 | int r; |
4507 | tunnel_destroy (t); | 4309 | |
4310 | r = tree_del_peer (t->tree, peer, &tunnel_child_removed, t); | ||
4311 | if (GNUNET_NO == r) | ||
4312 | { | ||
4313 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4314 | "Tunnel %u [%u] has no more nodes\n", | ||
4315 | t->id.oid, t->id.tid); | ||
4316 | } | ||
4508 | } | 4317 | } |
4509 | 4318 | ||
4510 | 4319 | ||
@@ -4521,21 +4330,23 @@ tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer) | |||
4521 | * @return GNUNET_OK, keep iterating. | 4330 | * @return GNUNET_OK, keep iterating. |
4522 | */ | 4331 | */ |
4523 | static int | 4332 | static int |
4524 | tunnel_destroy_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) | 4333 | tunnel_destroy_iterator (void *cls, |
4334 | const struct GNUNET_HashCode * key, | ||
4335 | void *value) | ||
4525 | { | 4336 | { |
4526 | struct MeshTunnel *t = value; | 4337 | struct MeshTunnel *t = value; |
4527 | struct MeshClient *c = cls; | 4338 | struct MeshClient *c = cls; |
4528 | 4339 | ||
4529 | send_client_tunnel_disconnect(t, c); | 4340 | send_client_tunnel_disconnect (t, c); |
4530 | if (c != t->owner) | 4341 | if (c != t->owner) |
4531 | { | 4342 | { |
4532 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 4343 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id); |
4533 | "Client %u is destination, keeping the tunnel alive.\n", c->id); | 4344 | tunnel_delete_client (t, c); |
4534 | tunnel_delete_client(t, c); | 4345 | client_delete_tunnel (c, t); |
4535 | client_delete_tunnel(c, t); | 4346 | tunnel_destroy_empty (t); |
4536 | return GNUNET_OK; | 4347 | return GNUNET_OK; |
4537 | } | 4348 | } |
4538 | tunnel_send_destroy(t); | 4349 | tunnel_send_destroy (t, 0); |
4539 | t->owner = NULL; | 4350 | t->owner = NULL; |
4540 | t->destroy = GNUNET_YES; | 4351 | t->destroy = GNUNET_YES; |
4541 | 4352 | ||
@@ -4751,7 +4562,7 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) | |||
4751 | { | 4562 | { |
4752 | struct MeshTransmissionDescriptor *dd; | 4563 | struct MeshTransmissionDescriptor *dd; |
4753 | struct MeshPathInfo *path_info; | 4564 | struct MeshPathInfo *path_info; |
4754 | struct MeshTunnelFlowControlInfo *fcinfo; | 4565 | struct MeshTunnelChildInfo *cinfo; |
4755 | struct GNUNET_PeerIdentity id; | 4566 | struct GNUNET_PeerIdentity id; |
4756 | unsigned int i; | 4567 | unsigned int i; |
4757 | unsigned int max; | 4568 | unsigned int max; |
@@ -4761,14 +4572,14 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) | |||
4761 | switch (queue->type) | 4572 | switch (queue->type) |
4762 | { | 4573 | { |
4763 | case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: | 4574 | case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: |
4764 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " cancelling TUNNEL_DESTROY\n"); | 4575 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " cancelling TUNNEL_DESTROY\n"); |
4765 | GNUNET_assert (GNUNET_YES == queue->tunnel->destroy); | 4576 | GNUNET_break (GNUNET_YES == queue->tunnel->destroy); |
4766 | /* FIXME: don't cancel, send and destroy tunnel in queue_send */ | ||
4767 | /* fall through */ | 4577 | /* fall through */ |
4768 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: | 4578 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: |
4769 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: | 4579 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: |
4770 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | 4580 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: |
4771 | case GNUNET_MESSAGE_TYPE_MESH_ACK: | 4581 | case GNUNET_MESSAGE_TYPE_MESH_ACK: |
4582 | case GNUNET_MESSAGE_TYPE_MESH_POLL: | ||
4772 | case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: | 4583 | case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: |
4773 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 4584 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4774 | " prebuilt message\n"); | 4585 | " prebuilt message\n"); |
@@ -4798,30 +4609,29 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) | |||
4798 | /* Delete from child_fc in the appropiate tunnel */ | 4609 | /* Delete from child_fc in the appropiate tunnel */ |
4799 | max = queue->tunnel->fwd_queue_max; | 4610 | max = queue->tunnel->fwd_queue_max; |
4800 | GNUNET_PEER_resolve (queue->peer->id, &id); | 4611 | GNUNET_PEER_resolve (queue->peer->id, &id); |
4801 | fcinfo = tunnel_get_neighbor_fc (queue->tunnel, &id); | 4612 | cinfo = tunnel_get_neighbor_fc (queue->tunnel, &id); |
4802 | if (NULL != fcinfo) | 4613 | if (NULL != cinfo) |
4803 | { | 4614 | { |
4804 | GNUNET_assert (NULL != fcinfo->peer); | 4615 | for (i = 0; i < cinfo->send_buffer_n; i++) |
4805 | for (i = 0; i < fcinfo->send_buffer_n; i++) | ||
4806 | { | 4616 | { |
4807 | unsigned int i2; | 4617 | unsigned int i2; |
4808 | i2 = (fcinfo->send_buffer_start + i) % max; | 4618 | i2 = (cinfo->send_buffer_start + i) % max; |
4809 | if (fcinfo->send_buffer[i2] == queue) | 4619 | if (cinfo->send_buffer[i2] == queue) |
4810 | { | 4620 | { |
4811 | /* Found corresponding entry in the send_buffer. Move all others back. */ | 4621 | /* Found corresponding entry in the send_buffer. Move all others back. */ |
4812 | unsigned int j; | 4622 | unsigned int j; |
4813 | unsigned int j2; | 4623 | unsigned int j2; |
4814 | unsigned int j3; | 4624 | unsigned int j3; |
4815 | 4625 | ||
4816 | for (j = i, j2 = 0, j3 = 0; j < fcinfo->send_buffer_n - 1; j++) | 4626 | for (j = i, j2 = 0, j3 = 0; j < cinfo->send_buffer_n - 1; j++) |
4817 | { | 4627 | { |
4818 | j2 = (fcinfo->send_buffer_start + j) % max; | 4628 | j2 = (cinfo->send_buffer_start + j) % max; |
4819 | j3 = (fcinfo->send_buffer_start + j + 1) % max; | 4629 | j3 = (cinfo->send_buffer_start + j + 1) % max; |
4820 | fcinfo->send_buffer[j2] = fcinfo->send_buffer[j3]; | 4630 | cinfo->send_buffer[j2] = cinfo->send_buffer[j3]; |
4821 | } | 4631 | } |
4822 | 4632 | ||
4823 | fcinfo->send_buffer[j3] = NULL; | 4633 | cinfo->send_buffer[j3] = NULL; |
4824 | fcinfo->send_buffer_n--; | 4634 | cinfo->send_buffer_n--; |
4825 | } | 4635 | } |
4826 | } | 4636 | } |
4827 | } | 4637 | } |
@@ -4847,7 +4657,7 @@ queue_get_next (const struct MeshPeerInfo *peer) | |||
4847 | struct MeshPeerQueue *q; | 4657 | struct MeshPeerQueue *q; |
4848 | struct MeshTunnel *t; | 4658 | struct MeshTunnel *t; |
4849 | struct MeshTransmissionDescriptor *info; | 4659 | struct MeshTransmissionDescriptor *info; |
4850 | struct MeshTunnelFlowControlInfo *fcinfo; | 4660 | struct MeshTunnelChildInfo *cinfo; |
4851 | struct GNUNET_MESH_Unicast *ucast; | 4661 | struct GNUNET_MESH_Unicast *ucast; |
4852 | struct GNUNET_MESH_ToOrigin *to_orig; | 4662 | struct GNUNET_MESH_ToOrigin *to_orig; |
4853 | struct GNUNET_MESH_Multicast *mcast; | 4663 | struct GNUNET_MESH_Multicast *mcast; |
@@ -4869,8 +4679,8 @@ queue_get_next (const struct MeshPeerInfo *peer) | |||
4869 | ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; | 4679 | ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; |
4870 | pid = ntohl (ucast->pid); | 4680 | pid = ntohl (ucast->pid); |
4871 | GNUNET_PEER_resolve (info->peer->id, &id); | 4681 | GNUNET_PEER_resolve (info->peer->id, &id); |
4872 | fcinfo = tunnel_get_neighbor_fc (t, &id); | 4682 | cinfo = tunnel_get_neighbor_fc(t, &id); |
4873 | ack = fcinfo->fwd_ack; | 4683 | ack = cinfo->fwd_ack; |
4874 | break; | 4684 | break; |
4875 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | 4685 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: |
4876 | to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data; | 4686 | to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data; |
@@ -4886,8 +4696,8 @@ queue_get_next (const struct MeshPeerInfo *peer) | |||
4886 | } | 4696 | } |
4887 | pid = ntohl (mcast->pid); | 4697 | pid = ntohl (mcast->pid); |
4888 | GNUNET_PEER_resolve (info->peer->id, &id); | 4698 | GNUNET_PEER_resolve (info->peer->id, &id); |
4889 | fcinfo = tunnel_get_neighbor_fc (t, &id); | 4699 | cinfo = tunnel_get_neighbor_fc(t, &id); |
4890 | ack = fcinfo->fwd_ack; | 4700 | ack = cinfo->fwd_ack; |
4891 | break; | 4701 | break; |
4892 | default: | 4702 | default: |
4893 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 4703 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -4931,12 +4741,12 @@ queue_send (void *cls, size_t size, void *buf) | |||
4931 | struct GNUNET_MessageHeader *msg; | 4741 | struct GNUNET_MessageHeader *msg; |
4932 | struct MeshPeerQueue *queue; | 4742 | struct MeshPeerQueue *queue; |
4933 | struct MeshTunnel *t; | 4743 | struct MeshTunnel *t; |
4934 | struct MeshTunnelFlowControlInfo *fcinfo; | 4744 | struct MeshTunnelChildInfo *cinfo; |
4935 | struct GNUNET_PeerIdentity dst_id; | 4745 | struct GNUNET_PeerIdentity dst_id; |
4936 | size_t data_size; | 4746 | size_t data_size; |
4937 | 4747 | ||
4938 | peer->core_transmit = NULL; | 4748 | peer->core_transmit = NULL; |
4939 | fcinfo = NULL; | 4749 | cinfo = NULL; |
4940 | 4750 | ||
4941 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n"); | 4751 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n"); |
4942 | queue = queue_get_next (peer); | 4752 | queue = queue_get_next (peer); |
@@ -4974,6 +4784,8 @@ queue_send (void *cls, size_t size, void *buf) | |||
4974 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* size ok\n"); | 4784 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* size ok\n"); |
4975 | 4785 | ||
4976 | t = queue->tunnel; | 4786 | t = queue->tunnel; |
4787 | GNUNET_assert (0 < t->pending_messages); | ||
4788 | t->pending_messages--; | ||
4977 | if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type) | 4789 | if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type) |
4978 | { | 4790 | { |
4979 | t->fwd_queue_n--; | 4791 | t->fwd_queue_n--; |
@@ -5031,6 +4843,12 @@ queue_send (void *cls, size_t size, void *buf) | |||
5031 | "********* considered sent\n"); | 4843 | "********* considered sent\n"); |
5032 | t->fwd_queue_n--; | 4844 | t->fwd_queue_n--; |
5033 | } | 4845 | } |
4846 | else | ||
4847 | { | ||
4848 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4849 | "********* NOT considered sent yet\n"); | ||
4850 | t->pending_messages++; | ||
4851 | } | ||
5034 | } | 4852 | } |
5035 | data_size = send_core_data_multicast(queue->cls, size, buf); | 4853 | data_size = send_core_data_multicast(queue->cls, size, buf); |
5036 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST); | 4854 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST); |
@@ -5059,22 +4877,22 @@ queue_send (void *cls, size_t size, void *buf) | |||
5059 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: | 4877 | case GNUNET_MESSAGE_TYPE_MESH_UNICAST: |
5060 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: | 4878 | case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: |
5061 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: | 4879 | case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: |
5062 | fcinfo = tunnel_get_neighbor_fc (t, &dst_id); | 4880 | cinfo = tunnel_get_neighbor_fc (t, &dst_id); |
5063 | if (fcinfo->send_buffer[fcinfo->send_buffer_start] != queue) | 4881 | if (cinfo->send_buffer[cinfo->send_buffer_start] != queue) |
5064 | { | 4882 | { |
5065 | GNUNET_break (0); | 4883 | GNUNET_break (0); |
5066 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 4884 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
5067 | "at pos %u (%p) != %p\n", | 4885 | "at pos %u (%p) != %p\n", |
5068 | fcinfo->send_buffer_start, | 4886 | cinfo->send_buffer_start, |
5069 | fcinfo->send_buffer[fcinfo->send_buffer_start], | 4887 | cinfo->send_buffer[cinfo->send_buffer_start], |
5070 | queue); | 4888 | queue); |
5071 | } | 4889 | } |
5072 | if (fcinfo->send_buffer_n > 0) | 4890 | if (cinfo->send_buffer_n > 0) |
5073 | { | 4891 | { |
5074 | fcinfo->send_buffer[fcinfo->send_buffer_start] = NULL; | 4892 | cinfo->send_buffer[cinfo->send_buffer_start] = NULL; |
5075 | fcinfo->send_buffer_n--; | 4893 | cinfo->send_buffer_n--; |
5076 | fcinfo->send_buffer_start++; | 4894 | cinfo->send_buffer_start++; |
5077 | fcinfo->send_buffer_start %= t->fwd_queue_max; | 4895 | cinfo->send_buffer_start %= t->fwd_queue_max; |
5078 | } | 4896 | } |
5079 | else | 4897 | else |
5080 | { | 4898 | { |
@@ -5088,9 +4906,8 @@ queue_send (void *cls, size_t size, void *buf) | |||
5088 | /* Free queue, but cls was freed by send_core_* */ | 4906 | /* Free queue, but cls was freed by send_core_* */ |
5089 | queue_destroy (queue, GNUNET_NO); | 4907 | queue_destroy (queue, GNUNET_NO); |
5090 | 4908 | ||
5091 | if (GNUNET_YES == t->destroy) | 4909 | if (GNUNET_YES == t->destroy && 0 == t->pending_messages) |
5092 | { | 4910 | { |
5093 | // FIXME fc tunnel destroy all pending traffic? wait for it? | ||
5094 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* destroying tunnel!\n"); | 4911 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* destroying tunnel!\n"); |
5095 | tunnel_destroy (t); | 4912 | tunnel_destroy (t); |
5096 | } | 4913 | } |
@@ -5120,10 +4937,14 @@ queue_send (void *cls, size_t size, void *buf) | |||
5120 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 4937 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
5121 | "********* %s stalled\n", | 4938 | "********* %s stalled\n", |
5122 | GNUNET_i2s(&my_full_id)); | 4939 | GNUNET_i2s(&my_full_id)); |
5123 | if (NULL == fcinfo) | 4940 | if (NULL == cinfo) |
5124 | fcinfo = tunnel_get_neighbor_fc (t, &dst_id); | 4941 | cinfo = tunnel_get_neighbor_fc (t, &dst_id); |
5125 | fcinfo->fc_poll = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, | 4942 | // FIXME unify bck/fwd structures, bck does not have cinfo right now |
5126 | &tunnel_poll, fcinfo); | 4943 | if (NULL != cinfo && GNUNET_SCHEDULER_NO_TASK == cinfo->fc_poll) |
4944 | { | ||
4945 | cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time, | ||
4946 | &tunnel_poll, cinfo); | ||
4947 | } | ||
5127 | } | 4948 | } |
5128 | } | 4949 | } |
5129 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* return %d\n", data_size); | 4950 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* return %d\n", data_size); |
@@ -5153,7 +4974,7 @@ queue_add (void *cls, uint16_t type, size_t size, | |||
5153 | struct MeshPeerInfo *dst, struct MeshTunnel *t) | 4974 | struct MeshPeerInfo *dst, struct MeshTunnel *t) |
5154 | { | 4975 | { |
5155 | struct MeshPeerQueue *queue; | 4976 | struct MeshPeerQueue *queue; |
5156 | struct MeshTunnelFlowControlInfo *fcinfo; | 4977 | struct MeshTunnelChildInfo *cinfo; |
5157 | struct GNUNET_PeerIdentity id; | 4978 | struct GNUNET_PeerIdentity id; |
5158 | unsigned int *max; | 4979 | unsigned int *max; |
5159 | unsigned int *n; | 4980 | unsigned int *n; |
@@ -5175,17 +4996,11 @@ queue_add (void *cls, uint16_t type, size_t size, | |||
5175 | { | 4996 | { |
5176 | if (*n >= *max) | 4997 | if (*n >= *max) |
5177 | { | 4998 | { |
5178 | struct MeshTransmissionDescriptor *td = cls; | ||
5179 | struct GNUNET_MESH_ToOrigin *to; | ||
5180 | |||
5181 | to = td->mesh_data->data; | ||
5182 | GNUNET_break(0); | 4999 | GNUNET_break(0); |
5183 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 5000 | GNUNET_STATISTICS_update(stats, |
5184 | "bck pid %u, bck ack %u, msg pid %u\n", | 5001 | "# messages dropped (buffer full)", |
5185 | t->bck_pid, t->bck_ack, ntohl(to->pid)); | ||
5186 | GNUNET_STATISTICS_update(stats, "# messages dropped (buffer full)", | ||
5187 | 1, GNUNET_NO); | 5002 | 1, GNUNET_NO); |
5188 | return; // Drop message | 5003 | return; // Drop message |
5189 | } | 5004 | } |
5190 | (*n)++; | 5005 | (*n)++; |
5191 | } | 5006 | } |
@@ -5209,28 +5024,29 @@ queue_add (void *cls, uint16_t type, size_t size, | |||
5209 | &queue_send, | 5024 | &queue_send, |
5210 | dst); | 5025 | dst); |
5211 | } | 5026 | } |
5027 | t->pending_messages++; | ||
5212 | if (NULL == n) // Is this internal mesh traffic? | 5028 | if (NULL == n) // Is this internal mesh traffic? |
5213 | return; | 5029 | return; |
5214 | 5030 | ||
5215 | // It's payload, keep track of buffer per peer. | 5031 | // It's payload, keep track of buffer per peer. |
5216 | fcinfo = tunnel_get_neighbor_fc (t, &id); | 5032 | cinfo = tunnel_get_neighbor_fc(t, &id); |
5217 | i = (fcinfo->send_buffer_start + fcinfo->send_buffer_n) % t->fwd_queue_max; | 5033 | i = (cinfo->send_buffer_start + cinfo->send_buffer_n) % t->fwd_queue_max; |
5218 | if (NULL != fcinfo->send_buffer[i]) | 5034 | if (NULL != cinfo->send_buffer[i]) |
5219 | { | 5035 | { |
5220 | GNUNET_break (fcinfo->send_buffer_n == t->fwd_queue_max); // aka i == start | 5036 | GNUNET_break (cinfo->send_buffer_n == t->fwd_queue_max); // aka i == start |
5221 | queue_destroy (fcinfo->send_buffer[fcinfo->send_buffer_start], GNUNET_YES); | 5037 | queue_destroy (cinfo->send_buffer[cinfo->send_buffer_start], GNUNET_YES); |
5222 | fcinfo->send_buffer_start++; | 5038 | cinfo->send_buffer_start++; |
5223 | fcinfo->send_buffer_start %= t->fwd_queue_max; | 5039 | cinfo->send_buffer_start %= t->fwd_queue_max; |
5224 | } | 5040 | } |
5225 | else | 5041 | else |
5226 | { | 5042 | { |
5227 | fcinfo->send_buffer_n++; | 5043 | cinfo->send_buffer_n++; |
5228 | } | 5044 | } |
5229 | fcinfo->send_buffer[i] = queue; | 5045 | cinfo->send_buffer[i] = queue; |
5230 | if (fcinfo->send_buffer_n > t->fwd_queue_max) | 5046 | if (cinfo->send_buffer_n > t->fwd_queue_max) |
5231 | { | 5047 | { |
5232 | GNUNET_break (0); | 5048 | GNUNET_break (0); |
5233 | fcinfo->send_buffer_n = t->fwd_queue_max; | 5049 | cinfo->send_buffer_n = t->fwd_queue_max; |
5234 | } | 5050 | } |
5235 | } | 5051 | } |
5236 | 5052 | ||
@@ -5571,26 +5387,43 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5571 | { | 5387 | { |
5572 | struct GNUNET_MESH_TunnelDestroy *msg; | 5388 | struct GNUNET_MESH_TunnelDestroy *msg; |
5573 | struct MeshTunnel *t; | 5389 | struct MeshTunnel *t; |
5390 | GNUNET_PEER_Id parent; | ||
5391 | GNUNET_PEER_Id pid; | ||
5574 | 5392 | ||
5575 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5576 | "Got a TUNNEL DESTROY packet from %s\n", GNUNET_i2s (peer)); | ||
5577 | msg = (struct GNUNET_MESH_TunnelDestroy *) message; | 5393 | msg = (struct GNUNET_MESH_TunnelDestroy *) message; |
5578 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for tunnel %s [%u]\n", | 5394 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
5395 | "Got a TUNNEL DESTROY packet from %s\n", | ||
5396 | GNUNET_i2s (peer)); | ||
5397 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5398 | " for tunnel %s [%u]\n", | ||
5579 | GNUNET_i2s (&msg->oid), ntohl (msg->tid)); | 5399 | GNUNET_i2s (&msg->oid), ntohl (msg->tid)); |
5580 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); | 5400 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); |
5401 | /* Check signature */ | ||
5581 | if (NULL == t) | 5402 | if (NULL == t) |
5582 | { | 5403 | { |
5583 | /* Probably already got the message from another path, | 5404 | /* Probably already got the message from another path, |
5584 | * destroyed the tunnel and retransmitted to children. | 5405 | * destroyed the tunnel and retransmitted to children. |
5585 | * Safe to ignore. | 5406 | * Safe to ignore. |
5586 | */ | 5407 | */ |
5587 | GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO); | 5408 | GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", |
5409 | 1, GNUNET_NO); | ||
5588 | return GNUNET_OK; | 5410 | return GNUNET_OK; |
5589 | } | 5411 | } |
5590 | if (t->id.oid == myid) | 5412 | parent = tree_get_predecessor (t->tree); |
5413 | pid = GNUNET_PEER_search (peer); | ||
5414 | if (pid != parent) | ||
5591 | { | 5415 | { |
5592 | GNUNET_break_op (0); | 5416 | unsigned int nc; |
5593 | return GNUNET_OK; | 5417 | |
5418 | tree_del_peer (t->tree, pid, &tunnel_child_removed, t); | ||
5419 | nc = tree_count_children (t->tree); | ||
5420 | if (nc > 0 || NULL != t->owner || t->nclients > 0) | ||
5421 | { | ||
5422 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5423 | "still in use: %u cl, %u ch\n", | ||
5424 | t->nclients, nc); | ||
5425 | return GNUNET_OK; | ||
5426 | } | ||
5594 | } | 5427 | } |
5595 | if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) | 5428 | if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) |
5596 | { | 5429 | { |
@@ -5599,7 +5432,7 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5599 | t->local_tid, t->local_tid_dest); | 5432 | t->local_tid, t->local_tid_dest); |
5600 | send_clients_tunnel_destroy (t); | 5433 | send_clients_tunnel_destroy (t); |
5601 | } | 5434 | } |
5602 | tunnel_send_destroy (t); | 5435 | tunnel_send_destroy (t, parent); |
5603 | t->destroy = GNUNET_YES; | 5436 | t->destroy = GNUNET_YES; |
5604 | // TODO: add timeout to destroy the tunnel anyway | 5437 | // TODO: add timeout to destroy the tunnel anyway |
5605 | return GNUNET_OK; | 5438 | return GNUNET_OK; |
@@ -5625,7 +5458,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5625 | { | 5458 | { |
5626 | struct GNUNET_MESH_Unicast *msg; | 5459 | struct GNUNET_MESH_Unicast *msg; |
5627 | struct GNUNET_PeerIdentity *neighbor; | 5460 | struct GNUNET_PeerIdentity *neighbor; |
5628 | struct MeshTunnelFlowControlInfo *fcinfo; | 5461 | struct MeshTunnelChildInfo *cinfo; |
5629 | struct MeshTunnel *t; | 5462 | struct MeshTunnel *t; |
5630 | GNUNET_PEER_Id dest_id; | 5463 | GNUNET_PEER_Id dest_id; |
5631 | uint32_t pid; | 5464 | uint32_t pid; |
@@ -5706,16 +5539,16 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5706 | " not for us, retransmitting...\n"); | 5539 | " not for us, retransmitting...\n"); |
5707 | 5540 | ||
5708 | neighbor = tree_get_first_hop (t->tree, dest_id); | 5541 | neighbor = tree_get_first_hop (t->tree, dest_id); |
5709 | fcinfo = tunnel_get_neighbor_fc (t, neighbor); | 5542 | cinfo = tunnel_get_neighbor_fc (t, neighbor); |
5710 | fcinfo->fwd_pid = pid; | 5543 | cinfo->fwd_pid = pid; |
5711 | GNUNET_CONTAINER_multihashmap_iterate (t->children_fc, | 5544 | GNUNET_CONTAINER_multihashmap_iterate (t->children_fc, |
5712 | &tunnel_add_skip, | 5545 | &tunnel_add_skip, |
5713 | &neighbor); | 5546 | &neighbor); |
5714 | if (GNUNET_YES == t->nobuffer && | 5547 | if (GNUNET_YES == t->nobuffer && |
5715 | GNUNET_YES == GMC_is_pid_bigger (pid, fcinfo->fwd_ack)) | 5548 | GNUNET_YES == GMC_is_pid_bigger (pid, cinfo->fwd_ack)) |
5716 | { | 5549 | { |
5717 | GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); | 5550 | GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); |
5718 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u > %u\n", pid, fcinfo->fwd_ack); | 5551 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u > %u\n", pid, cinfo->fwd_ack); |
5719 | GNUNET_break_op (0); | 5552 | GNUNET_break_op (0); |
5720 | return GNUNET_OK; | 5553 | return GNUNET_OK; |
5721 | } | 5554 | } |
@@ -5831,7 +5664,8 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5831 | struct GNUNET_PeerIdentity id; | 5664 | struct GNUNET_PeerIdentity id; |
5832 | struct MeshPeerInfo *peer_info; | 5665 | struct MeshPeerInfo *peer_info; |
5833 | struct MeshTunnel *t; | 5666 | struct MeshTunnel *t; |
5834 | struct MeshTunnelFlowControlInfo *fcinfo; | 5667 | struct MeshTunnelChildInfo *cinfo; |
5668 | GNUNET_PEER_Id predecessor; | ||
5835 | size_t size; | 5669 | size_t size; |
5836 | uint32_t pid; | 5670 | uint32_t pid; |
5837 | 5671 | ||
@@ -5854,21 +5688,20 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5854 | { | 5688 | { |
5855 | /* TODO notify that we dont know this tunnel (whom)? */ | 5689 | /* TODO notify that we dont know this tunnel (whom)? */ |
5856 | GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO); | 5690 | GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO); |
5857 | GNUNET_break_op (0); | ||
5858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 5691 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
5859 | "Received to_origin with PID %u on unknown tunnel\n", | 5692 | "Received to_origin with PID %u on unknown tunnel %s [%u]\n", |
5860 | pid); | 5693 | pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid)); |
5861 | return GNUNET_OK; | 5694 | return GNUNET_OK; |
5862 | } | 5695 | } |
5863 | 5696 | ||
5864 | fcinfo = tunnel_get_neighbor_fc (t, peer); | 5697 | cinfo = tunnel_get_neighbor_fc(t, peer); |
5865 | if (NULL == fcinfo) | 5698 | if (NULL == cinfo) |
5866 | { | 5699 | { |
5867 | GNUNET_break (0); | 5700 | GNUNET_break (0); |
5868 | return GNUNET_OK; | 5701 | return GNUNET_OK; |
5869 | } | 5702 | } |
5870 | 5703 | ||
5871 | if (fcinfo->bck_pid == pid) | 5704 | if (cinfo->bck_pid == pid) |
5872 | { | 5705 | { |
5873 | /* already seen this packet, drop */ | 5706 | /* already seen this packet, drop */ |
5874 | GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO); | 5707 | GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO); |
@@ -5880,7 +5713,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5880 | 5713 | ||
5881 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 5714 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
5882 | " pid %u not seen yet, forwarding\n", pid); | 5715 | " pid %u not seen yet, forwarding\n", pid); |
5883 | fcinfo->bck_pid = pid; | 5716 | cinfo->bck_pid = pid; |
5884 | 5717 | ||
5885 | if (NULL != t->owner) | 5718 | if (NULL != t->owner) |
5886 | { | 5719 | { |
@@ -5911,7 +5744,31 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5911 | GNUNET_break (0); | 5744 | GNUNET_break (0); |
5912 | return GNUNET_OK; | 5745 | return GNUNET_OK; |
5913 | } | 5746 | } |
5914 | GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); | 5747 | predecessor = tree_get_predecessor (t->tree); |
5748 | if (0 == predecessor) | ||
5749 | { | ||
5750 | if (GNUNET_YES == t->destroy) | ||
5751 | { | ||
5752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5753 | "to orig received on a dying tunnel %s [%X]\n", | ||
5754 | GNUNET_i2s (&msg->oid), ntohl(msg->tid)); | ||
5755 | return GNUNET_OK; | ||
5756 | } | ||
5757 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
5758 | "unknown to origin at %s\n", | ||
5759 | GNUNET_i2s (&my_full_id)); | ||
5760 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
5761 | "from peer %s\n", | ||
5762 | GNUNET_i2s (peer)); | ||
5763 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
5764 | "for tunnel %s [%X]\n", | ||
5765 | GNUNET_i2s (&msg->oid), ntohl(msg->tid)); | ||
5766 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
5767 | "current tree:\n"); | ||
5768 | tree_debug (t->tree); | ||
5769 | return GNUNET_OK; | ||
5770 | } | ||
5771 | GNUNET_PEER_resolve (predecessor, &id); | ||
5915 | send_prebuilt_message (message, &id, t); | 5772 | send_prebuilt_message (message, &id, t); |
5916 | GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO); | 5773 | GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO); |
5917 | 5774 | ||
@@ -5951,7 +5808,6 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5951 | { | 5808 | { |
5952 | /* TODO notify that we dont know this tunnel (whom)? */ | 5809 | /* TODO notify that we dont know this tunnel (whom)? */ |
5953 | GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO); | 5810 | GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO); |
5954 | GNUNET_break_op (0); | ||
5955 | return GNUNET_OK; | 5811 | return GNUNET_OK; |
5956 | } | 5812 | } |
5957 | ack = ntohl (msg->pid); | 5813 | ack = ntohl (msg->pid); |
@@ -5960,14 +5816,20 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
5960 | /* Is this a forward or backward ACK? */ | 5816 | /* Is this a forward or backward ACK? */ |
5961 | if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) | 5817 | if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) |
5962 | { | 5818 | { |
5963 | struct MeshTunnelFlowControlInfo *fcinfo; | 5819 | struct MeshTunnelChildInfo *cinfo; |
5964 | 5820 | ||
5965 | debug_bck_ack++; | 5821 | debug_bck_ack++; |
5966 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); | 5822 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); |
5967 | fcinfo = tunnel_get_neighbor_fc (t, peer); | 5823 | cinfo = tunnel_get_neighbor_fc (t, peer); |
5968 | fcinfo->fwd_ack = ack; | 5824 | cinfo->fwd_ack = ack; |
5969 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); | 5825 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); |
5970 | tunnel_unlock_fwd_queues (t); | 5826 | tunnel_unlock_fwd_queues (t); |
5827 | if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll) | ||
5828 | { | ||
5829 | GNUNET_SCHEDULER_cancel (cinfo->fc_poll); | ||
5830 | cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; | ||
5831 | cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
5832 | } | ||
5971 | } | 5833 | } |
5972 | else | 5834 | else |
5973 | { | 5835 | { |
@@ -6019,11 +5881,11 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6019 | /* Is this a forward or backward ACK? */ | 5881 | /* Is this a forward or backward ACK? */ |
6020 | if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) | 5882 | if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) |
6021 | { | 5883 | { |
6022 | struct MeshTunnelFlowControlInfo *fcinfo; | 5884 | struct MeshTunnelChildInfo *cinfo; |
6023 | 5885 | ||
6024 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n"); | 5886 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n"); |
6025 | fcinfo = tunnel_get_neighbor_fc (t, peer); | 5887 | cinfo = tunnel_get_neighbor_fc (t, peer); |
6026 | fcinfo->bck_ack = fcinfo->fwd_pid; // mark as ready to send | 5888 | cinfo->bck_ack = cinfo->fwd_pid; // mark as ready to send |
6027 | tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); | 5889 | tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); |
6028 | } | 5890 | } |
6029 | else | 5891 | else |
@@ -6035,7 +5897,6 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6035 | return GNUNET_OK; | 5897 | return GNUNET_OK; |
6036 | } | 5898 | } |
6037 | 5899 | ||
6038 | |||
6039 | /** | 5900 | /** |
6040 | * Core handler for path ACKs | 5901 | * Core handler for path ACKs |
6041 | * | 5902 | * |
@@ -6081,12 +5942,12 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6081 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", | 5942 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", |
6082 | GNUNET_i2s (peer)); | 5943 | GNUNET_i2s (peer)); |
6083 | 5944 | ||
6084 | if (NULL != t->regex_ctx && t->regex_ctx->info->peer == peer_info->id) | 5945 | if (NULL != t->regex_search && t->regex_search->peer == peer_info->id) |
6085 | { | 5946 | { |
6086 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 5947 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
6087 | "connect_by_string completed, stopping search\n"); | 5948 | "connect_by_string completed, stopping search\n"); |
6088 | regex_cancel_search (t->regex_ctx); | 5949 | regex_cancel_search (t->regex_search); |
6089 | t->regex_ctx = NULL; | 5950 | t->regex_search = NULL; |
6090 | } | 5951 | } |
6091 | 5952 | ||
6092 | /* Add paths to peers? */ | 5953 | /* Add paths to peers? */ |
@@ -6169,8 +6030,8 @@ handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6169 | if (NULL == t) | 6030 | if (NULL == t) |
6170 | { | 6031 | { |
6171 | /* TODO notify that we dont know that tunnel */ | 6032 | /* TODO notify that we dont know that tunnel */ |
6172 | GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1, GNUNET_NO); | 6033 | GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1, |
6173 | GNUNET_break_op (0); | 6034 | GNUNET_NO); |
6174 | return GNUNET_OK; | 6035 | return GNUNET_OK; |
6175 | } | 6036 | } |
6176 | 6037 | ||
@@ -6414,140 +6275,6 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
6414 | } | 6275 | } |
6415 | 6276 | ||
6416 | 6277 | ||
6417 | /** | ||
6418 | * Function to process DHT string to regex matching. | ||
6419 | * Called on each result obtained for the DHT search. | ||
6420 | * | ||
6421 | * @param cls closure (search context) | ||
6422 | * @param exp when will this value expire | ||
6423 | * @param key key of the result | ||
6424 | * @param get_path path of the get request (not used) | ||
6425 | * @param get_path_length lenght of get_path (not used) | ||
6426 | * @param put_path path of the put request (not used) | ||
6427 | * @param put_path_length length of the put_path (not used) | ||
6428 | * @param type type of the result | ||
6429 | * @param size number of bytes in data | ||
6430 | * @param data pointer to the result data | ||
6431 | */ | ||
6432 | static void | ||
6433 | dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
6434 | const struct GNUNET_HashCode * key, | ||
6435 | const struct GNUNET_PeerIdentity *get_path, | ||
6436 | unsigned int get_path_length, | ||
6437 | const struct GNUNET_PeerIdentity *put_path, | ||
6438 | unsigned int put_path_length, | ||
6439 | enum GNUNET_BLOCK_Type type, | ||
6440 | size_t size, const void *data) | ||
6441 | { | ||
6442 | const struct MeshRegexAccept *block = data; | ||
6443 | struct MeshRegexSearchContext *ctx = cls; | ||
6444 | struct MeshRegexSearchInfo *info = ctx->info; | ||
6445 | struct MeshPeerPath *p; | ||
6446 | struct MeshPeerInfo *peer_info; | ||
6447 | |||
6448 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | ||
6449 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", info->description); | ||
6450 | |||
6451 | peer_info = peer_info_get(&block->id); | ||
6452 | p = path_build_from_dht (get_path, get_path_length, put_path, | ||
6453 | put_path_length); | ||
6454 | path_add_to_peers (p, GNUNET_NO); | ||
6455 | path_destroy(p); | ||
6456 | |||
6457 | tunnel_add_peer (info->t, peer_info); | ||
6458 | peer_info_connect (peer_info, info->t); | ||
6459 | if (0 == info->peer) | ||
6460 | { | ||
6461 | info->peer = peer_info->id; | ||
6462 | } | ||
6463 | else | ||
6464 | { | ||
6465 | GNUNET_array_append (info->peers, info->n_peers, peer_info->id); | ||
6466 | } | ||
6467 | |||
6468 | info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, | ||
6469 | ®ex_connect_timeout, | ||
6470 | info); | ||
6471 | |||
6472 | return; | ||
6473 | } | ||
6474 | |||
6475 | |||
6476 | /** | ||
6477 | * Function to process DHT string to regex matching. | ||
6478 | * Called on each result obtained for the DHT search. | ||
6479 | * | ||
6480 | * @param cls closure (search context) | ||
6481 | * @param exp when will this value expire | ||
6482 | * @param key key of the result | ||
6483 | * @param get_path path of the get request (not used) | ||
6484 | * @param get_path_length lenght of get_path (not used) | ||
6485 | * @param put_path path of the put request (not used) | ||
6486 | * @param put_path_length length of the put_path (not used) | ||
6487 | * @param type type of the result | ||
6488 | * @param size number of bytes in data | ||
6489 | * @param data pointer to the result data | ||
6490 | * | ||
6491 | * TODO: re-issue the request after certain time? cancel after X results? | ||
6492 | */ | ||
6493 | static void | ||
6494 | dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
6495 | const struct GNUNET_HashCode * key, | ||
6496 | const struct GNUNET_PeerIdentity *get_path, | ||
6497 | unsigned int get_path_length, | ||
6498 | const struct GNUNET_PeerIdentity *put_path, | ||
6499 | unsigned int put_path_length, | ||
6500 | enum GNUNET_BLOCK_Type type, | ||
6501 | size_t size, const void *data) | ||
6502 | { | ||
6503 | const struct MeshRegexBlock *block = data; | ||
6504 | struct MeshRegexSearchContext *ctx = cls; | ||
6505 | struct MeshRegexSearchInfo *info = ctx->info; | ||
6506 | void *copy; | ||
6507 | size_t len; | ||
6508 | |||
6509 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6510 | "DHT GET STRING RETURNED RESULTS\n"); | ||
6511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6512 | " key: %s\n", GNUNET_h2s (key)); | ||
6513 | |||
6514 | copy = GNUNET_malloc (size); | ||
6515 | memcpy (copy, data, size); | ||
6516 | GNUNET_break (GNUNET_OK == | ||
6517 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_results, key, copy, | ||
6518 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
6519 | len = ntohl (block->n_proof); | ||
6520 | { | ||
6521 | char proof[len + 1]; | ||
6522 | |||
6523 | memcpy (proof, &block[1], len); | ||
6524 | proof[len] = '\0'; | ||
6525 | if (GNUNET_OK != GNUNET_REGEX_check_proof (proof, key)) | ||
6526 | { | ||
6527 | GNUNET_break_op (0); | ||
6528 | return; | ||
6529 | } | ||
6530 | } | ||
6531 | len = strlen (info->description); | ||
6532 | if (len == ctx->position) // String processed | ||
6533 | { | ||
6534 | if (GNUNET_YES == ntohl (block->accepting)) | ||
6535 | { | ||
6536 | regex_find_path(key, ctx); | ||
6537 | } | ||
6538 | else | ||
6539 | { | ||
6540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " block not accepting!\n"); | ||
6541 | // FIXME REGEX this block not successful, wait for more? start timeout? | ||
6542 | } | ||
6543 | return; | ||
6544 | } | ||
6545 | |||
6546 | regex_next_edge (block, size, ctx); | ||
6547 | |||
6548 | return; | ||
6549 | } | ||
6550 | |||
6551 | /******************************************************************************/ | 6278 | /******************************************************************************/ |
6552 | /********************* MESH LOCAL HANDLES **************************/ | 6279 | /********************* MESH LOCAL HANDLES **************************/ |
6553 | /******************************************************************************/ | 6280 | /******************************************************************************/ |
@@ -6573,6 +6300,7 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
6573 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); | 6300 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); |
6574 | return; | 6301 | return; |
6575 | } | 6302 | } |
6303 | |||
6576 | c = clients; | 6304 | c = clients; |
6577 | while (NULL != c) | 6305 | while (NULL != c) |
6578 | { | 6306 | { |
@@ -6615,6 +6343,8 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
6615 | for (i = 0; i < c->n_regex; i++) | 6343 | for (i = 0; i < c->n_regex; i++) |
6616 | { | 6344 | { |
6617 | GNUNET_free (c->regexes[i].regex); | 6345 | GNUNET_free (c->regexes[i].regex); |
6346 | if (NULL != c->regexes[i].h) | ||
6347 | GNUNET_REGEX_announce_cancel (c->regexes[i].h); | ||
6618 | } | 6348 | } |
6619 | GNUNET_free_non_null (c->regexes); | 6349 | GNUNET_free_non_null (c->regexes); |
6620 | if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task) | 6350 | if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task) |
@@ -6742,11 +6472,12 @@ static void | |||
6742 | handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, | 6472 | handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, |
6743 | const struct GNUNET_MessageHeader *message) | 6473 | const struct GNUNET_MessageHeader *message) |
6744 | { | 6474 | { |
6745 | struct GNUNET_MESH_RegexAnnounce *msg; | 6475 | const struct GNUNET_MESH_RegexAnnounce *msg; |
6746 | struct MeshRegexDescriptor rd; | 6476 | struct MeshRegexDescriptor rd; |
6747 | struct MeshClient *c; | 6477 | struct MeshClient *c; |
6748 | char *regex; | 6478 | char *regex; |
6749 | size_t len; | 6479 | size_t len; |
6480 | size_t offset; | ||
6750 | 6481 | ||
6751 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n"); | 6482 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n"); |
6752 | 6483 | ||
@@ -6759,20 +6490,46 @@ handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, | |||
6759 | } | 6490 | } |
6760 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | 6491 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); |
6761 | 6492 | ||
6762 | msg = (struct GNUNET_MESH_RegexAnnounce *) message; | 6493 | msg = (const struct GNUNET_MESH_RegexAnnounce *) message; |
6494 | |||
6763 | len = ntohs (message->size) - sizeof(struct GNUNET_MESH_RegexAnnounce); | 6495 | len = ntohs (message->size) - sizeof(struct GNUNET_MESH_RegexAnnounce); |
6764 | regex = GNUNET_malloc (len + 1); | 6496 | if (NULL != c->partial_regex) |
6765 | memcpy (regex, &msg[1], len); | 6497 | { |
6766 | regex[len] = '\0'; | 6498 | regex = c->partial_regex; |
6499 | offset = strlen (c->partial_regex); | ||
6500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6501 | " continuation, already have %u bytes\n", | ||
6502 | offset); | ||
6503 | } | ||
6504 | else | ||
6505 | { | ||
6506 | regex = NULL; | ||
6507 | offset = 0; | ||
6508 | } | ||
6509 | |||
6510 | regex = GNUNET_realloc (regex, offset + len + 1); | ||
6511 | memcpy (®ex[offset], &msg[1], len); | ||
6512 | regex[offset + len] = '\0'; | ||
6513 | if (0 == ntohs (msg->last)) | ||
6514 | { | ||
6515 | c->partial_regex = regex; | ||
6516 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6517 | " not ended, stored %u bytes for later\n", | ||
6518 | len); | ||
6519 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
6520 | return; | ||
6521 | } | ||
6767 | rd.regex = regex; | 6522 | rd.regex = regex; |
6768 | rd.compression = ntohs (msg->compression_characters); | 6523 | rd.compression = ntohs (msg->compression_characters); |
6524 | rd.h = NULL; | ||
6769 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len); | 6525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len); |
6770 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex); | 6526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex); |
6771 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " cm %u\n", ntohs(rd.compression)); | 6527 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " cm %u\n", ntohs(rd.compression)); |
6772 | GNUNET_array_append (c->regexes, c->n_regex, rd); | 6528 | GNUNET_array_append (c->regexes, c->n_regex, rd); |
6529 | c->partial_regex = NULL; | ||
6773 | if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task) | 6530 | if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task) |
6774 | { | 6531 | { |
6775 | c->regex_announce_task = GNUNET_SCHEDULER_add_now(&announce_regex, c); | 6532 | c->regex_announce_task = GNUNET_SCHEDULER_add_now(®ex_announce, c); |
6776 | } | 6533 | } |
6777 | else | 6534 | else |
6778 | { | 6535 | { |
@@ -6907,30 +6664,18 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | |||
6907 | if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) | 6664 | if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) |
6908 | { | 6665 | { |
6909 | client_ignore_tunnel (c, t); | 6666 | client_ignore_tunnel (c, t); |
6910 | #if 0 | 6667 | tunnel_destroy_empty (t); |
6911 | // TODO: when to destroy incoming tunnel? | ||
6912 | if (t->nclients == 0) | ||
6913 | { | ||
6914 | GNUNET_assert (GNUNET_YES == | ||
6915 | GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, | ||
6916 | &hash, t)); | ||
6917 | GNUNET_assert (GNUNET_YES == | ||
6918 | GNUNET_CONTAINER_multihashmap_remove (t->peers, | ||
6919 | &my_full_id.hashPubKey, | ||
6920 | t)); | ||
6921 | } | ||
6922 | #endif | ||
6923 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 6668 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
6924 | return; | 6669 | return; |
6925 | } | 6670 | } |
6926 | send_client_tunnel_disconnect(t, c); | 6671 | send_client_tunnel_disconnect (t, c); |
6927 | client_delete_tunnel(c, t); | 6672 | client_delete_tunnel (c, t); |
6928 | 6673 | ||
6929 | /* Don't try to ACK the client about the tunnel_destroy multicast packet */ | 6674 | /* Don't try to ACK the client about the tunnel_destroy multicast packet */ |
6930 | t->owner = NULL; | 6675 | t->owner = NULL; |
6931 | tunnel_send_destroy (t); | 6676 | tunnel_send_destroy (t, 0); |
6932 | t->destroy = GNUNET_YES; | 6677 | t->destroy = GNUNET_YES; |
6933 | // The tunnel will be destroyed when the last message is transmitted. | 6678 | /* The tunnel will be destroyed when the last message is transmitted. */ |
6934 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 6679 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
6935 | return; | 6680 | return; |
6936 | } | 6681 | } |
@@ -7441,9 +7186,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7441 | const struct GNUNET_MessageHeader *message) | 7186 | const struct GNUNET_MessageHeader *message) |
7442 | { | 7187 | { |
7443 | struct GNUNET_MESH_ConnectPeerByString *msg; | 7188 | struct GNUNET_MESH_ConnectPeerByString *msg; |
7444 | struct MeshRegexSearchContext *ctx; | ||
7445 | struct MeshRegexSearchInfo *info; | 7189 | struct MeshRegexSearchInfo *info; |
7446 | struct GNUNET_DHT_GetHandle *get_h; | ||
7447 | struct GNUNET_HashCode key; | 7190 | struct GNUNET_HashCode key; |
7448 | struct MeshTunnel *t; | 7191 | struct MeshTunnel *t; |
7449 | struct MeshClient *c; | 7192 | struct MeshClient *c; |
@@ -7451,6 +7194,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7451 | const char *string; | 7194 | const char *string; |
7452 | size_t size; | 7195 | size_t size; |
7453 | size_t len; | 7196 | size_t len; |
7197 | |||
7454 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7198 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
7455 | "Connect by string started\n"); | 7199 | "Connect by string started\n"); |
7456 | msg = (struct GNUNET_MESH_ConnectPeerByString *) message; | 7200 | msg = (struct GNUNET_MESH_ConnectPeerByString *) message; |
@@ -7498,7 +7242,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7498 | 7242 | ||
7499 | /* Only one connect_by_string allowed at the same time! */ | 7243 | /* Only one connect_by_string allowed at the same time! */ |
7500 | /* FIXME: allow more, return handle at api level to cancel, document */ | 7244 | /* FIXME: allow more, return handle at api level to cancel, document */ |
7501 | if (NULL != t->regex_ctx) | 7245 | if (NULL != t->regex_search) |
7502 | { | 7246 | { |
7503 | GNUNET_break (0); | 7247 | GNUNET_break (0); |
7504 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 7248 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -7510,7 +7254,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7510 | string = (const char *) &msg[1]; | 7254 | string = (const char *) &msg[1]; |
7511 | 7255 | ||
7512 | /* Initialize context */ | 7256 | /* Initialize context */ |
7513 | size = GNUNET_REGEX_get_first_key(string, len, &key); | 7257 | size = GNUNET_REGEX_get_first_key (string, len, &key); |
7514 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7258 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
7515 | " consumed %u bits out of %u\n", size, len); | 7259 | " consumed %u bits out of %u\n", size, len); |
7516 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -7518,35 +7262,15 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7518 | 7262 | ||
7519 | info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo)); | 7263 | info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo)); |
7520 | info->t = t; | 7264 | info->t = t; |
7521 | info->description = GNUNET_malloc (len + 1); | 7265 | info->description = GNUNET_strndup (string, len); |
7522 | memcpy (info->description, string, len); | ||
7523 | info->description[len] = '\0'; | ||
7524 | info->dht_get_handles = GNUNET_CONTAINER_multihashmap_create(32, GNUNET_NO); | ||
7525 | info->dht_get_results = GNUNET_CONTAINER_multihashmap_create(32, GNUNET_NO); | ||
7526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description); | 7266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description); |
7527 | 7267 | ||
7528 | ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext)); | 7268 | t->regex_search = info; |
7529 | ctx->position = size; | ||
7530 | ctx->info = info; | ||
7531 | t->regex_ctx = ctx; | ||
7532 | 7269 | ||
7533 | GNUNET_array_append (info->contexts, info->n_contexts, ctx); | 7270 | info->search_handle = GNUNET_REGEX_search (dht_handle, |
7534 | 7271 | info->description, | |
7535 | /* Start search in DHT */ | 7272 | ®ex_found_handler, info, |
7536 | get_h = GNUNET_DHT_get_start (dht_handle, /* handle */ | 7273 | stats); |
7537 | GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */ | ||
7538 | &key, /* key to search */ | ||
7539 | dht_replication_level, /* replication level */ | ||
7540 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
7541 | NULL, /* xquery */ // FIXME BLOOMFILTER | ||
7542 | 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE | ||
7543 | &dht_get_string_handler, ctx); | ||
7544 | |||
7545 | GNUNET_break (GNUNET_OK == | ||
7546 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | ||
7547 | &key, | ||
7548 | get_h, | ||
7549 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
7550 | 7274 | ||
7551 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 7275 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
7552 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n"); | 7276 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n"); |
@@ -7670,7 +7394,7 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
7670 | const struct GNUNET_MessageHeader *message) | 7394 | const struct GNUNET_MessageHeader *message) |
7671 | { | 7395 | { |
7672 | struct GNUNET_MESH_ToOrigin *data_msg; | 7396 | struct GNUNET_MESH_ToOrigin *data_msg; |
7673 | struct MeshTunnelFlowControlInfo *fcinfo; | 7397 | struct MeshTunnelClientInfo *clinfo; |
7674 | struct MeshClient *c; | 7398 | struct MeshClient *c; |
7675 | struct MeshTunnel *t; | 7399 | struct MeshTunnel *t; |
7676 | MESH_TunnelNumber tid; | 7400 | MESH_TunnelNumber tid; |
@@ -7727,18 +7451,18 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, | |||
7727 | } | 7451 | } |
7728 | 7452 | ||
7729 | /* PID should be as expected */ | 7453 | /* PID should be as expected */ |
7730 | fcinfo = tunnel_get_client_fc (t, c); | 7454 | clinfo = tunnel_get_client_fc (t, c); |
7731 | if (ntohl (data_msg->pid) != fcinfo->bck_pid + 1) | 7455 | if (ntohl (data_msg->pid) != clinfo->bck_pid + 1) |
7732 | { | 7456 | { |
7733 | GNUNET_break (0); | 7457 | GNUNET_break (0); |
7734 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 7458 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
7735 | "To Origin PID, expected %u, got %u\n", | 7459 | "To Origin PID, expected %u, got %u\n", |
7736 | fcinfo->bck_pid + 1, | 7460 | clinfo->bck_pid + 1, |
7737 | ntohl (data_msg->pid)); | 7461 | ntohl (data_msg->pid)); |
7738 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 7462 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
7739 | return; | 7463 | return; |
7740 | } | 7464 | } |
7741 | fcinfo->bck_pid++; | 7465 | clinfo->bck_pid++; |
7742 | 7466 | ||
7743 | /* Ok, everything is correct, send the message | 7467 | /* Ok, everything is correct, send the message |
7744 | * (pretend we got it from a mesh peer) | 7468 | * (pretend we got it from a mesh peer) |
@@ -7902,7 +7626,7 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, | |||
7902 | ack = ntohl (msg->max_pid); | 7626 | ack = ntohl (msg->max_pid); |
7903 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); | 7627 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); |
7904 | 7628 | ||
7905 | /* Does client own tunnel? I.E: Is this and ACK for BCK traffic? */ | 7629 | /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ |
7906 | if (NULL != t->owner && t->owner->handle == client) | 7630 | if (NULL != t->owner && t->owner->handle == client) |
7907 | { | 7631 | { |
7908 | /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ | 7632 | /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ |
@@ -7916,13 +7640,300 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, | |||
7916 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); | 7640 | tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); |
7917 | } | 7641 | } |
7918 | 7642 | ||
7919 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 7643 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
7920 | 7644 | ||
7921 | return; | 7645 | return; |
7922 | } | 7646 | } |
7923 | 7647 | ||
7924 | 7648 | ||
7925 | /** | 7649 | /** |
7650 | * Iterator over all peers to send a monitoring client info about a tunnel. | ||
7651 | * | ||
7652 | * @param cls Closure (message being built). | ||
7653 | * @param key Key (hashed tunnel ID, unused). | ||
7654 | * @param value Peer info. | ||
7655 | * | ||
7656 | * @return GNUNET_YES, to keep iterating. | ||
7657 | */ | ||
7658 | static int | ||
7659 | monitor_peers_iterator (void *cls, | ||
7660 | const struct GNUNET_HashCode * key, | ||
7661 | void *value) | ||
7662 | { | ||
7663 | struct GNUNET_MESH_LocalMonitor *msg = cls; | ||
7664 | struct GNUNET_PeerIdentity *id; | ||
7665 | struct MeshPeerInfo *info = value; | ||
7666 | |||
7667 | id = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
7668 | GNUNET_PEER_resolve (info->id, &id[msg->npeers]); | ||
7669 | msg->npeers++; | ||
7670 | |||
7671 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7672 | "* sending info about peer %s [%u]\n", | ||
7673 | GNUNET_i2s (&id[msg->npeers - 1]), msg->npeers); | ||
7674 | |||
7675 | return GNUNET_YES; | ||
7676 | } | ||
7677 | |||
7678 | |||
7679 | |||
7680 | /** | ||
7681 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
7682 | * | ||
7683 | * @param cls Closure (client handle). | ||
7684 | * @param key Key (hashed tunnel ID, unused). | ||
7685 | * @param value Tunnel info. | ||
7686 | * | ||
7687 | * @return GNUNET_YES, to keep iterating. | ||
7688 | */ | ||
7689 | static int | ||
7690 | monitor_all_tunnels_iterator (void *cls, | ||
7691 | const struct GNUNET_HashCode * key, | ||
7692 | void *value) | ||
7693 | { | ||
7694 | struct GNUNET_SERVER_Client *client = cls; | ||
7695 | struct MeshTunnel *t = value; | ||
7696 | struct GNUNET_MESH_LocalMonitor *msg; | ||
7697 | uint32_t npeers; | ||
7698 | |||
7699 | npeers = GNUNET_CONTAINER_multihashmap_size (t->peers); | ||
7700 | msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor) + | ||
7701 | npeers * sizeof (struct GNUNET_PeerIdentity)); | ||
7702 | GNUNET_PEER_resolve(t->id.oid, &msg->owner); | ||
7703 | msg->tunnel_id = htonl (t->id.tid); | ||
7704 | msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor) + | ||
7705 | npeers * sizeof (struct GNUNET_PeerIdentity)); | ||
7706 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); | ||
7707 | msg->npeers = 0; | ||
7708 | (void) GNUNET_CONTAINER_multihashmap_iterate (t->peers, | ||
7709 | monitor_peers_iterator, | ||
7710 | msg); | ||
7711 | |||
7712 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7713 | "* sending info about tunnel %s [%u] (%u peers)\n", | ||
7714 | GNUNET_i2s (&msg->owner), t->id.tid, npeers); | ||
7715 | |||
7716 | if (msg->npeers != npeers) | ||
7717 | { | ||
7718 | GNUNET_break (0); | ||
7719 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
7720 | "Get tunnels fail: size %u - iter %u\n", | ||
7721 | npeers, msg->npeers); | ||
7722 | } | ||
7723 | |||
7724 | msg->npeers = htonl (npeers); | ||
7725 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
7726 | &msg->header, GNUNET_NO); | ||
7727 | return GNUNET_YES; | ||
7728 | } | ||
7729 | |||
7730 | |||
7731 | /** | ||
7732 | * Handler for client's MONITOR request. | ||
7733 | * | ||
7734 | * @param cls Closure (unused). | ||
7735 | * @param client Identification of the client. | ||
7736 | * @param message The actual message. | ||
7737 | */ | ||
7738 | static void | ||
7739 | handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, | ||
7740 | const struct GNUNET_MessageHeader *message) | ||
7741 | { | ||
7742 | struct MeshClient *c; | ||
7743 | |||
7744 | /* Sanity check for client registration */ | ||
7745 | if (NULL == (c = client_get (client))) | ||
7746 | { | ||
7747 | GNUNET_break (0); | ||
7748 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
7749 | return; | ||
7750 | } | ||
7751 | |||
7752 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7753 | "Received get tunnels request from client %u\n", | ||
7754 | c->id); | ||
7755 | GNUNET_CONTAINER_multihashmap_iterate (tunnels, | ||
7756 | monitor_all_tunnels_iterator, | ||
7757 | client); | ||
7758 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7759 | "Get tunnels request from client %u completed\n", | ||
7760 | c->id); | ||
7761 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
7762 | } | ||
7763 | |||
7764 | |||
7765 | /** | ||
7766 | * Data needed to build a Monitor_Tunnel message. | ||
7767 | */ | ||
7768 | struct MeshMonitorTunnelContext | ||
7769 | { | ||
7770 | /** | ||
7771 | * Partial message, including peer count. | ||
7772 | */ | ||
7773 | struct GNUNET_MESH_LocalMonitor *msg; | ||
7774 | |||
7775 | /** | ||
7776 | * Hashmap with positions: peer->position. | ||
7777 | */ | ||
7778 | struct GNUNET_CONTAINER_MultiHashMap *lookup; | ||
7779 | |||
7780 | /** | ||
7781 | * Index of the parent of each peer in the message, realtive to the absolute | ||
7782 | * order in the array (can be in a previous message). | ||
7783 | */ | ||
7784 | uint32_t parents[1024]; | ||
7785 | |||
7786 | /** | ||
7787 | * Peers visited so far in the tree, aka position of the current peer. | ||
7788 | */ | ||
7789 | unsigned int npeers; | ||
7790 | |||
7791 | /** | ||
7792 | * Client requesting the info. | ||
7793 | */ | ||
7794 | struct MeshClient *c; | ||
7795 | }; | ||
7796 | |||
7797 | |||
7798 | /** | ||
7799 | * Send a client a message about the structure of a tunnel. | ||
7800 | * | ||
7801 | * @param ctx Context of the tunnel iteration, with info regarding the state | ||
7802 | * of the execution and the number of peers visited for this message. | ||
7803 | */ | ||
7804 | static void | ||
7805 | send_client_tunnel_info (struct MeshMonitorTunnelContext *ctx) | ||
7806 | { | ||
7807 | struct GNUNET_MESH_LocalMonitor *resp = ctx->msg; | ||
7808 | struct GNUNET_PeerIdentity *pid; | ||
7809 | unsigned int *parent; | ||
7810 | size_t size; | ||
7811 | |||
7812 | size = sizeof (struct GNUNET_MESH_LocalMonitor); | ||
7813 | size += (sizeof (struct GNUNET_PeerIdentity) + sizeof (int)) * resp->npeers; | ||
7814 | resp->header.size = htons (size); | ||
7815 | pid = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
7816 | parent = (unsigned int *) &pid[resp->npeers]; | ||
7817 | memcpy (parent, ctx->parents, sizeof(uint32_t) * resp->npeers); | ||
7818 | GNUNET_SERVER_notification_context_unicast (nc, ctx->c->handle, | ||
7819 | &resp->header, GNUNET_NO); | ||
7820 | } | ||
7821 | |||
7822 | /** | ||
7823 | * Iterator over a tunnel tree to build a message containing all peers | ||
7824 | * the in the tunnel, including relay nodes. | ||
7825 | * | ||
7826 | * @param cls Closure (pointer to pointer of message being built). | ||
7827 | * @param peer Short ID of a peer. | ||
7828 | * @param parent Short ID of the @c peer 's parent. | ||
7829 | */ | ||
7830 | static void | ||
7831 | tunnel_tree_iterator (void *cls, | ||
7832 | GNUNET_PEER_Id peer, | ||
7833 | GNUNET_PEER_Id parent) | ||
7834 | { | ||
7835 | struct MeshMonitorTunnelContext *ctx = cls; | ||
7836 | struct GNUNET_MESH_LocalMonitor *msg; | ||
7837 | struct GNUNET_PeerIdentity *pid; | ||
7838 | struct GNUNET_PeerIdentity ppid; | ||
7839 | |||
7840 | msg = ctx->msg; | ||
7841 | pid = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
7842 | GNUNET_PEER_resolve (peer, &pid[msg->npeers]); | ||
7843 | GNUNET_CONTAINER_multihashmap_put (ctx->lookup, | ||
7844 | &pid[msg->npeers].hashPubKey, | ||
7845 | (void *) (long) ctx->npeers, | ||
7846 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
7847 | GNUNET_PEER_resolve (parent, &ppid); | ||
7848 | ctx->parents[msg->npeers] = | ||
7849 | htonl ((long) GNUNET_CONTAINER_multihashmap_get (ctx->lookup, | ||
7850 | &ppid.hashPubKey)); | ||
7851 | |||
7852 | ctx->npeers++; | ||
7853 | msg->npeers++; | ||
7854 | |||
7855 | if (sizeof (struct GNUNET_MESH_LocalMonitor) + | ||
7856 | (msg->npeers + 1) * | ||
7857 | (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t)) | ||
7858 | > USHRT_MAX) | ||
7859 | { | ||
7860 | send_client_tunnel_info (ctx); | ||
7861 | msg->npeers = 0; | ||
7862 | } | ||
7863 | } | ||
7864 | |||
7865 | |||
7866 | /** | ||
7867 | * Handler for client's MONITOR_TUNNEL request. | ||
7868 | * | ||
7869 | * @param cls Closure (unused). | ||
7870 | * @param client Identification of the client. | ||
7871 | * @param message The actual message. | ||
7872 | */ | ||
7873 | static void | ||
7874 | handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, | ||
7875 | const struct GNUNET_MessageHeader *message) | ||
7876 | { | ||
7877 | const struct GNUNET_MESH_LocalMonitor *msg; | ||
7878 | struct GNUNET_MESH_LocalMonitor *resp; | ||
7879 | struct MeshMonitorTunnelContext ctx; | ||
7880 | struct MeshClient *c; | ||
7881 | struct MeshTunnel *t; | ||
7882 | |||
7883 | /* Sanity check for client registration */ | ||
7884 | if (NULL == (c = client_get (client))) | ||
7885 | { | ||
7886 | GNUNET_break (0); | ||
7887 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
7888 | return; | ||
7889 | } | ||
7890 | |||
7891 | msg = (struct GNUNET_MESH_LocalMonitor *) message; | ||
7892 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7893 | "Received tunnel info request from client %u for tunnel %s[%X]\n", | ||
7894 | c->id, | ||
7895 | &msg->owner, | ||
7896 | ntohl (msg->tunnel_id)); | ||
7897 | t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id)); | ||
7898 | if (NULL == t) | ||
7899 | { | ||
7900 | /* We don't know the tunnel */ | ||
7901 | struct GNUNET_MESH_LocalMonitor warn; | ||
7902 | |||
7903 | warn = *msg; | ||
7904 | warn.npeers = htonl (UINT_MAX); | ||
7905 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
7906 | &warn.header, | ||
7907 | GNUNET_NO); | ||
7908 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
7909 | return; | ||
7910 | } | ||
7911 | |||
7912 | /* Initialize context */ | ||
7913 | resp = GNUNET_malloc (USHRT_MAX); /* avoid realloc'ing on each step */ | ||
7914 | *resp = *msg; | ||
7915 | resp->npeers = 0; | ||
7916 | ctx.msg = resp; | ||
7917 | ctx.lookup = GNUNET_CONTAINER_multihashmap_create (4 * t->peers_total, | ||
7918 | GNUNET_YES); | ||
7919 | ctx.c = c; | ||
7920 | |||
7921 | /* Collect and send information */ | ||
7922 | tree_iterate_all (t->tree, &tunnel_tree_iterator, &ctx); | ||
7923 | send_client_tunnel_info (&ctx); | ||
7924 | |||
7925 | /* Free context */ | ||
7926 | GNUNET_CONTAINER_multihashmap_destroy (ctx.lookup); | ||
7927 | GNUNET_free (resp); | ||
7928 | |||
7929 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
7930 | "Monitor tunnel request from client %u completed\n", | ||
7931 | c->id); | ||
7932 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
7933 | } | ||
7934 | |||
7935 | |||
7936 | /** | ||
7926 | * Functions to handle messages from clients | 7937 | * Functions to handle messages from clients |
7927 | */ | 7938 | */ |
7928 | static struct GNUNET_SERVER_MessageHandler client_handlers[] = { | 7939 | static struct GNUNET_SERVER_MessageHandler client_handlers[] = { |
@@ -7974,6 +7985,12 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { | |||
7974 | {&handle_local_ack, NULL, | 7985 | {&handle_local_ack, NULL, |
7975 | GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, | 7986 | GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, |
7976 | sizeof (struct GNUNET_MESH_LocalAck)}, | 7987 | sizeof (struct GNUNET_MESH_LocalAck)}, |
7988 | {&handle_local_get_tunnels, NULL, | ||
7989 | GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS, | ||
7990 | sizeof (struct GNUNET_MessageHeader)}, | ||
7991 | {&handle_local_show_tunnel, NULL, | ||
7992 | GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL, | ||
7993 | sizeof (struct GNUNET_MESH_LocalMonitor)}, | ||
7977 | {NULL, NULL, 0, 0} | 7994 | {NULL, NULL, 0, 0} |
7978 | }; | 7995 | }; |
7979 | 7996 | ||
@@ -7996,6 +8013,12 @@ core_init (void *cls, struct GNUNET_CORE_Handle *server, | |||
7996 | NULL == server) | 8013 | NULL == server) |
7997 | { | 8014 | { |
7998 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); | 8015 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); |
8016 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
8017 | " core id %s\n", | ||
8018 | GNUNET_i2s (identity)); | ||
8019 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
8020 | " my id %s\n", | ||
8021 | GNUNET_i2s (&my_full_id)); | ||
7999 | GNUNET_SCHEDULER_shutdown (); // Try gracefully | 8022 | GNUNET_SCHEDULER_shutdown (); // Try gracefully |
8000 | if (10 < i++) | 8023 | if (10 < i++) |
8001 | GNUNET_abort(); // Try harder | 8024 | GNUNET_abort(); // Try harder |
@@ -8155,7 +8178,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
8155 | GNUNET_CORE_disconnect (core_handle); | 8178 | GNUNET_CORE_disconnect (core_handle); |
8156 | core_handle = NULL; | 8179 | core_handle = NULL; |
8157 | } | 8180 | } |
8158 | if (NULL != keygen) | 8181 | if (NULL != keygen) |
8159 | { | 8182 | { |
8160 | GNUNET_CRYPTO_rsa_key_create_stop (keygen); | 8183 | GNUNET_CRYPTO_rsa_key_create_stop (keygen); |
8161 | keygen = NULL; | 8184 | keygen = NULL; |
@@ -8177,6 +8200,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
8177 | GNUNET_SCHEDULER_cancel (announce_id_task); | 8200 | GNUNET_SCHEDULER_cancel (announce_id_task); |
8178 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | 8201 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; |
8179 | } | 8202 | } |
8203 | if (GNUNET_SCHEDULER_NO_TASK != announce_applications_task) | ||
8204 | { | ||
8205 | GNUNET_SCHEDULER_cancel (announce_applications_task); | ||
8206 | announce_applications_task = GNUNET_SCHEDULER_NO_TASK; | ||
8207 | } | ||
8180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); | 8208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); |
8181 | } | 8209 | } |
8182 | 8210 | ||
@@ -8184,7 +8212,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
8184 | /** | 8212 | /** |
8185 | * Callback for hostkey read/generation | 8213 | * Callback for hostkey read/generation |
8186 | * | 8214 | * |
8187 | * @param cls NULL | 8215 | * @param cls Closure (Configuration handle). |
8188 | * @param pk the private key | 8216 | * @param pk the private key |
8189 | * @param emsg error message | 8217 | * @param emsg error message |
8190 | */ | 8218 | */ |
@@ -8193,6 +8221,7 @@ key_generation_cb (void *cls, | |||
8193 | struct GNUNET_CRYPTO_RsaPrivateKey *pk, | 8221 | struct GNUNET_CRYPTO_RsaPrivateKey *pk, |
8194 | const char *emsg) | 8222 | const char *emsg) |
8195 | { | 8223 | { |
8224 | const struct GNUNET_CONFIGURATION_Handle *c = cls; | ||
8196 | struct MeshPeerInfo *peer; | 8225 | struct MeshPeerInfo *peer; |
8197 | struct MeshPeerPath *p; | 8226 | struct MeshPeerPath *p; |
8198 | 8227 | ||
@@ -8200,7 +8229,8 @@ key_generation_cb (void *cls, | |||
8200 | if (NULL == pk) | 8229 | if (NULL == pk) |
8201 | { | 8230 | { |
8202 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 8231 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
8203 | _("Mesh service could not access hostkey. Exiting.\n")); | 8232 | _("Mesh service could not access hostkey: %s. Exiting.\n"), |
8233 | emsg); | ||
8204 | GNUNET_SCHEDULER_shutdown (); | 8234 | GNUNET_SCHEDULER_shutdown (); |
8205 | return; | 8235 | return; |
8206 | } | 8236 | } |
@@ -8220,7 +8250,23 @@ key_generation_cb (void *cls, | |||
8220 | // NULL, | 8250 | // NULL, |
8221 | // NULL); | 8251 | // NULL); |
8222 | 8252 | ||
8223 | 8253 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | |
8254 | NULL, /* Closure passed to MESH functions */ | ||
8255 | &core_init, /* Call core_init once connected */ | ||
8256 | &core_connect, /* Handle connects */ | ||
8257 | &core_disconnect, /* remove peers on disconnects */ | ||
8258 | NULL, /* Don't notify about all incoming messages */ | ||
8259 | GNUNET_NO, /* For header only in notification */ | ||
8260 | NULL, /* Don't notify about all outbound messages */ | ||
8261 | GNUNET_NO, /* For header-only out notification */ | ||
8262 | core_handlers); /* Register these handlers */ | ||
8263 | |||
8264 | if (core_handle == NULL) | ||
8265 | { | ||
8266 | GNUNET_break (0); | ||
8267 | GNUNET_SCHEDULER_shutdown (); | ||
8268 | return; | ||
8269 | } | ||
8224 | 8270 | ||
8225 | next_tid = 0; | 8271 | next_tid = 0; |
8226 | next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; | 8272 | next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; |
@@ -8265,23 +8311,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
8265 | 8311 | ||
8266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); | 8312 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); |
8267 | server_handle = server; | 8313 | server_handle = server; |
8268 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | ||
8269 | NULL, /* Closure passed to MESH functions */ | ||
8270 | &core_init, /* Call core_init once connected */ | ||
8271 | &core_connect, /* Handle connects */ | ||
8272 | &core_disconnect, /* remove peers on disconnects */ | ||
8273 | NULL, /* Don't notify about all incoming messages */ | ||
8274 | GNUNET_NO, /* For header only in notification */ | ||
8275 | NULL, /* Don't notify about all outbound messages */ | ||
8276 | GNUNET_NO, /* For header-only out notification */ | ||
8277 | core_handlers); /* Register these handlers */ | ||
8278 | |||
8279 | if (core_handle == NULL) | ||
8280 | { | ||
8281 | GNUNET_break (0); | ||
8282 | GNUNET_SCHEDULER_shutdown (); | ||
8283 | return; | ||
8284 | } | ||
8285 | 8314 | ||
8286 | if (GNUNET_OK != | 8315 | if (GNUNET_OK != |
8287 | GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", | 8316 | GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", |
@@ -8318,8 +8347,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
8318 | GNUNET_SCHEDULER_shutdown (); | 8347 | GNUNET_SCHEDULER_shutdown (); |
8319 | return; | 8348 | return; |
8320 | } | 8349 | } |
8321 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "APP_ANNOUNCE_TIME %llu ms\n", app_announce_time.rel_value); | 8350 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
8322 | 8351 | "APP_ANNOUNCE_TIME %llu ms\n", | |
8352 | app_announce_time.rel_value); | ||
8323 | if (GNUNET_OK != | 8353 | if (GNUNET_OK != |
8324 | GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", | 8354 | GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", |
8325 | &id_announce_time)) | 8355 | &id_announce_time)) |
@@ -8331,9 +8361,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
8331 | GNUNET_SCHEDULER_shutdown (); | 8361 | GNUNET_SCHEDULER_shutdown (); |
8332 | return; | 8362 | return; |
8333 | } | 8363 | } |
8334 | else | ||
8335 | { | ||
8336 | } | ||
8337 | 8364 | ||
8338 | if (GNUNET_OK != | 8365 | if (GNUNET_OK != |
8339 | GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT", | 8366 | GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT", |
@@ -8383,14 +8410,24 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
8383 | } | 8410 | } |
8384 | 8411 | ||
8385 | if (GNUNET_OK != | 8412 | if (GNUNET_OK != |
8413 | GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS", | ||
8414 | &max_peers)) | ||
8415 | { | ||
8416 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
8417 | _("%s service is lacking key configuration settings (%s). Using default (%u).\n"), | ||
8418 | "mesh", "max peers", 1000); | ||
8419 | max_peers = 1000; | ||
8420 | } | ||
8421 | |||
8422 | if (GNUNET_OK != | ||
8386 | GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", | 8423 | GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", |
8387 | &dht_replication_level)) | 8424 | &dht_replication_level)) |
8388 | { | 8425 | { |
8389 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 8426 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
8390 | _ | 8427 | _ |
8391 | ("%s service is lacking key configuration settings (%s). Using default (%u).\n"), | 8428 | ("%s service is lacking key configuration settings (%s). Using default (%u).\n"), |
8392 | "mesh", "dht replication level", 10); | 8429 | "mesh", "dht replication level", 3); |
8393 | dht_replication_level = 10; | 8430 | dht_replication_level = 3; |
8394 | } | 8431 | } |
8395 | 8432 | ||
8396 | tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); | 8433 | tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); |
@@ -8410,7 +8447,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
8410 | /* Scheduled the task to clean up when shutdown is called */ | 8447 | /* Scheduled the task to clean up when shutdown is called */ |
8411 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | 8448 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, |
8412 | NULL); | 8449 | NULL); |
8413 | keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); | 8450 | keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, |
8451 | &key_generation_cb, | ||
8452 | (void *) c); | ||
8414 | GNUNET_free (keyfile); | 8453 | GNUNET_free (keyfile); |
8415 | } | 8454 | } |
8416 | 8455 | ||
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 7c9addeb6..e3b389ddb 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include "mesh_protocol.h" | 50 | #include "mesh_protocol.h" |
51 | #include "mesh_tunnel_tree.h" | 51 | #include "mesh_tunnel_tree.h" |
52 | #include "block_mesh.h" | 52 | #include "block_mesh.h" |
53 | #include "mesh_block_lib.h" | ||
54 | #include "gnunet_dht_service.h" | 53 | #include "gnunet_dht_service.h" |
55 | #include "gnunet_statistics_service.h" | 54 | #include "gnunet_statistics_service.h" |
56 | #include "gnunet_regex_lib.h" | 55 | #include "gnunet_regex_lib.h" |
@@ -184,17 +183,69 @@ struct MeshRegexDescriptor | |||
184 | */ | 183 | */ |
185 | char *regex; | 184 | char *regex; |
186 | 185 | ||
187 | /** | ||
188 | * Cached DFA for regular expression 'regex'. | ||
189 | */ | ||
190 | struct GNUNET_REGEX_Automaton *dfa; | ||
191 | |||
192 | /** | 186 | /** |
193 | * How many characters per edge can we squeeze? | 187 | * How many characters per edge can we squeeze? |
194 | */ | 188 | */ |
195 | uint16_t compression; | 189 | uint16_t compression; |
190 | |||
191 | /** | ||
192 | * Handle to announce the regex. | ||
193 | */ | ||
194 | struct GNUNET_REGEX_announce_handle *h; | ||
196 | }; | 195 | }; |
197 | 196 | ||
197 | |||
198 | /** | ||
199 | * Struct to keep information of searches of services described by a regex | ||
200 | * using a user-provided string service description. | ||
201 | */ | ||
202 | struct MeshRegexSearchInfo | ||
203 | { | ||
204 | /** | ||
205 | * Which tunnel is this for | ||
206 | */ | ||
207 | struct MeshTunnel *t; | ||
208 | |||
209 | /** | ||
210 | * User provided description of the searched service. | ||
211 | */ | ||
212 | char *description; | ||
213 | |||
214 | /** | ||
215 | * Regex search handle. | ||
216 | */ | ||
217 | struct GNUNET_REGEX_search_handle *search_handle; | ||
218 | |||
219 | /** | ||
220 | * Peer that is connecting via connect_by_string. When connected, free ctx. | ||
221 | */ | ||
222 | GNUNET_PEER_Id peer; | ||
223 | |||
224 | /** | ||
225 | * Other peers that are found but not yet being connected to. | ||
226 | */ | ||
227 | GNUNET_PEER_Id *peers; | ||
228 | |||
229 | /** | ||
230 | * Number of elements in peers. | ||
231 | */ | ||
232 | unsigned int n_peers; | ||
233 | |||
234 | /** | ||
235 | * Next peer to try to connect to. | ||
236 | */ | ||
237 | unsigned int i_peer; | ||
238 | |||
239 | /** | ||
240 | * Timeout for a connect attempt. | ||
241 | * When reached, try to connect to a different peer, if any. If not, | ||
242 | * try the same peer again. | ||
243 | */ | ||
244 | GNUNET_SCHEDULER_TaskIdentifier timeout; | ||
245 | |||
246 | }; | ||
247 | |||
248 | |||
198 | /** | 249 | /** |
199 | * Struct containing all info possibly needed to build a package when called | 250 | * Struct containing all info possibly needed to build a package when called |
200 | * back by core. | 251 | * back by core. |
@@ -495,9 +546,9 @@ struct MeshTunnel | |||
495 | struct GNUNET_DHT_GetHandle *dht_get_type; | 546 | struct GNUNET_DHT_GetHandle *dht_get_type; |
496 | 547 | ||
497 | /** | 548 | /** |
498 | * Initial context of the regex search for a connect_by_string | 549 | * Handle for the regex search for a connect_by_string |
499 | */ | 550 | */ |
500 | struct MeshRegexSearchContext *regex_ctx; | 551 | struct MeshRegexSearchInfo *regex_search; |
501 | 552 | ||
502 | /** | 553 | /** |
503 | * Task to keep the used paths alive | 554 | * Task to keep the used paths alive |
@@ -756,105 +807,6 @@ struct MeshClient | |||
756 | }; | 807 | }; |
757 | 808 | ||
758 | 809 | ||
759 | /** | ||
760 | * Struct to keep information of searches of services described by a regex | ||
761 | * using a user-provided string service description. | ||
762 | */ | ||
763 | struct MeshRegexSearchInfo | ||
764 | { | ||
765 | /** | ||
766 | * Which tunnel is this for | ||
767 | */ | ||
768 | struct MeshTunnel *t; | ||
769 | |||
770 | /** | ||
771 | * User provided description of the searched service. | ||
772 | */ | ||
773 | char *description; | ||
774 | |||
775 | /** | ||
776 | * Part of the description already consumed by the search. | ||
777 | */ | ||
778 | size_t position; | ||
779 | |||
780 | /** | ||
781 | * Running DHT GETs. | ||
782 | */ | ||
783 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; | ||
784 | |||
785 | /** | ||
786 | * Results from running DHT GETs. | ||
787 | */ | ||
788 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; | ||
789 | |||
790 | /** | ||
791 | * Contexts, for each running DHT GET. Free all on end of search. | ||
792 | */ | ||
793 | struct MeshRegexSearchContext **contexts; | ||
794 | |||
795 | /** | ||
796 | * Number of contexts (branches/steps in search). | ||
797 | */ | ||
798 | unsigned int n_contexts; | ||
799 | |||
800 | /** | ||
801 | * Peer that is connecting via connect_by_string. When connected, free ctx. | ||
802 | */ | ||
803 | GNUNET_PEER_Id peer; | ||
804 | |||
805 | /** | ||
806 | * Other peers that are found but not yet being connected to. | ||
807 | */ | ||
808 | GNUNET_PEER_Id *peers; | ||
809 | |||
810 | /** | ||
811 | * Number of elements in peers. | ||
812 | */ | ||
813 | unsigned int n_peers; | ||
814 | |||
815 | /** | ||
816 | * Next peer to try to connect to. | ||
817 | */ | ||
818 | unsigned int i_peer; | ||
819 | |||
820 | /** | ||
821 | * Timeout for a connect attempt. | ||
822 | * When reached, try to connect to a different peer, if any. If not, | ||
823 | * try the same peer again. | ||
824 | */ | ||
825 | GNUNET_SCHEDULER_TaskIdentifier timeout; | ||
826 | |||
827 | }; | ||
828 | |||
829 | /** | ||
830 | * Struct to keep state of running searches that have consumed a part of | ||
831 | * the inital string. | ||
832 | */ | ||
833 | struct MeshRegexSearchContext | ||
834 | { | ||
835 | /** | ||
836 | * Part of the description already consumed by | ||
837 | * this particular search branch. | ||
838 | */ | ||
839 | size_t position; | ||
840 | |||
841 | /** | ||
842 | * Information about the search. | ||
843 | */ | ||
844 | struct MeshRegexSearchInfo *info; | ||
845 | |||
846 | /** | ||
847 | * We just want to look for one edge, the longer the better. | ||
848 | * Keep its length. | ||
849 | */ | ||
850 | unsigned int longest_match; | ||
851 | |||
852 | /** | ||
853 | * Destination hash of the longest match. | ||
854 | */ | ||
855 | struct GNUNET_HashCode hash; | ||
856 | }; | ||
857 | |||
858 | /******************************************************************************/ | 810 | /******************************************************************************/ |
859 | /************************ DEBUG FUNCTIONS ****************************/ | 811 | /************************ DEBUG FUNCTIONS ****************************/ |
860 | /******************************************************************************/ | 812 | /******************************************************************************/ |
@@ -1090,56 +1042,15 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1090 | 1042 | ||
1091 | 1043 | ||
1092 | /** | 1044 | /** |
1093 | * Function to process DHT string to regex matching. | 1045 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one |
1094 | * Called on each result obtained for the DHT search. | 1046 | * and insert it in the appropiate structures if the peer is not known yet. |
1095 | * | ||
1096 | * @param cls closure (search context) | ||
1097 | * @param exp when will this value expire | ||
1098 | * @param key key of the result | ||
1099 | * @param get_path path of the get request (not used) | ||
1100 | * @param get_path_length lenght of get_path (not used) | ||
1101 | * @param put_path path of the put request (not used) | ||
1102 | * @param put_path_length length of the put_path (not used) | ||
1103 | * @param type type of the result | ||
1104 | * @param size number of bytes in data | ||
1105 | * @param data pointer to the result data | ||
1106 | * | 1047 | * |
1107 | * TODO: re-issue the request after certain time? cancel after X results? | 1048 | * @param peer Full identity of the peer. |
1108 | */ | ||
1109 | static void | ||
1110 | dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
1111 | const struct GNUNET_HashCode * key, | ||
1112 | const struct GNUNET_PeerIdentity *get_path, | ||
1113 | unsigned int get_path_length, | ||
1114 | const struct GNUNET_PeerIdentity *put_path, | ||
1115 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
1116 | size_t size, const void *data); | ||
1117 | |||
1118 | |||
1119 | /** | ||
1120 | * Function to process DHT string to regex matching. | ||
1121 | * Called on each result obtained for the DHT search. | ||
1122 | * | 1049 | * |
1123 | * @param cls closure (search context) | 1050 | * @return Existing or newly created peer info. |
1124 | * @param exp when will this value expire | ||
1125 | * @param key key of the result | ||
1126 | * @param get_path path of the get request (not used) | ||
1127 | * @param get_path_length lenght of get_path (not used) | ||
1128 | * @param put_path path of the put request (not used) | ||
1129 | * @param put_path_length length of the put_path (not used) | ||
1130 | * @param type type of the result | ||
1131 | * @param size number of bytes in data | ||
1132 | * @param data pointer to the result data | ||
1133 | */ | 1051 | */ |
1134 | static void | 1052 | static struct MeshPeerInfo * |
1135 | dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 1053 | peer_info_get (const struct GNUNET_PeerIdentity *peer); |
1136 | const struct GNUNET_HashCode * key, | ||
1137 | const struct GNUNET_PeerIdentity *get_path, | ||
1138 | unsigned int get_path_length, | ||
1139 | const struct GNUNET_PeerIdentity *put_path, | ||
1140 | unsigned int put_path_length, | ||
1141 | enum GNUNET_BLOCK_Type type, | ||
1142 | size_t size, const void *data); | ||
1143 | 1054 | ||
1144 | 1055 | ||
1145 | /** | 1056 | /** |
@@ -1168,6 +1079,29 @@ peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t); | |||
1168 | 1079 | ||
1169 | 1080 | ||
1170 | /** | 1081 | /** |
1082 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
1083 | * to obtain a local peer -> destination path and interning the peer ids. | ||
1084 | * | ||
1085 | * @return Newly allocated and created path | ||
1086 | */ | ||
1087 | static struct MeshPeerPath * | ||
1088 | path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | ||
1089 | unsigned int get_path_length, | ||
1090 | const struct GNUNET_PeerIdentity *put_path, | ||
1091 | unsigned int put_path_length); | ||
1092 | |||
1093 | |||
1094 | /** | ||
1095 | * Adds a path to the peer_infos of all the peers in the path | ||
1096 | * | ||
1097 | * @param p Path to process. | ||
1098 | * @param confirmed Whether we know if the path works or not. | ||
1099 | */ | ||
1100 | static void | ||
1101 | path_add_to_peers (struct MeshPeerPath *p, int confirmed); | ||
1102 | |||
1103 | |||
1104 | /** | ||
1171 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | 1105 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all |
1172 | * needed rescources. | 1106 | * needed rescources. |
1173 | * If peer already exists, reevaluate shortest path and change if different. | 1107 | * If peer already exists, reevaluate shortest path and change if different. |
@@ -1252,33 +1186,6 @@ tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c); | |||
1252 | 1186 | ||
1253 | 1187 | ||
1254 | /** | 1188 | /** |
1255 | * Jump to the next edge, with the longest matching token. | ||
1256 | * | ||
1257 | * @param block Block found in the DHT. | ||
1258 | * @param size Size of the block. | ||
1259 | * @param ctx Context of the search. | ||
1260 | * | ||
1261 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1262 | */ | ||
1263 | static void | ||
1264 | regex_next_edge (const struct MeshRegexBlock *block, | ||
1265 | size_t size, | ||
1266 | struct MeshRegexSearchContext *ctx); | ||
1267 | |||
1268 | |||
1269 | /** | ||
1270 | * Find a path to a peer that offers a regex servcie compatible | ||
1271 | * with a given string. | ||
1272 | * | ||
1273 | * @param key The key of the accepting state. | ||
1274 | * @param ctx Context containing info about the string, tunnel, etc. | ||
1275 | */ | ||
1276 | static void | ||
1277 | regex_find_path (const struct GNUNET_HashCode *key, | ||
1278 | struct MeshRegexSearchContext *ctx); | ||
1279 | |||
1280 | |||
1281 | /** | ||
1282 | * @brief Queue and pass message to core when possible. | 1189 | * @brief Queue and pass message to core when possible. |
1283 | * | 1190 | * |
1284 | * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status | 1191 | * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status |
@@ -1339,257 +1246,23 @@ static size_t | |||
1339 | queue_send (void *cls, size_t size, void *buf); | 1246 | queue_send (void *cls, size_t size, void *buf); |
1340 | 1247 | ||
1341 | /******************************************************************************/ | 1248 | /******************************************************************************/ |
1342 | /************************ ITERATORS ****************************/ | 1249 | /************************ REGEX INTEGRATION ****************************/ |
1343 | /******************************************************************************/ | 1250 | /******************************************************************************/ |
1344 | 1251 | ||
1345 | /** | 1252 | /** |
1346 | * Iterator over found existing mesh regex blocks that match an ongoing search. | 1253 | * Cancel a mesh regex search and free resources. |
1347 | * | ||
1348 | * @param cls closure | ||
1349 | * @param key current key code | ||
1350 | * @param value value in the hash map | ||
1351 | * @return GNUNET_YES if we should continue to iterate, | ||
1352 | * GNUNET_NO if not. | ||
1353 | */ | ||
1354 | static int | ||
1355 | regex_result_iterator (void *cls, | ||
1356 | const struct GNUNET_HashCode * key, | ||
1357 | void *value) | ||
1358 | { | ||
1359 | struct MeshRegexBlock *block = value; | ||
1360 | struct MeshRegexSearchContext *ctx = cls; | ||
1361 | |||
1362 | if (GNUNET_YES == ntohl(block->accepting) && | ||
1363 | ctx->position == strlen (ctx->info->description)) | ||
1364 | { | ||
1365 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Found accepting known block\n"); | ||
1366 | regex_find_path (key, ctx); | ||
1367 | return GNUNET_YES; // We found an accept state! | ||
1368 | } | ||
1369 | else | ||
1370 | { | ||
1371 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", | ||
1372 | ctx->position, strlen(ctx->info->description), | ||
1373 | ntohl(block->accepting)); | ||
1374 | |||
1375 | } | ||
1376 | regex_next_edge(block, SIZE_MAX, ctx); | ||
1377 | |||
1378 | GNUNET_STATISTICS_update (stats, "# regex mesh blocks iterated", 1, GNUNET_NO); | ||
1379 | |||
1380 | return GNUNET_YES; | ||
1381 | } | ||
1382 | |||
1383 | |||
1384 | /** | ||
1385 | * Iterator over edges in a regex block retrieved from the DHT. | ||
1386 | * | ||
1387 | * @param cls Closure (context of the search). | ||
1388 | * @param token Token that follows to next state. | ||
1389 | * @param len Lenght of token. | ||
1390 | * @param key Hash of next state. | ||
1391 | * | ||
1392 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1393 | */ | ||
1394 | static int | ||
1395 | regex_edge_iterator (void *cls, | ||
1396 | const char *token, | ||
1397 | size_t len, | ||
1398 | const struct GNUNET_HashCode *key) | ||
1399 | { | ||
1400 | struct MeshRegexSearchContext *ctx = cls; | ||
1401 | struct MeshRegexSearchInfo *info = ctx->info; | ||
1402 | char *current; | ||
1403 | size_t current_len; | ||
1404 | |||
1405 | GNUNET_STATISTICS_update (stats, "# regex edges iterated", 1, GNUNET_NO); | ||
1406 | |||
1407 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Start of regex edge iterator\n"); | ||
1408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* descr : %s\n", info->description); | ||
1409 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* posit : %u\n", ctx->position); | ||
1410 | current = &info->description[ctx->position]; | ||
1411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* currt : %s\n", current); | ||
1412 | current_len = strlen (info->description) - ctx->position; | ||
1413 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* ctlen : %u\n", current_len); | ||
1414 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* tklen : %u\n", len); | ||
1415 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* token : %.*s\n", len, token); | ||
1416 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* nextk : %s\n", GNUNET_h2s(key)); | ||
1417 | if (len > current_len) | ||
1418 | { | ||
1419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token too long, END\n"); | ||
1420 | return GNUNET_YES; // Token too long, wont match | ||
1421 | } | ||
1422 | if (0 != strncmp (current, token, len)) | ||
1423 | { | ||
1424 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token doesn't match, END\n"); | ||
1425 | return GNUNET_YES; // Token doesn't match | ||
1426 | } | ||
1427 | |||
1428 | if (len > ctx->longest_match) | ||
1429 | { | ||
1430 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is longer, KEEP\n"); | ||
1431 | ctx->longest_match = len; | ||
1432 | ctx->hash = *key; | ||
1433 | } | ||
1434 | else | ||
1435 | { | ||
1436 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is not longer, IGNORE\n"); | ||
1437 | } | ||
1438 | |||
1439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); | ||
1440 | return GNUNET_YES; | ||
1441 | } | ||
1442 | |||
1443 | |||
1444 | /** | ||
1445 | * Jump to the next edge, with the longest matching token. | ||
1446 | * | ||
1447 | * @param block Block found in the DHT. | ||
1448 | * @param size Size of the block. | ||
1449 | * @param ctx Context of the search. | ||
1450 | * | ||
1451 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
1452 | */ | 1254 | */ |
1453 | static void | 1255 | static void |
1454 | regex_next_edge (const struct MeshRegexBlock *block, | 1256 | regex_cancel_search (struct MeshRegexSearchInfo *regex_search) |
1455 | size_t size, | 1257 | { |
1456 | struct MeshRegexSearchContext *ctx) | 1258 | GNUNET_REGEX_search_cancel (regex_search->search_handle); |
1457 | { | 1259 | if (0 < regex_search->n_peers) |
1458 | struct MeshRegexSearchContext *new_ctx; | 1260 | GNUNET_free (regex_search->peers); |
1459 | struct MeshRegexSearchInfo *info = ctx->info; | 1261 | if (GNUNET_SCHEDULER_NO_TASK != regex_search->timeout) |
1460 | struct GNUNET_DHT_GetHandle *get_h; | ||
1461 | const char *rest; | ||
1462 | int result; | ||
1463 | |||
1464 | /* Find the longest match for the current string position, | ||
1465 | * among tokens in the given block */ | ||
1466 | ctx->longest_match = 0; | ||
1467 | result = GNUNET_MESH_regex_block_iterate (block, size, | ||
1468 | ®ex_edge_iterator, ctx); | ||
1469 | GNUNET_break (GNUNET_OK == result); | ||
1470 | |||
1471 | /* Did anything match? */ | ||
1472 | if (0 == ctx->longest_match) | ||
1473 | return; | ||
1474 | |||
1475 | new_ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext)); | ||
1476 | new_ctx->info = info; | ||
1477 | new_ctx->position = ctx->position + ctx->longest_match; | ||
1478 | GNUNET_array_append (info->contexts, info->n_contexts, new_ctx); | ||
1479 | |||
1480 | /* Check whether we already have a DHT GET running for it */ | ||
1481 | if (GNUNET_YES == | ||
1482 | GNUNET_CONTAINER_multihashmap_contains(info->dht_get_handles, &ctx->hash)) | ||
1483 | { | ||
1484 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* GET running, END\n"); | ||
1485 | GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, | ||
1486 | &ctx->hash, | ||
1487 | ®ex_result_iterator, | ||
1488 | new_ctx); | ||
1489 | // FIXME: "leaks" new_ctx? avoid keeping it around? | ||
1490 | return; // We are already looking for it | ||
1491 | } | ||
1492 | |||
1493 | GNUNET_STATISTICS_update (stats, "# regex nodes traversed", 1, GNUNET_NO); | ||
1494 | |||
1495 | /* Start search in DHT */ | ||
1496 | rest = &new_ctx->info->description[new_ctx->position]; | ||
1497 | get_h = | ||
1498 | GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
1499 | GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */ | ||
1500 | &ctx->hash, /* key to search */ | ||
1501 | dht_replication_level, /* replication level */ | ||
1502 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
1503 | rest, /* xquery */ | ||
1504 | // FIXME add BLOOMFILTER to exclude filtered peers | ||
1505 | strlen(rest) + 1, /* xquery bits */ | ||
1506 | // FIXME add BLOOMFILTER SIZE | ||
1507 | &dht_get_string_handler, new_ctx); | ||
1508 | if (GNUNET_OK != | ||
1509 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | ||
1510 | &ctx->hash, | ||
1511 | get_h, | ||
1512 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
1513 | { | 1262 | { |
1514 | GNUNET_break (0); | 1263 | GNUNET_SCHEDULER_cancel(regex_search->timeout); |
1515 | return; | ||
1516 | } | 1264 | } |
1517 | } | 1265 | GNUNET_free (regex_search); |
1518 | |||
1519 | |||
1520 | /** | ||
1521 | * Iterator over hash map entries to cancel DHT GET requests after a | ||
1522 | * successful connect_by_string. | ||
1523 | * | ||
1524 | * @param cls Closure (unused). | ||
1525 | * @param key Current key code (unused). | ||
1526 | * @param value Value in the hash map (get handle). | ||
1527 | * @return GNUNET_YES if we should continue to iterate, | ||
1528 | * GNUNET_NO if not. | ||
1529 | */ | ||
1530 | static int | ||
1531 | regex_cancel_dht_get (void *cls, | ||
1532 | const struct GNUNET_HashCode * key, | ||
1533 | void *value) | ||
1534 | { | ||
1535 | struct GNUNET_DHT_GetHandle *h = value; | ||
1536 | |||
1537 | GNUNET_DHT_get_stop (h); | ||
1538 | return GNUNET_YES; | ||
1539 | } | ||
1540 | |||
1541 | |||
1542 | /** | ||
1543 | * Iterator over hash map entries to free MeshRegexBlocks stored during the | ||
1544 | * search for connect_by_string. | ||
1545 | * | ||
1546 | * @param cls Closure (unused). | ||
1547 | * @param key Current key code (unused). | ||
1548 | * @param value MeshRegexBlock in the hash map. | ||
1549 | * @return GNUNET_YES if we should continue to iterate, | ||
1550 | * GNUNET_NO if not. | ||
1551 | */ | ||
1552 | static int | ||
1553 | regex_free_result (void *cls, | ||
1554 | const struct GNUNET_HashCode * key, | ||
1555 | void *value) | ||
1556 | { | ||
1557 | |||
1558 | GNUNET_free (value); | ||
1559 | return GNUNET_YES; | ||
1560 | } | ||
1561 | |||
1562 | |||
1563 | /** | ||
1564 | * Find a path to a peer that offers a regex servcie compatible | ||
1565 | * with a given string. | ||
1566 | * | ||
1567 | * @param key The key of the accepting state. | ||
1568 | * @param ctx Context containing info about the string, tunnel, etc. | ||
1569 | */ | ||
1570 | static void | ||
1571 | regex_find_path (const struct GNUNET_HashCode *key, | ||
1572 | struct MeshRegexSearchContext *ctx) | ||
1573 | { | ||
1574 | struct GNUNET_DHT_GetHandle *get_h; | ||
1575 | |||
1576 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n"); | ||
1577 | get_h = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
1578 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, /* type */ | ||
1579 | key, /* key to search */ | ||
1580 | dht_replication_level, /* replication level */ | ||
1581 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE/* | | ||
1582 | GNUNET_DHT_RO_RECORD_ROUTE*/, | ||
1583 | NULL, /* xquery */ | ||
1584 | // FIXME add BLOOMFILTER to exclude filtered peers | ||
1585 | 0, /* xquery bits */ | ||
1586 | // FIXME add BLOOMFILTER SIZE | ||
1587 | &dht_get_string_accept_handler, ctx); | ||
1588 | GNUNET_break (GNUNET_OK == | ||
1589 | GNUNET_CONTAINER_multihashmap_put(ctx->info->dht_get_handles, | ||
1590 | key, | ||
1591 | get_h, | ||
1592 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
1593 | } | 1266 | } |
1594 | 1267 | ||
1595 | 1268 | ||
@@ -1613,6 +1286,7 @@ regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1613 | info->timeout = GNUNET_SCHEDULER_NO_TASK; | 1286 | info->timeout = GNUNET_SCHEDULER_NO_TASK; |
1614 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 1287 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
1615 | { | 1288 | { |
1289 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " due to shutdown\n"); | ||
1616 | return; | 1290 | return; |
1617 | } | 1291 | } |
1618 | 1292 | ||
@@ -1646,37 +1320,109 @@ regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1646 | 1320 | ||
1647 | 1321 | ||
1648 | /** | 1322 | /** |
1649 | * Cancel an ongoing regex search in the DHT and free all resources. | 1323 | * Function to process DHT string to regex matching. |
1324 | * Called on each result obtained for the DHT search. | ||
1650 | * | 1325 | * |
1651 | * @param ctx The search context. | 1326 | * @param cls Closure provided in GNUNET_REGEX_search. |
1327 | * @param id Peer providing a regex that matches the string. | ||
1328 | * @param get_path Path of the get request. | ||
1329 | * @param get_path_length Lenght of get_path. | ||
1330 | * @param put_path Path of the put request. | ||
1331 | * @param put_path_length Length of the put_path. | ||
1652 | */ | 1332 | */ |
1653 | static void | 1333 | static void |
1654 | regex_cancel_search(struct MeshRegexSearchContext *ctx) | 1334 | regex_found_handler (void *cls, |
1335 | const struct GNUNET_PeerIdentity *id, | ||
1336 | const struct GNUNET_PeerIdentity *get_path, | ||
1337 | unsigned int get_path_length, | ||
1338 | const struct GNUNET_PeerIdentity *put_path, | ||
1339 | unsigned int put_path_length) | ||
1655 | { | 1340 | { |
1656 | struct MeshRegexSearchInfo *info = ctx->info; | 1341 | struct MeshRegexSearchInfo *info = cls; |
1657 | int i; | 1342 | struct MeshPeerPath *p; |
1343 | struct MeshPeerInfo *peer_info; | ||
1344 | |||
1345 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | ||
1346 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", info->description); | ||
1658 | 1347 | ||
1659 | GNUNET_free (info->description); | 1348 | peer_info = peer_info_get (id); |
1660 | GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_handles, | 1349 | p = path_build_from_dht (get_path, get_path_length, |
1661 | ®ex_cancel_dht_get, NULL); | 1350 | put_path, put_path_length); |
1662 | GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_results, | 1351 | path_add_to_peers (p, GNUNET_NO); |
1663 | ®ex_free_result, NULL); | 1352 | path_destroy(p); |
1664 | GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_results); | 1353 | |
1665 | GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_handles); | 1354 | tunnel_add_peer (info->t, peer_info); |
1666 | info->t->regex_ctx = NULL; | 1355 | peer_info_connect (peer_info, info->t); |
1667 | for (i = 0; i < info->n_contexts; i++) | 1356 | if (0 == info->peer) |
1668 | { | 1357 | { |
1669 | GNUNET_free (info->contexts[i]); | 1358 | info->peer = peer_info->id; |
1670 | } | 1359 | } |
1671 | if (0 < info->n_contexts) | 1360 | else |
1672 | GNUNET_free (info->contexts); | 1361 | { |
1673 | if (0 < info->n_peers) | 1362 | GNUNET_array_append (info->peers, info->n_peers, peer_info->id); |
1674 | GNUNET_free (info->peers); | 1363 | } |
1364 | |||
1675 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout) | 1365 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout) |
1366 | return; | ||
1367 | |||
1368 | info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, | ||
1369 | ®ex_connect_timeout, | ||
1370 | info); | ||
1371 | |||
1372 | return; | ||
1373 | } | ||
1374 | |||
1375 | |||
1376 | /** | ||
1377 | * Store the regular expression describing a local service into the DHT. | ||
1378 | * | ||
1379 | * @param regex The regular expresion. | ||
1380 | */ | ||
1381 | static void | ||
1382 | regex_put (struct MeshRegexDescriptor *regex) | ||
1383 | { | ||
1384 | DEBUG_DHT (" regex_put (%s) start\n", regex->regex); | ||
1385 | if (NULL == regex->h) | ||
1676 | { | 1386 | { |
1677 | GNUNET_SCHEDULER_cancel(info->timeout); | 1387 | DEBUG_DHT (" first put, creating DFA\n"); |
1388 | regex->h = GNUNET_REGEX_announce (dht_handle, | ||
1389 | &my_full_id, | ||
1390 | regex->regex, | ||
1391 | regex->compression, | ||
1392 | stats); | ||
1678 | } | 1393 | } |
1679 | GNUNET_free (info); | 1394 | else |
1395 | { | ||
1396 | DEBUG_DHT (" not first put, using cached data\n"); | ||
1397 | GNUNET_REGEX_reannounce (regex->h); | ||
1398 | } | ||
1399 | DEBUG_DHT (" regex_put (%s) end\n", regex->regex); | ||
1400 | } | ||
1401 | |||
1402 | |||
1403 | /** | ||
1404 | * Periodically announce what applications are provided by local clients | ||
1405 | * (by regex) | ||
1406 | * | ||
1407 | * @param cls closure | ||
1408 | * @param tc task context | ||
1409 | */ | ||
1410 | static void | ||
1411 | regex_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1412 | { | ||
1413 | struct MeshClient *c = cls; | ||
1414 | unsigned int i; | ||
1415 | |||
1416 | c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK; | ||
1417 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1418 | return; | ||
1419 | DEBUG_DHT ("Starting PUT for regex\n"); | ||
1420 | for (i = 0; i < c->n_regex; i++) | ||
1421 | regex_put (&c->regexes[i]); | ||
1422 | c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time, | ||
1423 | ®ex_announce, | ||
1424 | cls); | ||
1425 | DEBUG_DHT ("Finished PUT for regex\n"); | ||
1680 | } | 1426 | } |
1681 | 1427 | ||
1682 | 1428 | ||
@@ -1725,193 +1471,6 @@ announce_application (void *cls, const struct GNUNET_HashCode * key, void *value | |||
1725 | } | 1471 | } |
1726 | 1472 | ||
1727 | 1473 | ||
1728 | #if 0 | ||
1729 | /** | ||
1730 | * Function called when the DHT regex put is complete. | ||
1731 | * | ||
1732 | * @param the 'struct MeshClient' for which we were PUTting | ||
1733 | * @param success GNUNET_OK if the PUT was transmitted, | ||
1734 | * GNUNET_NO on timeout, | ||
1735 | * GNUNET_SYSERR on disconnect from service | ||
1736 | * after the PUT message was transmitted | ||
1737 | * (so we don't know if it was received or not) | ||
1738 | */ | ||
1739 | static void | ||
1740 | announce_regex_done (void *cls, | ||
1741 | int success) | ||
1742 | { | ||
1743 | struct MeshClient *c = cls; | ||
1744 | |||
1745 | } | ||
1746 | #endif | ||
1747 | |||
1748 | |||
1749 | /** | ||
1750 | * Regex callback iterator to store own service description in the DHT. | ||
1751 | * | ||
1752 | * @param cls closure. | ||
1753 | * @param key hash for current state. | ||
1754 | * @param proof proof for current state. | ||
1755 | * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. | ||
1756 | * @param num_edges number of edges leaving current state. | ||
1757 | * @param edges edges leaving current state. | ||
1758 | */ | ||
1759 | static void | ||
1760 | regex_iterator (void *cls, | ||
1761 | const struct GNUNET_HashCode *key, | ||
1762 | const char *proof, | ||
1763 | int accepting, | ||
1764 | unsigned int num_edges, | ||
1765 | const struct GNUNET_REGEX_Edge *edges) | ||
1766 | { | ||
1767 | struct MeshRegexBlock *block; | ||
1768 | struct MeshRegexEdge *block_edge; | ||
1769 | enum GNUNET_DHT_RouteOption opt; | ||
1770 | size_t size; | ||
1771 | size_t len; | ||
1772 | unsigned int i; | ||
1773 | unsigned int offset; | ||
1774 | char *aux; | ||
1775 | |||
1776 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1777 | " regex dht put for state %s\n", | ||
1778 | GNUNET_h2s(key)); | ||
1779 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1780 | " proof: %s\n", | ||
1781 | proof); | ||
1782 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1783 | " num edges: %u\n", | ||
1784 | num_edges); | ||
1785 | |||
1786 | opt = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE; | ||
1787 | if (GNUNET_YES == accepting) | ||
1788 | { | ||
1789 | struct MeshRegexAccept block; | ||
1790 | |||
1791 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1792 | " state %s is accepting, putting own id\n", | ||
1793 | GNUNET_h2s(key)); | ||
1794 | size = sizeof (block); | ||
1795 | block.key = *key; | ||
1796 | block.id = my_full_id; | ||
1797 | GNUNET_STATISTICS_update (stats, "# regex accepting blocks stored", | ||
1798 | 1, GNUNET_NO); | ||
1799 | GNUNET_STATISTICS_update (stats, "# regex accepting block bytes stored", | ||
1800 | sizeof (block), GNUNET_NO); | ||
1801 | (void) | ||
1802 | GNUNET_DHT_put(dht_handle, key, | ||
1803 | dht_replication_level, | ||
1804 | opt/* | GNUNET_DHT_RO_RECORD_ROUTE*/, | ||
1805 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, | ||
1806 | size, | ||
1807 | (char *) &block, | ||
1808 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: expiration time should be option */ | ||
1809 | app_announce_time, | ||
1810 | NULL, NULL); | ||
1811 | } | ||
1812 | len = strlen(proof); | ||
1813 | size = sizeof (struct MeshRegexBlock) + len; | ||
1814 | block = GNUNET_malloc (size); | ||
1815 | |||
1816 | block->key = *key; | ||
1817 | block->n_proof = htonl (len); | ||
1818 | block->n_edges = htonl (num_edges); | ||
1819 | block->accepting = htonl (accepting); | ||
1820 | |||
1821 | /* Store the proof at the end of the block. */ | ||
1822 | aux = (char *) &block[1]; | ||
1823 | memcpy (aux, proof, len); | ||
1824 | aux = &aux[len]; | ||
1825 | |||
1826 | /* Store each edge in a variable length MeshEdge struct at the | ||
1827 | * very end of the MeshRegexBlock structure. | ||
1828 | */ | ||
1829 | for (i = 0; i < num_edges; i++) | ||
1830 | { | ||
1831 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1832 | " edge %s towards %s\n", | ||
1833 | edges[i].label, | ||
1834 | GNUNET_h2s(&edges[i].destination)); | ||
1835 | |||
1836 | /* aux points at the end of the last block */ | ||
1837 | len = strlen (edges[i].label); | ||
1838 | size += sizeof (struct MeshRegexEdge) + len; | ||
1839 | // Calculate offset FIXME is this ok? use size instead? | ||
1840 | offset = aux - (char *) block; | ||
1841 | block = GNUNET_realloc (block, size); | ||
1842 | aux = &((char *) block)[offset]; | ||
1843 | block_edge = (struct MeshRegexEdge *) aux; | ||
1844 | block_edge->key = edges[i].destination; | ||
1845 | block_edge->n_token = htonl (len); | ||
1846 | aux = (char *) &block_edge[1]; | ||
1847 | memcpy (aux, edges[i].label, len); | ||
1848 | aux = &aux[len]; | ||
1849 | } | ||
1850 | (void) | ||
1851 | GNUNET_DHT_put(dht_handle, key, | ||
1852 | dht_replication_level, | ||
1853 | opt, | ||
1854 | GNUNET_BLOCK_TYPE_MESH_REGEX, size, | ||
1855 | (char *) block, | ||
1856 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: this should be an option */ | ||
1857 | app_announce_time, | ||
1858 | NULL, NULL); | ||
1859 | GNUNET_STATISTICS_update (stats, "# regex blocks stored", | ||
1860 | 1, GNUNET_NO); | ||
1861 | GNUNET_STATISTICS_update (stats, "# regex block bytes stored", | ||
1862 | size, GNUNET_NO); | ||
1863 | |||
1864 | GNUNET_free (block); | ||
1865 | } | ||
1866 | |||
1867 | |||
1868 | /** | ||
1869 | * Store the regular expression describing a local service into the DHT. | ||
1870 | * | ||
1871 | * @param regex The regular expresion. | ||
1872 | */ | ||
1873 | static void | ||
1874 | regex_put (struct MeshRegexDescriptor *regex) | ||
1875 | { | ||
1876 | if (NULL == regex->dfa) | ||
1877 | { | ||
1878 | regex->dfa = GNUNET_REGEX_construct_dfa (regex->regex, | ||
1879 | strlen (regex->regex), | ||
1880 | regex->compression); | ||
1881 | } | ||
1882 | |||
1883 | DEBUG_DHT (" regex_put (%s) start\n", regex->regex); | ||
1884 | GNUNET_REGEX_iterate_all_edges (regex->dfa, ®ex_iterator, NULL); | ||
1885 | DEBUG_DHT (" regex_put (%s) end\n", regex->regex); | ||
1886 | } | ||
1887 | |||
1888 | |||
1889 | /** | ||
1890 | * Periodically announce what applications are provided by local clients | ||
1891 | * (by regex) | ||
1892 | * | ||
1893 | * @param cls closure | ||
1894 | * @param tc task context | ||
1895 | */ | ||
1896 | static void | ||
1897 | announce_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1898 | { | ||
1899 | struct MeshClient *c = cls; | ||
1900 | unsigned int i; | ||
1901 | |||
1902 | c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK; | ||
1903 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1904 | return; | ||
1905 | DEBUG_DHT ("Starting PUT for regex\n"); | ||
1906 | for (i = 0; i < c->n_regex; i++) | ||
1907 | regex_put (&c->regexes[i]); | ||
1908 | c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time, | ||
1909 | &announce_regex, | ||
1910 | cls); | ||
1911 | DEBUG_DHT ("Finished PUT for regex\n"); | ||
1912 | } | ||
1913 | |||
1914 | |||
1915 | /** | 1474 | /** |
1916 | * Periodically announce what applications are provided by local clients | 1475 | * Periodically announce what applications are provided by local clients |
1917 | * (by type) | 1476 | * (by type) |
@@ -4559,8 +4118,8 @@ tunnel_destroy (struct MeshTunnel *t) | |||
4559 | tree_iterate_children (t->tree, &tunnel_cancel_queues, t); | 4118 | tree_iterate_children (t->tree, &tunnel_cancel_queues, t); |
4560 | tree_destroy (t->tree); | 4119 | tree_destroy (t->tree); |
4561 | 4120 | ||
4562 | if (NULL != t->regex_ctx) | 4121 | if (NULL != t->regex_search) |
4563 | regex_cancel_search (t->regex_ctx); | 4122 | GNUNET_REGEX_search_cancel (t->regex_search->search_handle); |
4564 | if (NULL != t->dht_get_type) | 4123 | if (NULL != t->dht_get_type) |
4565 | GNUNET_DHT_get_stop (t->dht_get_type); | 4124 | GNUNET_DHT_get_stop (t->dht_get_type); |
4566 | if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) | 4125 | if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) |
@@ -6338,7 +5897,6 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6338 | return GNUNET_OK; | 5897 | return GNUNET_OK; |
6339 | } | 5898 | } |
6340 | 5899 | ||
6341 | |||
6342 | /** | 5900 | /** |
6343 | * Core handler for path ACKs | 5901 | * Core handler for path ACKs |
6344 | * | 5902 | * |
@@ -6384,12 +5942,12 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
6384 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", | 5942 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", |
6385 | GNUNET_i2s (peer)); | 5943 | GNUNET_i2s (peer)); |
6386 | 5944 | ||
6387 | if (NULL != t->regex_ctx && t->regex_ctx->info->peer == peer_info->id) | 5945 | if (NULL != t->regex_search && t->regex_search->peer == peer_info->id) |
6388 | { | 5946 | { |
6389 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 5947 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
6390 | "connect_by_string completed, stopping search\n"); | 5948 | "connect_by_string completed, stopping search\n"); |
6391 | regex_cancel_search (t->regex_ctx); | 5949 | regex_cancel_search (t->regex_search); |
6392 | t->regex_ctx = NULL; | 5950 | t->regex_search = NULL; |
6393 | } | 5951 | } |
6394 | 5952 | ||
6395 | /* Add paths to peers? */ | 5953 | /* Add paths to peers? */ |
@@ -6717,152 +6275,6 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
6717 | } | 6275 | } |
6718 | 6276 | ||
6719 | 6277 | ||
6720 | /** | ||
6721 | * Function to process DHT string to regex matching. | ||
6722 | * Called on each result obtained for the DHT search. | ||
6723 | * | ||
6724 | * @param cls closure (search context) | ||
6725 | * @param exp when will this value expire | ||
6726 | * @param key key of the result | ||
6727 | * @param get_path path of the get request (not used) | ||
6728 | * @param get_path_length lenght of get_path (not used) | ||
6729 | * @param put_path path of the put request (not used) | ||
6730 | * @param put_path_length length of the put_path (not used) | ||
6731 | * @param type type of the result | ||
6732 | * @param size number of bytes in data | ||
6733 | * @param data pointer to the result data | ||
6734 | */ | ||
6735 | static void | ||
6736 | dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
6737 | const struct GNUNET_HashCode * key, | ||
6738 | const struct GNUNET_PeerIdentity *get_path, | ||
6739 | unsigned int get_path_length, | ||
6740 | const struct GNUNET_PeerIdentity *put_path, | ||
6741 | unsigned int put_path_length, | ||
6742 | enum GNUNET_BLOCK_Type type, | ||
6743 | size_t size, const void *data) | ||
6744 | { | ||
6745 | const struct MeshRegexAccept *block = data; | ||
6746 | struct MeshRegexSearchContext *ctx = cls; | ||
6747 | struct MeshRegexSearchInfo *info = ctx->info; | ||
6748 | // struct MeshPeerPath *p; | ||
6749 | struct MeshPeerInfo *peer_info; | ||
6750 | |||
6751 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | ||
6752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", info->description); | ||
6753 | GNUNET_STATISTICS_update (stats, "# regex accepting blocks found", | ||
6754 | 1, GNUNET_NO); | ||
6755 | GNUNET_STATISTICS_update (stats, "# regex accepting block bytes found", | ||
6756 | size, GNUNET_NO); | ||
6757 | |||
6758 | peer_info = peer_info_get(&block->id); | ||
6759 | // p = path_build_from_dht (get_path, get_path_length, put_path, | ||
6760 | // put_path_length); | ||
6761 | // path_add_to_peers (p, GNUNET_NO); | ||
6762 | // path_destroy(p); | ||
6763 | |||
6764 | tunnel_add_peer (info->t, peer_info); | ||
6765 | peer_info_connect (peer_info, info->t); | ||
6766 | if (0 == info->peer) | ||
6767 | { | ||
6768 | info->peer = peer_info->id; | ||
6769 | } | ||
6770 | else | ||
6771 | { | ||
6772 | GNUNET_array_append (info->peers, info->n_peers, peer_info->id); | ||
6773 | } | ||
6774 | |||
6775 | if (GNUNET_SCHEDULER_NO_TASK != info->timeout) | ||
6776 | return; | ||
6777 | |||
6778 | info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, | ||
6779 | ®ex_connect_timeout, | ||
6780 | info); | ||
6781 | |||
6782 | return; | ||
6783 | } | ||
6784 | |||
6785 | |||
6786 | /** | ||
6787 | * Function to process DHT string to regex matching. | ||
6788 | * Called on each result obtained for the DHT search. | ||
6789 | * | ||
6790 | * @param cls closure (search context) | ||
6791 | * @param exp when will this value expire | ||
6792 | * @param key key of the result | ||
6793 | * @param get_path path of the get request (not used) | ||
6794 | * @param get_path_length lenght of get_path (not used) | ||
6795 | * @param put_path path of the put request (not used) | ||
6796 | * @param put_path_length length of the put_path (not used) | ||
6797 | * @param type type of the result | ||
6798 | * @param size number of bytes in data | ||
6799 | * @param data pointer to the result data | ||
6800 | * | ||
6801 | * TODO: re-issue the request after certain time? cancel after X results? | ||
6802 | */ | ||
6803 | static void | ||
6804 | dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
6805 | const struct GNUNET_HashCode * key, | ||
6806 | const struct GNUNET_PeerIdentity *get_path, | ||
6807 | unsigned int get_path_length, | ||
6808 | const struct GNUNET_PeerIdentity *put_path, | ||
6809 | unsigned int put_path_length, | ||
6810 | enum GNUNET_BLOCK_Type type, | ||
6811 | size_t size, const void *data) | ||
6812 | { | ||
6813 | const struct MeshRegexBlock *block = data; | ||
6814 | struct MeshRegexSearchContext *ctx = cls; | ||
6815 | struct MeshRegexSearchInfo *info = ctx->info; | ||
6816 | void *copy; | ||
6817 | size_t len; | ||
6818 | |||
6819 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6820 | "DHT GET STRING RETURNED RESULTS\n"); | ||
6821 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6822 | " key: %s\n", GNUNET_h2s (key)); | ||
6823 | |||
6824 | GNUNET_STATISTICS_update (stats, "# regex blocks found", | ||
6825 | 1, GNUNET_NO); | ||
6826 | GNUNET_STATISTICS_update (stats, "# regex block bytes found", | ||
6827 | size, GNUNET_NO); | ||
6828 | |||
6829 | copy = GNUNET_malloc (size); | ||
6830 | memcpy (copy, data, size); | ||
6831 | GNUNET_break (GNUNET_OK == | ||
6832 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_results, key, copy, | ||
6833 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
6834 | len = ntohl (block->n_proof); | ||
6835 | { | ||
6836 | char proof[len + 1]; | ||
6837 | |||
6838 | memcpy (proof, &block[1], len); | ||
6839 | proof[len] = '\0'; | ||
6840 | if (GNUNET_OK != GNUNET_REGEX_check_proof (proof, key)) | ||
6841 | { | ||
6842 | GNUNET_break_op (0); | ||
6843 | return; | ||
6844 | } | ||
6845 | } | ||
6846 | len = strlen (info->description); | ||
6847 | if (len == ctx->position) // String processed | ||
6848 | { | ||
6849 | if (GNUNET_YES == ntohl (block->accepting)) | ||
6850 | { | ||
6851 | regex_find_path(key, ctx); | ||
6852 | } | ||
6853 | else | ||
6854 | { | ||
6855 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " block not accepting!\n"); | ||
6856 | // FIXME REGEX this block not successful, wait for more? start timeout? | ||
6857 | } | ||
6858 | return; | ||
6859 | } | ||
6860 | |||
6861 | regex_next_edge (block, size, ctx); | ||
6862 | |||
6863 | return; | ||
6864 | } | ||
6865 | |||
6866 | /******************************************************************************/ | 6278 | /******************************************************************************/ |
6867 | /********************* MESH LOCAL HANDLES **************************/ | 6279 | /********************* MESH LOCAL HANDLES **************************/ |
6868 | /******************************************************************************/ | 6280 | /******************************************************************************/ |
@@ -6931,8 +6343,8 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
6931 | for (i = 0; i < c->n_regex; i++) | 6343 | for (i = 0; i < c->n_regex; i++) |
6932 | { | 6344 | { |
6933 | GNUNET_free (c->regexes[i].regex); | 6345 | GNUNET_free (c->regexes[i].regex); |
6934 | if (NULL != c->regexes[i].dfa) | 6346 | if (NULL != c->regexes[i].h) |
6935 | GNUNET_REGEX_automaton_destroy (c->regexes[i].dfa); | 6347 | GNUNET_REGEX_announce_cancel (c->regexes[i].h); |
6936 | } | 6348 | } |
6937 | GNUNET_free_non_null (c->regexes); | 6349 | GNUNET_free_non_null (c->regexes); |
6938 | if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task) | 6350 | if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task) |
@@ -7109,7 +6521,7 @@ handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, | |||
7109 | } | 6521 | } |
7110 | rd.regex = regex; | 6522 | rd.regex = regex; |
7111 | rd.compression = ntohs (msg->compression_characters); | 6523 | rd.compression = ntohs (msg->compression_characters); |
7112 | rd.dfa = NULL; | 6524 | rd.h = NULL; |
7113 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len); | 6525 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len); |
7114 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex); | 6526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex); |
7115 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " cm %u\n", ntohs(rd.compression)); | 6527 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " cm %u\n", ntohs(rd.compression)); |
@@ -7117,7 +6529,7 @@ handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, | |||
7117 | c->partial_regex = NULL; | 6529 | c->partial_regex = NULL; |
7118 | if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task) | 6530 | if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task) |
7119 | { | 6531 | { |
7120 | c->regex_announce_task = GNUNET_SCHEDULER_add_now(&announce_regex, c); | 6532 | c->regex_announce_task = GNUNET_SCHEDULER_add_now(®ex_announce, c); |
7121 | } | 6533 | } |
7122 | else | 6534 | else |
7123 | { | 6535 | { |
@@ -7774,9 +7186,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7774 | const struct GNUNET_MessageHeader *message) | 7186 | const struct GNUNET_MessageHeader *message) |
7775 | { | 7187 | { |
7776 | struct GNUNET_MESH_ConnectPeerByString *msg; | 7188 | struct GNUNET_MESH_ConnectPeerByString *msg; |
7777 | struct MeshRegexSearchContext *ctx; | ||
7778 | struct MeshRegexSearchInfo *info; | 7189 | struct MeshRegexSearchInfo *info; |
7779 | struct GNUNET_DHT_GetHandle *get_h; | ||
7780 | struct GNUNET_HashCode key; | 7190 | struct GNUNET_HashCode key; |
7781 | struct MeshTunnel *t; | 7191 | struct MeshTunnel *t; |
7782 | struct MeshClient *c; | 7192 | struct MeshClient *c; |
@@ -7832,7 +7242,7 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7832 | 7242 | ||
7833 | /* Only one connect_by_string allowed at the same time! */ | 7243 | /* Only one connect_by_string allowed at the same time! */ |
7834 | /* FIXME: allow more, return handle at api level to cancel, document */ | 7244 | /* FIXME: allow more, return handle at api level to cancel, document */ |
7835 | if (NULL != t->regex_ctx) | 7245 | if (NULL != t->regex_search) |
7836 | { | 7246 | { |
7837 | GNUNET_break (0); | 7247 | GNUNET_break (0); |
7838 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 7248 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -7853,34 +7263,14 @@ handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, | |||
7853 | info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo)); | 7263 | info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo)); |
7854 | info->t = t; | 7264 | info->t = t; |
7855 | info->description = GNUNET_strndup (string, len); | 7265 | info->description = GNUNET_strndup (string, len); |
7856 | info->dht_get_handles = GNUNET_CONTAINER_multihashmap_create(32, GNUNET_NO); | ||
7857 | info->dht_get_results = GNUNET_CONTAINER_multihashmap_create(32, GNUNET_NO); | ||
7858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description); | 7266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description); |
7859 | 7267 | ||
7860 | ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext)); | 7268 | t->regex_search = info; |
7861 | ctx->position = size; | 7269 | |
7862 | ctx->info = info; | 7270 | info->search_handle = GNUNET_REGEX_search (dht_handle, |
7863 | t->regex_ctx = ctx; | 7271 | info->description, |
7864 | 7272 | ®ex_found_handler, info, | |
7865 | GNUNET_array_append (info->contexts, info->n_contexts, ctx); | 7273 | stats); |
7866 | |||
7867 | /* Start search in DHT */ | ||
7868 | get_h = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
7869 | GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */ | ||
7870 | &key, /* key to search */ | ||
7871 | dht_replication_level, /* replication level */ | ||
7872 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
7873 | &info->description[size], /* xquery */ | ||
7874 | // FIXME add BLOOMFILTER to exclude filtered peers | ||
7875 | len + 1 - size, /* xquery bits */ | ||
7876 | // FIXME add BLOOMFILTER SIZE | ||
7877 | &dht_get_string_handler, ctx); | ||
7878 | |||
7879 | GNUNET_break (GNUNET_OK == | ||
7880 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | ||
7881 | &key, | ||
7882 | get_h, | ||
7883 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
7884 | 7274 | ||
7885 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 7275 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
7886 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n"); | 7276 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n"); |
diff --git a/src/mesh/plugin_block_mesh.c b/src/mesh/plugin_block_mesh.c index b8a034da2..58faaa538 100644 --- a/src/mesh/plugin_block_mesh.c +++ b/src/mesh/plugin_block_mesh.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | (C) 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2012,2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -27,7 +27,6 @@ | |||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | #include "gnunet_block_plugin.h" | 28 | #include "gnunet_block_plugin.h" |
29 | #include "block_mesh.h" | 29 | #include "block_mesh.h" |
30 | #include "mesh_block_lib.h" | ||
31 | 30 | ||
32 | /** | 31 | /** |
33 | * Number of bits we set per entry in the bloomfilter. | 32 | * Number of bits we set per entry in the bloomfilter. |
@@ -127,92 +126,6 @@ block_plugin_mesh_evaluate (void *cls, enum GNUNET_BLOCK_Type type, | |||
127 | } | 126 | } |
128 | return GNUNET_BLOCK_EVALUATION_OK_MORE; | 127 | return GNUNET_BLOCK_EVALUATION_OK_MORE; |
129 | 128 | ||
130 | |||
131 | case GNUNET_BLOCK_TYPE_MESH_REGEX: | ||
132 | if (NULL == reply_block) | ||
133 | return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; | ||
134 | if (0 != xquery_size) | ||
135 | { | ||
136 | const char *query; | ||
137 | |||
138 | query = (const char *) xquery; | ||
139 | if ('\0' != query[xquery_size - 1]) /* must be valid string */ | ||
140 | { | ||
141 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
142 | "Block xquery not a valid string\n"); | ||
143 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
144 | } | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | GNUNET_break_op (0); | ||
149 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
150 | } | ||
151 | switch (GNUNET_MESH_regex_block_check (reply_block, | ||
152 | reply_block_size, | ||
153 | xquery)) | ||
154 | { | ||
155 | case GNUNET_SYSERR: | ||
156 | GNUNET_break_op(0); | ||
157 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
158 | case GNUNET_NO: | ||
159 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
160 | "BLOCK XQUERY %s not accepted\n", xquery); | ||
161 | return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT; | ||
162 | default: | ||
163 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
164 | "BLOCK XQUERY %s accepted\n", xquery); | ||
165 | break; | ||
166 | } | ||
167 | if (NULL != bf) | ||
168 | { | ||
169 | GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); | ||
170 | GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); | ||
171 | if (NULL != *bf) | ||
172 | { | ||
173 | if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) | ||
174 | return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; | ||
175 | } | ||
176 | else | ||
177 | { | ||
178 | *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); | ||
179 | } | ||
180 | GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); | ||
181 | } | ||
182 | return GNUNET_BLOCK_EVALUATION_OK_MORE; | ||
183 | |||
184 | |||
185 | case GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT: | ||
186 | if (0 != xquery_size) | ||
187 | { | ||
188 | GNUNET_break_op (0); | ||
189 | return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; | ||
190 | } | ||
191 | if (NULL == reply_block) | ||
192 | return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; | ||
193 | if (sizeof (struct MeshRegexAccept) != reply_block_size) | ||
194 | { | ||
195 | GNUNET_break_op(0); | ||
196 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
197 | } | ||
198 | if (NULL != bf) | ||
199 | { | ||
200 | GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); | ||
201 | GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); | ||
202 | if (NULL != *bf) | ||
203 | { | ||
204 | if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) | ||
205 | return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); | ||
210 | } | ||
211 | GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); | ||
212 | } | ||
213 | return GNUNET_BLOCK_EVALUATION_OK_MORE; | ||
214 | |||
215 | |||
216 | default: | 129 | default: |
217 | return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; | 130 | return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; |
218 | } | 131 | } |
@@ -264,8 +177,6 @@ libgnunet_plugin_block_mesh_init (void *cls) | |||
264 | { | 177 | { |
265 | GNUNET_BLOCK_TYPE_MESH_PEER, | 178 | GNUNET_BLOCK_TYPE_MESH_PEER, |
266 | GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, | 179 | GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, |
267 | GNUNET_BLOCK_TYPE_MESH_REGEX, | ||
268 | GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, | ||
269 | GNUNET_BLOCK_TYPE_ANY /* end of list */ | 180 | GNUNET_BLOCK_TYPE_ANY /* end of list */ |
270 | }; | 181 | }; |
271 | struct GNUNET_BLOCK_PluginFunctions *api; | 182 | struct GNUNET_BLOCK_PluginFunctions *api; |
diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am index f6ab33abf..7d7c84dfe 100644 --- a/src/regex/Makefile.am +++ b/src/regex/Makefile.am | |||
@@ -8,17 +8,53 @@ if USE_COVERAGE | |||
8 | AM_CFLAGS = --coverage | 8 | AM_CFLAGS = --coverage |
9 | endif | 9 | endif |
10 | 10 | ||
11 | lib_LTLIBRARIES = libgnunetregex.la | 11 | lib_LTLIBRARIES = libgnunetregexblock.la \ |
12 | libgnunetregex.la | ||
13 | |||
14 | |||
15 | libgnunetregexblock_la_SOURCES = \ | ||
16 | regex_block_lib.c regex_block_lib.h | ||
17 | libgnunetregexblock_la_LIBADD = \ | ||
18 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
19 | $(XLIB) \ | ||
20 | $(LTLIBINTL) | ||
21 | libgnunetregexblock_la_LDFLAGS = \ | ||
22 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
23 | -version-info 1:0:0 | ||
12 | 24 | ||
13 | libgnunetregex_la_SOURCES = \ | 25 | libgnunetregex_la_SOURCES = \ |
14 | regex_internal.h regex.c \ | 26 | regex_internal.h regex.c \ |
15 | regex_graph.c regex_random.c | 27 | regex_graph.c regex_random.c \ |
28 | regex_dht.c | ||
16 | libgnunetregex_la_LIBADD = -lm \ | 29 | libgnunetregex_la_LIBADD = -lm \ |
17 | $(top_builddir)/src/util/libgnunetutil.la | 30 | $(top_builddir)/src/util/libgnunetutil.la \ |
31 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
32 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
33 | $(top_builddir)/src/regex/libgnunetregexblock.la | ||
18 | libgnunetregex_la_LDFLAGS = \ | 34 | libgnunetregex_la_LDFLAGS = \ |
19 | $(GN_LIB_LDFLAGS) \ | 35 | $(GN_LIB_LDFLAGS) \ |
20 | -version-info 1:1:0 | 36 | -version-info 1:1:0 |
21 | 37 | ||
38 | |||
39 | plugindir = $(libdir)/gnunet | ||
40 | |||
41 | plugin_LTLIBRARIES = \ | ||
42 | libgnunet_plugin_block_regex.la | ||
43 | |||
44 | libgnunet_plugin_block_regex_la_SOURCES = \ | ||
45 | plugin_block_regex.c | ||
46 | libgnunet_plugin_block_regex_la_LIBADD = \ | ||
47 | $(top_builddir)/src/regex/libgnunetregexblock.la \ | ||
48 | $(top_builddir)/src/block/libgnunetblock.la \ | ||
49 | $(top_builddir)/src/util/libgnunetutil.la | ||
50 | libgnunet_plugin_block_regex_la_LDFLAGS = \ | ||
51 | $(GN_PLUGIN_LDFLAGS) | ||
52 | libgnunet_plugin_block_regex_la_DEPENDENCIES = \ | ||
53 | $(top_builddir)/src/regex/libgnunetregexblock.la \ | ||
54 | $(top_builddir)/src/block/libgnunetblock.la \ | ||
55 | $(top_builddir)/src/util/libgnunetutil.la | ||
56 | |||
57 | |||
22 | if HAVE_MYSQL | 58 | if HAVE_MYSQL |
23 | noinst_mysql_progs = \ | 59 | noinst_mysql_progs = \ |
24 | gnunet-regex-simulation-profiler | 60 | gnunet-regex-simulation-profiler |
diff --git a/src/regex/plugin_block_regex.c b/src/regex/plugin_block_regex.c new file mode 100644 index 000000000..9a5ab33ec --- /dev/null +++ b/src/regex/plugin_block_regex.c | |||
@@ -0,0 +1,221 @@ | |||
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 | /** | ||
22 | * @file regex/plugin_block_regex.c | ||
23 | * @brief blocks used for regex storage and search | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_block_plugin.h" | ||
29 | #include "block_regex.h" | ||
30 | #include "regex_block_lib.h" | ||
31 | |||
32 | /** | ||
33 | * Number of bits we set per entry in the bloomfilter. | ||
34 | * Do not change! | ||
35 | */ | ||
36 | #define BLOOMFILTER_K 16 | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Function called to validate a reply or a request. For | ||
41 | * request evaluation, simply pass "NULL" for the reply_block. | ||
42 | * Note that it is assumed that the reply has already been | ||
43 | * matched to the key (and signatures checked) as it would | ||
44 | * be done with the "get_key" function. | ||
45 | * | ||
46 | * @param cls closure | ||
47 | * @param type block type | ||
48 | * @param query original query (hash) | ||
49 | * @param bf pointer to bloom filter associated with query; possibly updated (!) | ||
50 | * @param bf_mutator mutation value for bf | ||
51 | * @param xquery extrended query data (can be NULL, depending on type) | ||
52 | * @param xquery_size number of bytes in xquery | ||
53 | * @param reply_block response to validate | ||
54 | * @param reply_block_size number of bytes in reply block | ||
55 | * @return characterization of result | ||
56 | */ | ||
57 | static enum GNUNET_BLOCK_EvaluationResult | ||
58 | block_plugin_regex_evaluate (void *cls, enum GNUNET_BLOCK_Type type, | ||
59 | const struct GNUNET_HashCode * query, | ||
60 | struct GNUNET_CONTAINER_BloomFilter **bf, | ||
61 | int32_t bf_mutator, const void *xquery, | ||
62 | size_t xquery_size, const void *reply_block, | ||
63 | size_t reply_block_size) | ||
64 | { | ||
65 | struct GNUNET_HashCode chash; | ||
66 | struct GNUNET_HashCode mhash; | ||
67 | |||
68 | switch (type) | ||
69 | { | ||
70 | case GNUNET_BLOCK_TYPE_REGEX: | ||
71 | if (NULL == reply_block) | ||
72 | return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; | ||
73 | if (0 != xquery_size) | ||
74 | { | ||
75 | const char *query; | ||
76 | |||
77 | query = (const char *) xquery; | ||
78 | if ('\0' != query[xquery_size - 1]) /* must be valid string */ | ||
79 | { | ||
80 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
81 | "Block xquery not a valid string\n"); | ||
82 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
83 | } | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | GNUNET_break_op (0); | ||
88 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
89 | } | ||
90 | switch (GNUNET_REGEX_block_check (reply_block, | ||
91 | reply_block_size, | ||
92 | xquery)) | ||
93 | { | ||
94 | case GNUNET_SYSERR: | ||
95 | GNUNET_break_op(0); | ||
96 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
97 | case GNUNET_NO: | ||
98 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
99 | "BLOCK XQUERY %s not accepted\n", xquery); | ||
100 | return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT; | ||
101 | default: | ||
102 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
103 | "BLOCK XQUERY %s accepted\n", xquery); | ||
104 | break; | ||
105 | } | ||
106 | if (NULL != bf) | ||
107 | { | ||
108 | GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); | ||
109 | GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); | ||
110 | if (NULL != *bf) | ||
111 | { | ||
112 | if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) | ||
113 | return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); | ||
118 | } | ||
119 | GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); | ||
120 | } | ||
121 | return GNUNET_BLOCK_EVALUATION_OK_MORE; | ||
122 | |||
123 | |||
124 | case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: | ||
125 | if (0 != xquery_size) | ||
126 | { | ||
127 | GNUNET_break_op (0); | ||
128 | return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; | ||
129 | } | ||
130 | if (NULL == reply_block) | ||
131 | return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; | ||
132 | if (sizeof (struct RegexAccept) != reply_block_size) | ||
133 | { | ||
134 | GNUNET_break_op(0); | ||
135 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
136 | } | ||
137 | if (NULL != bf) | ||
138 | { | ||
139 | GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); | ||
140 | GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); | ||
141 | if (NULL != *bf) | ||
142 | { | ||
143 | if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) | ||
144 | return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); | ||
149 | } | ||
150 | GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); | ||
151 | } | ||
152 | return GNUNET_BLOCK_EVALUATION_OK_MORE; | ||
153 | |||
154 | |||
155 | default: | ||
156 | return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * Function called to obtain the key for a block. | ||
163 | * | ||
164 | * @param cls closure | ||
165 | * @param type block type | ||
166 | * @param block block to get the key for | ||
167 | * @param block_size number of bytes in block | ||
168 | * @param key set to the key (query) for the given block | ||
169 | * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported | ||
170 | * (or if extracting a key from a block of this type does not work) | ||
171 | */ | ||
172 | static int | ||
173 | block_plugin_regex_get_key (void *cls, enum GNUNET_BLOCK_Type type, | ||
174 | const void *block, size_t block_size, | ||
175 | struct GNUNET_HashCode * key) | ||
176 | { | ||
177 | switch (type) | ||
178 | { | ||
179 | default: | ||
180 | /* FIXME */ | ||
181 | GNUNET_break (0); | ||
182 | return GNUNET_SYSERR; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Entry point for the plugin. | ||
189 | */ | ||
190 | void * | ||
191 | libgnunet_plugin_block_regex_init (void *cls) | ||
192 | { | ||
193 | static enum GNUNET_BLOCK_Type types[] = | ||
194 | { | ||
195 | GNUNET_BLOCK_TYPE_REGEX, | ||
196 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT, | ||
197 | GNUNET_BLOCK_TYPE_ANY /* end of list */ | ||
198 | }; | ||
199 | struct GNUNET_BLOCK_PluginFunctions *api; | ||
200 | |||
201 | api = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_PluginFunctions)); | ||
202 | api->evaluate = &block_plugin_regex_evaluate; | ||
203 | api->get_key = &block_plugin_regex_get_key; | ||
204 | api->types = types; | ||
205 | return api; | ||
206 | } | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Exit point from the plugin. | ||
211 | */ | ||
212 | void * | ||
213 | libgnunet_plugin_block_regex_done (void *cls) | ||
214 | { | ||
215 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | ||
216 | |||
217 | GNUNET_free (api); | ||
218 | return NULL; | ||
219 | } | ||
220 | |||
221 | /* end of plugin_block_regex.c */ | ||
diff --git a/src/regex/regex.c b/src/regex/regex.c index 92943391a..ad8e56b97 100644 --- a/src/regex/regex.c +++ b/src/regex/regex.c | |||
@@ -20,8 +20,7 @@ | |||
20 | /** | 20 | /** |
21 | * @file src/regex/regex.c | 21 | * @file src/regex/regex.c |
22 | * @brief library to create Deterministic Finite Automatons (DFAs) from regular | 22 | * @brief library to create Deterministic Finite Automatons (DFAs) from regular |
23 | * expressions (regexes). Used by mesh for announcing regexes in the network and | 23 | * expressions (regexes). |
24 | * matching strings against published regexes. | ||
25 | * @author Maximilian Szengel | 24 | * @author Maximilian Szengel |
26 | */ | 25 | */ |
27 | #include "platform.h" | 26 | #include "platform.h" |
diff --git a/src/mesh/mesh_block_lib.c b/src/regex/regex_block_lib.c index d414a5d81..95361ca95 100644 --- a/src/mesh/mesh_block_lib.c +++ b/src/regex/regex_block_lib.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2012,2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -19,16 +19,16 @@ | |||
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @author Bartlomiej Polot | 21 | * @author Bartlomiej Polot |
22 | * @file mesh/mesh_block_lib.c | 22 | * @file regex/regex_block_lib.c |
23 | */ | 23 | */ |
24 | #include "platform.h" | 24 | #include "platform.h" |
25 | #include "mesh_block_lib.h" | 25 | #include "regex_block_lib.h" |
26 | 26 | ||
27 | 27 | ||
28 | /** | 28 | /** |
29 | * Struct to keep track of the xquery while iterating all the edges in a block. | 29 | * Struct to keep track of the xquery while iterating all the edges in a block. |
30 | */ | 30 | */ |
31 | struct mesh_block_xquery_ctx | 31 | struct regex_block_xquery_ctx |
32 | { | 32 | { |
33 | /** | 33 | /** |
34 | * Xquery: string we are looking for. | 34 | * Xquery: string we are looking for. |
@@ -58,7 +58,7 @@ check_edge (void *cls, | |||
58 | size_t len, | 58 | size_t len, |
59 | const struct GNUNET_HashCode *key) | 59 | const struct GNUNET_HashCode *key) |
60 | { | 60 | { |
61 | struct mesh_block_xquery_ctx *ctx = cls; | 61 | struct regex_block_xquery_ctx *ctx = cls; |
62 | 62 | ||
63 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " edge %.*s [%u]\n", | 63 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " edge %.*s [%u]\n", |
64 | (int) len, token, len); | 64 | (int) len, token, len); |
@@ -93,12 +93,12 @@ check_edge (void *cls, | |||
93 | * GNUNET_SYSERR if the block is invalid. | 93 | * GNUNET_SYSERR if the block is invalid. |
94 | */ | 94 | */ |
95 | int | 95 | int |
96 | GNUNET_MESH_regex_block_check (const struct MeshRegexBlock *block, | 96 | GNUNET_REGEX_block_check (const struct RegexBlock *block, |
97 | size_t size, | 97 | size_t size, |
98 | const char *xquery) | 98 | const char *xquery) |
99 | { | 99 | { |
100 | int res; | 100 | int res; |
101 | struct mesh_block_xquery_ctx ctx; | 101 | struct regex_block_xquery_ctx ctx; |
102 | 102 | ||
103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
104 | "* Checking block with xquery \"%s\"\n", | 104 | "* Checking block with xquery \"%s\"\n", |
@@ -107,7 +107,7 @@ GNUNET_MESH_regex_block_check (const struct MeshRegexBlock *block, | |||
107 | return GNUNET_OK; | 107 | return GNUNET_OK; |
108 | ctx.xquery = xquery; | 108 | ctx.xquery = xquery; |
109 | ctx.found = GNUNET_NO; | 109 | ctx.found = GNUNET_NO; |
110 | res = GNUNET_MESH_regex_block_iterate (block, size, &check_edge, &ctx); | 110 | res = GNUNET_REGEX_block_iterate (block, size, &check_edge, &ctx); |
111 | if (GNUNET_SYSERR == res) | 111 | if (GNUNET_SYSERR == res) |
112 | return GNUNET_SYSERR; | 112 | return GNUNET_SYSERR; |
113 | return ctx.found; | 113 | return ctx.found; |
@@ -125,26 +125,26 @@ GNUNET_MESH_regex_block_check (const struct MeshRegexBlock *block, | |||
125 | * @return How many bytes of block have been processed | 125 | * @return How many bytes of block have been processed |
126 | */ | 126 | */ |
127 | int | 127 | int |
128 | GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block, | 128 | GNUNET_REGEX_block_iterate (const struct RegexBlock *block, |
129 | size_t size, | 129 | size_t size, |
130 | GNUNET_MESH_EgdeIterator iterator, | 130 | GNUNET_REGEX_EgdeIterator iterator, |
131 | void *iter_cls) | 131 | void *iter_cls) |
132 | { | 132 | { |
133 | struct MeshRegexEdge *edge; | 133 | struct RegexEdge *edge; |
134 | unsigned int n; | 134 | unsigned int n; |
135 | unsigned int n_token; | 135 | unsigned int n_token; |
136 | unsigned int i; | 136 | unsigned int i; |
137 | size_t offset; | 137 | size_t offset; |
138 | char *aux; | 138 | char *aux; |
139 | 139 | ||
140 | offset = sizeof (struct MeshRegexBlock); | 140 | offset = sizeof (struct RegexBlock); |
141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
142 | "* Start iterating block of size %u, off %u\n", | 142 | "* Start iterating block of size %u, off %u\n", |
143 | size, offset); | 143 | size, offset); |
144 | if (offset > size) // Is it safe to access the regex block? | 144 | if (offset > size) // Is it safe to access the regex block? |
145 | { | 145 | { |
146 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 146 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
147 | "* Block is smaller than struct MeshRegexBlock, END\n"); | 147 | "* Block is smaller than struct RegexBlock, END\n"); |
148 | GNUNET_break_op (0); | 148 | GNUNET_break_op (0); |
149 | return GNUNET_SYSERR; | 149 | return GNUNET_SYSERR; |
150 | } | 150 | } |
@@ -165,16 +165,16 @@ GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block, | |||
165 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Edges: %u\n", n); | 165 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Edges: %u\n", n); |
166 | for (i = 0; i < n; i++) // aux always points at the end of the previous block | 166 | for (i = 0; i < n; i++) // aux always points at the end of the previous block |
167 | { | 167 | { |
168 | offset += sizeof (struct MeshRegexEdge); | 168 | offset += sizeof (struct RegexEdge); |
169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Edge %u, off %u\n", i, offset); | 169 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Edge %u, off %u\n", i, offset); |
170 | if (offset > size) // Is it safe to access the next edge block? | 170 | if (offset > size) // Is it safe to access the next edge block? |
171 | { | 171 | { |
172 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 172 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
173 | "* Size not enough for MeshRegexEdge, END\n"); | 173 | "* Size not enough for RegexEdge, END\n"); |
174 | GNUNET_break_op (0); | 174 | GNUNET_break_op (0); |
175 | return GNUNET_SYSERR; | 175 | return GNUNET_SYSERR; |
176 | } | 176 | } |
177 | edge = (struct MeshRegexEdge *) aux; | 177 | edge = (struct RegexEdge *) aux; |
178 | n_token = ntohl (edge->n_token); | 178 | n_token = ntohl (edge->n_token); |
179 | offset += n_token; | 179 | offset += n_token; |
180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -207,4 +207,4 @@ GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block, | |||
207 | return GNUNET_SYSERR; | 207 | return GNUNET_SYSERR; |
208 | } | 208 | } |
209 | 209 | ||
210 | /* end of mesh_block_lib.c */ | 210 | /* end of regex_block_lib.c */ |
diff --git a/src/mesh/mesh_block_lib.h b/src/regex/regex_block_lib.h index 6ec268c6e..f591f5f61 100644 --- a/src/mesh/mesh_block_lib.h +++ b/src/regex/regex_block_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2012,2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -20,11 +20,11 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @author Bartlomiej Polot | 22 | * @author Bartlomiej Polot |
23 | * @file mesh/mesh_block_lib.h | 23 | * @file regex/regex_block_lib.h |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #ifndef MESH_BLOCK_LIB_H_ | 26 | #ifndef REGEX_BLOCK_LIB_H_ |
27 | #define MESH_BLOCK_LIB_H_ | 27 | #define REGEX_BLOCK_LIB_H_ |
28 | 28 | ||
29 | #ifdef __cplusplus | 29 | #ifdef __cplusplus |
30 | extern "C" | 30 | extern "C" |
@@ -36,7 +36,7 @@ extern "C" | |||
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #include "platform.h" | 38 | #include "platform.h" |
39 | #include "block_mesh.h" | 39 | #include "block_regex.h" |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * Check if the regex block is well formed, including all edges | 42 | * Check if the regex block is well formed, including all edges |
@@ -50,9 +50,9 @@ extern "C" | |||
50 | * GNUNET_SYSERR if the block is invalid. | 50 | * GNUNET_SYSERR if the block is invalid. |
51 | */ | 51 | */ |
52 | int | 52 | int |
53 | GNUNET_MESH_regex_block_check (const struct MeshRegexBlock *block, | 53 | GNUNET_REGEX_block_check (const struct RegexBlock *block, |
54 | size_t size, | 54 | size_t size, |
55 | const char *xquery); | 55 | const char *xquery); |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * Iterator over edges in a block. | 58 | * Iterator over edges in a block. |
@@ -64,10 +64,10 @@ GNUNET_MESH_regex_block_check (const struct MeshRegexBlock *block, | |||
64 | * | 64 | * |
65 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | 65 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. |
66 | */ | 66 | */ |
67 | typedef int (*GNUNET_MESH_EgdeIterator)(void *cls, | 67 | typedef int (*GNUNET_REGEX_EgdeIterator)(void *cls, |
68 | const char *token, | 68 | const char *token, |
69 | size_t len, | 69 | size_t len, |
70 | const struct GNUNET_HashCode *key); | 70 | const struct GNUNET_HashCode *key); |
71 | 71 | ||
72 | 72 | ||
73 | /** | 73 | /** |
@@ -81,10 +81,10 @@ typedef int (*GNUNET_MESH_EgdeIterator)(void *cls, | |||
81 | * @return GNUNET_SYSERR if an error has been encountered, GNUNET_OK otherwise | 81 | * @return GNUNET_SYSERR if an error has been encountered, GNUNET_OK otherwise |
82 | */ | 82 | */ |
83 | int | 83 | int |
84 | GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block, | 84 | GNUNET_REGEX_block_iterate (const struct RegexBlock *block, |
85 | size_t size, | 85 | size_t size, |
86 | GNUNET_MESH_EgdeIterator iterator, | 86 | GNUNET_REGEX_EgdeIterator iterator, |
87 | void *iter_cls); | 87 | void *iter_cls); |
88 | 88 | ||
89 | #if 0 /* keep Emacsens' auto-indent happy */ | 89 | #if 0 /* keep Emacsens' auto-indent happy */ |
90 | { | 90 | { |
@@ -93,6 +93,6 @@ GNUNET_MESH_regex_block_iterate (const struct MeshRegexBlock *block, | |||
93 | } | 93 | } |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | /* ifndef MESH_BLOCK_LIB_H */ | 96 | /* ifndef REGEX_BLOCK_LIB_H */ |
97 | #endif | 97 | #endif |
98 | /* end of mesh_block_lib.h */ | 98 | /* end of regex_block_lib.h */ |
diff --git a/src/regex/regex_dht.c b/src/regex/regex_dht.c new file mode 100644 index 000000000..ce9d4e2a1 --- /dev/null +++ b/src/regex/regex_dht.c | |||
@@ -0,0 +1,754 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2012 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 src/regex/regex_dht.c | ||
22 | * @brief library to announce regexes in the network and match strings | ||
23 | * against published regexes. | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_regex_lib.h" | ||
28 | #include "regex_block_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | |||
32 | #define DHT_REPLICATION 5 | ||
33 | #define DHT_TTL GNUNET_TIME_UNIT_HOURS | ||
34 | |||
35 | struct GNUNET_REGEX_announce_handle | ||
36 | { | ||
37 | /** | ||
38 | * DHT handle to use, must be initialized externally. | ||
39 | */ | ||
40 | struct GNUNET_DHT_Handle *dht; | ||
41 | |||
42 | /** | ||
43 | * Regular expression. | ||
44 | */ | ||
45 | const char *regex; | ||
46 | |||
47 | /** | ||
48 | * Automaton representation of the regex (expensive to build). | ||
49 | */ | ||
50 | struct GNUNET_REGEX_Automaton* dfa; | ||
51 | |||
52 | /** | ||
53 | * Identity under which to announce the regex. | ||
54 | */ | ||
55 | struct GNUNET_PeerIdentity *id; | ||
56 | |||
57 | /** | ||
58 | * Optional statistics handle to report usage. Can be NULL. | ||
59 | */ | ||
60 | struct GNUNET_STATISTICS_Handle *stats; | ||
61 | }; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Regex callback iterator to store own service description in the DHT. | ||
66 | * | ||
67 | * @param cls closure. | ||
68 | * @param key hash for current state. | ||
69 | * @param proof proof for current state. | ||
70 | * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. | ||
71 | * @param num_edges number of edges leaving current state. | ||
72 | * @param edges edges leaving current state. | ||
73 | */ | ||
74 | static void | ||
75 | regex_iterator (void *cls, | ||
76 | const struct GNUNET_HashCode *key, | ||
77 | const char *proof, | ||
78 | int accepting, | ||
79 | unsigned int num_edges, | ||
80 | const struct GNUNET_REGEX_Edge *edges) | ||
81 | { | ||
82 | struct GNUNET_REGEX_announce_handle *h = cls; | ||
83 | struct RegexBlock *block; | ||
84 | struct RegexEdge *block_edge; | ||
85 | enum GNUNET_DHT_RouteOption opt; | ||
86 | size_t size; | ||
87 | size_t len; | ||
88 | unsigned int i; | ||
89 | unsigned int offset; | ||
90 | char *aux; | ||
91 | |||
92 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
93 | " regex dht put for state %s\n", | ||
94 | GNUNET_h2s (key)); | ||
95 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
96 | " proof: %s\n", | ||
97 | proof); | ||
98 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
99 | " num edges: %u\n", | ||
100 | num_edges); | ||
101 | |||
102 | opt = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE; | ||
103 | if (GNUNET_YES == accepting) | ||
104 | { | ||
105 | struct RegexAccept block; | ||
106 | |||
107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
108 | " state %s is accepting, putting own id\n", | ||
109 | GNUNET_h2s(key)); | ||
110 | size = sizeof (block); | ||
111 | block.key = *key; | ||
112 | block.id = *(h->id); | ||
113 | GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored", | ||
114 | 1, GNUNET_NO); | ||
115 | GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored", | ||
116 | sizeof (block), GNUNET_NO); | ||
117 | (void) | ||
118 | GNUNET_DHT_put (h->dht, key, | ||
119 | 2, /* FIXME option */ | ||
120 | opt /* | GNUNET_DHT_RO_RECORD_ROUTE*/, | ||
121 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT, | ||
122 | size, | ||
123 | (char *) &block, | ||
124 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: expiration time should be option */ | ||
125 | GNUNET_TIME_UNIT_HOURS, /* FIXME option */ | ||
126 | NULL, NULL); | ||
127 | } | ||
128 | len = strlen(proof); | ||
129 | size = sizeof (struct RegexBlock) + len; | ||
130 | block = GNUNET_malloc (size); | ||
131 | |||
132 | block->key = *key; | ||
133 | block->n_proof = htonl (len); | ||
134 | block->n_edges = htonl (num_edges); | ||
135 | block->accepting = htonl (accepting); | ||
136 | |||
137 | /* Store the proof at the end of the block. */ | ||
138 | aux = (char *) &block[1]; | ||
139 | memcpy (aux, proof, len); | ||
140 | aux = &aux[len]; | ||
141 | |||
142 | /* Store each edge in a variable length MeshEdge struct at the | ||
143 | * very end of the MeshRegexBlock structure. | ||
144 | */ | ||
145 | for (i = 0; i < num_edges; i++) | ||
146 | { | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
148 | " edge %s towards %s\n", | ||
149 | edges[i].label, | ||
150 | GNUNET_h2s(&edges[i].destination)); | ||
151 | |||
152 | /* aux points at the end of the last block */ | ||
153 | len = strlen (edges[i].label); | ||
154 | size += sizeof (struct RegexEdge) + len; | ||
155 | // Calculate offset FIXME is this ok? use size instead? | ||
156 | offset = aux - (char *) block; | ||
157 | block = GNUNET_realloc (block, size); | ||
158 | aux = &((char *) block)[offset]; | ||
159 | block_edge = (struct RegexEdge *) aux; | ||
160 | block_edge->key = edges[i].destination; | ||
161 | block_edge->n_token = htonl (len); | ||
162 | aux = (char *) &block_edge[1]; | ||
163 | memcpy (aux, edges[i].label, len); | ||
164 | aux = &aux[len]; | ||
165 | } | ||
166 | (void) | ||
167 | GNUNET_DHT_put(h->dht, key, | ||
168 | DHT_REPLICATION, /* FIXME OPTION */ | ||
169 | opt, | ||
170 | GNUNET_BLOCK_TYPE_REGEX, size, | ||
171 | (char *) block, | ||
172 | GNUNET_TIME_relative_to_absolute (DHT_TTL), /* FIXME: this should be an option */ | ||
173 | DHT_TTL, | ||
174 | NULL, NULL); | ||
175 | GNUNET_STATISTICS_update (h->stats, "# regex blocks stored", | ||
176 | 1, GNUNET_NO); | ||
177 | GNUNET_STATISTICS_update (h->stats, "# regex block bytes stored", | ||
178 | size, GNUNET_NO); | ||
179 | |||
180 | GNUNET_free (block); | ||
181 | } | ||
182 | |||
183 | |||
184 | struct GNUNET_REGEX_announce_handle * | ||
185 | GNUNET_REGEX_announce (struct GNUNET_DHT_Handle *dht, | ||
186 | struct GNUNET_PeerIdentity *id, | ||
187 | const char *regex, | ||
188 | uint16_t compression, | ||
189 | struct GNUNET_STATISTICS_Handle *stats) | ||
190 | { | ||
191 | struct GNUNET_REGEX_announce_handle *h; | ||
192 | |||
193 | GNUNET_assert (NULL == dht); | ||
194 | h = GNUNET_malloc (sizeof (struct GNUNET_REGEX_announce_handle)); | ||
195 | h->regex = regex; | ||
196 | h->dht = dht; | ||
197 | h->stats = stats; | ||
198 | h->id = id; | ||
199 | h->dfa = GNUNET_REGEX_construct_dfa (regex, | ||
200 | strlen (regex), | ||
201 | compression); | ||
202 | GNUNET_REGEX_reannounce (h); | ||
203 | return h; | ||
204 | } | ||
205 | |||
206 | void | ||
207 | GNUNET_REGEX_reannounce (struct GNUNET_REGEX_announce_handle *h) | ||
208 | { | ||
209 | GNUNET_REGEX_iterate_all_edges (h->dfa, ®ex_iterator, h); | ||
210 | } | ||
211 | |||
212 | void | ||
213 | GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_announce_handle *h) | ||
214 | { | ||
215 | GNUNET_REGEX_automaton_destroy (h->dfa); | ||
216 | GNUNET_free (h); | ||
217 | } | ||
218 | |||
219 | |||
220 | /******************************************************************************/ | ||
221 | |||
222 | |||
223 | /** | ||
224 | * Struct to keep state of running searches that have consumed a part of | ||
225 | * the inital string. | ||
226 | */ | ||
227 | struct RegexSearchContext | ||
228 | { | ||
229 | /** | ||
230 | * Part of the description already consumed by | ||
231 | * this particular search branch. | ||
232 | */ | ||
233 | size_t position; | ||
234 | |||
235 | /** | ||
236 | * Information about the search. | ||
237 | */ | ||
238 | struct GNUNET_REGEX_search_handle *info; | ||
239 | |||
240 | /** | ||
241 | * We just want to look for one edge, the longer the better. | ||
242 | * Keep its length. | ||
243 | */ | ||
244 | unsigned int longest_match; | ||
245 | |||
246 | /** | ||
247 | * Destination hash of the longest match. | ||
248 | */ | ||
249 | struct GNUNET_HashCode hash; | ||
250 | }; | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Struct to keep information of searches of services described by a regex | ||
255 | * using a user-provided string service description. | ||
256 | */ | ||
257 | struct GNUNET_REGEX_search_handle | ||
258 | { | ||
259 | /** | ||
260 | * DHT handle to use, must be initialized externally. | ||
261 | */ | ||
262 | struct GNUNET_DHT_Handle *dht; | ||
263 | |||
264 | /** | ||
265 | * Optional statistics handle to report usage. Can be NULL. | ||
266 | */ | ||
267 | struct GNUNET_STATISTICS_Handle *stats; | ||
268 | |||
269 | /** | ||
270 | * User provided description of the searched service. | ||
271 | */ | ||
272 | char *description; | ||
273 | |||
274 | /** | ||
275 | * Running DHT GETs. | ||
276 | */ | ||
277 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; | ||
278 | |||
279 | /** | ||
280 | * Results from running DHT GETs. | ||
281 | */ | ||
282 | struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; | ||
283 | |||
284 | /** | ||
285 | * Contexts, for each running DHT GET. Free all on end of search. | ||
286 | */ | ||
287 | struct RegexSearchContext **contexts; | ||
288 | |||
289 | /** | ||
290 | * Number of contexts (branches/steps in search). | ||
291 | */ | ||
292 | unsigned int n_contexts; | ||
293 | |||
294 | /** | ||
295 | * @param callback Callback for found peers. | ||
296 | */ | ||
297 | GNUNET_REGEX_Found callback; | ||
298 | |||
299 | /** | ||
300 | * @param callback_cls Closure for @c callback. | ||
301 | */ | ||
302 | void *callback_cls; | ||
303 | }; | ||
304 | |||
305 | |||
306 | |||
307 | /** | ||
308 | * Jump to the next edge, with the longest matching token. | ||
309 | * | ||
310 | * @param block Block found in the DHT. | ||
311 | * @param size Size of the block. | ||
312 | * @param ctx Context of the search. | ||
313 | * | ||
314 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
315 | */ | ||
316 | static void | ||
317 | regex_next_edge (const struct RegexBlock *block, | ||
318 | size_t size, | ||
319 | struct RegexSearchContext *ctx); | ||
320 | |||
321 | |||
322 | /** | ||
323 | * Function to process DHT string to regex matching. | ||
324 | * Called on each result obtained for the DHT search. | ||
325 | * | ||
326 | * @param cls Closure (search context). | ||
327 | * @param exp When will this value expire. | ||
328 | * @param key Key of the result. | ||
329 | * @param get_path Path of the get request. | ||
330 | * @param get_path_length Lenght of get_path. | ||
331 | * @param put_path Path of the put request. | ||
332 | * @param put_path_length Length of the put_path. | ||
333 | * @param type Type of the result. | ||
334 | * @param size Number of bytes in data. | ||
335 | * @param data Pointer to the result data. | ||
336 | */ | ||
337 | static void | ||
338 | dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
339 | const struct GNUNET_HashCode * key, | ||
340 | const struct GNUNET_PeerIdentity *get_path, | ||
341 | unsigned int get_path_length, | ||
342 | const struct GNUNET_PeerIdentity *put_path, | ||
343 | unsigned int put_path_length, | ||
344 | enum GNUNET_BLOCK_Type type, | ||
345 | size_t size, const void *data) | ||
346 | { | ||
347 | const struct RegexAccept *block = data; | ||
348 | struct RegexSearchContext *ctx = cls; | ||
349 | struct GNUNET_REGEX_search_handle *info = ctx->info; | ||
350 | |||
351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n"); | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", info->description); | ||
353 | |||
354 | GNUNET_STATISTICS_update (info->stats, "# regex accepting blocks found", | ||
355 | 1, GNUNET_NO); | ||
356 | GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found", | ||
357 | size, GNUNET_NO); | ||
358 | |||
359 | info->callback (info->callback_cls, | ||
360 | &block->id, | ||
361 | get_path, get_path_length, | ||
362 | put_path, put_path_length); | ||
363 | |||
364 | return; | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * Find a path to a peer that offers a regex servcie compatible | ||
369 | * with a given string. | ||
370 | * | ||
371 | * @param key The key of the accepting state. | ||
372 | * @param ctx Context containing info about the string, tunnel, etc. | ||
373 | */ | ||
374 | static void | ||
375 | regex_find_path (const struct GNUNET_HashCode *key, | ||
376 | struct RegexSearchContext *ctx) | ||
377 | { | ||
378 | struct GNUNET_DHT_GetHandle *get_h; | ||
379 | |||
380 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n"); | ||
381 | get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ | ||
382 | GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ | ||
383 | key, /* key to search */ | ||
384 | DHT_REPLICATION, /* replication level */ | ||
385 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE | | ||
386 | GNUNET_DHT_RO_RECORD_ROUTE, | ||
387 | NULL, /* xquery */ // FIXME BLOOMFILTER | ||
388 | 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE | ||
389 | &dht_get_string_accept_handler, ctx); | ||
390 | GNUNET_break (GNUNET_OK == | ||
391 | GNUNET_CONTAINER_multihashmap_put(ctx->info->dht_get_handles, | ||
392 | key, | ||
393 | get_h, | ||
394 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Function to process DHT string to regex matching. | ||
400 | * Called on each result obtained for the DHT search. | ||
401 | * | ||
402 | * @param cls closure (search context) | ||
403 | * @param exp when will this value expire | ||
404 | * @param key key of the result | ||
405 | * @param get_path path of the get request (not used) | ||
406 | * @param get_path_length lenght of get_path (not used) | ||
407 | * @param put_path path of the put request (not used) | ||
408 | * @param put_path_length length of the put_path (not used) | ||
409 | * @param type type of the result | ||
410 | * @param size number of bytes in data | ||
411 | * @param data pointer to the result data | ||
412 | * | ||
413 | * TODO: re-issue the request after certain time? cancel after X results? | ||
414 | */ | ||
415 | static void | ||
416 | dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
417 | const struct GNUNET_HashCode * key, | ||
418 | const struct GNUNET_PeerIdentity *get_path, | ||
419 | unsigned int get_path_length, | ||
420 | const struct GNUNET_PeerIdentity *put_path, | ||
421 | unsigned int put_path_length, | ||
422 | enum GNUNET_BLOCK_Type type, | ||
423 | size_t size, const void *data) | ||
424 | { | ||
425 | const struct RegexBlock *block = data; | ||
426 | struct RegexSearchContext *ctx = cls; | ||
427 | struct GNUNET_REGEX_search_handle *info = ctx->info; | ||
428 | void *copy; | ||
429 | size_t len; | ||
430 | |||
431 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
432 | "DHT GET STRING RETURNED RESULTS\n"); | ||
433 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
434 | " key: %s\n", GNUNET_h2s (key)); | ||
435 | |||
436 | copy = GNUNET_malloc (size); | ||
437 | memcpy (copy, data, size); | ||
438 | GNUNET_break (GNUNET_OK == | ||
439 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_results, key, copy, | ||
440 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
441 | len = ntohl (block->n_proof); | ||
442 | { | ||
443 | char proof[len + 1]; | ||
444 | |||
445 | memcpy (proof, &block[1], len); | ||
446 | proof[len] = '\0'; | ||
447 | if (GNUNET_OK != GNUNET_REGEX_check_proof (proof, key)) | ||
448 | { | ||
449 | GNUNET_break_op (0); | ||
450 | return; | ||
451 | } | ||
452 | } | ||
453 | len = strlen (info->description); | ||
454 | if (len == ctx->position) // String processed | ||
455 | { | ||
456 | if (GNUNET_YES == ntohl (block->accepting)) | ||
457 | { | ||
458 | regex_find_path(key, ctx); | ||
459 | } | ||
460 | else | ||
461 | { | ||
462 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " block not accepting!\n"); | ||
463 | // FIXME REGEX this block not successful, wait for more? start timeout? | ||
464 | } | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | regex_next_edge (block, size, ctx); | ||
469 | |||
470 | return; | ||
471 | } | ||
472 | |||
473 | |||
474 | /** | ||
475 | * Iterator over found existing mesh regex blocks that match an ongoing search. | ||
476 | * | ||
477 | * @param cls closure | ||
478 | * @param key current key code | ||
479 | * @param value value in the hash map | ||
480 | * @return GNUNET_YES if we should continue to iterate, | ||
481 | * GNUNET_NO if not. | ||
482 | */ | ||
483 | static int | ||
484 | regex_result_iterator (void *cls, | ||
485 | const struct GNUNET_HashCode * key, | ||
486 | void *value) | ||
487 | { | ||
488 | struct RegexBlock *block = value; | ||
489 | struct RegexSearchContext *ctx = cls; | ||
490 | |||
491 | if (GNUNET_YES == ntohl(block->accepting) && | ||
492 | ctx->position == strlen (ctx->info->description)) | ||
493 | { | ||
494 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Found accepting known block\n"); | ||
495 | regex_find_path (key, ctx); | ||
496 | return GNUNET_YES; // We found an accept state! | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", | ||
501 | ctx->position, strlen(ctx->info->description), | ||
502 | ntohl(block->accepting)); | ||
503 | |||
504 | } | ||
505 | regex_next_edge(block, SIZE_MAX, ctx); | ||
506 | |||
507 | GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated", | ||
508 | 1, GNUNET_NO); | ||
509 | |||
510 | return GNUNET_YES; | ||
511 | } | ||
512 | |||
513 | |||
514 | /** | ||
515 | * Iterator over edges in a regex block retrieved from the DHT. | ||
516 | * | ||
517 | * @param cls Closure (context of the search). | ||
518 | * @param token Token that follows to next state. | ||
519 | * @param len Lenght of token. | ||
520 | * @param key Hash of next state. | ||
521 | * | ||
522 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
523 | */ | ||
524 | static int | ||
525 | regex_edge_iterator (void *cls, | ||
526 | const char *token, | ||
527 | size_t len, | ||
528 | const struct GNUNET_HashCode *key) | ||
529 | { | ||
530 | struct RegexSearchContext *ctx = cls; | ||
531 | struct GNUNET_REGEX_search_handle *info = ctx->info; | ||
532 | const char *current; | ||
533 | size_t current_len; | ||
534 | |||
535 | GNUNET_STATISTICS_update (info->stats, "# regex edges iterated", | ||
536 | 1, GNUNET_NO); | ||
537 | |||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Start of regex edge iterator\n"); | ||
539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* descr : %s\n", info->description); | ||
540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* posit : %u\n", ctx->position); | ||
541 | current = &info->description[ctx->position]; | ||
542 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* currt : %s\n", current); | ||
543 | current_len = strlen (info->description) - ctx->position; | ||
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* ctlen : %u\n", current_len); | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* tklen : %u\n", len); | ||
546 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* token : %.*s\n", len, token); | ||
547 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* nextk : %s\n", GNUNET_h2s(key)); | ||
548 | if (len > current_len) | ||
549 | { | ||
550 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token too long, END\n"); | ||
551 | return GNUNET_YES; // Token too long, wont match | ||
552 | } | ||
553 | if (0 != strncmp (current, token, len)) | ||
554 | { | ||
555 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token doesn't match, END\n"); | ||
556 | return GNUNET_YES; // Token doesn't match | ||
557 | } | ||
558 | |||
559 | if (len > ctx->longest_match) | ||
560 | { | ||
561 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is longer, KEEP\n"); | ||
562 | ctx->longest_match = len; | ||
563 | ctx->hash = *key; | ||
564 | } | ||
565 | else | ||
566 | { | ||
567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Token is not longer, IGNORE\n"); | ||
568 | } | ||
569 | |||
570 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); | ||
571 | return GNUNET_YES; | ||
572 | } | ||
573 | |||
574 | |||
575 | /** | ||
576 | * Jump to the next edge, with the longest matching token. | ||
577 | * | ||
578 | * @param block Block found in the DHT. | ||
579 | * @param size Size of the block. | ||
580 | * @param ctx Context of the search. | ||
581 | * | ||
582 | * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. | ||
583 | */ | ||
584 | static void | ||
585 | regex_next_edge (const struct RegexBlock *block, | ||
586 | size_t size, | ||
587 | struct RegexSearchContext *ctx) | ||
588 | { | ||
589 | struct RegexSearchContext *new_ctx; | ||
590 | struct GNUNET_REGEX_search_handle *info = ctx->info; | ||
591 | struct GNUNET_DHT_GetHandle *get_h; | ||
592 | const char *rest; | ||
593 | int result; | ||
594 | |||
595 | /* Find the longest match for the current string position, | ||
596 | * among tokens in the given block */ | ||
597 | ctx->longest_match = 0; | ||
598 | result = GNUNET_REGEX_block_iterate (block, size, | ||
599 | ®ex_edge_iterator, ctx); | ||
600 | GNUNET_break (GNUNET_OK == result); | ||
601 | |||
602 | /* Did anything match? */ | ||
603 | if (0 == ctx->longest_match) | ||
604 | return; | ||
605 | |||
606 | new_ctx = GNUNET_malloc (sizeof (struct RegexSearchContext)); | ||
607 | new_ctx->info = info; | ||
608 | new_ctx->position = ctx->position + ctx->longest_match; | ||
609 | GNUNET_array_append (info->contexts, info->n_contexts, new_ctx); | ||
610 | |||
611 | /* Check whether we already have a DHT GET running for it */ | ||
612 | if (GNUNET_YES == | ||
613 | GNUNET_CONTAINER_multihashmap_contains(info->dht_get_handles, &ctx->hash)) | ||
614 | { | ||
615 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* GET running, END\n"); | ||
616 | GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, | ||
617 | &ctx->hash, | ||
618 | ®ex_result_iterator, | ||
619 | new_ctx); | ||
620 | // FIXME: "leaks" new_ctx? avoid keeping it around? | ||
621 | return; // We are already looking for it | ||
622 | } | ||
623 | |||
624 | GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed", | ||
625 | 1, GNUNET_NO); | ||
626 | |||
627 | /* Start search in DHT */ | ||
628 | rest = &new_ctx->info->description[new_ctx->position]; | ||
629 | get_h = | ||
630 | GNUNET_DHT_get_start (info->dht, /* handle */ | ||
631 | GNUNET_BLOCK_TYPE_REGEX, /* type */ | ||
632 | &ctx->hash, /* key to search */ | ||
633 | DHT_REPLICATION, /* replication level */ | ||
634 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
635 | rest, /* xquery */ | ||
636 | // FIXME add BLOOMFILTER to exclude filtered peers | ||
637 | strlen(rest) + 1, /* xquery bits */ | ||
638 | // FIXME add BLOOMFILTER SIZE | ||
639 | &dht_get_string_handler, new_ctx); | ||
640 | if (GNUNET_OK != | ||
641 | GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, | ||
642 | &ctx->hash, | ||
643 | get_h, | ||
644 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
645 | { | ||
646 | GNUNET_break (0); | ||
647 | return; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | |||
652 | struct GNUNET_REGEX_search_handle * | ||
653 | GNUNET_REGEX_search (struct GNUNET_DHT_Handle *dht, | ||
654 | const char *string, | ||
655 | GNUNET_REGEX_Found callback, | ||
656 | void *callback_cls, | ||
657 | struct GNUNET_STATISTICS_Handle *stats) | ||
658 | { | ||
659 | struct GNUNET_REGEX_search_handle *h; | ||
660 | |||
661 | GNUNET_assert (NULL == dht); | ||
662 | h = GNUNET_malloc (sizeof (struct GNUNET_REGEX_search_handle)); | ||
663 | h->dht = dht; | ||
664 | h->description = GNUNET_strdup (string); | ||
665 | h->callback = callback; | ||
666 | h->callback_cls = callback_cls; | ||
667 | h->stats = stats; | ||
668 | |||
669 | h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); | ||
670 | h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); | ||
671 | return h; | ||
672 | } | ||
673 | |||
674 | |||
675 | /** | ||
676 | * Iterator over hash map entries to cancel DHT GET requests after a | ||
677 | * successful connect_by_string. | ||
678 | * | ||
679 | * @param cls Closure (unused). | ||
680 | * @param key Current key code (unused). | ||
681 | * @param value Value in the hash map (get handle). | ||
682 | * @return GNUNET_YES if we should continue to iterate, | ||
683 | * GNUNET_NO if not. | ||
684 | */ | ||
685 | static int | ||
686 | regex_cancel_dht_get (void *cls, | ||
687 | const struct GNUNET_HashCode * key, | ||
688 | void *value) | ||
689 | { | ||
690 | struct GNUNET_DHT_GetHandle *h = value; | ||
691 | |||
692 | GNUNET_DHT_get_stop (h); | ||
693 | return GNUNET_YES; | ||
694 | } | ||
695 | |||
696 | |||
697 | /** | ||
698 | * Iterator over hash map entries to free MeshRegexBlocks stored during the | ||
699 | * search for connect_by_string. | ||
700 | * | ||
701 | * @param cls Closure (unused). | ||
702 | * @param key Current key code (unused). | ||
703 | * @param value MeshRegexBlock in the hash map. | ||
704 | * @return GNUNET_YES if we should continue to iterate, | ||
705 | * GNUNET_NO if not. | ||
706 | */ | ||
707 | static int | ||
708 | regex_free_result (void *cls, | ||
709 | const struct GNUNET_HashCode * key, | ||
710 | void *value) | ||
711 | { | ||
712 | |||
713 | GNUNET_free (value); | ||
714 | return GNUNET_YES; | ||
715 | } | ||
716 | |||
717 | |||
718 | /** | ||
719 | * Cancel an ongoing regex search in the DHT and free all resources. | ||
720 | * | ||
721 | * @param ctx The search context. | ||
722 | */ | ||
723 | static void | ||
724 | regex_cancel_search (struct GNUNET_REGEX_search_handle *ctx) | ||
725 | { | ||
726 | GNUNET_free (ctx->description); | ||
727 | GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_handles, | ||
728 | ®ex_cancel_dht_get, NULL); | ||
729 | GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_results, | ||
730 | ®ex_free_result, NULL); | ||
731 | GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_results); | ||
732 | GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_handles); | ||
733 | if (0 < ctx->n_contexts) | ||
734 | { | ||
735 | int i; | ||
736 | |||
737 | for (i = 0; i < ctx->n_contexts; i++) | ||
738 | { | ||
739 | GNUNET_free (ctx->contexts[i]); | ||
740 | } | ||
741 | GNUNET_free (ctx->contexts); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | void | ||
746 | GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_search_handle *h) | ||
747 | { | ||
748 | regex_cancel_search (h); | ||
749 | GNUNET_free (h); | ||
750 | } | ||
751 | |||
752 | |||
753 | |||
754 | /* end of regex_dht.c */ \ No newline at end of file | ||