diff options
-rw-r--r-- | src/dht/Makefile.am | 51 | ||||
-rw-r--r-- | src/dht/dht.h | 146 | ||||
-rw-r--r-- | src/dht/dht_api.c | 583 | ||||
-rw-r--r-- | src/dht/gnunet-service-dht.c | 385 | ||||
-rw-r--r-- | src/dht/test_dht_api.c | 216 | ||||
-rw-r--r-- | src/dht/test_dht_api_data.conf | 143 | ||||
-rw-r--r-- | src/dht/test_dht_api_peer1.conf | 144 |
7 files changed, 1668 insertions, 0 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am new file mode 100644 index 000000000..333034ecd --- /dev/null +++ b/src/dht/Makefile.am | |||
@@ -0,0 +1,51 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -luuid -liconv -lstdc++ -lcomdlg32 -lgdi32 | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | |||
12 | lib_LTLIBRARIES = libgnunetdht.la | ||
13 | |||
14 | libgnunetdht_la_SOURCES = \ | ||
15 | dht_api.c dht.h | ||
16 | libgnunetdht_la_LIBADD = \ | ||
17 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
18 | $(XLIB) | ||
19 | libgnunetdht_la_LDFLAGS = \ | ||
20 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
21 | -version-info 0:0:0 | ||
22 | |||
23 | |||
24 | bin_PROGRAMS = \ | ||
25 | gnunet-service-dht | ||
26 | |||
27 | gnunet_service_dht_SOURCES = \ | ||
28 | gnunet-service-dht.c | ||
29 | gnunet_service_dht_LDADD = \ | ||
30 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
31 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
32 | $(top_builddir)/src/datastore/libgnunetdatastore.la \ | ||
33 | $(top_builddir)/src/util/libgnunetutil.la | ||
34 | |||
35 | |||
36 | check_PROGRAMS = \ | ||
37 | test_dht_api | ||
38 | |||
39 | TESTS = $(check_PROGRAMS) # $(check_SCRIPTS) | ||
40 | |||
41 | test_dht_api_SOURCES = \ | ||
42 | test_dht_api.c | ||
43 | test_dht_api_LDADD = \ | ||
44 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
45 | $(top_builddir)/src/dht/libgnunetdht.la | ||
46 | |||
47 | EXTRA_DIST = \ | ||
48 | test_dht_api_data.conf | ||
49 | |||
50 | #check_SCRIPTS = \ | ||
51 | # test_gnunet_peerinfo.sh | ||
diff --git a/src/dht/dht.h b/src/dht/dht.h new file mode 100644 index 000000000..5293bf6bd --- /dev/null +++ b/src/dht/dht.h | |||
@@ -0,0 +1,146 @@ | |||
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 2, 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_YES | ||
31 | |||
32 | typedef void (*GNUNET_DHT_MessageReceivedHandler) (void *cls, | ||
33 | struct GNUNET_MessageHeader *msg); | ||
34 | |||
35 | /** | ||
36 | * Message to insert data into the DHT | ||
37 | */ | ||
38 | struct GNUNET_DHT_PutMessage | ||
39 | { | ||
40 | /** | ||
41 | * Type: GNUNET_MESSAGE_TYPE_DHT_PUT | ||
42 | */ | ||
43 | struct GNUNET_MessageHeader header; | ||
44 | |||
45 | /** | ||
46 | * The type of data to insert. | ||
47 | */ | ||
48 | size_t type; | ||
49 | |||
50 | /** | ||
51 | * The key to insert data under. | ||
52 | */ | ||
53 | GNUNET_HashCode key; | ||
54 | |||
55 | /** | ||
56 | * The size of the data, appended to the end of this message. | ||
57 | */ | ||
58 | size_t data_size; | ||
59 | |||
60 | /** | ||
61 | * How long should this data persist? | ||
62 | */ | ||
63 | struct GNUNET_TIME_Relative timeout; | ||
64 | |||
65 | }; | ||
66 | |||
67 | |||
68 | /** | ||
69 | * Message to request data from the DHT | ||
70 | */ | ||
71 | struct GNUNET_DHT_GetMessage | ||
72 | { | ||
73 | /** | ||
74 | * Type: GNUNET_MESSAGE_TYPE_DHT_GET | ||
75 | */ | ||
76 | struct GNUNET_MessageHeader header; | ||
77 | |||
78 | /** | ||
79 | * The type for the data for the GET request | ||
80 | */ | ||
81 | size_t type; | ||
82 | |||
83 | /** | ||
84 | * The key to search for | ||
85 | */ | ||
86 | GNUNET_HashCode key; | ||
87 | |||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * Message to return data from the DHT | ||
92 | */ | ||
93 | struct GNUNET_DHT_GetResultMessage | ||
94 | { | ||
95 | /** | ||
96 | * Type: GNUNET_MESSAGE_TYPE_DHT_GET_RESULT | ||
97 | */ | ||
98 | struct GNUNET_MessageHeader header; | ||
99 | |||
100 | /** | ||
101 | * The type for the data for the GET request | ||
102 | */ | ||
103 | size_t type; | ||
104 | |||
105 | /** | ||
106 | * The key to search for | ||
107 | */ | ||
108 | GNUNET_HashCode key; | ||
109 | |||
110 | /** | ||
111 | * The size of the data, appended to the end of this message. | ||
112 | */ | ||
113 | size_t data_size; | ||
114 | |||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * Response to PUT request from the DHT | ||
119 | */ | ||
120 | struct GNUNET_DHT_PutResultMessage | ||
121 | { | ||
122 | /** | ||
123 | * Type: GNUNET_MESSAGE_TYPE_DHT_PUT_RESULT | ||
124 | */ | ||
125 | struct GNUNET_MessageHeader header; | ||
126 | |||
127 | /** | ||
128 | * The type for the data for the GET request | ||
129 | */ | ||
130 | size_t type; | ||
131 | |||
132 | /** | ||
133 | * The key to search for | ||
134 | */ | ||
135 | GNUNET_HashCode key; | ||
136 | |||
137 | /** | ||
138 | * Was the put successful? GNUNET_YES or GNUNET_NO | ||
139 | */ | ||
140 | size_t result; | ||
141 | |||
142 | }; | ||
143 | |||
144 | |||
145 | |||
146 | #endif /* DHT_H_ */ | ||
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c new file mode 100644 index 000000000..db25379fa --- /dev/null +++ b/src/dht/dht_api.c | |||
@@ -0,0 +1,583 @@ | |||
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 2, 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 | #include "platform.h" | ||
28 | #include "gnunet_bandwidth_lib.h" | ||
29 | #include "gnunet_client_lib.h" | ||
30 | #include "gnunet_constants.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_arm_service.h" | ||
33 | #include "gnunet_hello_lib.h" | ||
34 | #include "gnunet_protocols.h" | ||
35 | #include "gnunet_server_lib.h" | ||
36 | #include "gnunet_time_lib.h" | ||
37 | #include "gnunet_dht_service.h" | ||
38 | #include "dht.h" | ||
39 | |||
40 | #define DEBUG_DHT_API GNUNET_YES | ||
41 | |||
42 | struct PendingMessages | ||
43 | { | ||
44 | /** | ||
45 | * Linked list of pending messages | ||
46 | */ | ||
47 | struct PendingMessages *next; | ||
48 | |||
49 | /** | ||
50 | * Message that is pending | ||
51 | */ | ||
52 | struct GNUNET_MessageHeader *msg; | ||
53 | |||
54 | /** | ||
55 | * Timeout for this message | ||
56 | */ | ||
57 | struct GNUNET_TIME_Relative timeout; | ||
58 | |||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * Connection to the DHT service. | ||
63 | */ | ||
64 | struct GNUNET_DHT_Handle | ||
65 | { | ||
66 | /** | ||
67 | * Our scheduler. | ||
68 | */ | ||
69 | struct GNUNET_SCHEDULER_Handle *sched; | ||
70 | |||
71 | /** | ||
72 | * Configuration to use. | ||
73 | */ | ||
74 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
75 | |||
76 | /** | ||
77 | * Socket (if available). | ||
78 | */ | ||
79 | struct GNUNET_CLIENT_Connection *client; | ||
80 | |||
81 | /** | ||
82 | * Currently pending transmission request. | ||
83 | */ | ||
84 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
85 | |||
86 | /** | ||
87 | * List of the currently pending messages for the DHT service. | ||
88 | */ | ||
89 | struct PendingMessages *pending_list; | ||
90 | |||
91 | /** | ||
92 | * Message we are currently sending. | ||
93 | */ | ||
94 | struct PendingMessages *current; | ||
95 | |||
96 | /** | ||
97 | * Hash map containing the current outstanding get requests | ||
98 | */ | ||
99 | struct GNUNET_CONTAINER_MultiHashMap *outstanding_get_requests; | ||
100 | |||
101 | /** | ||
102 | * Hash map containing the current outstanding put requests, awaiting | ||
103 | * a response | ||
104 | */ | ||
105 | struct GNUNET_CONTAINER_MultiHashMap *outstanding_put_requests; | ||
106 | |||
107 | /** | ||
108 | * Kill off the connection and any pending messages. | ||
109 | */ | ||
110 | int do_destroy; | ||
111 | |||
112 | }; | ||
113 | |||
114 | static struct GNUNET_TIME_Relative default_request_timeout; | ||
115 | |||
116 | /* Forward declaration */ | ||
117 | static void process_pending_message(struct GNUNET_DHT_Handle *handle); | ||
118 | |||
119 | /** | ||
120 | * Handler for messages received from the DHT service | ||
121 | * a demultiplexer which handles numerous message types | ||
122 | * | ||
123 | */ | ||
124 | void service_message_handler (void *cls, | ||
125 | const struct GNUNET_MessageHeader *msg) | ||
126 | { | ||
127 | |||
128 | /* TODO: find out message type, handle callbacks for different types of messages. | ||
129 | * Should be a put acknowledgment, get data or find node result. */ | ||
130 | } | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Initialize the connection with the DHT service. | ||
135 | * | ||
136 | * @param cfg configuration to use | ||
137 | * @param sched scheduler to use | ||
138 | * @return NULL on error | ||
139 | */ | ||
140 | struct GNUNET_DHT_Handle * | ||
141 | GNUNET_DHT_connect (struct GNUNET_SCHEDULER_Handle *sched, | ||
142 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
143 | { | ||
144 | struct GNUNET_DHT_Handle *handle; | ||
145 | |||
146 | handle = GNUNET_malloc(sizeof(struct GNUNET_DHT_Handle)); | ||
147 | |||
148 | default_request_timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); | ||
149 | handle->cfg = cfg; | ||
150 | handle->sched = sched; | ||
151 | handle->pending_list = NULL; | ||
152 | handle->current = NULL; | ||
153 | handle->do_destroy = GNUNET_NO; | ||
154 | handle->th = NULL; | ||
155 | |||
156 | handle->client = GNUNET_CLIENT_connect(sched, "dht", cfg); | ||
157 | handle->outstanding_get_requests = GNUNET_CONTAINER_multihashmap_create(100); /* FIXME: better number */ | ||
158 | handle->outstanding_put_requests = GNUNET_CONTAINER_multihashmap_create(100); /* FIXME: better number */ | ||
159 | if (handle->client == NULL) | ||
160 | return NULL; | ||
161 | #if DEBUG_DHT_API | ||
162 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
163 | "`%s': Connection to service in progress\n", "DHT API"); | ||
164 | #endif | ||
165 | GNUNET_CLIENT_receive (handle->client, | ||
166 | &service_message_handler, | ||
167 | handle, GNUNET_TIME_UNIT_FOREVER_REL); | ||
168 | |||
169 | return handle; | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Shutdown connection with the DHT service. | ||
175 | * | ||
176 | * @param h connection to shut down | ||
177 | */ | ||
178 | void | ||
179 | GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle) | ||
180 | { | ||
181 | struct PendingMessages *pos; | ||
182 | #if DEBUG_DHT_API | ||
183 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
184 | "`%s': Called GNUNET_DHT_disconnect\n", "DHT API"); | ||
185 | #endif | ||
186 | GNUNET_assert(handle != NULL); | ||
187 | |||
188 | if (handle->th != NULL) /* We have a live transmit request in the Aether */ | ||
189 | { | ||
190 | GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); | ||
191 | handle->th = NULL; | ||
192 | } | ||
193 | if (handle->current != NULL) /* We are trying to send something now, clean it up */ | ||
194 | GNUNET_free(handle->current); | ||
195 | |||
196 | while (NULL != (pos = handle->pending_list)) /* Remove all pending sends from the list */ | ||
197 | { | ||
198 | handle->pending_list = pos->next; | ||
199 | GNUNET_free(pos); | ||
200 | } | ||
201 | if (handle->client != NULL) /* Finally, disconnect from the service */ | ||
202 | { | ||
203 | GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO); | ||
204 | handle->client = NULL; | ||
205 | } | ||
206 | |||
207 | GNUNET_free (handle); | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Handle to control a GET operation. | ||
213 | */ | ||
214 | struct GNUNET_DHT_GetHandle | ||
215 | { | ||
216 | |||
217 | /** | ||
218 | * Key that this get request is for | ||
219 | */ | ||
220 | GNUNET_HashCode key; | ||
221 | |||
222 | /** | ||
223 | * Type of data get request was for | ||
224 | */ | ||
225 | uint32_t type; | ||
226 | |||
227 | /** | ||
228 | * Iterator to call on data receipt | ||
229 | */ | ||
230 | GNUNET_DHT_Iterator iter; | ||
231 | |||
232 | /** | ||
233 | * Closure for the iterator callback | ||
234 | */ | ||
235 | void *iter_cls; | ||
236 | }; | ||
237 | |||
238 | /** | ||
239 | * Handle for a PUT request, holds callback | ||
240 | */ | ||
241 | struct GNUNET_DHT_PutHandle | ||
242 | { | ||
243 | /** | ||
244 | * Key that this get request is for | ||
245 | */ | ||
246 | GNUNET_HashCode key; | ||
247 | |||
248 | /** | ||
249 | * Type of data get request was for | ||
250 | */ | ||
251 | uint32_t type; | ||
252 | |||
253 | /** | ||
254 | * Continuation to call on put send | ||
255 | */ | ||
256 | GNUNET_SCHEDULER_Task cont; | ||
257 | |||
258 | /** | ||
259 | * Send continuation cls | ||
260 | */ | ||
261 | void *cont_cls; | ||
262 | }; | ||
263 | |||
264 | /** | ||
265 | * Send complete (or failed), schedule next (or don't) | ||
266 | */ | ||
267 | static void | ||
268 | finish (struct GNUNET_DHT_Handle *handle, int code) | ||
269 | { | ||
270 | /* TODO: if code is not GNUNET_OK, do something! */ | ||
271 | struct PendingMessages *pos = handle->current; | ||
272 | struct GNUNET_DHT_GetMessage *get; | ||
273 | struct GNUNET_DHT_PutMessage *put; | ||
274 | |||
275 | GNUNET_assert(pos != NULL); | ||
276 | |||
277 | switch (ntohs(pos->msg->type)) | ||
278 | { | ||
279 | case GNUNET_MESSAGE_TYPE_DHT_GET: | ||
280 | get = (struct GNUNET_DHT_GetMessage *)pos->msg; | ||
281 | GNUNET_free(get); | ||
282 | break; | ||
283 | case GNUNET_MESSAGE_TYPE_DHT_PUT: | ||
284 | put = (struct GNUNET_DHT_PutMessage *)pos->msg; | ||
285 | GNUNET_free(put); | ||
286 | break; | ||
287 | default: | ||
288 | GNUNET_break(0); | ||
289 | } | ||
290 | |||
291 | handle->current = NULL; | ||
292 | |||
293 | if (code != GNUNET_SYSERR) | ||
294 | process_pending_message (handle); | ||
295 | |||
296 | GNUNET_free(pos); | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Transmit the next pending message, called by notify_transmit_ready | ||
301 | */ | ||
302 | static size_t | ||
303 | transmit_pending (void *cls, size_t size, void *buf) | ||
304 | { | ||
305 | struct GNUNET_DHT_Handle *handle = cls; | ||
306 | size_t ret; | ||
307 | size_t tsize; | ||
308 | |||
309 | if (buf == NULL) | ||
310 | { | ||
311 | #if DEBUG_DHT_API | ||
312 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
313 | "`%s': In transmit_pending buf is NULL\n", "DHT API"); | ||
314 | #endif | ||
315 | /* FIXME: free associated resources or summat */ | ||
316 | finish(handle, GNUNET_SYSERR); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | handle->th = NULL; | ||
321 | ret = 0; | ||
322 | |||
323 | if (handle->current != NULL) | ||
324 | { | ||
325 | tsize = ntohs(handle->current->msg->size); | ||
326 | if (size >= tsize) | ||
327 | { | ||
328 | #if DEBUG_DHT_API | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "`%s': Sending message size %d\n", "DHT API", tsize); | ||
331 | #endif | ||
332 | memcpy(buf, handle->current->msg, tsize); | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | return ret; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Try to (re)connect to the dht service. | ||
346 | * | ||
347 | * @return GNUNET_YES on success, GNUNET_NO on failure. | ||
348 | */ | ||
349 | static int | ||
350 | try_connect (struct GNUNET_DHT_Handle *ret) | ||
351 | { | ||
352 | if (ret->client != NULL) | ||
353 | return GNUNET_OK; | ||
354 | ret->client = GNUNET_CLIENT_connect (ret->sched, "dht", ret->cfg); | ||
355 | if (ret->client != NULL) | ||
356 | return GNUNET_YES; | ||
357 | #if DEBUG_STATISTICS | ||
358 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
359 | _("Failed to connect to the dht service!\n")); | ||
360 | #endif | ||
361 | return GNUNET_NO; | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * Try to send messages from list of messages to send | ||
367 | */ | ||
368 | static void process_pending_message(struct GNUNET_DHT_Handle *handle) | ||
369 | { | ||
370 | |||
371 | if (handle->current != NULL) | ||
372 | return; /* action already pending */ | ||
373 | if (GNUNET_YES != try_connect (handle)) | ||
374 | { | ||
375 | finish (handle, GNUNET_SYSERR); | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | /* TODO: set do_destroy somewhere's, see what needs to happen in that case! */ | ||
380 | if (handle->do_destroy) | ||
381 | { | ||
382 | //GNUNET_DHT_disconnect (handle); /* FIXME: replace with proper disconnect stuffs */ | ||
383 | } | ||
384 | |||
385 | /* schedule next action */ | ||
386 | handle->current = handle->pending_list; | ||
387 | if (NULL == handle->current) | ||
388 | { | ||
389 | return; | ||
390 | } | ||
391 | handle->pending_list = handle->pending_list->next; | ||
392 | handle->current->next = NULL; | ||
393 | |||
394 | if (NULL == | ||
395 | (handle->th = GNUNET_CLIENT_notify_transmit_ready (handle->client, | ||
396 | ntohs(handle->current->msg->size), | ||
397 | handle->current->timeout, | ||
398 | GNUNET_YES, | ||
399 | &transmit_pending, handle))) | ||
400 | { | ||
401 | #if DEBUG_DHT_API | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
403 | "Failed to transmit request to dht service.\n"); | ||
404 | #endif | ||
405 | finish (handle, GNUNET_SYSERR); | ||
406 | } | ||
407 | #if DEBUG_DHT_API | ||
408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
409 | "`%s': Scheduled sending message of size %d to service\n", "DHT API", ntohs(handle->current->msg->size)); | ||
410 | #endif | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * Add a pending message to the linked list of messages which need to be sent | ||
415 | * | ||
416 | * @param handle handle to the specified DHT api | ||
417 | * @param msg the message to add to the list | ||
418 | */ | ||
419 | static void add_pending(struct GNUNET_DHT_Handle *handle, struct GNUNET_MessageHeader *msg) | ||
420 | { | ||
421 | struct PendingMessages *new_message; | ||
422 | struct PendingMessages *pos; | ||
423 | struct PendingMessages *last; | ||
424 | |||
425 | new_message = GNUNET_malloc(sizeof(struct PendingMessages)); | ||
426 | new_message->msg = msg; | ||
427 | new_message->timeout = default_request_timeout; | ||
428 | |||
429 | if (handle->pending_list != NULL) | ||
430 | { | ||
431 | pos = handle->pending_list; | ||
432 | while(pos != NULL) | ||
433 | { | ||
434 | last = pos; | ||
435 | pos = pos->next; | ||
436 | } | ||
437 | new_message->next = last->next; /* Should always be null */ | ||
438 | last->next = new_message; | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | new_message->next = handle->pending_list; /* Will always be null */ | ||
443 | handle->pending_list = new_message; | ||
444 | } | ||
445 | |||
446 | process_pending_message(handle); | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * Perform an asynchronous GET operation on the DHT identified. | ||
451 | * | ||
452 | * @param h handle to the DHT service | ||
453 | * @param type expected type of the response object | ||
454 | * @param key the key to look up | ||
455 | * @param iter function to call on each result | ||
456 | * @param iter_cls closure for iter | ||
457 | * @return handle to stop the async get | ||
458 | */ | ||
459 | struct GNUNET_DHT_GetHandle * | ||
460 | GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle, | ||
461 | uint32_t type, | ||
462 | const GNUNET_HashCode * key, | ||
463 | GNUNET_DHT_Iterator iter, | ||
464 | void *iter_cls) | ||
465 | { | ||
466 | struct GNUNET_DHT_GetMessage *get_msg; | ||
467 | struct GNUNET_DHT_GetHandle *get_handle; | ||
468 | |||
469 | get_handle = GNUNET_CONTAINER_multihashmap_get(handle->outstanding_get_requests, key); | ||
470 | |||
471 | if (get_handle != NULL) | ||
472 | { | ||
473 | /* | ||
474 | * A get has been previously sent, return existing handle. | ||
475 | * FIXME: should we re-transmit the request to the DHT service? | ||
476 | */ | ||
477 | return get_handle; | ||
478 | } | ||
479 | |||
480 | get_handle = GNUNET_malloc(sizeof(struct GNUNET_DHT_GetHandle)); | ||
481 | get_handle->type = type; | ||
482 | memcpy(&get_handle->key, key, sizeof(GNUNET_HashCode)); | ||
483 | get_handle->iter = iter; | ||
484 | get_handle->iter_cls = iter_cls; | ||
485 | |||
486 | GNUNET_CONTAINER_multihashmap_put(handle->outstanding_get_requests, key, get_handle, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
487 | |||
488 | get_msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_GetMessage)); | ||
489 | get_msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_GET); | ||
490 | get_msg->header.size = htons(sizeof(struct GNUNET_DHT_GetMessage)); | ||
491 | get_msg->type = htonl(type); | ||
492 | memcpy(&get_msg->key, key, sizeof(GNUNET_HashCode)); | ||
493 | |||
494 | add_pending(handle, &get_msg->header); | ||
495 | |||
496 | return get_handle; | ||
497 | } | ||
498 | |||
499 | |||
500 | /** | ||
501 | * Stop async DHT-get. Frees associated resources. | ||
502 | * | ||
503 | * @param record GET operation to stop. | ||
504 | */ | ||
505 | void | ||
506 | GNUNET_DHT_get_stop (struct GNUNET_DHT_Handle *handle, struct GNUNET_DHT_GetHandle *get_handle) | ||
507 | { | ||
508 | struct GNUNET_DHT_GetMessage *get_msg; | ||
509 | |||
510 | if (handle->do_destroy == GNUNET_NO) | ||
511 | { | ||
512 | get_msg = GNUNET_malloc(sizeof(struct GNUNET_DHT_GetMessage)); | ||
513 | get_msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_GET_STOP); | ||
514 | get_msg->header.size = htons(sizeof(struct GNUNET_DHT_GetMessage)); | ||
515 | get_msg->type = htonl(get_handle->type); | ||
516 | memcpy(&get_msg->key, &get_handle->key, sizeof(GNUNET_HashCode)); | ||
517 | |||
518 | add_pending(handle, &get_msg->header); | ||
519 | } | ||
520 | |||
521 | GNUNET_assert(GNUNET_CONTAINER_multihashmap_remove(handle->outstanding_get_requests, &get_handle->key, get_handle) == GNUNET_YES); | ||
522 | GNUNET_free(get_handle); | ||
523 | } | ||
524 | |||
525 | |||
526 | /** | ||
527 | * Perform a PUT operation storing data in the DHT. | ||
528 | * | ||
529 | * @param h handle to DHT service | ||
530 | * @param key the key to store under | ||
531 | * @param type type of the value | ||
532 | * @param size number of bytes in data; must be less than 64k | ||
533 | * @param data the data to store | ||
534 | * @param exp desired expiration time for the value | ||
535 | * @param cont continuation to call when done; | ||
536 | * reason will be TIMEOUT on error, | ||
537 | * reason will be PREREQ_DONE on success | ||
538 | * @param cont_cls closure for cont | ||
539 | * | ||
540 | * @return GNUNET_YES if put message is queued for transmission | ||
541 | */ | ||
542 | int GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, | ||
543 | const GNUNET_HashCode * key, | ||
544 | uint32_t type, | ||
545 | uint32_t size, | ||
546 | const char *data, | ||
547 | struct GNUNET_TIME_Relative exp, | ||
548 | GNUNET_SCHEDULER_Task cont, | ||
549 | void *cont_cls) | ||
550 | { | ||
551 | struct GNUNET_DHT_PutMessage *put_msg; | ||
552 | struct GNUNET_DHT_PutHandle *put_handle; | ||
553 | size_t msize; | ||
554 | |||
555 | put_handle = GNUNET_CONTAINER_multihashmap_get(handle->outstanding_put_requests, key); | ||
556 | |||
557 | if (put_handle != NULL) | ||
558 | { | ||
559 | /* | ||
560 | * A put has been previously queued, but not yet sent. | ||
561 | * FIXME: change the continuation function and callback or something? | ||
562 | */ | ||
563 | return GNUNET_NO; | ||
564 | } | ||
565 | |||
566 | put_handle = GNUNET_malloc(sizeof(struct GNUNET_DHT_PutHandle)); | ||
567 | put_handle->type = type; | ||
568 | memcpy(&put_handle->key, key, sizeof(GNUNET_HashCode)); | ||
569 | |||
570 | GNUNET_CONTAINER_multihashmap_put(handle->outstanding_put_requests, key, put_handle, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
571 | |||
572 | msize = sizeof(struct GNUNET_DHT_PutMessage) + size; | ||
573 | put_msg = GNUNET_malloc(msize); | ||
574 | put_msg->header.type = htons(GNUNET_MESSAGE_TYPE_DHT_PUT); | ||
575 | put_msg->header.size = htons(msize); | ||
576 | put_msg->type = htonl(type); | ||
577 | memcpy(&put_msg->key, key, sizeof(GNUNET_HashCode)); | ||
578 | memcpy(&put_msg[1], data, size); | ||
579 | |||
580 | add_pending(handle, &put_msg->header); | ||
581 | |||
582 | return GNUNET_YES; | ||
583 | } | ||
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c new file mode 100644 index 000000000..3dcb75353 --- /dev/null +++ b/src/dht/gnunet-service-dht.c | |||
@@ -0,0 +1,385 @@ | |||
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 2, 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/gnunet_dht_service.c | ||
23 | * @brief main DHT service shell, building block for DHT implementations | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_client_lib.h" | ||
30 | #include "gnunet_getopt_lib.h" | ||
31 | #include "gnunet_os_lib.h" | ||
32 | #include "gnunet_protocols.h" | ||
33 | #include "gnunet_service_lib.h" | ||
34 | #include "gnunet_core_service.h" | ||
35 | #include "gnunet_signal_lib.h" | ||
36 | #include "gnunet_util_lib.h" | ||
37 | #include "gnunet_datastore_service.h" | ||
38 | #include "dht.h" | ||
39 | |||
40 | /** | ||
41 | * Handle to the datastore service (for inserting/retrieving data) | ||
42 | */ | ||
43 | static struct GNUNET_DATASTORE_Handle *datastore; | ||
44 | |||
45 | /** | ||
46 | * The main scheduler to use for the DHT service | ||
47 | */ | ||
48 | static struct GNUNET_SCHEDULER_Handle *sched; | ||
49 | |||
50 | /** | ||
51 | * The configuration the DHT service is running with | ||
52 | */ | ||
53 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
54 | |||
55 | /** | ||
56 | * Timeout for transmissions to clients | ||
57 | */ | ||
58 | static struct GNUNET_TIME_Relative client_transmit_timeout; | ||
59 | |||
60 | /** | ||
61 | * Handle to the core service | ||
62 | */ | ||
63 | static struct GNUNET_CORE_Handle *coreAPI; | ||
64 | |||
65 | /** | ||
66 | * The identity of our peer. | ||
67 | */ | ||
68 | static struct GNUNET_PeerIdentity my_identity; | ||
69 | |||
70 | /** | ||
71 | * Task to run when we shut down, cleaning up all our trash | ||
72 | */ | ||
73 | static GNUNET_SCHEDULER_TaskIdentifier cleanup_task; | ||
74 | |||
75 | struct ClientList | ||
76 | { | ||
77 | /** | ||
78 | * This is a linked list | ||
79 | */ | ||
80 | struct ClientList *next; | ||
81 | |||
82 | /** | ||
83 | * The client in question | ||
84 | */ | ||
85 | struct GNUNET_SERVER_Client *client; | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * Server handler for initiating local dht get requests | ||
90 | */ | ||
91 | static void handle_dht_get (void *cls, struct GNUNET_SERVER_Client * client, | ||
92 | const struct GNUNET_MessageHeader *message); | ||
93 | |||
94 | /** | ||
95 | * Server handler for stopping local dht get requests | ||
96 | */ | ||
97 | static void handle_dht_get_stop (void *cls, struct GNUNET_SERVER_Client * client, | ||
98 | const struct GNUNET_MessageHeader *message); | ||
99 | |||
100 | /** | ||
101 | * Server handler for initiating local dht find peer requests | ||
102 | */ | ||
103 | static void handle_dht_find_peer (void *cls, struct GNUNET_SERVER_Client * | ||
104 | client, const struct GNUNET_MessageHeader * | ||
105 | message); | ||
106 | |||
107 | /** | ||
108 | * Server handler for stopping local dht find peer requests | ||
109 | */ | ||
110 | static void handle_dht_find_peer_stop (void *cls, struct GNUNET_SERVER_Client * | ||
111 | client, const struct GNUNET_MessageHeader * | ||
112 | message); | ||
113 | |||
114 | /** | ||
115 | * Server handler for initiating local dht put requests | ||
116 | */ | ||
117 | static void handle_dht_put (void *cls, struct GNUNET_SERVER_Client * client, | ||
118 | const struct GNUNET_MessageHeader *message); | ||
119 | |||
120 | |||
121 | static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { | ||
122 | {&handle_dht_get, NULL, GNUNET_MESSAGE_TYPE_DHT_GET, 0}, | ||
123 | {&handle_dht_get_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_GET_STOP, 0}, | ||
124 | {&handle_dht_put, NULL, GNUNET_MESSAGE_TYPE_DHT_PUT, 0}, | ||
125 | {&handle_dht_find_peer, NULL, GNUNET_MESSAGE_TYPE_DHT_FIND_PEER, 0}, | ||
126 | {&handle_dht_find_peer_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_FIND_PEER_STOP, 0}, | ||
127 | {NULL, NULL, 0, 0} | ||
128 | }; | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Core handler for p2p dht get requests. | ||
133 | */ | ||
134 | static int handle_dht_p2p_get (void *cls, | ||
135 | const struct GNUNET_PeerIdentity * peer, | ||
136 | const struct GNUNET_MessageHeader * message, | ||
137 | struct GNUNET_TIME_Relative latency, | ||
138 | uint32_t distance); | ||
139 | |||
140 | /** | ||
141 | * Core handler for p2p dht put requests. | ||
142 | */ | ||
143 | static int handle_dht_p2p_put (void *cls, | ||
144 | const struct GNUNET_PeerIdentity * peer, | ||
145 | const struct GNUNET_MessageHeader * message, | ||
146 | struct GNUNET_TIME_Relative latency, | ||
147 | uint32_t distance); | ||
148 | |||
149 | /** | ||
150 | * Core handler for p2p dht find peer requests. | ||
151 | */ | ||
152 | static int handle_dht_p2p_find_peer (void *cls, | ||
153 | const struct GNUNET_PeerIdentity * peer, | ||
154 | const struct GNUNET_MessageHeader * message, | ||
155 | struct GNUNET_TIME_Relative latency, | ||
156 | uint32_t distance); | ||
157 | |||
158 | static struct GNUNET_CORE_MessageHandler core_handlers[] = { | ||
159 | {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_GET, 0}, | ||
160 | {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_PUT, 0}, | ||
161 | {&handle_dht_p2p_find_peer, GNUNET_MESSAGE_TYPE_DHT_PUT, 0}, | ||
162 | {NULL, 0, 0} | ||
163 | }; | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Server handler for initiating local dht get requests | ||
168 | */ | ||
169 | static void handle_dht_get (void *cls, struct GNUNET_SERVER_Client * client, | ||
170 | const struct GNUNET_MessageHeader *message) | ||
171 | { | ||
172 | #if DEBUG_DHT | ||
173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
174 | "`%s': Received `%s' request from client\n", "DHT", "GET"); | ||
175 | #endif | ||
176 | |||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Server handler for stopping local dht get requests | ||
181 | */ | ||
182 | static void handle_dht_get_stop (void *cls, struct GNUNET_SERVER_Client * client, | ||
183 | const struct GNUNET_MessageHeader *message) | ||
184 | { | ||
185 | #if DEBUG_DHT | ||
186 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
187 | "`%s': Received `%s' request from client\n", "DHT", "GET STOP"); | ||
188 | #endif | ||
189 | |||
190 | } | ||
191 | |||
192 | /** | ||
193 | * Server handler for initiating local dht find peer requests | ||
194 | */ | ||
195 | static void handle_dht_find_peer (void *cls, struct GNUNET_SERVER_Client * | ||
196 | client, const struct GNUNET_MessageHeader * | ||
197 | message) | ||
198 | { | ||
199 | #if DEBUG_DHT | ||
200 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
201 | "`%s': Received `%s' request from client\n", "DHT", "FIND PEER"); | ||
202 | #endif | ||
203 | |||
204 | } | ||
205 | |||
206 | /** | ||
207 | * Server handler for stopping local dht find peer requests | ||
208 | */ | ||
209 | static void handle_dht_find_peer_stop (void *cls, struct GNUNET_SERVER_Client * | ||
210 | client, const struct GNUNET_MessageHeader * | ||
211 | message) | ||
212 | { | ||
213 | #if DEBUG_DHT | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
215 | "`%s': Received `%s' request from client\n", "DHT", "FIND PEER STOP"); | ||
216 | #endif | ||
217 | |||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Server handler for initiating local dht put requests | ||
222 | */ | ||
223 | static void handle_dht_put (void *cls, struct GNUNET_SERVER_Client * client, | ||
224 | const struct GNUNET_MessageHeader *message) | ||
225 | { | ||
226 | #if DEBUG_DHT | ||
227 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
228 | "`%s': Received `%s' request from client\n", "DHT", "PUT"); | ||
229 | #endif | ||
230 | |||
231 | } | ||
232 | |||
233 | /** | ||
234 | * Core handler for p2p dht get requests. | ||
235 | */ | ||
236 | static int handle_dht_p2p_get (void *cls, | ||
237 | const struct GNUNET_PeerIdentity * peer, | ||
238 | const struct GNUNET_MessageHeader * message, | ||
239 | struct GNUNET_TIME_Relative latency, | ||
240 | uint32_t distance) | ||
241 | { | ||
242 | #if DEBUG_DHT | ||
243 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
244 | "`%s': Received `%s' request from another peer\n", "DHT", "GET"); | ||
245 | #endif | ||
246 | |||
247 | return GNUNET_YES; | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * Core handler for p2p dht put requests. | ||
252 | */ | ||
253 | static int handle_dht_p2p_put (void *cls, | ||
254 | const struct GNUNET_PeerIdentity * peer, | ||
255 | const struct GNUNET_MessageHeader * message, | ||
256 | struct GNUNET_TIME_Relative latency, | ||
257 | uint32_t distance) | ||
258 | { | ||
259 | #if DEBUG_DHT | ||
260 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
261 | "`%s': Received `%s' request from another peer\n", "DHT", "PUT"); | ||
262 | #endif | ||
263 | |||
264 | return GNUNET_YES; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * Core handler for p2p dht find peer requests. | ||
269 | */ | ||
270 | static int handle_dht_p2p_find_peer (void *cls, | ||
271 | const struct GNUNET_PeerIdentity * peer, | ||
272 | const struct GNUNET_MessageHeader * message, | ||
273 | struct GNUNET_TIME_Relative latency, | ||
274 | uint32_t distance) | ||
275 | { | ||
276 | #if DEBUG_DHT | ||
277 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
278 | "`%s': Received `%s' request from another peer\n", "DHT", "FIND PEER"); | ||
279 | #endif | ||
280 | |||
281 | return GNUNET_YES; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * Task run during shutdown. | ||
286 | * | ||
287 | * @param cls unused | ||
288 | * @param tc unused | ||
289 | */ | ||
290 | static void | ||
291 | shutdown_task (void *cls, | ||
292 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
293 | { | ||
294 | GNUNET_CORE_disconnect (coreAPI); | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * To be called on core init/fail. | ||
299 | */ | ||
300 | void core_init (void *cls, | ||
301 | struct GNUNET_CORE_Handle * server, | ||
302 | const struct GNUNET_PeerIdentity *identity, | ||
303 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey) | ||
304 | { | ||
305 | |||
306 | if (server == NULL) | ||
307 | { | ||
308 | GNUNET_SCHEDULER_cancel(sched, cleanup_task); | ||
309 | GNUNET_SCHEDULER_add_now(sched, &shutdown_task, NULL); | ||
310 | return; | ||
311 | } | ||
312 | #if DEBUG_DHT | ||
313 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
314 | "%s: Core connection initialized, I am peer: %s\n", "dht", GNUNET_i2s(identity)); | ||
315 | #endif | ||
316 | memcpy(&my_identity, identity, sizeof(struct GNUNET_PeerIdentity)); | ||
317 | coreAPI = server; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * Process dht requests. | ||
322 | * | ||
323 | * @param cls closure | ||
324 | * @param scheduler scheduler to use | ||
325 | * @param server the initialized server | ||
326 | * @param c configuration to use | ||
327 | */ | ||
328 | static void | ||
329 | run (void *cls, | ||
330 | struct GNUNET_SCHEDULER_Handle *scheduler, | ||
331 | struct GNUNET_SERVER_Handle *server, | ||
332 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
333 | { | ||
334 | sched = scheduler; | ||
335 | cfg = c; | ||
336 | |||
337 | datastore = GNUNET_DATASTORE_connect(c, scheduler); | ||
338 | |||
339 | client_transmit_timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); | ||
340 | GNUNET_SERVER_add_handlers (server, plugin_handlers); | ||
341 | |||
342 | coreAPI = | ||
343 | GNUNET_CORE_connect (sched, | ||
344 | cfg, | ||
345 | client_transmit_timeout, | ||
346 | NULL, /* FIXME: anything we want to pass around? */ | ||
347 | &core_init, | ||
348 | NULL, /* Don't care about pre-connects */ | ||
349 | NULL, /* Don't care about connects */ | ||
350 | NULL, /* Don't care about disconnects */ | ||
351 | NULL, | ||
352 | GNUNET_NO, | ||
353 | NULL, | ||
354 | GNUNET_NO, | ||
355 | core_handlers); | ||
356 | |||
357 | if (coreAPI == NULL) | ||
358 | return; | ||
359 | /* load (server); Huh? */ | ||
360 | |||
361 | /* Scheduled the task to clean up when shutdown is called */ | ||
362 | cleanup_task = GNUNET_SCHEDULER_add_delayed (sched, | ||
363 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
364 | &shutdown_task, | ||
365 | NULL); | ||
366 | } | ||
367 | |||
368 | |||
369 | /** | ||
370 | * The main function for the dv service. | ||
371 | * | ||
372 | * @param argc number of arguments from the command line | ||
373 | * @param argv command line arguments | ||
374 | * @return 0 ok, 1 on error | ||
375 | */ | ||
376 | int | ||
377 | main (int argc, char *const *argv) | ||
378 | { | ||
379 | return (GNUNET_OK == | ||
380 | GNUNET_SERVICE_run (argc, | ||
381 | argv, | ||
382 | "dht", | ||
383 | GNUNET_SERVICE_OPTION_NONE, | ||
384 | &run, NULL)) ? 0 : 1; | ||
385 | } | ||
diff --git a/src/dht/test_dht_api.c b/src/dht/test_dht_api.c new file mode 100644 index 000000000..9c9fcb4d0 --- /dev/null +++ b/src/dht/test_dht_api.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 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 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file dht/test_dht_api.c | ||
22 | * @brief base test case for dht api | ||
23 | * | ||
24 | * This test case tests DHT api to DUMMY DHT service communication. | ||
25 | * | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_common.h" | ||
29 | #include "gnunet_hello_lib.h" | ||
30 | #include "gnunet_getopt_lib.h" | ||
31 | #include "gnunet_os_lib.h" | ||
32 | #include "gnunet_program_lib.h" | ||
33 | #include "gnunet_scheduler_lib.h" | ||
34 | #include "gnunet_dht_service.h" | ||
35 | |||
36 | #define VERBOSE GNUNET_YES | ||
37 | |||
38 | #define VERBOSE_ARM GNUNET_YES | ||
39 | |||
40 | #define START_ARM GNUNET_YES | ||
41 | |||
42 | /** | ||
43 | * How long until we give up on transmitting the message? | ||
44 | */ | ||
45 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 50) | ||
46 | |||
47 | #define MTYPE 12345 | ||
48 | |||
49 | struct PeerContext | ||
50 | { | ||
51 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
52 | struct GNUNET_DHT_Handle *dht_handle; | ||
53 | struct GNUNET_PeerIdentity id; | ||
54 | #if START_ARM | ||
55 | pid_t arm_pid; | ||
56 | #endif | ||
57 | }; | ||
58 | |||
59 | static struct PeerContext p1; | ||
60 | |||
61 | static struct GNUNET_SCHEDULER_Handle *sched; | ||
62 | |||
63 | static int ok; | ||
64 | |||
65 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
66 | |||
67 | #if VERBOSE | ||
68 | #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) | ||
69 | #else | ||
70 | #define OKPP do { ok++; } while (0) | ||
71 | #endif | ||
72 | |||
73 | |||
74 | static void | ||
75 | end () | ||
76 | { | ||
77 | /* do work here */ | ||
78 | GNUNET_SCHEDULER_cancel (sched, die_task); | ||
79 | |||
80 | GNUNET_DHT_disconnect (p1.dht_handle); | ||
81 | |||
82 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
83 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DHT disconnected, returning success!\n"); | ||
84 | ok = 0; | ||
85 | } | ||
86 | |||
87 | static void | ||
88 | stop_arm (struct PeerContext *p) | ||
89 | { | ||
90 | #if START_ARM | ||
91 | if (0 != PLIBC_KILL (p->arm_pid, SIGTERM)) | ||
92 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
93 | GNUNET_OS_process_wait (p->arm_pid); | ||
94 | #endif | ||
95 | GNUNET_CONFIGURATION_destroy (p->cfg); | ||
96 | } | ||
97 | |||
98 | |||
99 | static void | ||
100 | end_badly () | ||
101 | { | ||
102 | /* do work here */ | ||
103 | #if VERBOSE | ||
104 | fprintf(stderr, "Ending on an unhappy note.\n"); | ||
105 | #endif | ||
106 | |||
107 | GNUNET_DHT_disconnect (p1.dht_handle); | ||
108 | |||
109 | ok = 1; | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Signature of the main function of a task. | ||
115 | * | ||
116 | * @param cls closure | ||
117 | * @param tc context information (why was this task triggered now) | ||
118 | */ | ||
119 | void test_get (void *cls, | ||
120 | const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
121 | { | ||
122 | struct PeerContext *peer = cls; | ||
123 | GNUNET_HashCode hash; | ||
124 | memset(&hash, 42, sizeof(GNUNET_HashCode)); | ||
125 | |||
126 | peer->dht_handle = GNUNET_DHT_connect (sched, peer->cfg); | ||
127 | GNUNET_assert (peer->dht_handle != NULL); | ||
128 | |||
129 | GNUNET_DHT_get_start(peer->dht_handle, 42, &hash, NULL, NULL); | ||
130 | |||
131 | GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10), &end, &p1); | ||
132 | } | ||
133 | |||
134 | static void | ||
135 | setup_peer (struct PeerContext *p, const char *cfgname) | ||
136 | { | ||
137 | p->cfg = GNUNET_CONFIGURATION_create (); | ||
138 | #if START_ARM | ||
139 | p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm", | ||
140 | "gnunet-service-arm", | ||
141 | #if VERBOSE_ARM | ||
142 | "-L", "DEBUG", | ||
143 | #endif | ||
144 | "-c", cfgname, NULL); | ||
145 | #endif | ||
146 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); | ||
147 | |||
148 | } | ||
149 | |||
150 | static void | ||
151 | run (void *cls, | ||
152 | struct GNUNET_SCHEDULER_Handle *s, | ||
153 | char *const *args, | ||
154 | const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
155 | { | ||
156 | GNUNET_assert (ok == 1); | ||
157 | OKPP; | ||
158 | sched = s; | ||
159 | |||
160 | die_task = GNUNET_SCHEDULER_add_delayed (sched, | ||
161 | GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 1), &end_badly, NULL); | ||
162 | |||
163 | setup_peer (&p1, "test_dht_api_peer1.conf"); | ||
164 | |||
165 | GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2), &test_get, &p1); | ||
166 | } | ||
167 | |||
168 | static int | ||
169 | check () | ||
170 | { | ||
171 | |||
172 | char *const argv[] = { "test-dht-api", | ||
173 | "-c", | ||
174 | "test_dht_api_data.conf", | ||
175 | #if VERBOSE | ||
176 | "-L", "DEBUG", | ||
177 | #endif | ||
178 | NULL | ||
179 | }; | ||
180 | |||
181 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
182 | GNUNET_GETOPT_OPTION_END | ||
183 | }; | ||
184 | |||
185 | ok = 1; | ||
186 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | ||
187 | argv, "test-dht-api", "nohelp", | ||
188 | options, &run, &ok); | ||
189 | stop_arm (&p1); | ||
190 | return ok; | ||
191 | } | ||
192 | |||
193 | |||
194 | int | ||
195 | main (int argc, char *argv[]) | ||
196 | { | ||
197 | int ret; | ||
198 | #ifdef MINGW | ||
199 | return GNUNET_SYSERR; | ||
200 | #endif | ||
201 | |||
202 | GNUNET_log_setup ("test-dht-api", | ||
203 | #if VERBOSE | ||
204 | "DEBUG", | ||
205 | #else | ||
206 | "WARNING", | ||
207 | #endif | ||
208 | NULL); | ||
209 | ret = check (); | ||
210 | |||
211 | //GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-dht-peer-1"); | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | /* end of test_dht_api.c */ | ||
diff --git a/src/dht/test_dht_api_data.conf b/src/dht/test_dht_api_data.conf new file mode 100644 index 000000000..8b3c17ea4 --- /dev/null +++ b/src/dht/test_dht_api_data.conf | |||
@@ -0,0 +1,143 @@ | |||
1 | [PATHS] | ||
2 | SERVICEHOME = /tmp/test-dht-api/ | ||
3 | DEFAULTCONFIG = test_dht_api_data.conf | ||
4 | |||
5 | [fs] | ||
6 | ALLOW_SHUTDOWN = YES | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | ACCEPT_FROM = 127.0.0.1; | ||
9 | BINARY = gnunet-service-fs | ||
10 | CONFIG = $DEFAULTCONFIG | ||
11 | HOME = $SERVICEHOME | ||
12 | HOSTNAME = localhost | ||
13 | PORT = 2094 | ||
14 | INDEXDB = $SERVICEHOME/idxinfo.lst | ||
15 | |||
16 | [datastore-sqlite] | ||
17 | FILENAME = $SERVICEHOME/datastore/sqlite.db | ||
18 | |||
19 | [datastore] | ||
20 | DATABASE = sqlite | ||
21 | BLOOMFILTER = $SERVICEHOME/fs/bloomfilter | ||
22 | QUOTA = 100000000 | ||
23 | ALLOW_SHUTDOWN = YES | ||
24 | ACCEPT_FROM6 = ::1; | ||
25 | ACCEPT_FROM = 127.0.0.1; | ||
26 | BINARY = gnunet-service-datastore | ||
27 | CONFIG = $DEFAULTCONFIG | ||
28 | HOME = $SERVICEHOME | ||
29 | HOSTNAME = localhost | ||
30 | PORT = 2093 | ||
31 | |||
32 | [hostlist] | ||
33 | HTTP-PROXY = | ||
34 | SERVERS = http://gnunet.org:8080/ | ||
35 | OPTIONS = -b | ||
36 | BINARY = gnunet-daemon-hostlist | ||
37 | CONFIG = $DEFAULTCONFIG | ||
38 | HOME = $SERVICEHOME | ||
39 | HOSTNAME = localhost | ||
40 | HTTPPORT = 8080 | ||
41 | |||
42 | [topology] | ||
43 | BINARY = gnunet-daemon-topology | ||
44 | CONFIG = $DEFAULTCONFIG | ||
45 | FRIENDS = $SERVICEHOME/friends | ||
46 | TARGET-CONNECTION-COUNT = 16 | ||
47 | AUTOCONNECT = YES | ||
48 | FRIENDS-ONLY = NO | ||
49 | MINIMUM-FRIENDS = 0 | ||
50 | |||
51 | [core] | ||
52 | TOTAL_QUOTA_OUT = 3932160 | ||
53 | TOTAL_QUOTA_IN = 3932160 | ||
54 | ALLOW_SHUTDOWN = YES | ||
55 | ACCEPT_FROM6 = ::1; | ||
56 | ACCEPT_FROM = 127.0.0.1; | ||
57 | BINARY = gnunet-service-core | ||
58 | CONFIG = $DEFAULTCONFIG | ||
59 | HOME = $SERVICEHOME | ||
60 | HOSTNAME = localhost | ||
61 | PORT = 2092 | ||
62 | |||
63 | [dht] | ||
64 | DEBUG = YES | ||
65 | ALLOW_SHUTDOWN = YES | ||
66 | ACCEPT_FROM6 = ::1; | ||
67 | ACCEPT_FROM = 127.0.0.1; | ||
68 | BINARY = gnunet-service-dht | ||
69 | #BINARY = /root/documents/research/gnunet/gnunet-ng/src/dv/.libs/gnunet-service-dv | ||
70 | #PREFIX = xterm -T dvservice -e gdb --args | ||
71 | CONFIG = $DEFAULTCONFIG | ||
72 | HOME = $SERVICEHOME | ||
73 | HOSTNAME = localhost | ||
74 | PORT = 12370 | ||
75 | |||
76 | [transport] | ||
77 | plugins = tcp | ||
78 | DEBUG = NO | ||
79 | PREFIX = | ||
80 | ALLOW_SHUTDOWN = YES | ||
81 | ACCEPT_FROM6 = ::1; | ||
82 | ACCEPT_FROM = 127.0.0.1; | ||
83 | NEIGHBOUR_LIMIT = 50 | ||
84 | BINARY = gnunet-service-transport | ||
85 | CONFIG = $DEFAULTCONFIG | ||
86 | HOME = $SERVICEHOME | ||
87 | HOSTNAME = localhost | ||
88 | PORT = 2091 | ||
89 | |||
90 | [peerinfo] | ||
91 | TRUST = $SERVICEHOME/data/credit/ | ||
92 | HOSTS = $SERVICEHOME/data/hosts/ | ||
93 | ALLOW_SHUTDOWN = YES | ||
94 | ACCEPT_FROM6 = ::1; | ||
95 | ACCEPT_FROM = 127.0.0.1; | ||
96 | BINARY = gnunet-service-peerinfo | ||
97 | CONFIG = $DEFAULTCONFIG | ||
98 | HOME = $SERVICEHOME | ||
99 | HOSTNAME = localhost | ||
100 | PORT = 2090 | ||
101 | |||
102 | [resolver] | ||
103 | ALLOW_SHUTDOWN = YES | ||
104 | ACCEPT_FROM6 = ::1; | ||
105 | ACCEPT_FROM = 127.0.0.1; | ||
106 | BINARY = gnunet-service-resolver | ||
107 | CONFIG = $DEFAULTCONFIG | ||
108 | HOME = $SERVICEHOME | ||
109 | HOSTNAME = localhost | ||
110 | PORT = 2089 | ||
111 | |||
112 | [statistics] | ||
113 | ALLOW_SHUTDOWN = YES | ||
114 | ACCEPT_FROM6 = ::1; | ||
115 | ACCEPT_FROM = 127.0.0.1; | ||
116 | BINARY = gnunet-service-statistics | ||
117 | CONFIG = $DEFAULTCONFIG | ||
118 | HOME = $SERVICEHOME | ||
119 | HOSTNAME = localhost | ||
120 | PORT = 2088 | ||
121 | |||
122 | [arm] | ||
123 | DEFAULTSERVICES = resolver transport core | ||
124 | ALLOW_SHUTDOWN = YES | ||
125 | ACCEPT_FROM6 = ::1; | ||
126 | ACCEPT_FROM = 127.0.0.1; | ||
127 | BINARY = gnunet-service-arm | ||
128 | CONFIG = $DEFAULTCONFIG | ||
129 | HOME = $SERVICEHOME | ||
130 | HOSTNAME = localhost | ||
131 | PORT = 2087 | ||
132 | |||
133 | [transport-tcp] | ||
134 | ALLOW_SHUTDOWN = NO | ||
135 | TIMEOUT = 300000 | ||
136 | PORT = 2094 | ||
137 | |||
138 | [TESTING] | ||
139 | WEAKRANDOM = NO | ||
140 | |||
141 | [gnunetd] | ||
142 | HOSTKEY = $SERVICEHOME/.hostkey | ||
143 | |||
diff --git a/src/dht/test_dht_api_peer1.conf b/src/dht/test_dht_api_peer1.conf new file mode 100644 index 000000000..5eb4079f4 --- /dev/null +++ b/src/dht/test_dht_api_peer1.conf | |||
@@ -0,0 +1,144 @@ | |||
1 | [fs] | ||
2 | ALLOW_SHUTDOWN = YES | ||
3 | ACCEPT_FROM6 = ::1; | ||
4 | ACCEPT_FROM = 127.0.0.1; | ||
5 | BINARY = gnunet-service-fs | ||
6 | CONFIG = $DEFAULTCONFIG | ||
7 | HOME = $SERVICEHOME | ||
8 | HOSTNAME = localhost | ||
9 | PORT = 2094 | ||
10 | INDEXDB = $SERVICEHOME/idxinfo.lst | ||
11 | |||
12 | [datastore-sqlite] | ||
13 | FILENAME = $SERVICEHOME/datastore/sqlite.db | ||
14 | |||
15 | [datastore] | ||
16 | DATABASE = sqlite | ||
17 | BLOOMFILTER = $SERVICEHOME/fs/bloomfilter | ||
18 | QUOTA = 100000000 | ||
19 | ALLOW_SHUTDOWN = YES | ||
20 | ACCEPT_FROM6 = ::1; | ||
21 | ACCEPT_FROM = 127.0.0.1; | ||
22 | BINARY = gnunet-service-datastore | ||
23 | CONFIG = $DEFAULTCONFIG | ||
24 | HOME = $SERVICEHOME | ||
25 | HOSTNAME = localhost | ||
26 | PORT = 2093 | ||
27 | |||
28 | [dht] | ||
29 | DEBUG = YES | ||
30 | ALLOW_SHUTDOWN = YES | ||
31 | ACCEPT_FROM6 = ::1; | ||
32 | ACCEPT_FROM = 127.0.0.1; | ||
33 | BINARY = gnunet-service-dht | ||
34 | #BINARY = /root/documents/research/gnunet/gnunet-ng/src/dht/.libs/gnunet-service-dht | ||
35 | #PREFIX = xterm -T dvservice -e gdb --args | ||
36 | CONFIG = $DEFAULTCONFIG | ||
37 | HOME = $SERVICEHOME | ||
38 | HOSTNAME = localhost | ||
39 | PORT = 2100 | ||
40 | |||
41 | [hostlist] | ||
42 | HTTP-PROXY = | ||
43 | SERVERS = http://gnunet.org:8080/ | ||
44 | OPTIONS = -b | ||
45 | BINARY = gnunet-daemon-hostlist | ||
46 | CONFIG = $DEFAULTCONFIG | ||
47 | HOME = $SERVICEHOME | ||
48 | HOSTNAME = localhost | ||
49 | HTTPPORT = 8080 | ||
50 | |||
51 | [topology] | ||
52 | BINARY = gnunet-daemon-topology | ||
53 | CONFIG = $DEFAULTCONFIG | ||
54 | FRIENDS = $SERVICEHOME/friends | ||
55 | TARGET-CONNECTION-COUNT = 16 | ||
56 | AUTOCONNECT = YES | ||
57 | FRIENDS-ONLY = NO | ||
58 | MINIMUM-FRIENDS = 0 | ||
59 | |||
60 | [transport] | ||
61 | PLUGINS = tcp | ||
62 | DEBUG = NO | ||
63 | #PREFIX = xterm -T transport2 -e gdb --command=cmd --args | ||
64 | #PREFIX = valgrind --leak-check=full | ||
65 | ALLOW_SHUTDOWN = YES | ||
66 | ACCEPT_FROM6 = ::1; | ||
67 | ACCEPT_FROM = 127.0.0.1; | ||
68 | NEIGHBOUR_LIMIT = 50 | ||
69 | BINARY = gnunet-service-transport | ||
70 | CONFIG = $DEFAULTCONFIG | ||
71 | HOME = $SERVICEHOME | ||
72 | HOSTNAME = localhost | ||
73 | PORT = 12365 | ||
74 | |||
75 | [peerinfo] | ||
76 | TRUST = $SERVICEHOME/data/credit/ | ||
77 | HOSTS = $SERVICEHOME/data/hosts/ | ||
78 | ALLOW_SHUTDOWN = YES | ||
79 | ACCEPT_FROM6 = ::1; | ||
80 | ACCEPT_FROM = 127.0.0.1; | ||
81 | BINARY = gnunet-service-peerinfo | ||
82 | CONFIG = $DEFAULTCONFIG | ||
83 | HOME = $SERVICEHOME | ||
84 | HOSTNAME = localhost | ||
85 | PORT = 12369 | ||
86 | |||
87 | [resolver] | ||
88 | ALLOW_SHUTDOWN = YES | ||
89 | ACCEPT_FROM6 = ::1; | ||
90 | ACCEPT_FROM = 127.0.0.1; | ||
91 | BINARY = gnunet-service-resolver | ||
92 | CONFIG = $DEFAULTCONFIG | ||
93 | HOME = $SERVICEHOME | ||
94 | HOSTNAME = localhost | ||
95 | PORT = 12364 | ||
96 | |||
97 | [statistics] | ||
98 | ALLOW_SHUTDOWN = YES | ||
99 | ACCEPT_FROM6 = ::1; | ||
100 | ACCEPT_FROM = 127.0.0.1; | ||
101 | BINARY = gnunet-service-statistics | ||
102 | CONFIG = $DEFAULTCONFIG | ||
103 | HOME = $SERVICEHOME | ||
104 | HOSTNAME = localhost | ||
105 | PORT = 12367 | ||
106 | |||
107 | [core] | ||
108 | TOTAL_QUOTA_OUT = 3932160 | ||
109 | TOTAL_QUOTA_IN = 3932160 | ||
110 | ALLOW_SHUTDOWN = YES | ||
111 | ACCEPT_FROM6 = ::1; | ||
112 | ACCEPT_FROM = 127.0.0.1; | ||
113 | BINARY = gnunet-service-core | ||
114 | CONFIG = $DEFAULTCONFIG | ||
115 | HOME = $SERVICEHOME | ||
116 | HOSTNAME = localhost | ||
117 | PORT = 12092 | ||
118 | |||
119 | [arm] | ||
120 | DEFAULTSERVICES = core dht | ||
121 | ALLOW_SHUTDOWN = YES | ||
122 | ACCEPT_FROM6 = ::1; | ||
123 | ACCEPT_FROM = 127.0.0.1; | ||
124 | BINARY = gnunet-service-arm | ||
125 | CONFIG = $DEFAULTCONFIG | ||
126 | HOME = $SERVICEHOME | ||
127 | HOSTNAME = localhost | ||
128 | PORT = 12366 | ||
129 | |||
130 | [transport-tcp] | ||
131 | ALLOW_SHUTDOWN = NO | ||
132 | TIMEOUT = 300000 | ||
133 | PORT = 12368 | ||
134 | |||
135 | [TESTING] | ||
136 | WEAKRANDOM = YES | ||
137 | |||
138 | [gnunetd] | ||
139 | HOSTKEY = $SERVICEHOME/.hostkey | ||
140 | |||
141 | [PATHS] | ||
142 | DEFAULTCONFIG = test_dht_api_peer1.conf | ||
143 | SERVICEHOME = /tmp/test-gnunetd-dht-peer-1/ | ||
144 | |||