aboutsummaryrefslogtreecommitdiff
path: root/src/dht
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-09-27 20:49:32 +0000
committerChristian Grothoff <christian@grothoff.org>2011-09-27 20:49:32 +0000
commit2d10e77135a8db547c187c4aadcff8d1f1763412 (patch)
treef5083f58af35a8d1ffd07838d690d6d511b49608 /src/dht
parent18ad006e1f9b322d4760fb1473e8182f0d6ae7f0 (diff)
downloadgnunet-2d10e77135a8db547c187c4aadcff8d1f1763412.tar.gz
gnunet-2d10e77135a8db547c187c4aadcff8d1f1763412.zip
fixes
Diffstat (limited to 'src/dht')
-rw-r--r--src/dht/Makefile.am17
-rw-r--r--src/dht/dht.h485
-rw-r--r--src/dht/dht_api.c909
-rw-r--r--src/dht/dht_api_find_peer.c150
-rw-r--r--src/dht/dht_api_get_put.c274
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c7
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
15endif 15endif
16 16
17lib_LTLIBRARIES = \ 17lib_LTLIBRARIES = \
18 libgnunetdht.la \
19 libgnunetdhtnew.la 18 libgnunetdhtnew.la
20 19
21 20
22libgnunetdht_la_SOURCES = \
23 dht_api.c dht.h \
24 dht_api_get_put.c \
25 dht_api_find_peer.c
26libgnunetdht_la_LIBADD = \
27 $(top_builddir)/src/util/libgnunetutil.la \
28 $(XLIB)
29libgnunetdht_la_LDFLAGS = \
30 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
31 -version-info 0:0:0
32
33libgnunetdhtnew_la_SOURCES = \ 21libgnunetdhtnew_la_SOURCES = \
34 dht_api_new.c dht_new.h 22 dht_api_new.c dht_new.h
35libgnunetdhtnew_la_LIBADD = \ 23libgnunetdhtnew_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
47if HAVE_MALICIOUS
48noinst_PROGRAMS = \
49 gnunet-dht-driver
50endif
51
52gnunet_service_dht_new_SOURCES = \ 35gnunet_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 */
99typedef void (*GNUNET_DHT_MessageReceivedHandler) (void *cls,
100 const struct
101 GNUNET_MessageHeader * msg);
102
103
104/**
105 * FIXME: document.
106 */
107struct 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 */
130struct 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 */
159struct 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 */
201struct 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 */
235struct 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 */
300struct 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 */
347struct 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 */
375struct 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 */
414struct 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 */
433struct 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 */
467struct 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 */
46struct 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 */
109struct 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 */
150struct 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 */
206static size_t
207transmit_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 */
215static void
216service_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 */
226static int
227try_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 */
257static int
258add_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 */
277static void
278process_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 */
287static void
288try_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 */
317static void
318do_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 */
336static void
337process_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 */
367static size_t
368transmit_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 */
421static int
422process_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 */
491static void
492service_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 */
541struct GNUNET_DHT_Handle *
542GNUNET_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 */
566void
567GNUNET_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 */
615static void
616timeout_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 */
657struct GNUNET_DHT_RouteHandle *
658GNUNET_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 */
734void
735GNUNET_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 */
792static void
793send_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 */
830void
831GNUNET_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 */
851void
852GNUNET_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 */
874void
875GNUNET_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 */
899void
900GNUNET_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 */
40struct 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 */
73static void
74find_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 */
112struct GNUNET_DHT_FindPeerHandle *
113GNUNET_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 */
142void
143GNUNET_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 */
54void
55GNUNET_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 */
92struct 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 */
123static void
124get_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 */
200struct GNUNET_DHT_GetHandle *
201GNUNET_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 */
266void
267GNUNET_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,