diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-09-27 20:49:32 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-09-27 20:49:32 +0000 |
commit | 2d10e77135a8db547c187c4aadcff8d1f1763412 (patch) | |
tree | f5083f58af35a8d1ffd07838d690d6d511b49608 /src/dht | |
parent | 18ad006e1f9b322d4760fb1473e8182f0d6ae7f0 (diff) | |
download | gnunet-2d10e77135a8db547c187c4aadcff8d1f1763412.tar.gz gnunet-2d10e77135a8db547c187c4aadcff8d1f1763412.zip |
fixes
Diffstat (limited to 'src/dht')
-rw-r--r-- | src/dht/Makefile.am | 17 | ||||
-rw-r--r-- | src/dht/dht.h | 485 | ||||
-rw-r--r-- | src/dht/dht_api.c | 909 | ||||
-rw-r--r-- | src/dht/dht_api_find_peer.c | 150 | ||||
-rw-r--r-- | src/dht/dht_api_get_put.c | 274 | ||||
-rw-r--r-- | src/dht/gnunet-service-dht_neighbours.c | 7 |
6 files changed, 3 insertions, 1839 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am index 147248234..d6045112b 100644 --- a/src/dht/Makefile.am +++ b/src/dht/Makefile.am | |||
@@ -15,21 +15,9 @@ if USE_COVERAGE | |||
15 | endif | 15 | endif |
16 | 16 | ||
17 | lib_LTLIBRARIES = \ | 17 | lib_LTLIBRARIES = \ |
18 | libgnunetdht.la \ | ||
19 | libgnunetdhtnew.la | 18 | libgnunetdhtnew.la |
20 | 19 | ||
21 | 20 | ||
22 | libgnunetdht_la_SOURCES = \ | ||
23 | dht_api.c dht.h \ | ||
24 | dht_api_get_put.c \ | ||
25 | dht_api_find_peer.c | ||
26 | libgnunetdht_la_LIBADD = \ | ||
27 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
28 | $(XLIB) | ||
29 | libgnunetdht_la_LDFLAGS = \ | ||
30 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
31 | -version-info 0:0:0 | ||
32 | |||
33 | libgnunetdhtnew_la_SOURCES = \ | 21 | libgnunetdhtnew_la_SOURCES = \ |
34 | dht_api_new.c dht_new.h | 22 | dht_api_new.c dht_new.h |
35 | libgnunetdhtnew_la_LIBADD = \ | 23 | libgnunetdhtnew_la_LIBADD = \ |
@@ -44,11 +32,6 @@ bin_PROGRAMS = \ | |||
44 | gnunet-dht-get \ | 32 | gnunet-dht-get \ |
45 | gnunet-dht-put | 33 | gnunet-dht-put |
46 | 34 | ||
47 | if HAVE_MALICIOUS | ||
48 | noinst_PROGRAMS = \ | ||
49 | gnunet-dht-driver | ||
50 | endif | ||
51 | |||
52 | gnunet_service_dht_new_SOURCES = \ | 35 | gnunet_service_dht_new_SOURCES = \ |
53 | gnunet-service-dht-new.c gnunet-service-dht.h \ | 36 | gnunet-service-dht-new.c gnunet-service-dht.h \ |
54 | gnunet-service-dht_clients.c gnunet-service-dht_clients.h \ | 37 | gnunet-service-dht_clients.c gnunet-service-dht_clients.h \ |
diff --git a/src/dht/dht.h b/src/dht/dht.h deleted file mode 100644 index 4832df490..000000000 --- a/src/dht/dht.h +++ /dev/null | |||
@@ -1,485 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001, 2002, 2003, 2004, 2009 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 | * @author Christian Grothoff | ||
23 | * @author Nathan Evans | ||
24 | * @file dht/dht.h | ||
25 | */ | ||
26 | |||
27 | #ifndef DHT_H_ | ||
28 | #define DHT_H_ | ||
29 | |||
30 | #define DEBUG_DHT GNUNET_NO | ||
31 | |||
32 | /** | ||
33 | * Add a unique ID to every request to make testing/profiling easier. | ||
34 | * Should NEVER be enabled in production and makes the DHT incompatible | ||
35 | * (since this changes the message format). | ||
36 | */ | ||
37 | #define HAVE_UID_FOR_TESTING GNUNET_NO | ||
38 | |||
39 | /** | ||
40 | * Needs to be GNUNET_YES for logging to dhtlog to work! | ||
41 | */ | ||
42 | #define DEBUG_DHT_ROUTING GNUNET_YES | ||
43 | |||
44 | /** | ||
45 | * Size of the bloom filter the DHT uses to filter peers. | ||
46 | */ | ||
47 | #define DHT_BLOOM_SIZE 128 | ||
48 | |||
49 | /** | ||
50 | * Number of bits set per entry in the bloom filter for peers. | ||
51 | */ | ||
52 | #define DHT_BLOOM_K 6 | ||
53 | |||
54 | /** | ||
55 | * How many requests to remember for forwarding responses. | ||
56 | */ | ||
57 | #define MAX_OUTSTANDING_FORWARDS 100 | ||
58 | |||
59 | /** | ||
60 | * How long to remember requests so we can forward responses. | ||
61 | */ | ||
62 | #define DHT_FORWARD_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
63 | |||
64 | /** | ||
65 | * Priority for routing results from other peers through | ||
66 | * the DHT. | ||
67 | */ | ||
68 | #define DHT_SEND_PRIORITY 4 | ||
69 | |||
70 | |||
71 | #define STAT_ROUTES "# DHT ROUTE Requests Seen" | ||
72 | #define STAT_ROUTE_FORWARDS "# DHT ROUTE Requests Forwarded" | ||
73 | #define STAT_ROUTE_FORWARDS_CLOSEST "# DHT ROUTE Requests Forwarded to Closest Known Peer" | ||
74 | #define STAT_RESULTS "# DHT ROUTE RESULT Requests Seen" | ||
75 | #define STAT_RESULTS_TO_CLIENT "# DHT ROUTE RESULT Sent to Client" | ||
76 | #define STAT_RESULT_FORWARDS "# DHT ROUTE RESULT Requests Forwarded" | ||
77 | #define STAT_GETS "# DHT GET Requests Handled" | ||
78 | #define STAT_PUTS "# DHT PUT Requests Handled" | ||
79 | #define STAT_PUTS_INSERTED "# DHT PUT Data Inserts" | ||
80 | #define STAT_FIND_PEER "# DHT FIND_PEER Requests Handled" | ||
81 | #define STAT_FIND_PEER_START "# DHT FIND_PEER Requests Initiated" | ||
82 | #define STAT_GET_START "# DHT GET Requests Initiated" | ||
83 | #define STAT_PUT_START "# DHT PUT Requests Initiated" | ||
84 | #define STAT_FIND_PEER_REPLY "# DHT FIND_PEER Responses Received" | ||
85 | #define STAT_GET_REPLY "# DHT GET Responses Received" | ||
86 | #define STAT_FIND_PEER_ANSWER "# DHT FIND_PEER Responses Initiated" | ||
87 | #define STAT_BLOOM_FIND_PEER "# DHT FIND_PEER Responses Ignored (bloom match)" | ||
88 | #define STAT_GET_RESPONSE_START "# DHT GET Responses Initiated" | ||
89 | #define STAT_HELLOS_PROVIDED "# HELLO Messages given to transport" | ||
90 | #define STAT_DISCONNECTS "# Disconnects received" | ||
91 | #define STAT_DUPLICATE_UID "# Duplicate UID's encountered (bad if any!)" | ||
92 | #define STAT_RECENT_SEEN "# recent requests seen again (routing loops, alternate paths)" | ||
93 | #define STAT_PEERS_KNOWN "# DHT Peers known" | ||
94 | |||
95 | |||
96 | /** | ||
97 | * FIXME: document. | ||
98 | */ | ||
99 | typedef void (*GNUNET_DHT_MessageReceivedHandler) (void *cls, | ||
100 | const struct | ||
101 | GNUNET_MessageHeader * msg); | ||
102 | |||
103 | |||
104 | /** | ||
105 | * FIXME: document. | ||
106 | */ | ||
107 | struct GNUNET_DHT_ControlMessage | ||
108 | { | ||
109 | /** | ||
110 | * Type: GNUNET_MESSAGE_TYPE_DHT_CONTROL | ||
111 | */ | ||
112 | struct GNUNET_MessageHeader header; | ||
113 | |||
114 | /** | ||
115 | * Command code of the message. | ||
116 | */ | ||
117 | uint16_t command; | ||
118 | |||
119 | /** | ||
120 | * Variable parameter for the command. | ||
121 | */ | ||
122 | uint16_t variable; | ||
123 | }; | ||
124 | |||
125 | |||
126 | /** | ||
127 | * Message which indicates the DHT should cancel outstanding | ||
128 | * requests and discard any state. | ||
129 | */ | ||
130 | struct GNUNET_DHT_StopMessage | ||
131 | { | ||
132 | /** | ||
133 | * Type: GNUNET_MESSAGE_TYPE_DHT_STOP | ||
134 | */ | ||
135 | struct GNUNET_MessageHeader header; | ||
136 | |||
137 | /** | ||
138 | * Always zero. | ||
139 | */ | ||
140 | uint32_t reserved GNUNET_PACKED; | ||
141 | |||
142 | /** | ||
143 | * Unique ID identifying this request | ||
144 | */ | ||
145 | uint64_t unique_id GNUNET_PACKED; | ||
146 | |||
147 | /** | ||
148 | * Key of this request | ||
149 | */ | ||
150 | GNUNET_HashCode key; | ||
151 | |||
152 | }; | ||
153 | |||
154 | |||
155 | /** | ||
156 | * Generic DHT message, indicates that a route request | ||
157 | * should be issued. | ||
158 | */ | ||
159 | struct GNUNET_DHT_RouteMessage | ||
160 | { | ||
161 | /** | ||
162 | * Type: GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE | ||
163 | */ | ||
164 | struct GNUNET_MessageHeader header; | ||
165 | |||
166 | /** | ||
167 | * Message options, actually an 'enum GNUNET_DHT_RouteOption' value. | ||
168 | */ | ||
169 | uint32_t options GNUNET_PACKED; | ||
170 | |||
171 | /** | ||
172 | * Replication level for this message | ||
173 | */ | ||
174 | uint32_t desired_replication_level GNUNET_PACKED; | ||
175 | |||
176 | /** | ||
177 | * For alignment, always zero. | ||
178 | */ | ||
179 | uint32_t reserved GNUNET_PACKED; | ||
180 | |||
181 | /** | ||
182 | * The key to search for | ||
183 | */ | ||
184 | GNUNET_HashCode key; | ||
185 | |||
186 | /** | ||
187 | * Unique ID identifying this request, if 0 then | ||
188 | * the client will not expect a response | ||
189 | */ | ||
190 | uint64_t unique_id GNUNET_PACKED; | ||
191 | |||
192 | |||
193 | /* GNUNET_MessageHeader *enc actual DHT message, copied to end of this dealy do */ | ||
194 | |||
195 | }; | ||
196 | |||
197 | |||
198 | /** | ||
199 | * Generic local route result message | ||
200 | */ | ||
201 | struct GNUNET_DHT_RouteResultMessage | ||
202 | { | ||
203 | /** | ||
204 | * Type: GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE_RESULT | ||
205 | */ | ||
206 | struct GNUNET_MessageHeader header; | ||
207 | |||
208 | /** | ||
209 | * Number of peers recorded in the outgoing | ||
210 | * path from source to the final destination | ||
211 | * of this message. | ||
212 | */ | ||
213 | uint32_t outgoing_path_length GNUNET_PACKED; | ||
214 | |||
215 | /** | ||
216 | * Unique ID identifying this request (necessary for | ||
217 | * client to compare to sent requests) | ||
218 | */ | ||
219 | uint64_t unique_id GNUNET_PACKED; | ||
220 | |||
221 | /** | ||
222 | * The key that was searched for | ||
223 | */ | ||
224 | GNUNET_HashCode key; | ||
225 | |||
226 | /* GNUNET_MessageHeader *enc actual DHT message, copied to end of this dealy do */ | ||
227 | |||
228 | /* OUTGOING path */ | ||
229 | }; | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Generic P2P DHT route message | ||
234 | */ | ||
235 | struct GNUNET_DHT_P2PRouteMessage | ||
236 | { | ||
237 | /** | ||
238 | * Type: GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE | ||
239 | */ | ||
240 | struct GNUNET_MessageHeader header; | ||
241 | |||
242 | /** | ||
243 | * Always zero. | ||
244 | */ | ||
245 | uint32_t reserved GNUNET_PACKED; | ||
246 | |||
247 | /** | ||
248 | * Message options | ||
249 | */ | ||
250 | uint32_t options GNUNET_PACKED; | ||
251 | |||
252 | /** | ||
253 | * Hop count | ||
254 | */ | ||
255 | uint32_t hop_count GNUNET_PACKED; | ||
256 | |||
257 | /** | ||
258 | * Replication level for this message | ||
259 | */ | ||
260 | uint32_t desired_replication_level GNUNET_PACKED; | ||
261 | |||
262 | /** | ||
263 | * Network size estimate | ||
264 | */ | ||
265 | uint32_t network_size GNUNET_PACKED; | ||
266 | |||
267 | /** | ||
268 | * Generic route path length for a message in the | ||
269 | * DHT that arrived at a peer and generated | ||
270 | * a reply. Copied to the end of this message. | ||
271 | */ | ||
272 | uint32_t outgoing_path_length GNUNET_PACKED; | ||
273 | |||
274 | #if HAVE_UID_FOR_TESTING | ||
275 | /** | ||
276 | * Unique ID identifying this request (may not be set) | ||
277 | */ | ||
278 | uint64_t unique_id GNUNET_PACKED; | ||
279 | #endif | ||
280 | |||
281 | /** | ||
282 | * Bloomfilter (for peer identities) to stop circular routes | ||
283 | */ | ||
284 | char bloomfilter[DHT_BLOOM_SIZE]; | ||
285 | |||
286 | /** | ||
287 | * The key to search for | ||
288 | */ | ||
289 | GNUNET_HashCode key; | ||
290 | |||
291 | /* GNUNET_MessageHeader *enc actual DHT message, copied to end of this dealy do */ | ||
292 | |||
293 | /* OUTGOING PATH */ | ||
294 | |||
295 | }; | ||
296 | |||
297 | /** | ||
298 | * Generic P2P route result | ||
299 | */ | ||
300 | struct GNUNET_DHT_P2PRouteResultMessage | ||
301 | { | ||
302 | /** | ||
303 | * Type: GNUNET_MESSAGE_TYPE_DHT_P2P_ROUTE_RESULT | ||
304 | */ | ||
305 | struct GNUNET_MessageHeader header; | ||
306 | |||
307 | /** | ||
308 | * Number of peers recorded in the path | ||
309 | * (inverse of the path the outgoing message took). | ||
310 | * These peer identities follow this message. | ||
311 | */ | ||
312 | uint32_t outgoing_path_length GNUNET_PACKED; | ||
313 | |||
314 | /** | ||
315 | * Message options | ||
316 | */ | ||
317 | uint32_t options GNUNET_PACKED; | ||
318 | |||
319 | /** | ||
320 | * Hop count | ||
321 | */ | ||
322 | uint32_t hop_count GNUNET_PACKED; | ||
323 | |||
324 | #if HAVE_UID_FOR_TESTING | ||
325 | /** | ||
326 | * Unique ID identifying this request (may not be set) | ||
327 | */ | ||
328 | uint64_t unique_id GNUNET_PACKED; | ||
329 | #endif | ||
330 | |||
331 | /** | ||
332 | * The key that was searched for | ||
333 | */ | ||
334 | GNUNET_HashCode key; | ||
335 | |||
336 | /* GNUNET_MessageHeader *enc actual DHT message, copied to end of this dealy do */ | ||
337 | |||
338 | /* OUTGOING PATH */ | ||
339 | }; | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Message to insert data into the DHT, shared | ||
344 | * between api->server communication and P2P communication. | ||
345 | * The type must be different for the two purposes. | ||
346 | */ | ||
347 | struct GNUNET_DHT_PutMessage | ||
348 | { | ||
349 | /** | ||
350 | * Type: GNUNET_MESSAGE_TYPE_DHT_PUT / GNUNET_MESSAGE_TYPE_DHT_P2P_PUT | ||
351 | */ | ||
352 | struct GNUNET_MessageHeader header; | ||
353 | |||
354 | /** | ||
355 | * The type of data to insert. | ||
356 | */ | ||
357 | uint32_t type GNUNET_PACKED; | ||
358 | |||
359 | /** | ||
360 | * How long should this data persist? | ||
361 | */ | ||
362 | struct GNUNET_TIME_AbsoluteNBO expiration; | ||
363 | |||
364 | /* DATA copied to end of this message */ | ||
365 | |||
366 | }; | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Message to request data from the DHT, shared | ||
371 | * between P2P requests and local get requests. | ||
372 | * Main difference is that if the request comes in | ||
373 | * locally we need to remember it (for client response). | ||
374 | */ | ||
375 | struct GNUNET_DHT_GetMessage | ||
376 | { | ||
377 | /** | ||
378 | * Type: GNUNET_MESSAGE_TYPE_DHT_GET / GNUNET_MESSAGE_TYPE_DHT_P2P_GET | ||
379 | */ | ||
380 | struct GNUNET_MessageHeader header; | ||
381 | |||
382 | /** | ||
383 | * The type for the data for the GET request; actually an 'enum | ||
384 | * GNUNET_BLOCK_Type'. | ||
385 | */ | ||
386 | uint32_t type; | ||
387 | |||
388 | /** | ||
389 | * Mutator used for the bloom filter (0 if no bf is used). | ||
390 | */ | ||
391 | uint32_t bf_mutator; | ||
392 | |||
393 | /** | ||
394 | * Size of the eXtended query (xquery). | ||
395 | */ | ||
396 | uint16_t xquery_size; | ||
397 | |||
398 | /** | ||
399 | * Size of the bloom filter. | ||
400 | */ | ||
401 | uint16_t bf_size; | ||
402 | |||
403 | /* Followed by the xquery which has 'xquery_size' bytes */ | ||
404 | |||
405 | /* Followed by the bloom filter (after xquery) with 'bf_size' bytes */ | ||
406 | }; | ||
407 | |||
408 | |||
409 | /** | ||
410 | * Generic DHT message, indicates that a route request | ||
411 | * should be issued, if coming from a client. Shared | ||
412 | * usage for api->server and P2P message passing. | ||
413 | */ | ||
414 | struct GNUNET_DHT_FindPeerMessage | ||
415 | { | ||
416 | /** | ||
417 | * Type: GNUNET_MESSAGE_TYPE_DHT_FIND_PEER | ||
418 | */ | ||
419 | struct GNUNET_MessageHeader header; | ||
420 | |||
421 | /** | ||
422 | * Bloomfilter to reduce find peer responses | ||
423 | */ | ||
424 | char bloomfilter[DHT_BLOOM_SIZE]; | ||
425 | }; | ||
426 | |||
427 | |||
428 | /** | ||
429 | * Message to return data either to the client API | ||
430 | * or to respond to a request received from another | ||
431 | * peer. Shared format, different types. | ||
432 | */ | ||
433 | struct GNUNET_DHT_GetResultMessage | ||
434 | { | ||
435 | /** | ||
436 | * Type: GNUNET_MESSAGE_TYPE_DHT_GET_RESULT / GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT | ||
437 | */ | ||
438 | struct GNUNET_MessageHeader header; | ||
439 | |||
440 | /** | ||
441 | * The type for the data for the GET request | ||
442 | * FIXME: use 32-bit types, as in block? What is this type exactly for? | ||
443 | */ | ||
444 | uint16_t type; | ||
445 | |||
446 | /** | ||
447 | * The number of peer identities appended to the end of this | ||
448 | * message. | ||
449 | */ | ||
450 | uint16_t put_path_length; | ||
451 | |||
452 | /** | ||
453 | * When does this entry expire? | ||
454 | */ | ||
455 | struct GNUNET_TIME_AbsoluteNBO expiration; | ||
456 | |||
457 | /* OUTGOING path copied to end of this message */ | ||
458 | /* DATA result copied to end of this message */ | ||
459 | |||
460 | }; | ||
461 | |||
462 | /** | ||
463 | * Entry for inserting data into datacache from the DHT. | ||
464 | * Needed here so block library can verify entries that | ||
465 | * are shoveled into the DHT. | ||
466 | */ | ||
467 | struct DHTPutEntry | ||
468 | { | ||
469 | /** | ||
470 | * Size of data. | ||
471 | */ | ||
472 | uint16_t data_size; | ||
473 | |||
474 | /** | ||
475 | * Length of recorded path. | ||
476 | */ | ||
477 | uint16_t path_length; | ||
478 | |||
479 | /* PUT DATA */ | ||
480 | |||
481 | /* PATH ENTRIES */ | ||
482 | }; | ||
483 | |||
484 | |||
485 | #endif /* DHT_H_ */ | ||
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c deleted file mode 100644 index 2a14b216f..000000000 --- a/src/dht/dht_api.c +++ /dev/null | |||
@@ -1,909 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010 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 dht/dht_api.c | ||
23 | * @brief library to access the DHT service | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_bandwidth_lib.h" | ||
30 | #include "gnunet_client_lib.h" | ||
31 | #include "gnunet_constants.h" | ||
32 | #include "gnunet_container_lib.h" | ||
33 | #include "gnunet_arm_service.h" | ||
34 | #include "gnunet_hello_lib.h" | ||
35 | #include "gnunet_protocols.h" | ||
36 | #include "gnunet_server_lib.h" | ||
37 | #include "gnunet_time_lib.h" | ||
38 | #include "gnunet_dht_service.h" | ||
39 | #include "dht.h" | ||
40 | |||
41 | #define DEBUG_DHT_API GNUNET_NO | ||
42 | |||
43 | /** | ||
44 | * Entry in our list of messages to be (re-)transmitted. | ||
45 | */ | ||
46 | struct PendingMessage | ||
47 | { | ||
48 | /** | ||
49 | * This is a doubly-linked list. | ||
50 | */ | ||
51 | struct PendingMessage *prev; | ||
52 | |||
53 | /** | ||
54 | * This is a doubly-linked list. | ||
55 | */ | ||
56 | struct PendingMessage *next; | ||
57 | |||
58 | /** | ||
59 | * Message that is pending, allocated at the end | ||
60 | * of this struct. | ||
61 | */ | ||
62 | const struct GNUNET_MessageHeader *msg; | ||
63 | |||
64 | /** | ||
65 | * Handle to the DHT API context. | ||
66 | */ | ||
67 | struct GNUNET_DHT_Handle *handle; | ||
68 | |||
69 | /** | ||
70 | * Continuation to call when the request has been | ||
71 | * transmitted (for the first time) to the service; can be NULL. | ||
72 | */ | ||
73 | GNUNET_SCHEDULER_Task cont; | ||
74 | |||
75 | /** | ||
76 | * Closure for 'cont'. | ||
77 | */ | ||
78 | void *cont_cls; | ||
79 | |||
80 | /** | ||
81 | * Timeout task for this message | ||
82 | */ | ||
83 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
84 | |||
85 | /** | ||
86 | * Unique ID for this request | ||
87 | */ | ||
88 | uint64_t unique_id; | ||
89 | |||
90 | /** | ||
91 | * Free the saved message once sent, set to GNUNET_YES for messages | ||
92 | * that do not receive responses; GNUNET_NO if this pending message | ||
93 | * is aliased from a 'struct GNUNET_DHT_RouteHandle' and will be freed | ||
94 | * from there. | ||
95 | */ | ||
96 | int free_on_send; | ||
97 | |||
98 | /** | ||
99 | * GNUNET_YES if this message is in our pending queue right now. | ||
100 | */ | ||
101 | int in_pending_queue; | ||
102 | |||
103 | }; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Handle to a route request | ||
108 | */ | ||
109 | struct GNUNET_DHT_RouteHandle | ||
110 | { | ||
111 | |||
112 | /** | ||
113 | * Iterator to call on data receipt | ||
114 | */ | ||
115 | GNUNET_DHT_ReplyProcessor iter; | ||
116 | |||
117 | /** | ||
118 | * Closure for the iterator callback | ||
119 | */ | ||
120 | void *iter_cls; | ||
121 | |||
122 | /** | ||
123 | * Main handle to this DHT api | ||
124 | */ | ||
125 | struct GNUNET_DHT_Handle *dht_handle; | ||
126 | |||
127 | /** | ||
128 | * The actual message sent for this request, | ||
129 | * used for retransmitting requests on service | ||
130 | * failure/reconnect. Freed on route_stop. | ||
131 | */ | ||
132 | struct PendingMessage *message; | ||
133 | |||
134 | /** | ||
135 | * Key that this get request is for | ||
136 | */ | ||
137 | GNUNET_HashCode key; | ||
138 | |||
139 | /** | ||
140 | * Unique identifier for this request (for key collisions). FIXME: redundant!? | ||
141 | */ | ||
142 | uint64_t uid; | ||
143 | |||
144 | }; | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Connection to the DHT service. | ||
149 | */ | ||
150 | struct GNUNET_DHT_Handle | ||
151 | { | ||
152 | |||
153 | /** | ||
154 | * Configuration to use. | ||
155 | */ | ||
156 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
157 | |||
158 | /** | ||
159 | * Socket (if available). | ||
160 | */ | ||
161 | struct GNUNET_CLIENT_Connection *client; | ||
162 | |||
163 | /** | ||
164 | * Currently pending transmission request (or NULL). | ||
165 | */ | ||
166 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
167 | |||
168 | /** | ||
169 | * Head of linked list of messages we would like to transmit. | ||
170 | */ | ||
171 | struct PendingMessage *pending_head; | ||
172 | |||
173 | /** | ||
174 | * Tail of linked list of messages we would like to transmit. | ||
175 | */ | ||
176 | struct PendingMessage *pending_tail; | ||
177 | |||
178 | /** | ||
179 | * Hash map containing the current outstanding unique requests | ||
180 | * (values are of type 'struct GNUNET_DHT_RouteHandle'). | ||
181 | */ | ||
182 | struct GNUNET_CONTAINER_MultiHashMap *active_requests; | ||
183 | |||
184 | /** | ||
185 | * Task for trying to reconnect. | ||
186 | */ | ||
187 | GNUNET_SCHEDULER_TaskIdentifier reconnect_task; | ||
188 | |||
189 | /** | ||
190 | * How quickly should we retry? Used for exponential back-off on | ||
191 | * connect-errors. | ||
192 | */ | ||
193 | struct GNUNET_TIME_Relative retry_time; | ||
194 | |||
195 | /** | ||
196 | * Generator for unique ids. | ||
197 | */ | ||
198 | uint64_t uid_gen; | ||
199 | |||
200 | }; | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Transmit the next pending message, called by notify_transmit_ready | ||
205 | */ | ||
206 | static size_t | ||
207 | transmit_pending (void *cls, size_t size, void *buf); | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Handler for messages received from the DHT service | ||
212 | * a demultiplexer which handles numerous message types | ||
213 | * | ||
214 | */ | ||
215 | static void | ||
216 | service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg); | ||
217 | |||
218 | |||
219 | |||
220 | |||
221 | /** | ||
222 | * Try to (re)connect to the DHT service. | ||
223 | * | ||
224 | * @return GNUNET_YES on success, GNUNET_NO on failure. | ||
225 | */ | ||
226 | static int | ||
227 | try_connect (struct GNUNET_DHT_Handle *handle) | ||
228 | { | ||
229 | if (handle->client != NULL) | ||
230 | return GNUNET_OK; | ||
231 | handle->client = GNUNET_CLIENT_connect ("dht", handle->cfg); | ||
232 | if (handle->client == NULL) | ||
233 | { | ||
234 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
235 | _("Failed to connect to the DHT service!\n")); | ||
236 | return GNUNET_NO; | ||
237 | } | ||
238 | #if DEBUG_DHT | ||
239 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
240 | "Starting to process replies from DHT\n"); | ||
241 | #endif | ||
242 | GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle, | ||
243 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
244 | return GNUNET_YES; | ||
245 | } | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Add the request corresponding to the given route handle | ||
250 | * to the pending queue (if it is not already in there). | ||
251 | * | ||
252 | * @param cls the 'struct GNUNET_DHT_Handle*' | ||
253 | * @param key key for the request (not used) | ||
254 | * @param value the 'struct GNUNET_DHT_RouteHandle*' | ||
255 | * @return GNUNET_YES (always) | ||
256 | */ | ||
257 | static int | ||
258 | add_request_to_pending (void *cls, const GNUNET_HashCode * key, void *value) | ||
259 | { | ||
260 | struct GNUNET_DHT_Handle *handle = cls; | ||
261 | struct GNUNET_DHT_RouteHandle *rh = value; | ||
262 | |||
263 | if (GNUNET_NO == rh->message->in_pending_queue) | ||
264 | { | ||
265 | GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, | ||
266 | rh->message); | ||
267 | rh->message->in_pending_queue = GNUNET_YES; | ||
268 | } | ||
269 | return GNUNET_YES; | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
274 | * Try to send messages from list of messages to send | ||
275 | * @param handle DHT_Handle | ||
276 | */ | ||
277 | static void | ||
278 | process_pending_messages (struct GNUNET_DHT_Handle *handle); | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Try reconnecting to the dht service. | ||
283 | * | ||
284 | * @param cls GNUNET_DHT_Handle | ||
285 | * @param tc scheduler context | ||
286 | */ | ||
287 | static void | ||
288 | try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
289 | { | ||
290 | struct GNUNET_DHT_Handle *handle = cls; | ||
291 | |||
292 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
293 | if (handle->retry_time.rel_value < GNUNET_CONSTANTS_SERVICE_RETRY.rel_value) | ||
294 | handle->retry_time = GNUNET_CONSTANTS_SERVICE_RETRY; | ||
295 | else | ||
296 | handle->retry_time = GNUNET_TIME_relative_multiply (handle->retry_time, 2); | ||
297 | if (handle->retry_time.rel_value > GNUNET_CONSTANTS_SERVICE_TIMEOUT.rel_value) | ||
298 | handle->retry_time = GNUNET_CONSTANTS_SERVICE_TIMEOUT; | ||
299 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
300 | handle->client = GNUNET_CLIENT_connect ("dht", handle->cfg); | ||
301 | if (handle->client == NULL) | ||
302 | { | ||
303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dht reconnect failed(!)\n"); | ||
304 | return; | ||
305 | } | ||
306 | GNUNET_CONTAINER_multihashmap_iterate (handle->active_requests, | ||
307 | &add_request_to_pending, handle); | ||
308 | process_pending_messages (handle); | ||
309 | } | ||
310 | |||
311 | |||
312 | /** | ||
313 | * Try reconnecting to the DHT service. | ||
314 | * | ||
315 | * @param handle handle to dht to (possibly) disconnect and reconnect | ||
316 | */ | ||
317 | static void | ||
318 | do_disconnect (struct GNUNET_DHT_Handle *handle) | ||
319 | { | ||
320 | if (handle->client == NULL) | ||
321 | return; | ||
322 | GNUNET_assert (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK); | ||
323 | if (NULL != handle->th) | ||
324 | GNUNET_CLIENT_notify_transmit_ready_cancel(handle->th); | ||
325 | handle->th = NULL; | ||
326 | GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO); | ||
327 | handle->client = NULL; | ||
328 | handle->reconnect_task = | ||
329 | GNUNET_SCHEDULER_add_delayed (handle->retry_time, &try_reconnect, handle); | ||
330 | } | ||
331 | |||
332 | |||
333 | /** | ||
334 | * Try to send messages from list of messages to send | ||
335 | */ | ||
336 | static void | ||
337 | process_pending_messages (struct GNUNET_DHT_Handle *handle) | ||
338 | { | ||
339 | struct PendingMessage *head; | ||
340 | |||
341 | if (handle->client == NULL) | ||
342 | { | ||
343 | do_disconnect (handle); | ||
344 | return; | ||
345 | } | ||
346 | if (handle->th != NULL) | ||
347 | return; | ||
348 | if (NULL == (head = handle->pending_head)) | ||
349 | return; | ||
350 | handle->th = | ||
351 | GNUNET_CLIENT_notify_transmit_ready (handle->client, | ||
352 | ntohs (head->msg->size), | ||
353 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
354 | GNUNET_YES, &transmit_pending, | ||
355 | handle); | ||
356 | if (NULL == handle->th) | ||
357 | { | ||
358 | do_disconnect (handle); | ||
359 | return; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * Transmit the next pending message, called by notify_transmit_ready | ||
366 | */ | ||
367 | static size_t | ||
368 | transmit_pending (void *cls, size_t size, void *buf) | ||
369 | { | ||
370 | struct GNUNET_DHT_Handle *handle = cls; | ||
371 | struct PendingMessage *head; | ||
372 | size_t tsize; | ||
373 | |||
374 | handle->th = NULL; | ||
375 | if (buf == NULL) | ||
376 | { | ||
377 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
378 | "Transmission to DHT service failed! Reconnecting!\n"); | ||
379 | do_disconnect (handle); | ||
380 | return 0; | ||
381 | } | ||
382 | if (NULL == (head = handle->pending_head)) | ||
383 | return 0; | ||
384 | |||
385 | tsize = ntohs (head->msg->size); | ||
386 | if (size < tsize) | ||
387 | { | ||
388 | process_pending_messages (handle); | ||
389 | return 0; | ||
390 | } | ||
391 | memcpy (buf, head->msg, tsize); | ||
392 | GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, | ||
393 | head); | ||
394 | if (head->timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
395 | { | ||
396 | GNUNET_SCHEDULER_cancel (head->timeout_task); | ||
397 | head->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
398 | } | ||
399 | if (NULL != head->cont) | ||
400 | { | ||
401 | GNUNET_SCHEDULER_add_continuation (head->cont, head->cont_cls, | ||
402 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
403 | head->cont = NULL; | ||
404 | head->cont_cls = NULL; | ||
405 | } | ||
406 | head->in_pending_queue = GNUNET_NO; | ||
407 | if (GNUNET_YES == head->free_on_send) | ||
408 | GNUNET_free (head); | ||
409 | process_pending_messages (handle); | ||
410 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
411 | "Forwarded request of %u bytes to DHT service\n", | ||
412 | (unsigned int) tsize); | ||
413 | return tsize; | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Process a given reply that might match the given | ||
419 | * request. | ||
420 | */ | ||
421 | static int | ||
422 | process_reply (void *cls, const GNUNET_HashCode * key, void *value) | ||
423 | { | ||
424 | const struct GNUNET_DHT_RouteResultMessage *dht_msg = cls; | ||
425 | struct GNUNET_DHT_RouteHandle *rh = value; | ||
426 | const struct GNUNET_MessageHeader *enc_msg; | ||
427 | size_t enc_size; | ||
428 | const struct GNUNET_PeerIdentity **outgoing_path; | ||
429 | const struct GNUNET_PeerIdentity *pos; | ||
430 | uint32_t outgoing_path_length; | ||
431 | unsigned int i; | ||
432 | char *path_offset; | ||
433 | #if HAVE_UID_FOR_TESTING | ||
434 | uint64_t uid; | ||
435 | |||
436 | uid = GNUNET_ntohll (dht_msg->unique_id); | ||
437 | if (uid != rh->uid) | ||
438 | { | ||
439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
440 | "Reply UID did not match request UID\n"); | ||
441 | return GNUNET_YES; | ||
442 | } | ||
443 | #endif | ||
444 | enc_msg = (const struct GNUNET_MessageHeader *) &dht_msg[1]; | ||
445 | enc_size = ntohs (enc_msg->size); | ||
446 | if (enc_size < sizeof (struct GNUNET_MessageHeader)) | ||
447 | { | ||
448 | GNUNET_break (0); | ||
449 | return GNUNET_NO; | ||
450 | } | ||
451 | path_offset = (char *) &dht_msg[1]; | ||
452 | path_offset += enc_size; | ||
453 | pos = (const struct GNUNET_PeerIdentity *) path_offset; | ||
454 | outgoing_path_length = ntohl (dht_msg->outgoing_path_length); | ||
455 | if (outgoing_path_length * sizeof (struct GNUNET_PeerIdentity) > | ||
456 | ntohs (dht_msg->header.size) - enc_size) | ||
457 | { | ||
458 | GNUNET_break (0); | ||
459 | return GNUNET_NO; | ||
460 | } | ||
461 | |||
462 | if (outgoing_path_length > 0) | ||
463 | { | ||
464 | outgoing_path = | ||
465 | GNUNET_malloc ((outgoing_path_length + | ||
466 | 1) * sizeof (struct GNUNET_PeerIdentity *)); | ||
467 | for (i = 0; i < outgoing_path_length; i++) | ||
468 | { | ||
469 | outgoing_path[i] = pos; | ||
470 | pos++; | ||
471 | } | ||
472 | outgoing_path[outgoing_path_length] = NULL; | ||
473 | } | ||
474 | else | ||
475 | outgoing_path = NULL; | ||
476 | |||
477 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing reply.\n"); | ||
478 | rh->iter (rh->iter_cls, &rh->key, outgoing_path, enc_msg); | ||
479 | GNUNET_free_non_null (outgoing_path); | ||
480 | return GNUNET_YES; | ||
481 | } | ||
482 | |||
483 | |||
484 | /** | ||
485 | * Handler for messages received from the DHT service | ||
486 | * a demultiplexer which handles numerous message types | ||
487 | * | ||
488 | * @param cls the 'struct GNUNET_DHT_Handle' | ||
489 | * @param msg the incoming message | ||
490 | */ | ||
491 | static void | ||
492 | service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg) | ||
493 | { | ||
494 | struct GNUNET_DHT_Handle *handle = cls; | ||
495 | const struct GNUNET_DHT_RouteResultMessage *dht_msg; | ||
496 | |||
497 | if (msg == NULL) | ||
498 | { | ||
499 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
500 | "Error receiving data from DHT service, reconnecting\n"); | ||
501 | do_disconnect (handle); | ||
502 | return; | ||
503 | } | ||
504 | if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE_RESULT) | ||
505 | { | ||
506 | GNUNET_break (0); | ||
507 | do_disconnect (handle); | ||
508 | return; | ||
509 | } | ||
510 | if (ntohs (msg->size) < sizeof (struct GNUNET_DHT_RouteResultMessage)) | ||
511 | { | ||
512 | GNUNET_break (0); | ||
513 | do_disconnect (handle); | ||
514 | return; | ||
515 | } | ||
516 | dht_msg = (const struct GNUNET_DHT_RouteResultMessage *) msg; | ||
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
518 | "Comparing reply `%s' against %u pending requests.\n", | ||
519 | GNUNET_h2s (&dht_msg->key), | ||
520 | GNUNET_CONTAINER_multihashmap_size (handle->active_requests)); | ||
521 | GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_requests, | ||
522 | &dht_msg->key, &process_reply, | ||
523 | (void *) dht_msg); | ||
524 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
525 | "Continuing to process replies from DHT\n"); | ||
526 | GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle, | ||
527 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
528 | |||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Initialize the connection with the DHT service. | ||
534 | * | ||
535 | * @param cfg configuration to use | ||
536 | * @param ht_len size of the internal hash table to use for | ||
537 | * processing multiple GET/FIND requests in parallel | ||
538 | * | ||
539 | * @return handle to the DHT service, or NULL on error | ||
540 | */ | ||
541 | struct GNUNET_DHT_Handle * | ||
542 | GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
543 | unsigned int ht_len) | ||
544 | { | ||
545 | struct GNUNET_DHT_Handle *handle; | ||
546 | |||
547 | handle = GNUNET_malloc (sizeof (struct GNUNET_DHT_Handle)); | ||
548 | handle->cfg = cfg; | ||
549 | handle->uid_gen = | ||
550 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | ||
551 | handle->active_requests = GNUNET_CONTAINER_multihashmap_create (ht_len); | ||
552 | if (GNUNET_NO == try_connect (handle)) | ||
553 | { | ||
554 | GNUNET_DHT_disconnect (handle); | ||
555 | return NULL; | ||
556 | } | ||
557 | return handle; | ||
558 | } | ||
559 | |||
560 | |||
561 | /** | ||
562 | * Shutdown connection with the DHT service. | ||
563 | * | ||
564 | * @param handle handle of the DHT connection to stop | ||
565 | */ | ||
566 | void | ||
567 | GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle) | ||
568 | { | ||
569 | struct PendingMessage *pm; | ||
570 | |||
571 | GNUNET_assert (handle != NULL); | ||
572 | GNUNET_assert (0 == | ||
573 | GNUNET_CONTAINER_multihashmap_size (handle->active_requests)); | ||
574 | if (handle->th != NULL) | ||
575 | { | ||
576 | GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); | ||
577 | handle->th = NULL; | ||
578 | } | ||
579 | while (NULL != (pm = handle->pending_head)) | ||
580 | { | ||
581 | GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, | ||
582 | pm); | ||
583 | GNUNET_assert (GNUNET_YES == pm->free_on_send); | ||
584 | if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task) | ||
585 | GNUNET_SCHEDULER_cancel (pm->timeout_task); | ||
586 | if (NULL != pm->cont) | ||
587 | GNUNET_SCHEDULER_add_continuation (pm->cont, pm->cont_cls, | ||
588 | GNUNET_SCHEDULER_REASON_TIMEOUT); | ||
589 | pm->in_pending_queue = GNUNET_NO; | ||
590 | GNUNET_free (pm); | ||
591 | } | ||
592 | if (handle->client != NULL) | ||
593 | { | ||
594 | GNUNET_CLIENT_disconnect (handle->client, GNUNET_YES); | ||
595 | handle->client = NULL; | ||
596 | } | ||
597 | if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
598 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
599 | GNUNET_CONTAINER_multihashmap_destroy (handle->active_requests); | ||
600 | GNUNET_free (handle); | ||
601 | } | ||
602 | |||
603 | |||
604 | |||
605 | |||
606 | /* ***** Special low-level API providing generic routing abstraction ***** */ | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Timeout for the transmission of a fire&forget-request. Clean it up. | ||
611 | * | ||
612 | * @param cls the 'struct PendingMessage' | ||
613 | * @param tc scheduler context | ||
614 | */ | ||
615 | static void | ||
616 | timeout_route_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
617 | { | ||
618 | struct PendingMessage *pending = cls; | ||
619 | struct GNUNET_DHT_Handle *handle; | ||
620 | |||
621 | if (pending->free_on_send != GNUNET_YES) | ||
622 | { | ||
623 | /* timeouts should only apply to fire & forget requests! */ | ||
624 | GNUNET_break (0); | ||
625 | return; | ||
626 | } | ||
627 | handle = pending->handle; | ||
628 | GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, | ||
629 | pending); | ||
630 | if (pending->cont != NULL) | ||
631 | pending->cont (pending->cont_cls, tc); | ||
632 | GNUNET_free (pending); | ||
633 | } | ||
634 | |||
635 | |||
636 | /** | ||
637 | * Initiate a generic DHT route operation. | ||
638 | * | ||
639 | * @param handle handle to the DHT service | ||
640 | * @param key the key to look up | ||
641 | * @param desired_replication_level how many peers should ultimately receive | ||
642 | * this message (advisory only, target may be too high for the | ||
643 | * given DHT or not hit exactly). | ||
644 | * @param options options for routing | ||
645 | * @param enc send the encapsulated message to a peer close to the key | ||
646 | * @param iter function to call on each result, NULL if no replies are expected | ||
647 | * @param iter_cls closure for iter | ||
648 | * @param timeout when to abort with an error if we fail to get | ||
649 | * a confirmation for the request (when necessary) or how long | ||
650 | * to wait for tramission to the service; only applies | ||
651 | * if 'iter' is NULL | ||
652 | * @param cont continuation to call when the request has been transmitted | ||
653 | * the first time to the service | ||
654 | * @param cont_cls closure for cont | ||
655 | * @return handle to stop the request, NULL if the request is "fire and forget" | ||
656 | */ | ||
657 | struct GNUNET_DHT_RouteHandle * | ||
658 | GNUNET_DHT_route_start (struct GNUNET_DHT_Handle *handle, | ||
659 | const GNUNET_HashCode * key, | ||
660 | uint32_t desired_replication_level, | ||
661 | enum GNUNET_DHT_RouteOption options, | ||
662 | const struct GNUNET_MessageHeader *enc, | ||
663 | struct GNUNET_TIME_Relative timeout, | ||
664 | GNUNET_DHT_ReplyProcessor iter, void *iter_cls, | ||
665 | GNUNET_SCHEDULER_Task cont, void *cont_cls) | ||
666 | { | ||
667 | struct PendingMessage *pending; | ||
668 | struct GNUNET_DHT_RouteMessage *message; | ||
669 | struct GNUNET_DHT_RouteHandle *route_handle; | ||
670 | uint16_t msize; | ||
671 | uint16_t esize; | ||
672 | |||
673 | esize = ntohs (enc->size); | ||
674 | if (sizeof (struct GNUNET_DHT_RouteMessage) + esize >= | ||
675 | GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
676 | { | ||
677 | GNUNET_break (0); | ||
678 | return NULL; | ||
679 | } | ||
680 | msize = sizeof (struct GNUNET_DHT_RouteMessage) + esize; | ||
681 | pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); | ||
682 | message = (struct GNUNET_DHT_RouteMessage *) &pending[1]; | ||
683 | pending->msg = &message->header; | ||
684 | pending->handle = handle; | ||
685 | pending->cont = cont; | ||
686 | pending->cont_cls = cont_cls; | ||
687 | |||
688 | message->header.size = htons (msize); | ||
689 | message->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE); | ||
690 | message->options = htonl ((uint32_t) options); | ||
691 | message->desired_replication_level = htonl (desired_replication_level); | ||
692 | message->reserved = 0; | ||
693 | message->key = *key; | ||
694 | handle->uid_gen++; | ||
695 | message->unique_id = GNUNET_htonll (handle->uid_gen); | ||
696 | memcpy (&message[1], enc, esize); | ||
697 | |||
698 | if (iter != NULL) | ||
699 | { | ||
700 | route_handle = GNUNET_malloc (sizeof (struct GNUNET_DHT_RouteHandle)); | ||
701 | route_handle->key = *key; | ||
702 | route_handle->iter = iter; | ||
703 | route_handle->iter_cls = iter_cls; | ||
704 | route_handle->dht_handle = handle; | ||
705 | route_handle->uid = handle->uid_gen; | ||
706 | route_handle->message = pending; | ||
707 | GNUNET_CONTAINER_multihashmap_put (handle->active_requests, key, | ||
708 | route_handle, | ||
709 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | route_handle = NULL; | ||
714 | pending->free_on_send = GNUNET_YES; | ||
715 | pending->timeout_task = | ||
716 | GNUNET_SCHEDULER_add_delayed (timeout, &timeout_route_request, pending); | ||
717 | } | ||
718 | GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, | ||
719 | pending); | ||
720 | pending->in_pending_queue = GNUNET_YES; | ||
721 | process_pending_messages (handle); | ||
722 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
723 | "DHT route start request processed, returning %p\n", | ||
724 | route_handle); | ||
725 | return route_handle; | ||
726 | } | ||
727 | |||
728 | |||
729 | /** | ||
730 | * Stop a previously issued routing request | ||
731 | * | ||
732 | * @param route_handle handle to the request to stop | ||
733 | */ | ||
734 | void | ||
735 | GNUNET_DHT_route_stop (struct GNUNET_DHT_RouteHandle *route_handle) | ||
736 | { | ||
737 | struct GNUNET_DHT_Handle *handle; | ||
738 | struct PendingMessage *pending; | ||
739 | struct GNUNET_DHT_StopMessage *message; | ||
740 | size_t msize; | ||
741 | |||
742 | handle = route_handle->dht_handle; | ||
743 | if (GNUNET_NO == route_handle->message->in_pending_queue) | ||
744 | { | ||
745 | /* need to send stop message */ | ||
746 | msize = sizeof (struct GNUNET_DHT_StopMessage); | ||
747 | pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); | ||
748 | message = (struct GNUNET_DHT_StopMessage *) &pending[1]; | ||
749 | pending->msg = &message->header; | ||
750 | message->header.size = htons (msize); | ||
751 | message->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_LOCAL_ROUTE_STOP); | ||
752 | message->reserved = 0; | ||
753 | message->unique_id = GNUNET_htonll (route_handle->uid); | ||
754 | message->key = route_handle->key; | ||
755 | pending->handle = handle; | ||
756 | pending->free_on_send = GNUNET_YES; | ||
757 | pending->in_pending_queue = GNUNET_YES; | ||
758 | GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, | ||
759 | pending); | ||
760 | process_pending_messages (handle); | ||
761 | } | ||
762 | else | ||
763 | { | ||
764 | /* simply remove pending request from message queue before | ||
765 | * transmission, no need to transmit STOP request! */ | ||
766 | GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, | ||
767 | route_handle->message); | ||
768 | } | ||
769 | GNUNET_assert (GNUNET_YES == | ||
770 | GNUNET_CONTAINER_multihashmap_remove | ||
771 | (route_handle->dht_handle->active_requests, &route_handle->key, | ||
772 | route_handle)); | ||
773 | GNUNET_free (route_handle->message); | ||
774 | GNUNET_free (route_handle); | ||
775 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DHT route stop request processed\n"); | ||
776 | } | ||
777 | |||
778 | |||
779 | |||
780 | /* ***** Special API for controlling DHT routing maintenance ******* */ | ||
781 | |||
782 | |||
783 | /** | ||
784 | * Send a control message to the DHT. | ||
785 | * | ||
786 | * @param handle handle to the DHT service | ||
787 | * @param command command | ||
788 | * @param variable variable to the command | ||
789 | * @param cont continuation to call when done (transmitting request to service) | ||
790 | * @param cont_cls closure for cont | ||
791 | */ | ||
792 | static void | ||
793 | send_control_message (struct GNUNET_DHT_Handle *handle, uint16_t command, | ||
794 | uint16_t variable, GNUNET_SCHEDULER_Task cont, | ||
795 | void *cont_cls) | ||
796 | { | ||
797 | struct GNUNET_DHT_ControlMessage *msg; | ||
798 | struct PendingMessage *pending; | ||
799 | |||
800 | pending = | ||
801 | GNUNET_malloc (sizeof (struct PendingMessage) + | ||
802 | sizeof (struct GNUNET_DHT_ControlMessage)); | ||
803 | msg = (struct GNUNET_DHT_ControlMessage *) &pending[1]; | ||
804 | pending->msg = &msg->header; | ||
805 | msg->header.size = htons (sizeof (struct GNUNET_DHT_ControlMessage)); | ||
806 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CONTROL); | ||
807 | msg->command = htons (command); | ||
808 | msg->variable = htons (variable); | ||
809 | pending->free_on_send = GNUNET_YES; | ||
810 | pending->cont = cont; | ||
811 | pending->cont_cls = cont_cls; | ||
812 | pending->in_pending_queue = GNUNET_YES; | ||
813 | GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, | ||
814 | pending); | ||
815 | process_pending_messages (handle); | ||
816 | } | ||
817 | |||
818 | |||
819 | /** | ||
820 | * Send a message to the DHT telling it to issue a single find | ||
821 | * peer request using the peers unique identifier as key. This | ||
822 | * is used to fill the routing table, and is normally controlled | ||
823 | * by the DHT itself. However, for testing and perhaps more | ||
824 | * close control over the DHT, this can be explicitly managed. | ||
825 | * | ||
826 | * @param handle handle to the DHT service | ||
827 | * @param cont continuation to call when done (transmitting request to service) | ||
828 | * @param cont_cls closure for cont | ||
829 | */ | ||
830 | void | ||
831 | GNUNET_DHT_find_peers (struct GNUNET_DHT_Handle *handle, | ||
832 | GNUNET_SCHEDULER_Task cont, void *cont_cls) | ||
833 | { | ||
834 | send_control_message (handle, GNUNET_MESSAGE_TYPE_DHT_FIND_PEER, 0, cont, | ||
835 | cont_cls); | ||
836 | } | ||
837 | |||
838 | |||
839 | |||
840 | #if HAVE_MALICIOUS | ||
841 | |||
842 | /** | ||
843 | * Send a message to the DHT telling it to start issuing random GET | ||
844 | * requests every 'frequency' milliseconds. | ||
845 | * | ||
846 | * @param handle handle to the DHT service | ||
847 | * @param frequency delay between sending malicious messages | ||
848 | * @param cont continuation to call when done (transmitting request to service) | ||
849 | * @param cont_cls closure for cont | ||
850 | */ | ||
851 | void | ||
852 | GNUNET_DHT_set_malicious_getter (struct GNUNET_DHT_Handle *handle, | ||
853 | struct GNUNET_TIME_Relative frequency, | ||
854 | GNUNET_SCHEDULER_Task cont, void *cont_cls) | ||
855 | { | ||
856 | if (frequency.rel_value > UINT16_MAX) | ||
857 | { | ||
858 | GNUNET_break (0); | ||
859 | return; | ||
860 | } | ||
861 | send_control_message (handle, GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_GET, | ||
862 | frequency.rel_value, cont, cont_cls); | ||
863 | } | ||
864 | |||
865 | /** | ||
866 | * Send a message to the DHT telling it to start issuing random PUT | ||
867 | * requests every 'frequency' milliseconds. | ||
868 | * | ||
869 | * @param handle handle to the DHT service | ||
870 | * @param frequency delay between sending malicious messages | ||
871 | * @param cont continuation to call when done (transmitting request to service) | ||
872 | * @param cont_cls closure for cont | ||
873 | */ | ||
874 | void | ||
875 | GNUNET_DHT_set_malicious_putter (struct GNUNET_DHT_Handle *handle, | ||
876 | struct GNUNET_TIME_Relative frequency, | ||
877 | GNUNET_SCHEDULER_Task cont, void *cont_cls) | ||
878 | { | ||
879 | if (frequency.rel_value > UINT16_MAX) | ||
880 | { | ||
881 | GNUNET_break (0); | ||
882 | return; | ||
883 | } | ||
884 | |||
885 | send_control_message (handle, GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_PUT, | ||
886 | frequency.rel_value, cont, cont_cls); | ||
887 | } | ||
888 | |||
889 | |||
890 | /** | ||
891 | * Send a message to the DHT telling it to start dropping | ||
892 | * all requests received. | ||
893 | * | ||
894 | * @param handle handle to the DHT service | ||
895 | * @param cont continuation to call when done (transmitting request to service) | ||
896 | * @param cont_cls closure for cont | ||
897 | * | ||
898 | */ | ||
899 | void | ||
900 | GNUNET_DHT_set_malicious_dropper (struct GNUNET_DHT_Handle *handle, | ||
901 | GNUNET_SCHEDULER_Task cont, void *cont_cls) | ||
902 | { | ||
903 | send_control_message (handle, GNUNET_MESSAGE_TYPE_DHT_MALICIOUS_DROP, 0, cont, | ||
904 | cont_cls); | ||
905 | } | ||
906 | |||
907 | #endif | ||
908 | |||
909 | /* end of dht_api.c */ | ||
diff --git a/src/dht/dht_api_find_peer.c b/src/dht/dht_api_find_peer.c deleted file mode 100644 index a9ecc7b59..000000000 --- a/src/dht/dht_api_find_peer.c +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010 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 dht/dht_api_find_peer.c | ||
23 | * @brief library to access the DHT to find peers | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_arm_service.h" | ||
31 | #include "gnunet_protocols.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_dht_service.h" | ||
34 | #include "dht.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Handle to control a find peer operation. | ||
39 | */ | ||
40 | struct GNUNET_DHT_FindPeerHandle | ||
41 | { | ||
42 | |||
43 | /** | ||
44 | * Handle to the actual route operation for the request | ||
45 | */ | ||
46 | struct GNUNET_DHT_RouteHandle *route_handle; | ||
47 | |||
48 | /** | ||
49 | * Iterator to call on data receipt | ||
50 | */ | ||
51 | GNUNET_DHT_FindPeerProcessor proc; | ||
52 | |||
53 | /** | ||
54 | * Closure for the iterator callback | ||
55 | */ | ||
56 | void *proc_cls; | ||
57 | |||
58 | }; | ||
59 | |||
60 | |||
61 | |||
62 | /** | ||
63 | * Iterator called on each result obtained from a generic route | ||
64 | * operation | ||
65 | * | ||
66 | * @param cls closure | ||
67 | * @param key key that was used | ||
68 | * @param outgoing_path NULL-terminated array of pointers | ||
69 | * to the peers on reverse path | ||
70 | * (or NULL if not recorded) | ||
71 | * @param reply response | ||
72 | */ | ||
73 | static void | ||
74 | find_peer_reply_iterator (void *cls, const GNUNET_HashCode * key, | ||
75 | const struct GNUNET_PeerIdentity *const | ||
76 | *outgoing_path, | ||
77 | const struct GNUNET_MessageHeader *reply) | ||
78 | { | ||
79 | struct GNUNET_DHT_FindPeerHandle *find_peer_handle = cls; | ||
80 | const struct GNUNET_MessageHeader *hello; | ||
81 | |||
82 | if (ntohs (reply->type) != GNUNET_MESSAGE_TYPE_DHT_FIND_PEER_RESULT) | ||
83 | { | ||
84 | GNUNET_break (0); | ||
85 | return; | ||
86 | } | ||
87 | GNUNET_assert (ntohs (reply->size) >= sizeof (struct GNUNET_MessageHeader)); | ||
88 | hello = (const struct GNUNET_MessageHeader *) &reply[1]; | ||
89 | if (ntohs (hello->type) != GNUNET_MESSAGE_TYPE_HELLO) | ||
90 | { | ||
91 | GNUNET_break (0); | ||
92 | return; | ||
93 | } | ||
94 | find_peer_handle->proc (find_peer_handle->proc_cls, | ||
95 | (const struct GNUNET_HELLO_Message *) hello); | ||
96 | } | ||
97 | |||
98 | |||
99 | |||
100 | /** | ||
101 | * Perform an asynchronous FIND PEER operation on the DHT. | ||
102 | * | ||
103 | * @param handle handle to the DHT service | ||
104 | * @param timeout timeout for this request to be sent to the | ||
105 | * service | ||
106 | * @param options routing options for this message | ||
107 | * @param key the key to look up | ||
108 | * @param proc function to call on each result | ||
109 | * @param proc_cls closure for proc | ||
110 | * @return handle to stop the async get, NULL on error | ||
111 | */ | ||
112 | struct GNUNET_DHT_FindPeerHandle * | ||
113 | GNUNET_DHT_find_peer_start (struct GNUNET_DHT_Handle *handle, | ||
114 | struct GNUNET_TIME_Relative timeout, | ||
115 | const GNUNET_HashCode * key, | ||
116 | enum GNUNET_DHT_RouteOption options, | ||
117 | GNUNET_DHT_FindPeerProcessor proc, void *proc_cls) | ||
118 | { | ||
119 | struct GNUNET_DHT_FindPeerHandle *find_peer_handle; | ||
120 | struct GNUNET_DHT_FindPeerMessage find_peer_msg; | ||
121 | |||
122 | find_peer_handle = GNUNET_malloc (sizeof (struct GNUNET_DHT_FindPeerHandle)); | ||
123 | find_peer_handle->proc = proc; | ||
124 | find_peer_handle->proc_cls = proc_cls; | ||
125 | find_peer_msg.header.size = | ||
126 | htons (sizeof (struct GNUNET_DHT_FindPeerMessage)); | ||
127 | find_peer_msg.header.type = htons (GNUNET_MESSAGE_TYPE_DHT_FIND_PEER); | ||
128 | find_peer_handle->route_handle = | ||
129 | GNUNET_DHT_route_start (handle, key, 0, options, &find_peer_msg.header, | ||
130 | timeout, &find_peer_reply_iterator, | ||
131 | find_peer_handle, NULL, NULL); | ||
132 | GNUNET_break (find_peer_handle->route_handle != NULL); | ||
133 | return find_peer_handle; | ||
134 | } | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Stop async find peer. Frees associated resources. | ||
139 | * | ||
140 | * @param find_peer_handle GET operation to stop. | ||
141 | */ | ||
142 | void | ||
143 | GNUNET_DHT_find_peer_stop (struct GNUNET_DHT_FindPeerHandle *find_peer_handle) | ||
144 | { | ||
145 | GNUNET_DHT_route_stop (find_peer_handle->route_handle); | ||
146 | GNUNET_free (find_peer_handle); | ||
147 | } | ||
148 | |||
149 | |||
150 | /* end of dht_api_find_peer.c */ | ||
diff --git a/src/dht/dht_api_get_put.c b/src/dht/dht_api_get_put.c deleted file mode 100644 index 20778908d..000000000 --- a/src/dht/dht_api_get_put.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010 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 dht/dht_api_get_put.c | ||
23 | * @brief library to perform DHT gets and puts | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_constants.h" | ||
30 | #include "gnunet_arm_service.h" | ||
31 | #include "gnunet_protocols.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | #include "gnunet_dht_service.h" | ||
34 | #include "dht.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Perform a PUT operation storing data in the DHT. | ||
39 | * | ||
40 | * @param handle handle to DHT service | ||
41 | * @param key the key to store under | ||
42 | * @param desired_replication_level estimate of how many | ||
43 | * nearest peers this request should reach | ||
44 | * @param options routing options for this message | ||
45 | * @param type type of the value | ||
46 | * @param size number of bytes in data; must be less than 64k | ||
47 | * @param data the data to store | ||
48 | * @param exp desired expiration time for the value | ||
49 | * @param timeout how long to wait for transmission of this request | ||
50 | * @param cont continuation to call when done (transmitting request to service) | ||
51 | * @param cont_cls closure for cont | ||
52 | * @return GNUNET_YES if put message is queued for transmission | ||
53 | */ | ||
54 | void | ||
55 | GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, const GNUNET_HashCode * key, | ||
56 | uint32_t desired_replication_level, | ||
57 | enum GNUNET_DHT_RouteOption options, | ||
58 | enum GNUNET_BLOCK_Type type, size_t size, const char *data, | ||
59 | struct GNUNET_TIME_Absolute exp, | ||
60 | struct GNUNET_TIME_Relative timeout, GNUNET_SCHEDULER_Task cont, | ||
61 | void *cont_cls) | ||
62 | { | ||
63 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE]; | ||
64 | struct GNUNET_DHT_PutMessage *put_msg; | ||
65 | |||
66 | if (size >= sizeof (buf) - sizeof (struct GNUNET_DHT_PutMessage)) | ||
67 | { | ||
68 | GNUNET_break (0); | ||
69 | return; | ||
70 | } | ||
71 | put_msg = (struct GNUNET_DHT_PutMessage *) buf; | ||
72 | put_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_PUT); | ||
73 | put_msg->header.size = htons (sizeof (struct GNUNET_DHT_PutMessage) + size); | ||
74 | put_msg->type = htonl ((uint32_t) type); | ||
75 | put_msg->expiration = GNUNET_TIME_absolute_hton (exp); | ||
76 | memcpy (&put_msg[1], data, size); | ||
77 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
78 | "Starting route for %u byte `%s' message of type %u \n", | ||
79 | (unsigned int) (sizeof (struct GNUNET_DHT_PutMessage) + size), | ||
80 | "PUT", type); | ||
81 | GNUNET_break (NULL == | ||
82 | GNUNET_DHT_route_start (handle, key, desired_replication_level, | ||
83 | options, &put_msg->header, timeout, | ||
84 | NULL, NULL, cont, cont_cls)); | ||
85 | } | ||
86 | |||
87 | |||
88 | |||
89 | /** | ||
90 | * Handle to control a get operation. | ||
91 | */ | ||
92 | struct GNUNET_DHT_GetHandle | ||
93 | { | ||
94 | /** | ||
95 | * Handle to the actual route operation for the get | ||
96 | */ | ||
97 | struct GNUNET_DHT_RouteHandle *route_handle; | ||
98 | |||
99 | /** | ||
100 | * Iterator to call on data receipt | ||
101 | */ | ||
102 | GNUNET_DHT_GetIterator iter; | ||
103 | |||
104 | /** | ||
105 | * Closure for the iterator callback | ||
106 | */ | ||
107 | void *iter_cls; | ||
108 | |||
109 | }; | ||
110 | |||
111 | |||
112 | |||
113 | /** | ||
114 | * Iterator called on each result obtained from a generic route | ||
115 | * operation | ||
116 | * | ||
117 | * @param cls the 'struct GNUNET_DHT_GetHandle' | ||
118 | * @param key key that was used | ||
119 | * @param outgoing_path path of the message from this peer | ||
120 | * to the target | ||
121 | * @param reply response | ||
122 | */ | ||
123 | static void | ||
124 | get_reply_iterator (void *cls, const GNUNET_HashCode * key, | ||
125 | const struct GNUNET_PeerIdentity *const *outgoing_path, | ||
126 | const struct GNUNET_MessageHeader *reply) | ||
127 | { | ||
128 | struct GNUNET_DHT_GetHandle *get_handle = cls; | ||
129 | const struct GNUNET_DHT_GetResultMessage *result; | ||
130 | const struct GNUNET_PeerIdentity **put_path; | ||
131 | char *path_offset; | ||
132 | const struct GNUNET_PeerIdentity *pos; | ||
133 | unsigned int i; | ||
134 | uint16_t put_path_length; | ||
135 | uint16_t data_size; | ||
136 | |||
137 | if (ntohs (reply->type) != GNUNET_MESSAGE_TYPE_DHT_GET_RESULT) | ||
138 | { | ||
139 | GNUNET_break (0); | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | GNUNET_assert (ntohs (reply->size) >= | ||
144 | sizeof (struct GNUNET_DHT_GetResultMessage)); | ||
145 | result = (const struct GNUNET_DHT_GetResultMessage *) reply; | ||
146 | |||
147 | put_path = NULL; | ||
148 | put_path_length = ntohs (result->put_path_length); | ||
149 | data_size = | ||
150 | ntohs (result->header.size) - | ||
151 | (put_path_length * sizeof (struct GNUNET_PeerIdentity)) - | ||
152 | sizeof (struct GNUNET_DHT_GetResultMessage); | ||
153 | if (put_path_length > 0) | ||
154 | { | ||
155 | path_offset = (char *) &result[1]; | ||
156 | //GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "In get_reply_iterator, result->header.size is %d, put_path_length %d, offset is %d, data_size is %d\n", ntohs(result->header.size), put_path_length, ntohs(result->header.size) - (put_path_length * sizeof(struct GNUNET_PeerIdentity)), data_size); | ||
157 | path_offset += data_size; | ||
158 | pos = (const struct GNUNET_PeerIdentity *) path_offset; | ||
159 | //GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Found put peer %s\n", GNUNET_i2s((const struct GNUNET_PeerIdentity *)path_offset)); | ||
160 | put_path = | ||
161 | GNUNET_malloc ((put_path_length + | ||
162 | 1) * sizeof (struct GNUNET_PeerIdentity *)); | ||
163 | for (i = 0; i < put_path_length; i++) | ||
164 | { | ||
165 | put_path[i] = pos; | ||
166 | pos++; | ||
167 | } | ||
168 | put_path[put_path_length] = NULL; | ||
169 | } | ||
170 | |||
171 | get_handle->iter (get_handle->iter_cls, | ||
172 | GNUNET_TIME_absolute_ntoh (result->expiration), key, | ||
173 | outgoing_path, put_path, ntohs (result->type), data_size, | ||
174 | &result[1]); | ||
175 | GNUNET_free_non_null (put_path); | ||
176 | } | ||
177 | |||
178 | |||
179 | |||
180 | /** | ||
181 | * Perform an asynchronous GET operation on the DHT identified. See | ||
182 | * also "GNUNET_BLOCK_evaluate". | ||
183 | * | ||
184 | * @param handle handle to the DHT service | ||
185 | * @param timeout how long to wait for transmission of this request to the service | ||
186 | * @param type expected type of the response object | ||
187 | * @param key the key to look up | ||
188 | * @param desired_replication_level estimate of how many | ||
189 | nearest peers this request should reach | ||
190 | * @param options routing options for this message | ||
191 | * @param bf bloom filter associated with query (can be NULL) | ||
192 | * @param bf_mutator mutation value for bf | ||
193 | * @param xquery extended query data (can be NULL, depending on type) | ||
194 | * @param xquery_size number of bytes in xquery | ||
195 | * @param iter function to call on each result | ||
196 | * @param iter_cls closure for iter | ||
197 | * | ||
198 | * @return handle to stop the async get | ||
199 | */ | ||
200 | struct GNUNET_DHT_GetHandle * | ||
201 | GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle, | ||
202 | struct GNUNET_TIME_Relative timeout, | ||
203 | enum GNUNET_BLOCK_Type type, const GNUNET_HashCode * key, | ||
204 | uint32_t desired_replication_level, | ||
205 | enum GNUNET_DHT_RouteOption options, | ||
206 | const struct GNUNET_CONTAINER_BloomFilter *bf, | ||
207 | int32_t bf_mutator, const void *xquery, | ||
208 | size_t xquery_size, GNUNET_DHT_GetIterator iter, | ||
209 | void *iter_cls) | ||
210 | { | ||
211 | struct GNUNET_DHT_GetHandle *get_handle; | ||
212 | char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; | ||
213 | struct GNUNET_DHT_GetMessage *get_msg; | ||
214 | size_t bf_size; | ||
215 | |||
216 | bf_size = GNUNET_CONTAINER_bloomfilter_get_size (bf); | ||
217 | if ((sizeof (buf) <= | ||
218 | sizeof (struct GNUNET_DHT_GetMessage) + xquery_size + bf_size) || | ||
219 | (sizeof (buf) <= bf_size)) | ||
220 | { | ||
221 | GNUNET_break (0); | ||
222 | return NULL; | ||
223 | } | ||
224 | get_handle = GNUNET_malloc (sizeof (struct GNUNET_DHT_GetHandle)); | ||
225 | get_handle->iter = iter; | ||
226 | get_handle->iter_cls = iter_cls; | ||
227 | get_msg = (struct GNUNET_DHT_GetMessage *) buf; | ||
228 | get_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_GET); | ||
229 | get_msg->header.size = | ||
230 | htons (sizeof (struct GNUNET_DHT_GetMessage) + xquery_size + bf_size); | ||
231 | get_msg->type = htonl ((uint32_t) type); | ||
232 | get_msg->bf_mutator = bf_mutator; | ||
233 | get_msg->xquery_size = htons ((uint16_t) xquery_size); | ||
234 | get_msg->bf_size = htons (bf_size); | ||
235 | if (xquery != NULL) | ||
236 | memcpy (&buf[sizeof (struct GNUNET_DHT_GetMessage)], xquery, xquery_size); | ||
237 | else | ||
238 | GNUNET_assert (xquery_size == 0); | ||
239 | (void) GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, | ||
240 | &buf[sizeof | ||
241 | (struct | ||
242 | GNUNET_DHT_GetMessage) | ||
243 | + xquery_size], | ||
244 | bf_size); | ||
245 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
246 | "Starting route for %u byte `%s' message\n", | ||
247 | (unsigned int) (sizeof (struct GNUNET_DHT_GetMessage) + | ||
248 | xquery_size + bf_size), "GET"); | ||
249 | get_handle->route_handle = | ||
250 | GNUNET_DHT_route_start (handle, key, desired_replication_level, options, | ||
251 | &get_msg->header, timeout, &get_reply_iterator, | ||
252 | get_handle, NULL, NULL); | ||
253 | GNUNET_break (NULL != get_handle->route_handle); | ||
254 | return get_handle; | ||
255 | } | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Stop async DHT-get. | ||
260 | * | ||
261 | * @param get_handle handle to the GET operation to stop | ||
262 | * | ||
263 | * On return get_handle will no longer be valid, caller | ||
264 | * must not use again!!! | ||
265 | */ | ||
266 | void | ||
267 | GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle) | ||
268 | { | ||
269 | GNUNET_DHT_route_stop (get_handle->route_handle); | ||
270 | GNUNET_free (get_handle); | ||
271 | } | ||
272 | |||
273 | |||
274 | /* end of dht_api_get_put.c */ | ||
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c index 1dfd1fbb1..80efd5d40 100644 --- a/src/dht/gnunet-service-dht_neighbours.c +++ b/src/dht/gnunet-service-dht_neighbours.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include "gnunet_hello_lib.h" | 38 | #include "gnunet_hello_lib.h" |
39 | #include "gnunet_dht_service_new.h" | 39 | #include "gnunet_dht_service_new.h" |
40 | #include "gnunet_statistics_service.h" | 40 | #include "gnunet_statistics_service.h" |
41 | #include "dht.h" | ||
42 | #include "gnunet-service-dht.h" | 41 | #include "gnunet-service-dht.h" |
43 | #include "gnunet-service-dht_clients.h" | 42 | #include "gnunet-service-dht_clients.h" |
44 | #include "gnunet-service-dht_datacache.h" | 43 | #include "gnunet-service-dht_datacache.h" |
@@ -593,7 +592,7 @@ send_find_peer_message (void *cls, | |||
593 | } | 592 | } |
594 | bcc.bf_mutator = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); | 593 | bcc.bf_mutator = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); |
595 | bcc.bloom = | 594 | bcc.bloom = |
596 | GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, DHT_BLOOM_K); | 595 | GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); |
597 | GNUNET_CONTAINER_multihashmap_iterate (all_known_peers, | 596 | GNUNET_CONTAINER_multihashmap_iterate (all_known_peers, |
598 | &add_known_to_bloom, | 597 | &add_known_to_bloom, |
599 | &bcc); | 598 | &bcc); |
@@ -1508,7 +1507,7 @@ handle_dht_p2p_put (void *cls, | |||
1508 | } | 1507 | } |
1509 | bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter, | 1508 | bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter, |
1510 | DHT_BLOOM_SIZE, | 1509 | DHT_BLOOM_SIZE, |
1511 | DHT_BLOOM_K); | 1510 | GNUNET_CONSTANTS_BLOOMFILTER_K); |
1512 | { | 1511 | { |
1513 | struct GNUNET_PeerIdentity pp[putlen+1]; | 1512 | struct GNUNET_PeerIdentity pp[putlen+1]; |
1514 | 1513 | ||
@@ -1710,7 +1709,7 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1710 | peer_bf = | 1709 | peer_bf = |
1711 | GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, | 1710 | GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, |
1712 | DHT_BLOOM_SIZE, | 1711 | DHT_BLOOM_SIZE, |
1713 | DHT_BLOOM_K); | 1712 | GNUNET_CONSTANTS_BLOOMFILTER_K); |
1714 | 1713 | ||
1715 | /* remember request for routing replies */ | 1714 | /* remember request for routing replies */ |
1716 | GDS_ROUTING_add (peer, | 1715 | GDS_ROUTING_add (peer, |