2 This file is part of GNUnet.
3 Copyright (C) 2017 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.
22 * @file cadet/gnunet-service-cadet_core.c
23 * @brief cadet service; interaction with CORE service
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
27 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
30 * - Optimization: given BROKEN messages, destroy paths (?)
33 #include "gnunet-service-cadet-new_core.h"
34 #include "gnunet-service-cadet-new_paths.h"
35 #include "gnunet-service-cadet-new_peer.h"
36 #include "gnunet-service-cadet-new_connection.h"
37 #include "gnunet-service-cadet-new_tunnels.h"
38 #include "gnunet_core_service.h"
39 #include "cadet_protocol.h"
42 * Number of messages we are willing to buffer per route.
44 #define ROUTE_BUFFER_SIZE 8
48 * Information we keep per direction for a route.
55 struct CadetPeer *hop;
58 * Route this direction is part of.
60 struct CadetRoute *my_route;
63 * Message queue manager for @e hop.
65 struct GCP_MessageQueueManager *mqm;
68 * Cyclic message buffer to @e hop.
70 struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
73 * Next write offset to use to append messages to @e out_buffer.
75 unsigned int out_wpos;
78 * Next read offset to use to retrieve messages from @e out_buffer.
80 unsigned int out_rpos;
83 * Is @e mqm currently ready for transmission?
91 * Description of a segment of a `struct CadetConnection` at the
92 * intermediate peers. Routes are basically entries in a peer's
93 * routing table for forwarding traffic. At both endpoints, the
94 * routes are terminated by a `struct CadetConnection`, which knows
95 * the complete `struct CadetPath` that is formed by the individual
102 * Information about the next hop on this route.
104 struct RouteDirection next;
107 * Information about the previous hop on this route.
109 struct RouteDirection prev;
112 * Unique identifier for the connection that uses this route.
114 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
117 * When was this route last in use?
119 struct GNUNET_TIME_Absolute last_use;
125 * Handle to the CORE service.
127 static struct GNUNET_CORE_Handle *core;
130 * Routes on which this peer is an intermediate.
132 static struct GNUNET_CONTAINER_MultiShortmap *routes;
136 * Get the route corresponding to a hash.
138 * @param cid hash generated from the connection identifier
140 static struct CadetRoute *
141 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
143 return GNUNET_CONTAINER_multishortmap_get (routes,
144 &cid->connection_of_tunnel);
149 * We message @a msg from @a prev. Find its route by @a cid and
150 * forward to the next hop. Drop and signal broken route if we do not
153 * @param prev previous hop (sender)
154 * @param cid connection identifier, tells us which route to use
155 * @param msg the message to forward
158 route_message (struct CadetPeer *prev,
159 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
160 const struct GNUNET_MessageHeader *msg)
162 struct CadetRoute *route;
163 struct RouteDirection *dir;
164 struct GNUNET_MQ_Envelope *env;
166 route = get_route (cid);
169 struct GNUNET_MQ_Envelope *env;
170 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
172 env = GNUNET_MQ_msg (bm,
173 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
175 bm->peer1 = my_full_id;
180 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
181 if (GNUNET_YES == dir->is_ready)
183 dir->is_ready = GNUNET_NO;
185 GNUNET_MQ_msg_copy (msg));
188 env = dir->out_buffer[dir->out_wpos];
191 /* Queue full, drop earliest message in queue */
192 GNUNET_assert (dir->out_rpos == dir->out_wpos);
193 GNUNET_MQ_discard (env);
195 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
198 env = GNUNET_MQ_msg_copy (msg);
199 dir->out_buffer[dir->out_wpos] = env;
201 if (ROUTE_BUFFER_SIZE == dir->out_wpos)
207 * Check if the create_connection message has the appropriate size.
209 * @param cls Closure (unused).
210 * @param msg Message to check.
212 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
215 check_connection_create (void *cls,
216 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
218 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
220 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
230 * Free internal data of a route direction.
232 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
235 destroy_direction (struct RouteDirection *dir)
237 for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
238 if (NULL != dir->out_buffer[i])
240 GNUNET_MQ_discard (dir->out_buffer[i]);
241 dir->out_buffer[i] = NULL;
243 if (NULL != dir->mqm)
245 GCP_request_mq_cancel (dir->mqm,
253 * Destroy our state for @a route.
255 * @param route route to destroy
258 destroy_route (struct CadetRoute *route)
260 destroy_direction (&route->prev);
261 destroy_direction (&route->next);
267 * Send message that a route is broken between @a peer1 and @a peer2.
269 * @param target where to send the message
270 * @param cid connection identifier to use
271 * @param peer1 one of the peers where a link is broken
272 * @param peer2 another one of the peers where a link is broken
275 send_broken (struct RouteDirection *target,
276 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
277 const struct GNUNET_PeerIdentity *peer1,
278 const struct GNUNET_PeerIdentity *peer2)
280 struct GNUNET_MQ_Envelope *env;
281 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
283 env = GNUNET_MQ_msg (bm,
284 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
290 GCP_request_mq_cancel (target->mqm,
297 * Function called when the message queue to the previous hop
298 * becomes available/unavailable. We expect this function to
299 * be called immediately when we register, and then again
300 * later if the connection ever goes down.
302 * @param cls the `struct RouteDirection`
303 * @param available #GNUNET_YES if sending is now possible,
304 * #GNUNET_NO if sending is no longer possible
305 * #GNUNET_SYSERR if sending is no longer possible
306 * and the last envelope was discarded
309 dir_ready_cb (void *cls,
312 struct RouteDirection *dir = cls;
313 struct CadetRoute *route = dir->my_route;
314 struct RouteDirection *odir;
316 if (GNUNET_YES == ready)
318 struct GNUNET_MQ_Envelope *env;
320 dir->is_ready = GNUNET_YES;
321 if (NULL != (env = dir->out_buffer[dir->out_rpos]))
323 dir->out_buffer[dir->out_rpos] = NULL;
325 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
327 dir->is_ready = GNUNET_NO;
333 odir = (dir == &route->next) ? &route->prev : &route->next;
334 send_broken (&route->next,
336 GCP_get_id (odir->hop),
338 destroy_route (route);
343 * Initialize one of the directions of a route.
345 * @param route route the direction belongs to
346 * @param dir direction to initialize
347 * @param hop next hop on in the @a dir
350 dir_init (struct RouteDirection *dir,
351 struct CadetRoute *route,
352 struct CadetPeer *hop)
355 dir->my_route = route;
356 dir->mqm = GCP_request_mq (hop,
359 GNUNET_assert (GNUNET_YES == dir->is_ready);
364 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
366 * @param cls Closure (CadetPeer for neighbor that sent the message).
367 * @param msg Message itself.
370 handle_connection_create (void *cls,
371 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
373 struct CadetPeer *sender = cls;
374 struct CadetPeer *next;
375 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
376 struct CadetRoute *route;
377 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
378 unsigned int path_length;
381 path_length = size / sizeof (struct GNUNET_PeerIdentity);
382 /* Initiator is at offset 0. */
383 for (off=1;off<path_length;off++)
384 if (0 == memcmp (&my_full_id,
386 sizeof (struct GNUNET_PeerIdentity)))
388 if (off == path_length)
390 /* We are not on the path, bogus request */
394 /* Check previous hop */
395 if (sender != GCP_get (&pids[off - 1],
398 /* sender is not on the path, not allowed */
403 get_route (&msg->cid))
405 /* Duplicate CREATE, pass it on, previous one might have been lost! */
406 route_message (sender,
411 if (off == path_length - 1)
413 /* We are the destination, create connection */
414 struct CadetConnection *cc;
415 struct CadetPeerPath *path;
416 struct CadetPeer *origin;
418 cc = GNUNET_CONTAINER_multishortmap_get (connections,
419 &msg->cid.connection_of_tunnel);
422 GCC_handle_duplicate_create (cc);
426 path = GCPP_get_path_from_route (path_length,
428 origin = GCP_get (&pids[0],
430 GCT_add_inbound_connection (GCT_create_tunnel (origin),
435 /* We are merely a hop on the way, check if we can support the route */
436 next = GCP_get (&pids[off + 1],
438 if ( (NULL == next) ||
439 (GNUNET_NO == GCP_has_core_connection (next)) )
441 /* unworkable, send back BROKEN notification */
442 struct GNUNET_MQ_Envelope *env;
443 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
445 env = GNUNET_MQ_msg (bm,
446 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
448 bm->peer1 = pids[off + 1];
449 bm->peer2 = my_full_id;
450 GCP_send_ooo (sender,
455 /* Workable route, create routing entry */
456 route = GNUNET_new (struct CadetRoute);
457 route->cid = msg->cid;
458 dir_init (&route->prev,
461 dir_init (&route->next,
464 GNUNET_assert (GNUNET_OK ==
465 GNUNET_CONTAINER_multishortmap_put (routes,
466 &route->cid.connection_of_tunnel,
468 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
473 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
475 * @param cls Closure (CadetPeer for neighbor that sent the message).
476 * @param msg Message itself.
479 handle_connection_create_ack (void *cls,
480 const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
482 struct CadetPeer *peer = cls;
483 struct CadetConnection *cc;
485 /* First, check if ACK belongs to a connection that ends here. */
486 cc = GNUNET_CONTAINER_multishortmap_get (connections,
487 &msg->cid.connection_of_tunnel);
490 /* verify ACK came from the right direction */
491 struct CadetPeerPath *path = GCC_get_path (cc);
494 GCPP_get_peer_at_offset (path,
497 /* received ACK from unexpected direction, ignore! */
501 GCC_handle_connection_ack (cc);
505 /* We're just an intermediary peer, route the message along its path */
513 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
515 * @param cls Closure (CadetPeer for neighbor that sent the message).
516 * @param msg Message itself.
517 * @deprecated duplicate logic with #handle_destroy(); dedup!
520 handle_connection_broken (void *cls,
521 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
523 struct CadetPeer *peer = cls;
524 struct CadetConnection *cc;
525 struct CadetRoute *route;
527 /* First, check if message belongs to a connection that ends here. */
528 cc = GNUNET_CONTAINER_multishortmap_get (connections,
529 &msg->cid.connection_of_tunnel);
532 /* verify message came from the right direction */
533 struct CadetPeerPath *path = GCC_get_path (cc);
536 GCPP_get_peer_at_offset (path,
539 /* received message from unexpected direction, ignore! */
545 /* FIXME: also destroy the path up to the specified link! */
549 /* We're just an intermediary peer, route the message along its path */
550 route = get_route (&msg->cid);
554 destroy_route (route);
555 /* FIXME: also destroy paths we MAY have up to the specified link! */
560 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
562 * @param cls Closure (CadetPeer for neighbor that sent the message).
563 * @param msg Message itself.
566 handle_connection_destroy (void *cls,
567 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
569 struct CadetPeer *peer = cls;
570 struct CadetConnection *cc;
571 struct CadetRoute *route;
573 /* First, check if message belongs to a connection that ends here. */
574 cc = GNUNET_CONTAINER_multishortmap_get (connections,
575 &msg->cid.connection_of_tunnel);
578 /* verify message came from the right direction */
579 struct CadetPeerPath *path = GCC_get_path (cc);
582 GCPP_get_peer_at_offset (path,
585 /* received message from unexpected direction, ignore! */
593 /* We're just an intermediary peer, route the message along its path */
594 route = get_route (&msg->cid);
598 destroy_route (route);
603 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
605 * @param cls Closure (CadetPeer for neighbor that sent the message).
606 * @param msg Message itself.
609 handle_tunnel_kx (void *cls,
610 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
612 struct CadetPeer *peer = cls;
613 struct CadetConnection *cc;
615 /* First, check if message belongs to a connection that ends here. */
616 cc = GNUNET_CONTAINER_multishortmap_get (connections,
617 &msg->cid.connection_of_tunnel);
620 /* verify message came from the right direction */
621 struct CadetPeerPath *path = GCC_get_path (cc);
624 GCPP_get_peer_at_offset (path,
627 /* received message from unexpected direction, ignore! */
636 /* We're just an intermediary peer, route the message along its path */
644 * Check if the encrypted message has the appropriate size.
646 * @param cls Closure (unused).
647 * @param msg Message to check.
649 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
652 check_tunnel_encrypted (void *cls,
653 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
660 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
662 * @param cls Closure (CadetPeer for neighbor that sent the message).
663 * @param msg Message itself.
666 handle_tunnel_encrypted (void *cls,
667 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
669 struct CadetPeer *peer = cls;
670 struct CadetConnection *cc;
672 /* First, check if message belongs to a connection that ends here. */
673 cc = GNUNET_CONTAINER_multishortmap_get (connections,
674 &msg->cid.connection_of_tunnel);
677 /* verify message came from the right direction */
678 struct CadetPeerPath *path = GCC_get_path (cc);
681 GCPP_get_peer_at_offset (path,
684 /* received message from unexpected direction, ignore! */
688 GCC_handle_encrypted (cc,
692 /* We're just an intermediary peer, route the message along its path */
700 * Function called after #GNUNET_CORE_connect has succeeded (or failed
701 * for good). Note that the private key of the peer is intentionally
702 * not exposed here; if you need it, your process should try to read
703 * the private key file directly (which should work if you are
704 * authorized...). Implementations of this function must not call
705 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
709 * @param my_identity ID of this peer, NULL if we failed
712 core_init_cb (void *cls,
713 const struct GNUNET_PeerIdentity *my_identity)
715 if (NULL == my_identity)
723 sizeof (struct GNUNET_PeerIdentity)));
728 * Method called whenever a given peer connects.
731 * @param peer peer identity this notification is about
734 core_connect_cb (void *cls,
735 const struct GNUNET_PeerIdentity *peer,
736 struct GNUNET_MQ_Handle *mq)
738 struct CadetPeer *cp;
749 * Method called whenever a peer disconnects.
752 * @param peer peer identity this notification is about
755 core_disconnect_cb (void *cls,
756 const struct GNUNET_PeerIdentity *peer,
759 struct CadetPeer *cp = peer_cls;
767 * Initialize the CORE subsystem.
769 * @param c Configuration.
772 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
774 struct GNUNET_MQ_MessageHandler handlers[] = {
775 GNUNET_MQ_hd_var_size (connection_create,
776 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
777 struct GNUNET_CADET_ConnectionCreateMessage,
779 GNUNET_MQ_hd_fixed_size (connection_create_ack,
780 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
781 struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
783 GNUNET_MQ_hd_fixed_size (connection_broken,
784 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
785 struct GNUNET_CADET_ConnectionBrokenMessage,
787 GNUNET_MQ_hd_fixed_size (connection_destroy,
788 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
789 struct GNUNET_CADET_ConnectionDestroyMessage,
791 GNUNET_MQ_hd_fixed_size (tunnel_kx,
792 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
793 struct GNUNET_CADET_TunnelKeyExchangeMessage,
795 GNUNET_MQ_hd_var_size (tunnel_encrypted,
796 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
797 struct GNUNET_CADET_TunnelEncryptedMessage,
799 GNUNET_MQ_handler_end ()
802 routes = GNUNET_CONTAINER_multishortmap_create (1024,
804 core = GNUNET_CORE_connect (c,
814 * Shut down the CORE subsystem.
821 GNUNET_CORE_disconnect (core);
824 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
825 GNUNET_CONTAINER_multishortmap_destroy (routes);
828 /* end of gnunet-cadet-service_core.c */