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 * - properly implement GLOBAL message buffer, instead of per-route buffers
31 * - do NOT use buffering if the route options say no buffer!
32 * - Optimization: given BROKEN messages, destroy paths (?)
35 #include "gnunet-service-cadet-new_core.h"
36 #include "gnunet-service-cadet-new_paths.h"
37 #include "gnunet-service-cadet-new_peer.h"
38 #include "gnunet-service-cadet-new_connection.h"
39 #include "gnunet-service-cadet-new_tunnels.h"
40 #include "gnunet_core_service.h"
41 #include "gnunet_statistics_service.h"
42 #include "cadet_protocol.h"
45 #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__)
49 * Number of messages we are willing to buffer per route.
50 * FIXME: have global buffer pool instead!
52 #define ROUTE_BUFFER_SIZE 8
56 * Information we keep per direction for a route.
63 struct CadetPeer *hop;
66 * Route this direction is part of.
68 struct CadetRoute *my_route;
71 * Message queue manager for @e hop.
73 struct GCP_MessageQueueManager *mqm;
76 * Cyclic message buffer to @e hop.
78 struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
81 * Next write offset to use to append messages to @e out_buffer.
83 unsigned int out_wpos;
86 * Next read offset to use to retrieve messages from @e out_buffer.
88 unsigned int out_rpos;
91 * Is @e mqm currently ready for transmission?
99 * Description of a segment of a `struct CadetConnection` at the
100 * intermediate peers. Routes are basically entries in a peer's
101 * routing table for forwarding traffic. At both endpoints, the
102 * routes are terminated by a `struct CadetConnection`, which knows
103 * the complete `struct CadetPath` that is formed by the individual
110 * Information about the next hop on this route.
112 struct RouteDirection next;
115 * Information about the previous hop on this route.
117 struct RouteDirection prev;
120 * Unique identifier for the connection that uses this route.
122 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
125 * When was this route last in use?
127 struct GNUNET_TIME_Absolute last_use;
130 * Position of this route in the #route_heap.
132 struct GNUNET_CONTAINER_HeapNode *hn;
135 * Options for the route, control buffering.
137 enum GNUNET_CADET_ChannelOption options;
142 * Handle to the CORE service.
144 static struct GNUNET_CORE_Handle *core;
147 * Routes on which this peer is an intermediate.
149 static struct GNUNET_CONTAINER_MultiShortmap *routes;
152 * Heap of routes, MIN-sorted by last activity.
154 static struct GNUNET_CONTAINER_Heap *route_heap;
157 * Maximum number of concurrent routes this peer will support.
159 static unsigned long long max_routes;
162 * Task to timeout routes.
164 static struct GNUNET_SCHEDULER_Task *timeout_task;
168 * Get the route corresponding to a hash.
170 * @param cid hash generated from the connection identifier
172 static struct CadetRoute *
173 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
175 return GNUNET_CONTAINER_multishortmap_get (routes,
176 &cid->connection_of_tunnel);
181 * We message @a msg from @a prev. Find its route by @a cid and
182 * forward to the next hop. Drop and signal broken route if we do not
185 * @param prev previous hop (sender)
186 * @param cid connection identifier, tells us which route to use
187 * @param msg the message to forward
190 route_message (struct CadetPeer *prev,
191 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
192 const struct GNUNET_MessageHeader *msg)
194 struct CadetRoute *route;
195 struct RouteDirection *dir;
196 struct GNUNET_MQ_Envelope *env;
198 route = get_route (cid);
201 struct GNUNET_MQ_Envelope *env;
202 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
204 LOG (GNUNET_ERROR_TYPE_DEBUG,
205 "Failed to route message of type %u from %s on connection %s: no route\n",
208 GNUNET_sh2s (&cid->connection_of_tunnel));
209 env = GNUNET_MQ_msg (bm,
210 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
212 bm->peer1 = my_full_id;
217 route->last_use = GNUNET_TIME_absolute_get ();
218 GNUNET_CONTAINER_heap_update_cost (route->hn,
219 route->last_use.abs_value_us);
220 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
221 if (GNUNET_YES == dir->is_ready)
223 LOG (GNUNET_ERROR_TYPE_DEBUG,
224 "Routing message of type %u from %s to %s on connection %s\n",
227 GNUNET_i2s (GCP_get_id (dir->hop)),
228 GNUNET_sh2s (&cid->connection_of_tunnel));
229 dir->is_ready = GNUNET_NO;
231 GNUNET_MQ_msg_copy (msg));
234 env = dir->out_buffer[dir->out_wpos];
237 /* Queue full, drop earliest message in queue */
238 LOG (GNUNET_ERROR_TYPE_DEBUG,
239 "Queue full due to new message of type %u from %s to %s on connection %s, dropping old message\n",
242 GNUNET_i2s (GCP_get_id (dir->hop)),
243 GNUNET_sh2s (&cid->connection_of_tunnel));
244 GNUNET_STATISTICS_update (stats,
245 "# messages dropped due to full buffer",
248 GNUNET_assert (dir->out_rpos == dir->out_wpos);
249 GNUNET_MQ_discard (env);
251 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
254 LOG (GNUNET_ERROR_TYPE_DEBUG,
255 "Queueing new message of type %u from %s to %s on connection %s\n",
258 GNUNET_i2s (GCP_get_id (dir->hop)),
259 GNUNET_sh2s (&cid->connection_of_tunnel));
260 env = GNUNET_MQ_msg_copy (msg);
261 dir->out_buffer[dir->out_wpos] = env;
263 if (ROUTE_BUFFER_SIZE == dir->out_wpos)
269 * Check if the create_connection message has the appropriate size.
271 * @param cls Closure (unused).
272 * @param msg Message to check.
274 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
277 check_connection_create (void *cls,
278 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
280 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
282 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
292 * Free internal data of a route direction.
294 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
297 destroy_direction (struct RouteDirection *dir)
299 for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
300 if (NULL != dir->out_buffer[i])
302 GNUNET_MQ_discard (dir->out_buffer[i]);
303 dir->out_buffer[i] = NULL;
305 if (NULL != dir->mqm)
307 GCP_request_mq_cancel (dir->mqm,
315 * Destroy our state for @a route.
317 * @param route route to destroy
320 destroy_route (struct CadetRoute *route)
322 LOG (GNUNET_ERROR_TYPE_DEBUG,
323 "Destroying route from %s to %s of connection %s\n",
324 GNUNET_i2s (GCP_get_id (route->prev.hop)),
325 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
326 GNUNET_sh2s (&route->cid.connection_of_tunnel));
327 GNUNET_assert (route ==
328 GNUNET_CONTAINER_heap_remove_node (route->hn));
329 destroy_direction (&route->prev);
330 destroy_direction (&route->next);
336 * Send message that a route is broken between @a peer1 and @a peer2.
338 * @param target where to send the message
339 * @param cid connection identifier to use
340 * @param peer1 one of the peers where a link is broken
341 * @param peer2 another one of the peers where a link is broken
344 send_broken (struct RouteDirection *target,
345 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
346 const struct GNUNET_PeerIdentity *peer1,
347 const struct GNUNET_PeerIdentity *peer2)
349 struct GNUNET_MQ_Envelope *env;
350 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
352 if (NULL == target->mqm)
353 return; /* Can't send notification, connection is down! */
354 LOG (GNUNET_ERROR_TYPE_DEBUG,
355 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
356 GCP_2s (target->hop),
359 GNUNET_sh2s (&cid->connection_of_tunnel));
361 env = GNUNET_MQ_msg (bm,
362 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
369 GCP_request_mq_cancel (target->mqm,
376 * Function called to check if any routes have timed out, and if
377 * so, to clean them up. Finally, schedules itself again at the
378 * earliest time where there might be more work.
383 timeout_cb (void *cls)
385 struct CadetRoute *r;
386 struct GNUNET_TIME_Relative linger;
387 struct GNUNET_TIME_Absolute exp;
390 linger = GNUNET_TIME_relative_multiply (keepalive_period,
392 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
394 exp = GNUNET_TIME_absolute_add (r->last_use,
396 if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
398 /* Route not yet timed out, wait until it does. */
399 timeout_task = GNUNET_SCHEDULER_add_at (exp,
404 send_broken (&r->prev,
408 send_broken (&r->next,
414 /* No more routes left, so no need for a #timeout_task */
419 * Function called when the message queue to the previous hop
420 * becomes available/unavailable. We expect this function to
421 * be called immediately when we register, and then again
422 * later if the connection ever goes down.
424 * @param cls the `struct RouteDirection`
425 * @param available #GNUNET_YES if sending is now possible,
426 * #GNUNET_NO if sending is no longer possible
427 * #GNUNET_SYSERR if sending is no longer possible
428 * and the last envelope was discarded
431 dir_ready_cb (void *cls,
434 struct RouteDirection *dir = cls;
435 struct CadetRoute *route = dir->my_route;
436 struct RouteDirection *odir;
438 if (GNUNET_YES == ready)
440 struct GNUNET_MQ_Envelope *env;
442 dir->is_ready = GNUNET_YES;
443 if (NULL != (env = dir->out_buffer[dir->out_rpos]))
445 dir->out_buffer[dir->out_rpos] = NULL;
447 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
449 dir->is_ready = GNUNET_NO;
455 odir = (dir == &route->next) ? &route->prev : &route->next;
456 send_broken (&route->next,
458 GCP_get_id (odir->hop),
460 destroy_route (route);
465 * Initialize one of the directions of a route.
467 * @param route route the direction belongs to
468 * @param dir direction to initialize
469 * @param hop next hop on in the @a dir
472 dir_init (struct RouteDirection *dir,
473 struct CadetRoute *route,
474 struct CadetPeer *hop)
477 dir->my_route = route;
478 dir->mqm = GCP_request_mq (hop,
481 GNUNET_assert (GNUNET_YES == dir->is_ready);
486 * We could not create the desired route. Send a
487 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
488 * message to @a target.
490 * @param target who should receive the message
491 * @param cid identifier of the connection/route that failed
492 * @param failure_at neighbour with which we failed to route,
496 send_broken_without_mqm (struct CadetPeer *target,
497 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
498 const struct GNUNET_PeerIdentity *failure_at)
500 struct GNUNET_MQ_Envelope *env;
501 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
503 env = GNUNET_MQ_msg (bm,
504 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
506 bm->peer1 = my_full_id;
507 if (NULL != failure_at)
508 bm->peer2 = *failure_at;
509 GCP_send_ooo (target,
515 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
517 * @param cls Closure (CadetPeer for neighbor that sent the message).
518 * @param msg Message itself.
521 handle_connection_create (void *cls,
522 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
524 struct CadetPeer *sender = cls;
525 struct CadetPeer *next;
526 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
527 struct CadetRoute *route;
528 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
529 unsigned int path_length;
531 enum GNUNET_CADET_ChannelOption options;
533 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
534 path_length = size / sizeof (struct GNUNET_PeerIdentity);
535 /* Initiator is at offset 0. */
536 for (off=1;off<path_length;off++)
537 if (0 == memcmp (&my_full_id,
539 sizeof (struct GNUNET_PeerIdentity)))
541 if (off == path_length)
543 /* We are not on the path, bogus request */
547 /* Check previous hop */
548 if (sender != GCP_get (&pids[off - 1],
551 /* sender is not on the path, not allowed */
556 get_route (&msg->cid))
558 /* Duplicate CREATE, pass it on, previous one might have been lost! */
559 LOG (GNUNET_ERROR_TYPE_DEBUG,
560 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
561 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
562 route_message (sender,
567 if (off == path_length - 1)
569 /* We are the destination, create connection */
570 struct CadetConnection *cc;
571 struct CadetPeerPath *path;
572 struct CadetPeer *origin;
574 cc = GNUNET_CONTAINER_multishortmap_get (connections,
575 &msg->cid.connection_of_tunnel);
578 LOG (GNUNET_ERROR_TYPE_DEBUG,
579 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
580 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
581 GCC_handle_duplicate_create (cc);
585 origin = GCP_get (&pids[0],
587 LOG (GNUNET_ERROR_TYPE_DEBUG,
588 "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
590 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
591 path = GCPP_get_path_from_route (path_length - 1,
594 GCT_add_inbound_connection (GCP_get_tunnel (origin,
597 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
600 /* Send back BROKEN: duplicate connection on the same path,
601 we will use the other one. */
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
605 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
607 send_broken_without_mqm (sender,
614 /* We are merely a hop on the way, check if we can support the route */
615 next = GCP_get (&pids[off + 1],
617 if ( (NULL == next) ||
618 (GNUNET_NO == GCP_has_core_connection (next)) )
620 /* unworkable, send back BROKEN notification */
621 LOG (GNUNET_ERROR_TYPE_DEBUG,
622 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
624 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
625 GNUNET_i2s (&pids[off + 1]),
627 send_broken_without_mqm (sender,
632 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
634 LOG (GNUNET_ERROR_TYPE_DEBUG,
635 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
637 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
638 send_broken_without_mqm (sender,
644 /* Workable route, create routing entry */
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
648 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
649 GNUNET_i2s (&pids[off + 1]),
651 route = GNUNET_new (struct CadetRoute);
652 route->options = options;
653 route->cid = msg->cid;
654 route->last_use = GNUNET_TIME_absolute_get ();
655 dir_init (&route->prev,
658 dir_init (&route->next,
661 GNUNET_assert (GNUNET_OK ==
662 GNUNET_CONTAINER_multishortmap_put (routes,
663 &route->cid.connection_of_tunnel,
665 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
666 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
668 route->last_use.abs_value_us);
669 if (NULL == timeout_task)
670 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
678 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
680 * @param cls Closure (CadetPeer for neighbor that sent the message).
681 * @param msg Message itself.
684 handle_connection_create_ack (void *cls,
685 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
687 struct CadetPeer *peer = cls;
688 struct CadetConnection *cc;
690 /* First, check if ACK belongs to a connection that ends here. */
691 cc = GNUNET_CONTAINER_multishortmap_get (connections,
692 &msg->cid.connection_of_tunnel);
695 /* verify ACK came from the right direction */
696 struct CadetPeerPath *path = GCC_get_path (cc);
699 GCPP_get_peer_at_offset (path,
702 /* received ACK from unexpected direction, ignore! */
706 LOG (GNUNET_ERROR_TYPE_DEBUG,
707 "Received CONNECTION_CREATE_ACK for connection %s.\n",
708 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
709 GCC_handle_connection_create_ack (cc);
713 /* We're just an intermediary peer, route the message along its path */
721 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
723 * @param cls Closure (CadetPeer for neighbor that sent the message).
724 * @param msg Message itself.
725 * @deprecated duplicate logic with #handle_destroy(); dedup!
728 handle_connection_broken (void *cls,
729 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
731 struct CadetPeer *peer = cls;
732 struct CadetConnection *cc;
733 struct CadetRoute *route;
735 /* First, check if message belongs to a connection that ends here. */
736 cc = GNUNET_CONTAINER_multishortmap_get (connections,
737 &msg->cid.connection_of_tunnel);
740 /* verify message came from the right direction */
741 struct CadetPeerPath *path = GCC_get_path (cc);
744 GCPP_get_peer_at_offset (path,
747 /* received message from unexpected direction, ignore! */
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
753 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
754 GCC_destroy_without_core (cc);
756 /* FIXME: also destroy the path up to the specified link! */
760 /* We're just an intermediary peer, route the message along its path */
761 route = get_route (&msg->cid);
765 destroy_route (route);
766 /* FIXME: also destroy paths we MAY have up to the specified link! */
771 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
773 * @param cls Closure (CadetPeer for neighbor that sent the message).
774 * @param msg Message itself.
777 handle_connection_destroy (void *cls,
778 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
780 struct CadetPeer *peer = cls;
781 struct CadetConnection *cc;
782 struct CadetRoute *route;
784 /* First, check if message belongs to a connection that ends here. */
785 cc = GNUNET_CONTAINER_multishortmap_get (connections,
786 &msg->cid.connection_of_tunnel);
789 /* verify message came from the right direction */
790 struct CadetPeerPath *path = GCC_get_path (cc);
793 GCPP_get_peer_at_offset (path,
796 /* received message from unexpected direction, ignore! */
800 LOG (GNUNET_ERROR_TYPE_DEBUG,
801 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
802 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
804 GCC_destroy_without_core (cc);
808 /* We're just an intermediary peer, route the message along its path */
809 LOG (GNUNET_ERROR_TYPE_DEBUG,
810 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
811 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
812 route = get_route (&msg->cid);
816 destroy_route (route);
821 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
823 * @param cls Closure (CadetPeer for neighbor that sent the message).
824 * @param msg Message itself.
827 handle_tunnel_kx (void *cls,
828 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
830 struct CadetPeer *peer = cls;
831 struct CadetConnection *cc;
833 /* First, check if message belongs to a connection that ends here. */
834 cc = GNUNET_CONTAINER_multishortmap_get (connections,
835 &msg->cid.connection_of_tunnel);
838 /* verify message came from the right direction */
839 struct CadetPeerPath *path = GCC_get_path (cc);
842 GCPP_get_peer_at_offset (path,
845 /* received message from unexpected direction, ignore! */
854 /* We're just an intermediary peer, route the message along its path */
862 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
864 * @param cls Closure (CadetPeer for neighbor that sent the message).
865 * @param msg Message itself.
868 handle_tunnel_kx_auth (void *cls,
869 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
871 struct CadetPeer *peer = cls;
872 struct CadetConnection *cc;
874 /* First, check if message belongs to a connection that ends here. */
875 cc = GNUNET_CONTAINER_multishortmap_get (connections,
876 &msg->kx.cid.connection_of_tunnel);
879 /* verify message came from the right direction */
880 struct CadetPeerPath *path = GCC_get_path (cc);
883 GCPP_get_peer_at_offset (path,
886 /* received message from unexpected direction, ignore! */
890 GCC_handle_kx_auth (cc,
895 /* We're just an intermediary peer, route the message along its path */
903 * Check if the encrypted message has the appropriate size.
905 * @param cls Closure (unused).
906 * @param msg Message to check.
908 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
911 check_tunnel_encrypted (void *cls,
912 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
919 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
921 * @param cls Closure (CadetPeer for neighbor that sent the message).
922 * @param msg Message itself.
925 handle_tunnel_encrypted (void *cls,
926 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
928 struct CadetPeer *peer = cls;
929 struct CadetConnection *cc;
931 /* First, check if message belongs to a connection that ends here. */
932 cc = GNUNET_CONTAINER_multishortmap_get (connections,
933 &msg->cid.connection_of_tunnel);
936 /* verify message came from the right direction */
937 struct CadetPeerPath *path = GCC_get_path (cc);
940 GCPP_get_peer_at_offset (path,
943 /* received message from unexpected direction, ignore! */
947 GCC_handle_encrypted (cc,
951 /* We're just an intermediary peer, route the message along its path */
959 * Function called after #GNUNET_CORE_connect has succeeded (or failed
960 * for good). Note that the private key of the peer is intentionally
961 * not exposed here; if you need it, your process should try to read
962 * the private key file directly (which should work if you are
963 * authorized...). Implementations of this function must not call
964 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
968 * @param my_identity ID of this peer, NULL if we failed
971 core_init_cb (void *cls,
972 const struct GNUNET_PeerIdentity *my_identity)
974 if (NULL == my_identity)
982 sizeof (struct GNUNET_PeerIdentity)));
987 * Method called whenever a given peer connects.
990 * @param peer peer identity this notification is about
993 core_connect_cb (void *cls,
994 const struct GNUNET_PeerIdentity *peer,
995 struct GNUNET_MQ_Handle *mq)
997 struct CadetPeer *cp;
999 LOG (GNUNET_ERROR_TYPE_DEBUG,
1000 "CORE connection to peer %s was established.\n",
1011 * Method called whenever a peer disconnects.
1013 * @param cls closure
1014 * @param peer peer identity this notification is about
1017 core_disconnect_cb (void *cls,
1018 const struct GNUNET_PeerIdentity *peer,
1021 struct CadetPeer *cp = peer_cls;
1023 LOG (GNUNET_ERROR_TYPE_DEBUG,
1024 "CORE connection to peer %s went down.\n",
1032 * Initialize the CORE subsystem.
1034 * @param c Configuration.
1037 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1039 struct GNUNET_MQ_MessageHandler handlers[] = {
1040 GNUNET_MQ_hd_var_size (connection_create,
1041 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1042 struct GNUNET_CADET_ConnectionCreateMessage,
1044 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1045 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1046 struct GNUNET_CADET_ConnectionCreateAckMessage,
1048 GNUNET_MQ_hd_fixed_size (connection_broken,
1049 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1050 struct GNUNET_CADET_ConnectionBrokenMessage,
1052 GNUNET_MQ_hd_fixed_size (connection_destroy,
1053 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1054 struct GNUNET_CADET_ConnectionDestroyMessage,
1056 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1057 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1058 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1060 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1061 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1062 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1064 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1065 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1066 struct GNUNET_CADET_TunnelEncryptedMessage,
1068 GNUNET_MQ_handler_end ()
1072 GNUNET_CONFIGURATION_get_value_number (c,
1077 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1079 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1080 core = GNUNET_CORE_connect (c,
1084 &core_disconnect_cb,
1090 * Shut down the CORE subsystem.
1097 GNUNET_CORE_disconnect (core);
1100 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1101 GNUNET_CONTAINER_multishortmap_destroy (routes);
1103 GNUNET_CONTAINER_heap_destroy (route_heap);
1105 if (NULL != timeout_task)
1107 GNUNET_SCHEDULER_cancel (timeout_task);
1108 timeout_task = NULL;
1112 /* end of gnunet-cadet-service_core.c */