2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
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.
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.
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.
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
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"
41 * Handle to the datastore service (for inserting/retrieving data)
43 static struct GNUNET_DATASTORE_Handle *datastore;
46 * The main scheduler to use for the DHT service
48 static struct GNUNET_SCHEDULER_Handle *sched;
51 * The configuration the DHT service is running with
53 static const struct GNUNET_CONFIGURATION_Handle *cfg;
56 * Timeout for transmissions to clients
58 static struct GNUNET_TIME_Relative client_transmit_timeout;
61 * Handle to the core service
63 static struct GNUNET_CORE_Handle *coreAPI;
66 * The identity of our peer.
68 static struct GNUNET_PeerIdentity my_identity;
71 * Task to run when we shut down, cleaning up all our trash
73 static GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
78 * This is a linked list
80 struct ClientList *next;
83 * The client in question
85 struct GNUNET_SERVER_Client *client;
89 * Server handler for initiating local dht get requests
91 static void handle_dht_get (void *cls, struct GNUNET_SERVER_Client * client,
92 const struct GNUNET_MessageHeader *message);
95 * Server handler for stopping local dht get requests
97 static void handle_dht_get_stop (void *cls, struct GNUNET_SERVER_Client * client,
98 const struct GNUNET_MessageHeader *message);
101 * Server handler for initiating local dht find peer requests
103 static void handle_dht_find_peer (void *cls, struct GNUNET_SERVER_Client *
104 client, const struct GNUNET_MessageHeader *
108 * Server handler for stopping local dht find peer requests
110 static void handle_dht_find_peer_stop (void *cls, struct GNUNET_SERVER_Client *
111 client, const struct GNUNET_MessageHeader *
115 * Server handler for initiating local dht put requests
117 static void handle_dht_put (void *cls, struct GNUNET_SERVER_Client * client,
118 const struct GNUNET_MessageHeader *message);
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},
132 * Core handler for p2p dht get requests.
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,
141 * Core handler for p2p dht put requests.
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,
150 * Core handler for p2p dht find peer requests.
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,
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},
167 * Server handler for initiating local dht get requests
169 static void handle_dht_get (void *cls, struct GNUNET_SERVER_Client * client,
170 const struct GNUNET_MessageHeader *message)
172 struct GNUNET_DHT_GetMessage *get_msg = (struct GNUNET_DHT_GetMessage *)message;
173 GNUNET_HashCode get_key;
176 GNUNET_assert(ntohs(get_msg->header.size) >= sizeof(struct GNUNET_DHT_GetMessage));
177 memcpy(&get_key, &get_msg->key, sizeof(GNUNET_HashCode));
178 get_type = ntohs(get_msg->type);
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182 "`%s': Received `%s' request from client, message type %d, key %s\n", "DHT", "GET", get_type, GNUNET_h2s(&get_key));
185 /* FIXME: Implement get stop functionality here */
190 * Server handler for stopping local dht get requests
192 static void handle_dht_get_stop (void *cls, struct GNUNET_SERVER_Client * client,
193 const struct GNUNET_MessageHeader *message)
195 struct GNUNET_DHT_GetMessage *get_msg = (struct GNUNET_DHT_GetMessage *)message; /* Get message and get stop message are the same except for type */
196 GNUNET_HashCode get_key;
199 GNUNET_assert(ntohs(get_msg->header.size) >= sizeof(struct GNUNET_DHT_GetMessage));
201 memcpy(&get_key, &get_msg->key, sizeof(GNUNET_HashCode));
202 get_type = ntohs(get_msg->type);
205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
206 "`%s': Received `%s' request from client, message type %d, key %s\n", "DHT", "GET STOP", get_type, GNUNET_h2s(&get_key));
209 /* FIXME: Implement get stop functionality here */
214 * Server handler for initiating local dht find peer requests
216 static void handle_dht_find_peer (void *cls, struct GNUNET_SERVER_Client *
217 client, const struct GNUNET_MessageHeader *
220 struct GNUNET_DHT_FindPeerMessage *find_msg = (struct GNUNET_DHT_FindPeerMessage *)message;
221 struct GNUNET_PeerIdentity peer;
223 GNUNET_assert(ntohs(find_msg->header.size) == sizeof(struct GNUNET_DHT_FindPeerMessage));
224 memcpy(&peer, &find_msg->peer, sizeof(struct GNUNET_PeerIdentity));
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
228 "`%s': Received `%s' request from client, peer id %s\n", "DHT", "FIND PEER", GNUNET_i2s(&peer));
231 /* FIXME: Implement find peer functionality here */
235 * Server handler for stopping local dht find peer requests
237 static void handle_dht_find_peer_stop (void *cls, struct GNUNET_SERVER_Client *
238 client, const struct GNUNET_MessageHeader *
241 struct GNUNET_DHT_FindPeerMessage *find_msg = (struct GNUNET_DHT_FindPeerMessage *)message; /* Find peer stop message is identical to find peer message */
242 struct GNUNET_PeerIdentity peer;
244 GNUNET_assert(ntohs(find_msg->header.size) == sizeof(struct GNUNET_DHT_FindPeerMessage));
245 memcpy(&peer, &find_msg->peer, sizeof(struct GNUNET_PeerIdentity));
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "`%s': Received `%s' request from client, for peer id %s\n", "DHT", "FIND PEER STOP", GNUNET_i2s(&peer));
252 /* FIXME: Implement find peer stop functionality here */
257 * Server handler for initiating local dht put requests
259 static void handle_dht_put (void *cls, struct GNUNET_SERVER_Client * client,
260 const struct GNUNET_MessageHeader *message)
262 struct GNUNET_DHT_PutMessage *put_msg = (struct GNUNET_DHT_PutMessage *)message;
263 GNUNET_HashCode put_key;
268 GNUNET_assert(ntohs(put_msg->header.size) >= sizeof(struct GNUNET_DHT_PutMessage));
270 memcpy(&put_key, &put_msg->key, sizeof(GNUNET_HashCode));
271 put_type = ntohs(put_msg->type);
272 data_size = ntohs(put_msg->data_size);
273 GNUNET_assert(ntohs(put_msg->header.size) == sizeof(struct GNUNET_DHT_PutMessage) + data_size);
274 data = GNUNET_malloc(data_size);
275 memcpy(data, &put_msg[1], data_size);
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279 "`%s': Received `%s' request from client, message type %d, key %s\n", "DHT", "PUT", put_type, GNUNET_h2s(&put_key));
283 * FIXME: Implement dht put request functionality here!
291 * Core handler for p2p dht get requests.
293 static int handle_dht_p2p_get (void *cls,
294 const struct GNUNET_PeerIdentity * peer,
295 const struct GNUNET_MessageHeader * message,
296 struct GNUNET_TIME_Relative latency,
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
301 "`%s': Received `%s' request from another peer\n", "DHT", "GET");
308 * Core handler for p2p dht put requests.
310 static int handle_dht_p2p_put (void *cls,
311 const struct GNUNET_PeerIdentity * peer,
312 const struct GNUNET_MessageHeader * message,
313 struct GNUNET_TIME_Relative latency,
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
318 "`%s': Received `%s' request from another peer\n", "DHT", "PUT");
325 * Core handler for p2p dht find peer requests.
327 static int handle_dht_p2p_find_peer (void *cls,
328 const struct GNUNET_PeerIdentity * peer,
329 const struct GNUNET_MessageHeader * message,
330 struct GNUNET_TIME_Relative latency,
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335 "`%s': Received `%s' request from another peer\n", "DHT", "FIND PEER");
342 * Task run during shutdown.
348 shutdown_task (void *cls,
349 const struct GNUNET_SCHEDULER_TaskContext *tc)
351 GNUNET_CORE_disconnect (coreAPI);
355 * To be called on core init/fail.
357 void core_init (void *cls,
358 struct GNUNET_CORE_Handle * server,
359 const struct GNUNET_PeerIdentity *identity,
360 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey)
365 GNUNET_SCHEDULER_cancel(sched, cleanup_task);
366 GNUNET_SCHEDULER_add_now(sched, &shutdown_task, NULL);
370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
371 "%s: Core connection initialized, I am peer: %s\n", "dht", GNUNET_i2s(identity));
373 memcpy(&my_identity, identity, sizeof(struct GNUNET_PeerIdentity));
378 * Process dht requests.
381 * @param scheduler scheduler to use
382 * @param server the initialized server
383 * @param c configuration to use
387 struct GNUNET_SCHEDULER_Handle *scheduler,
388 struct GNUNET_SERVER_Handle *server,
389 const struct GNUNET_CONFIGURATION_Handle *c)
394 datastore = GNUNET_DATASTORE_connect(c, scheduler);
396 client_transmit_timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5);
397 GNUNET_SERVER_add_handlers (server, plugin_handlers);
400 GNUNET_CORE_connect (sched, /* Main scheduler */
401 cfg, /* Main configuration */
402 client_transmit_timeout, /* Delay for connecting */
403 NULL, /* FIXME: anything we want to pass around? */
404 &core_init, /* Call core_init once connected */
405 NULL, /* Don't care about pre-connects */
406 NULL, /* Don't care about connects */
407 NULL, /* Don't care about disconnects */
408 NULL, /* Don't want notified about all incoming messages */
409 GNUNET_NO, /* For header only inbound notification */
410 NULL, /* Don't want notified about all outbound messages */
411 GNUNET_NO, /* For header only outbound notification */
412 core_handlers); /* Register these handlers */
417 /* Scheduled the task to clean up when shutdown is called */
418 cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
419 GNUNET_TIME_UNIT_FOREVER_REL,
426 * The main function for the dv service.
428 * @param argc number of arguments from the command line
429 * @param argv command line arguments
430 * @return 0 ok, 1 on error
433 main (int argc, char *const *argv)
436 GNUNET_SERVICE_run (argc,
439 GNUNET_SERVICE_OPTION_NONE,
440 &run, NULL)) ? 0 : 1;