2 This file is part of GNUnet.
3 Copyright (C) 2009--2013, 2016 GNUnet e.V.
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.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
23 * @brief library to access the DV service
24 * @author Christian Grothoff
25 * @author Nathan Evans
28 #include "gnunet_util_lib.h"
29 #include "gnunet_dv_service.h"
30 #include "gnunet_protocols.h"
32 #include "gnunet_transport_plugin.h"
34 #define LOG(kind,...) GNUNET_log_from (kind, "dv-api",__VA_ARGS__)
38 * Information we track for each peer.
44 * Identity of the peer.
46 struct GNUNET_PeerIdentity pid;
52 * Handle to the DV service.
54 struct GNUNET_DV_ServiceHandle
58 * Connection to DV service.
60 struct GNUNET_MQ_Handle *mq;
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
68 * Closure for the callbacks.
73 * Function to call on connect events.
75 GNUNET_DV_ConnectCallback connect_cb;
78 * Function to call on distance change events.
80 GNUNET_DV_DistanceChangedCallback distance_cb;
83 * Function to call on disconnect events.
85 GNUNET_DV_DisconnectCallback disconnect_cb;
88 * Function to call on receiving messages events.
90 GNUNET_DV_MessageReceivedCallback message_cb;
93 * Information tracked per connected peer. Maps peer
94 * identities to `struct ConnectedPeer` entries.
96 struct GNUNET_CONTAINER_MultiPeerMap *peers;
102 * Disconnect and then reconnect to the DV service.
104 * @param sh service handle
107 reconnect (struct GNUNET_DV_ServiceHandle *sh);
111 * We got disconnected from the service and thus all of the
112 * connections need to be torn down.
114 * @param cls the `struct GNUNET_DV_ServiceHandle`
115 * @param key a peer identity
116 * @param value a `struct ConnectedPeer` to clean up
117 * @return #GNUNET_OK (continue to iterate)
120 cleanup_send_cb (void *cls,
121 const struct GNUNET_PeerIdentity *key,
124 struct GNUNET_DV_ServiceHandle *sh = cls;
125 struct ConnectedPeer *peer = value;
127 GNUNET_assert (GNUNET_YES ==
128 GNUNET_CONTAINER_multipeermap_remove (sh->peers,
131 sh->disconnect_cb (sh->cls,
139 * Handles a message sent from the DV service to us.
140 * Parse it out and give it to the plugin.
142 * @param cls the handle to the DV API
143 * @param cm the message that was received
146 handle_connect (void *cls,
147 const struct GNUNET_DV_ConnectMessage *cm)
149 struct GNUNET_DV_ServiceHandle *sh = cls;
150 struct ConnectedPeer *peer;
152 peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
160 peer = GNUNET_new (struct ConnectedPeer);
161 peer->pid = cm->peer;
162 GNUNET_assert (GNUNET_OK ==
163 GNUNET_CONTAINER_multipeermap_put (sh->peers,
166 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
167 sh->connect_cb (sh->cls,
169 ntohl (cm->distance),
170 (enum GNUNET_ATS_Network_Type) ntohl (cm->network));
175 * Handles a message sent from the DV service to us.
176 * Parse it out and give it to the plugin.
178 * @param cls the handle to the DV API
179 * @param dm the message that was received
182 handle_disconnect (void *cls,
183 const struct GNUNET_DV_DisconnectMessage *dm)
185 struct GNUNET_DV_ServiceHandle *sh = cls;
186 struct ConnectedPeer *peer;
188 peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
203 * Handles a message sent from the DV service to us.
204 * Parse it out and give it to the plugin.
206 * @param cls the handle to the DV API
207 * @param msg the message that was received
210 handle_distance_update (void *cls,
211 const struct GNUNET_DV_DistanceUpdateMessage *dum)
213 struct GNUNET_DV_ServiceHandle *sh = cls;
214 struct ConnectedPeer *peer;
216 peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
224 sh->distance_cb (sh->cls,
226 ntohl (dum->distance),
227 (enum GNUNET_ATS_Network_Type) ntohl (dum->network));
232 * Handles a message sent from the DV service to us.
233 * Parse it out and give it to the plugin.
235 * @param cls the handle to the DV API
236 * @param rm the message that was received
239 check_received (void *cls,
240 const struct GNUNET_DV_ReceivedMessage *rm)
242 struct GNUNET_DV_ServiceHandle *sh = cls;
243 const struct GNUNET_MessageHeader *payload;
246 GNUNET_CONTAINER_multipeermap_get (sh->peers,
250 return GNUNET_SYSERR;
252 if (ntohs (rm->header.size) - sizeof (struct GNUNET_DV_ReceivedMessage) <
256 return GNUNET_SYSERR;
258 payload = (const struct GNUNET_MessageHeader *) &rm[1];
259 if (ntohs (rm->header.size) !=
260 sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (payload->size))
263 return GNUNET_SYSERR;
270 * Handles a message sent from the DV service to us.
271 * Parse it out and give it to the plugin.
273 * @param cls the handle to the DV API
274 * @param rm the message that was received
277 handle_received (void *cls,
278 const struct GNUNET_DV_ReceivedMessage *rm)
280 struct GNUNET_DV_ServiceHandle *sh = cls;
281 const struct GNUNET_MessageHeader *payload;
283 payload = (const struct GNUNET_MessageHeader *) &rm[1];
284 sh->message_cb (sh->cls,
286 ntohl (rm->distance),
292 * Generic error handler, called with the appropriate error code and
293 * the same closure specified at the creation of the message queue.
294 * Not every message queue implementation supports an error handler.
296 * @param cls closure with the `struct GNUNET_DV_ServiceHandle *`
297 * @param error error code
300 mq_error_handler (void *cls,
301 enum GNUNET_MQ_Error error)
303 struct GNUNET_DV_ServiceHandle *sh = cls;
310 * Disconnect and then reconnect to the DV service.
312 * @param sh service handle
315 reconnect (struct GNUNET_DV_ServiceHandle *sh)
317 GNUNET_MQ_hd_fixed_size (connect,
318 GNUNET_MESSAGE_TYPE_DV_CONNECT,
319 struct GNUNET_DV_ConnectMessage);
320 GNUNET_MQ_hd_fixed_size (disconnect,
321 GNUNET_MESSAGE_TYPE_DV_DISCONNECT,
322 struct GNUNET_DV_DisconnectMessage);
323 GNUNET_MQ_hd_fixed_size (distance_update,
324 GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED,
325 struct GNUNET_DV_DistanceUpdateMessage);
326 GNUNET_MQ_hd_var_size (received,
327 GNUNET_MESSAGE_TYPE_DV_RECV,
328 struct GNUNET_DV_ReceivedMessage);
329 struct GNUNET_MQ_MessageHandler handlers[] = {
330 make_connect_handler (sh),
331 make_disconnect_handler (sh),
332 make_distance_update_handler (sh),
333 make_received_handler (sh),
334 GNUNET_MQ_handler_end ()
336 struct GNUNET_MessageHeader *sm;
337 struct GNUNET_MQ_Envelope *env;
341 GNUNET_MQ_destroy (sh->mq);
344 GNUNET_CONTAINER_multipeermap_iterate (sh->peers,
347 LOG (GNUNET_ERROR_TYPE_DEBUG,
348 "Connecting to DV service\n");
349 sh->mq = GNUNET_CLIENT_connecT (sh->cfg,
359 env = GNUNET_MQ_msg (sm,
360 GNUNET_MESSAGE_TYPE_DV_START);
361 GNUNET_MQ_send (sh->mq,
367 * Connect to the DV service.
369 * @param cfg configuration
370 * @param cls closure for callbacks
371 * @param connect_cb function to call on connects
372 * @param distance_cb function to call if distances change
373 * @param disconnect_cb function to call on disconnects
374 * @param message_cb function to call if we receive messages
375 * @return handle to access the service
377 struct GNUNET_DV_ServiceHandle *
378 GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
380 GNUNET_DV_ConnectCallback connect_cb,
381 GNUNET_DV_DistanceChangedCallback distance_cb,
382 GNUNET_DV_DisconnectCallback disconnect_cb,
383 GNUNET_DV_MessageReceivedCallback message_cb)
385 struct GNUNET_DV_ServiceHandle *sh;
387 sh = GNUNET_new (struct GNUNET_DV_ServiceHandle);
390 sh->connect_cb = connect_cb;
391 sh->distance_cb = distance_cb;
392 sh->disconnect_cb = disconnect_cb;
393 sh->message_cb = message_cb;
394 sh->peers = GNUNET_CONTAINER_multipeermap_create (128,
402 * Disconnect from DV service.
404 * @param sh service handle
407 GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh)
413 GNUNET_MQ_destroy (sh->mq);
416 GNUNET_CONTAINER_multipeermap_iterate (sh->peers,
419 GNUNET_CONTAINER_multipeermap_destroy (sh->peers);
425 * Send a message via DV service.
427 * @param sh service handle
428 * @param target intended recpient
429 * @param msg message payload
432 GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh,
433 const struct GNUNET_PeerIdentity *target,
434 const struct GNUNET_MessageHeader *msg)
436 struct GNUNET_DV_SendMessage *sm;
437 struct ConnectedPeer *peer;
438 struct GNUNET_MQ_Envelope *env;
440 if (ntohs (msg->size) + sizeof (*sm) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
445 LOG (GNUNET_ERROR_TYPE_DEBUG,
446 "Asked to send %u bytes of type %u to %s\n",
447 (unsigned int) ntohs (msg->size),
448 (unsigned int) ntohs (msg->type),
449 GNUNET_i2s (target));
450 peer = GNUNET_CONTAINER_multipeermap_get (sh->peers,
457 GNUNET_assert (NULL != sh->mq);
458 env = GNUNET_MQ_msg_nested_mh (sm,
459 GNUNET_MESSAGE_TYPE_DV_SEND,
461 sm->target = *target;
462 GNUNET_MQ_send (sh->mq,
467 /* end of dv_api.c */