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 #include "gnunet-service-cadet-new_core.h"
31 #include "gnunet-service-cadet-new_paths.h"
32 #include "gnunet-service-cadet-new_peer.h"
33 #include "gnunet-service-cadet-new_connection.h"
34 #include "gnunet_core_service.h"
35 #include "cadet_protocol.h"
39 * Description of a segment of a `struct CadetConnection` at the
40 * intermediate peers. Routes are basically entries in a peer's
41 * routing table for forwarding traffic. At both endpoints, the
42 * routes are terminated by a `struct CadetConnection`, which knows
43 * the complete `struct CadetPath` that is formed by the individual
50 * Previous hop on this route.
52 struct CadetPeer *prev_hop;
55 * Next hop on this route.
57 struct CadetPeer *next_hop;
60 * Message queue notifications for @e prev_hop.
62 struct GCP_MessageQueueManager *prev_mqm;
65 * Message queue notifications for @e next_hop.
67 struct GCP_MessageQueueManager *next_mqm;
70 * Unique identifier for the connection that uses this route.
72 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
75 * When was this route last in use?
77 struct GNUNET_TIME_Absolute last_use;
83 * Handle to the CORE service.
85 static struct GNUNET_CORE_Handle *core;
88 * Routes on which this peer is an intermediate.
90 static struct GNUNET_CONTAINER_MultiShortmap *routes;
94 * Get the route corresponding to a hash.
96 * @param cid hash generated from the connection identifier
98 static struct CadetRoute *
99 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
101 return GNUNET_CONTAINER_multishortmap_get (routes,
102 &cid->connection_of_tunnel);
107 * We message @a msg from @a prev. Find its route by @a cid and
108 * forward to the next hop. Drop and signal broken route if we do not
111 * @param prev previous hop (sender)
112 * @param cid connection identifier, tells us which route to use
113 * @param msg the message to forward
116 route_message (struct CadetPeer *prev,
117 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
118 const struct GNUNET_MessageHeader *msg)
120 struct CadetRoute *route;
122 route = get_route (cid);
125 struct GNUNET_MQ_Envelope *env;
126 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
128 env = GNUNET_MQ_msg (bm,
129 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
131 bm->peer1 = my_full_id;
136 /* FIXME: support round-robin queue management here somewhere! */
137 GCP_send ((prev == route->prev_hop) ? route->next_hop : route->prev_hop,
138 GNUNET_MQ_msg_copy (msg));
143 * Check if the create_connection message has the appropriate size.
145 * @param cls Closure (unused).
146 * @param msg Message to check.
148 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
151 check_connection_create (void *cls,
152 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
154 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
156 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
166 * Destroy our state for @a route.
168 * @param route route to destroy
171 destroy_route (struct CadetRoute *route)
173 GCP_request_mq_cancel (route->next_mqm);
174 GCP_request_mq_cancel (route->prev_mqm);
180 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
182 * @param cls Closure (CadetPeer for neighbor that sent the message).
183 * @param msg Message itself.
186 handle_connection_create (void *cls,
187 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
189 struct CadetPeer *sender = cls;
190 struct CadetPeer *next;
191 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
192 struct CadetRoute *route;
193 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
194 unsigned int path_length;
197 path_length = size / sizeof (struct GNUNET_PeerIdentity);
198 /* Initiator is at offset 0. */
199 for (off=1;off<path_length;off++)
200 if (0 == memcmp (&my_full_id,
202 sizeof (struct GNUNET_PeerIdentity)))
204 if (off == path_length)
206 /* We are not on the path, bogus request */
210 /* Check previous hop */
211 if (sender != GCP_get (&pids[off - 1],
214 /* sender is not on the path, not allowed */
218 if (off == path_length - 1)
220 /* We are the destination, create connection */
223 /* We are merely a hop on the way, check if we can support the route */
224 next = GCP_get (&pids[off + 1],
228 /* unworkable, send back BROKEN */
229 GNUNET_break (0); // FIXME...
233 route = GNUNET_new (struct CadetRoute);
236 GCC_handle_create (peer,
245 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
247 * @param cls Closure (CadetPeer for neighbor that sent the message).
248 * @param msg Message itself.
251 handle_connection_ack (void *cls,
252 const struct GNUNET_CADET_ConnectionCreateMessageAckMessage *msg)
254 struct CadetPeer *peer = cls;
255 struct CadetConnection *cc;
257 /* First, check if ACK belongs to a connection that ends here. */
258 cc = GNUNET_CONTAINER_multishortmap_get (connections,
259 &msg->cid.connection_of_tunnel);
262 /* verify ACK came from the right direction */
263 struct CadetPeerPath *path = GCC_get_path (cc);
266 GCPP_get_peer_at_offset (path,
269 /* received ACK from unexpected direction, ignore! */
273 GCC_handle_connection_ack (cc);
277 /* We're just an intermediary peer, route the message along its path */
285 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
287 * @param cls Closure (CadetPeer for neighbor that sent the message).
288 * @param msg Message itself.
289 * @deprecated duplicate logic with #handle_destroy(); dedup!
292 handle_connection_broken (void *cls,
293 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
295 struct CadetPeer *peer = cls;
296 struct CadetConnection *cc;
297 struct CadetRoute *route;
299 /* First, check if message belongs to a connection that ends here. */
300 cc = GNUNET_CONTAINER_multishortmap_get (connections,
301 &msg->cid.connection_of_tunnel);
304 /* verify message came from the right direction */
305 struct CadetPeerPath *path = GCC_get_path (cc);
308 GCPP_get_peer_at_offset (path,
311 /* received message from unexpected direction, ignore! */
317 /* FIXME: also destroy the path up to the specified link! */
321 /* We're just an intermediary peer, route the message along its path */
322 route = get_route (&msg->cid);
326 destroy_route (route);
327 /* FIXME: also destroy paths we MAY have up to the specified link! */
332 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
334 * @param cls Closure (CadetPeer for neighbor that sent the message).
335 * @param msg Message itself.
338 handle_connection_destroy (void *cls,
339 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
341 struct CadetPeer *peer = cls;
342 struct CadetConnection *cc;
343 struct CadetRoute *route;
345 /* First, check if message belongs to a connection that ends here. */
346 cc = GNUNET_CONTAINER_multishortmap_get (connections,
347 &msg->cid.connection_of_tunnel);
350 /* verify message came from the right direction */
351 struct CadetPeerPath *path = GCC_get_path (cc);
354 GCPP_get_peer_at_offset (path,
357 /* received message from unexpected direction, ignore! */
365 /* We're just an intermediary peer, route the message along its path */
366 route = get_route (&msg->cid);
370 destroy_route (route);
375 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_HOP_BY_HOP_ENCRYPTED_ACK.
377 * @param cls Closure (CadetPeer for neighbor that sent the message).
378 * @param msg Message itself.
381 handle_hop_by_hop_encrypted_ack (void *cls,
382 const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
384 struct CadetPeer *peer = cls;
387 GCC_handle_poll (peer,
394 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
396 * @param cls Closure (CadetPeer for neighbor that sent the message).
397 * @param msg Message itself.
400 handle_poll (void *cls,
401 const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
403 struct CadetPeer *peer = cls;
406 GCC_handle_poll (peer,
413 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
415 * @param cls Closure (CadetPeer for neighbor that sent the message).
416 * @param msg Message itself.
419 handle_tunnel_kx (void *cls,
420 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
422 struct CadetPeer *peer = cls;
423 struct CadetConnection *cc;
425 /* First, check if message belongs to a connection that ends here. */
426 cc = GNUNET_CONTAINER_multishortmap_get (connections,
427 &msg->cid.connection_of_tunnel);
430 /* verify message came from the right direction */
431 struct CadetPeerPath *path = GCC_get_path (cc);
434 GCPP_get_peer_at_offset (path,
437 /* received message from unexpected direction, ignore! */
446 /* We're just an intermediary peer, route the message along its path */
454 * Check if the encrypted message has the appropriate size.
456 * @param cls Closure (unused).
457 * @param msg Message to check.
459 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
462 check_tunnel_encrypted (void *cls,
463 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
470 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
472 * @param cls Closure (CadetPeer for neighbor that sent the message).
473 * @param msg Message itself.
476 handle_tunnel_encrypted (void *cls,
477 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
479 struct CadetPeer *peer = cls;
480 struct CadetConnection *cc;
482 /* First, check if message belongs to a connection that ends here. */
483 cc = GNUNET_CONTAINER_multishortmap_get (connections,
484 &msg->cid.connection_of_tunnel);
487 /* verify message came from the right direction */
488 struct CadetPeerPath *path = GCC_get_path (cc);
491 GCPP_get_peer_at_offset (path,
494 /* received message from unexpected direction, ignore! */
498 GCC_handle_encrypted (cc,
503 /* We're just an intermediary peer, route the message along its path */
511 * Function called after #GNUNET_CORE_connect has succeeded (or failed
512 * for good). Note that the private key of the peer is intentionally
513 * not exposed here; if you need it, your process should try to read
514 * the private key file directly (which should work if you are
515 * authorized...). Implementations of this function must not call
516 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
520 * @param my_identity ID of this peer, NULL if we failed
523 core_init_cb (void *cls,
524 const struct GNUNET_PeerIdentity *my_identity)
526 if (NULL == my_identity)
534 sizeof (struct GNUNET_PeerIdentity)));
539 * Method called whenever a given peer connects.
542 * @param peer peer identity this notification is about
545 core_connect_cb (void *cls,
546 const struct GNUNET_PeerIdentity *peer,
547 struct GNUNET_MQ_Handle *mq)
549 struct CadetPeer *cp;
560 * Method called whenever a peer disconnects.
563 * @param peer peer identity this notification is about
566 core_disconnect_cb (void *cls,
567 const struct GNUNET_PeerIdentity *peer,
570 struct CadetPeer *cp = peer_cls;
572 /* FIXME: also check all routes going via peer and
573 send broken messages to the other direction! */
581 * Initialize the CORE subsystem.
583 * @param c Configuration.
586 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
588 struct GNUNET_MQ_MessageHandler handlers[] = {
589 GNUNET_MQ_hd_var_size (connection_create,
590 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
591 struct GNUNET_CADET_ConnectionCreateMessage,
593 GNUNET_MQ_hd_fixed_size (connection_ack,
594 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
595 struct GNUNET_CADET_ConnectionCreateMessageAckMessage,
597 GNUNET_MQ_hd_fixed_size (connection_broken,
598 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
599 struct GNUNET_CADET_ConnectionBrokenMessage,
601 GNUNET_MQ_hd_fixed_size (connection_destroy,
602 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
603 struct GNUNET_CADET_ConnectionDestroyMessage,
605 GNUNET_MQ_hd_fixed_size (hop_by_hop_encrypted_ack,
606 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
607 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
609 GNUNET_MQ_hd_fixed_size (poll,
610 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
611 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
613 GNUNET_MQ_hd_fixed_size (tunnel_kx,
614 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
615 struct GNUNET_CADET_TunnelKeyExchangeMessage,
617 GNUNET_MQ_hd_var_size (tunnel_encrypted,
618 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
619 struct GNUNET_CADET_TunnelEncryptedMessage,
621 GNUNET_MQ_handler_end ()
624 routes = GNUNET_CONTAINER_multishortmap_create (1024,
626 core = GNUNET_CORE_connect (c,
636 * Shut down the CORE subsystem.
643 GNUNET_CORE_disconnect (core);
646 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
647 GNUNET_CONTAINER_multishortmap_destroy (routes);
650 /* end of gnunet-cadet-service_core.c */