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 "gnunet_statistics_service.h"
40 #include "cadet_protocol.h"
43 #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__)
47 * Number of messages we are willing to buffer per route.
49 #define ROUTE_BUFFER_SIZE 8
53 * Information we keep per direction for a route.
60 struct CadetPeer *hop;
63 * Route this direction is part of.
65 struct CadetRoute *my_route;
68 * Message queue manager for @e hop.
70 struct GCP_MessageQueueManager *mqm;
73 * Cyclic message buffer to @e hop.
75 struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE];
78 * Next write offset to use to append messages to @e out_buffer.
80 unsigned int out_wpos;
83 * Next read offset to use to retrieve messages from @e out_buffer.
85 unsigned int out_rpos;
88 * Is @e mqm currently ready for transmission?
96 * Description of a segment of a `struct CadetConnection` at the
97 * intermediate peers. Routes are basically entries in a peer's
98 * routing table for forwarding traffic. At both endpoints, the
99 * routes are terminated by a `struct CadetConnection`, which knows
100 * the complete `struct CadetPath` that is formed by the individual
107 * Information about the next hop on this route.
109 struct RouteDirection next;
112 * Information about the previous hop on this route.
114 struct RouteDirection prev;
117 * Unique identifier for the connection that uses this route.
119 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
122 * When was this route last in use?
124 struct GNUNET_TIME_Absolute last_use;
130 * Handle to the CORE service.
132 static struct GNUNET_CORE_Handle *core;
135 * Routes on which this peer is an intermediate.
137 static struct GNUNET_CONTAINER_MultiShortmap *routes;
141 * Get the route corresponding to a hash.
143 * @param cid hash generated from the connection identifier
145 static struct CadetRoute *
146 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
148 return GNUNET_CONTAINER_multishortmap_get (routes,
149 &cid->connection_of_tunnel);
154 * We message @a msg from @a prev. Find its route by @a cid and
155 * forward to the next hop. Drop and signal broken route if we do not
158 * @param prev previous hop (sender)
159 * @param cid connection identifier, tells us which route to use
160 * @param msg the message to forward
163 route_message (struct CadetPeer *prev,
164 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
165 const struct GNUNET_MessageHeader *msg)
167 struct CadetRoute *route;
168 struct RouteDirection *dir;
169 struct GNUNET_MQ_Envelope *env;
171 route = get_route (cid);
174 struct GNUNET_MQ_Envelope *env;
175 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
177 LOG (GNUNET_ERROR_TYPE_DEBUG,
178 "Failed to route message of type %u from %s on connection %s: no route\n",
181 GNUNET_sh2s (&cid->connection_of_tunnel));
182 env = GNUNET_MQ_msg (bm,
183 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
185 bm->peer1 = my_full_id;
190 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
191 if (GNUNET_YES == dir->is_ready)
193 LOG (GNUNET_ERROR_TYPE_DEBUG,
194 "Routing message of type %u from %s to %s on connection %s\n",
197 GNUNET_i2s (GCP_get_id (dir->hop)),
198 GNUNET_sh2s (&cid->connection_of_tunnel));
199 dir->is_ready = GNUNET_NO;
201 GNUNET_MQ_msg_copy (msg));
204 env = dir->out_buffer[dir->out_wpos];
207 /* Queue full, drop earliest message in queue */
208 LOG (GNUNET_ERROR_TYPE_DEBUG,
209 "Queue full due to new message of type %u from %s to %s on connection %s, dropping old message\n",
212 GNUNET_i2s (GCP_get_id (dir->hop)),
213 GNUNET_sh2s (&cid->connection_of_tunnel));
214 GNUNET_STATISTICS_update (stats,
215 "# messages dropped due to full buffer",
218 GNUNET_assert (dir->out_rpos == dir->out_wpos);
219 GNUNET_MQ_discard (env);
221 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
224 LOG (GNUNET_ERROR_TYPE_DEBUG,
225 "Queueing new message of type %u from %s to %s on connection %s\n",
228 GNUNET_i2s (GCP_get_id (dir->hop)),
229 GNUNET_sh2s (&cid->connection_of_tunnel));
230 env = GNUNET_MQ_msg_copy (msg);
231 dir->out_buffer[dir->out_wpos] = env;
233 if (ROUTE_BUFFER_SIZE == dir->out_wpos)
239 * Check if the create_connection message has the appropriate size.
241 * @param cls Closure (unused).
242 * @param msg Message to check.
244 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
247 check_connection_create (void *cls,
248 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
250 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
252 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
262 * Free internal data of a route direction.
264 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
267 destroy_direction (struct RouteDirection *dir)
269 for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++)
270 if (NULL != dir->out_buffer[i])
272 GNUNET_MQ_discard (dir->out_buffer[i]);
273 dir->out_buffer[i] = NULL;
275 if (NULL != dir->mqm)
277 GCP_request_mq_cancel (dir->mqm,
285 * Destroy our state for @a route.
287 * @param route route to destroy
290 destroy_route (struct CadetRoute *route)
292 LOG (GNUNET_ERROR_TYPE_DEBUG,
293 "Destroying route from %s to %s of connection %s\n",
294 GNUNET_i2s (GCP_get_id (route->prev.hop)),
295 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
296 GNUNET_sh2s (&route->cid.connection_of_tunnel));
297 destroy_direction (&route->prev);
298 destroy_direction (&route->next);
304 * Send message that a route is broken between @a peer1 and @a peer2.
306 * @param target where to send the message
307 * @param cid connection identifier to use
308 * @param peer1 one of the peers where a link is broken
309 * @param peer2 another one of the peers where a link is broken
312 send_broken (struct RouteDirection *target,
313 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
314 const struct GNUNET_PeerIdentity *peer1,
315 const struct GNUNET_PeerIdentity *peer2)
317 struct GNUNET_MQ_Envelope *env;
318 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
320 if (NULL == target->mqm)
321 return; /* Can't send notification, connection is down! */
322 LOG (GNUNET_ERROR_TYPE_DEBUG,
323 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
324 GCP_2s (target->hop),
327 GNUNET_sh2s (&cid->connection_of_tunnel));
329 env = GNUNET_MQ_msg (bm,
330 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
337 GCP_request_mq_cancel (target->mqm,
344 * Function called when the message queue to the previous hop
345 * becomes available/unavailable. We expect this function to
346 * be called immediately when we register, and then again
347 * later if the connection ever goes down.
349 * @param cls the `struct RouteDirection`
350 * @param available #GNUNET_YES if sending is now possible,
351 * #GNUNET_NO if sending is no longer possible
352 * #GNUNET_SYSERR if sending is no longer possible
353 * and the last envelope was discarded
356 dir_ready_cb (void *cls,
359 struct RouteDirection *dir = cls;
360 struct CadetRoute *route = dir->my_route;
361 struct RouteDirection *odir;
363 if (GNUNET_YES == ready)
365 struct GNUNET_MQ_Envelope *env;
367 dir->is_ready = GNUNET_YES;
368 if (NULL != (env = dir->out_buffer[dir->out_rpos]))
370 dir->out_buffer[dir->out_rpos] = NULL;
372 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
374 dir->is_ready = GNUNET_NO;
380 odir = (dir == &route->next) ? &route->prev : &route->next;
381 send_broken (&route->next,
383 GCP_get_id (odir->hop),
385 destroy_route (route);
390 * Initialize one of the directions of a route.
392 * @param route route the direction belongs to
393 * @param dir direction to initialize
394 * @param hop next hop on in the @a dir
397 dir_init (struct RouteDirection *dir,
398 struct CadetRoute *route,
399 struct CadetPeer *hop)
402 dir->my_route = route;
403 dir->mqm = GCP_request_mq (hop,
406 GNUNET_assert (GNUNET_YES == dir->is_ready);
411 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
413 * @param cls Closure (CadetPeer for neighbor that sent the message).
414 * @param msg Message itself.
417 handle_connection_create (void *cls,
418 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
420 struct CadetPeer *sender = cls;
421 struct CadetPeer *next;
422 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
423 struct CadetRoute *route;
424 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
425 unsigned int path_length;
428 path_length = size / sizeof (struct GNUNET_PeerIdentity);
429 /* Initiator is at offset 0. */
430 for (off=1;off<path_length;off++)
431 if (0 == memcmp (&my_full_id,
433 sizeof (struct GNUNET_PeerIdentity)))
435 if (off == path_length)
437 /* We are not on the path, bogus request */
441 /* Check previous hop */
442 if (sender != GCP_get (&pids[off - 1],
445 /* sender is not on the path, not allowed */
450 get_route (&msg->cid))
452 /* Duplicate CREATE, pass it on, previous one might have been lost! */
453 LOG (GNUNET_ERROR_TYPE_DEBUG,
454 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
455 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
456 route_message (sender,
461 if (off == path_length - 1)
463 /* We are the destination, create connection */
464 struct CadetConnection *cc;
465 struct CadetPeerPath *path;
466 struct CadetPeer *origin;
468 cc = GNUNET_CONTAINER_multishortmap_get (connections,
469 &msg->cid.connection_of_tunnel);
472 LOG (GNUNET_ERROR_TYPE_DEBUG,
473 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
474 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
475 GCC_handle_duplicate_create (cc);
479 origin = GCP_get (&pids[0],
481 LOG (GNUNET_ERROR_TYPE_DEBUG,
482 "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
484 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
485 path = GCPP_get_path_from_route (path_length - 1,
488 GCT_add_inbound_connection (GCP_get_tunnel (origin,
493 /* Send back BROKEN: duplicate connection on the same path,
494 we will use the other one. */
495 struct GNUNET_MQ_Envelope *env;
496 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
498 LOG (GNUNET_ERROR_TYPE_DEBUG,
499 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
501 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
503 env = GNUNET_MQ_msg (bm,
504 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
506 bm->peer1 = my_full_id;
507 GCP_send_ooo (sender,
513 /* We are merely a hop on the way, check if we can support the route */
514 next = GCP_get (&pids[off + 1],
516 if ( (NULL == next) ||
517 (GNUNET_NO == GCP_has_core_connection (next)) )
519 /* unworkable, send back BROKEN notification */
520 struct GNUNET_MQ_Envelope *env;
521 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
523 LOG (GNUNET_ERROR_TYPE_DEBUG,
524 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
526 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
527 GNUNET_i2s (&pids[off + 1]),
529 env = GNUNET_MQ_msg (bm,
530 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
532 bm->peer1 = pids[off + 1];
533 bm->peer2 = my_full_id;
534 GCP_send_ooo (sender,
539 /* Workable route, create routing entry */
540 LOG (GNUNET_ERROR_TYPE_DEBUG,
541 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
543 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
544 GNUNET_i2s (&pids[off + 1]),
546 route = GNUNET_new (struct CadetRoute);
547 route->cid = msg->cid;
548 dir_init (&route->prev,
551 dir_init (&route->next,
554 GNUNET_assert (GNUNET_OK ==
555 GNUNET_CONTAINER_multishortmap_put (routes,
556 &route->cid.connection_of_tunnel,
558 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
563 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
565 * @param cls Closure (CadetPeer for neighbor that sent the message).
566 * @param msg Message itself.
569 handle_connection_create_ack (void *cls,
570 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
572 struct CadetPeer *peer = cls;
573 struct CadetConnection *cc;
575 /* First, check if ACK belongs to a connection that ends here. */
576 cc = GNUNET_CONTAINER_multishortmap_get (connections,
577 &msg->cid.connection_of_tunnel);
580 /* verify ACK came from the right direction */
581 struct CadetPeerPath *path = GCC_get_path (cc);
584 GCPP_get_peer_at_offset (path,
587 /* received ACK from unexpected direction, ignore! */
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Received CONNECTION_CREATE_ACK for connection %s.\n",
593 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
594 GCC_handle_connection_create_ack (cc);
598 /* We're just an intermediary peer, route the message along its path */
606 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
608 * @param cls Closure (CadetPeer for neighbor that sent the message).
609 * @param msg Message itself.
610 * @deprecated duplicate logic with #handle_destroy(); dedup!
613 handle_connection_broken (void *cls,
614 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
616 struct CadetPeer *peer = cls;
617 struct CadetConnection *cc;
618 struct CadetRoute *route;
620 /* First, check if message belongs to a connection that ends here. */
621 cc = GNUNET_CONTAINER_multishortmap_get (connections,
622 &msg->cid.connection_of_tunnel);
625 /* verify message came from the right direction */
626 struct CadetPeerPath *path = GCC_get_path (cc);
629 GCPP_get_peer_at_offset (path,
632 /* received message from unexpected direction, ignore! */
636 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
638 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
639 GCC_destroy_without_core (cc);
641 /* FIXME: also destroy the path up to the specified link! */
645 /* We're just an intermediary peer, route the message along its path */
646 route = get_route (&msg->cid);
650 destroy_route (route);
651 /* FIXME: also destroy paths we MAY have up to the specified link! */
656 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
658 * @param cls Closure (CadetPeer for neighbor that sent the message).
659 * @param msg Message itself.
662 handle_connection_destroy (void *cls,
663 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
665 struct CadetPeer *peer = cls;
666 struct CadetConnection *cc;
667 struct CadetRoute *route;
669 /* First, check if message belongs to a connection that ends here. */
670 cc = GNUNET_CONTAINER_multishortmap_get (connections,
671 &msg->cid.connection_of_tunnel);
674 /* verify message came from the right direction */
675 struct CadetPeerPath *path = GCC_get_path (cc);
678 GCPP_get_peer_at_offset (path,
681 /* received message from unexpected direction, ignore! */
685 LOG (GNUNET_ERROR_TYPE_DEBUG,
686 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
687 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
689 GCC_destroy_without_core (cc);
693 /* We're just an intermediary peer, route the message along its path */
694 LOG (GNUNET_ERROR_TYPE_DEBUG,
695 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
696 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
697 route = get_route (&msg->cid);
701 destroy_route (route);
706 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
708 * @param cls Closure (CadetPeer for neighbor that sent the message).
709 * @param msg Message itself.
712 handle_tunnel_kx (void *cls,
713 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
715 struct CadetPeer *peer = cls;
716 struct CadetConnection *cc;
718 /* First, check if message belongs to a connection that ends here. */
719 cc = GNUNET_CONTAINER_multishortmap_get (connections,
720 &msg->cid.connection_of_tunnel);
723 /* verify message came from the right direction */
724 struct CadetPeerPath *path = GCC_get_path (cc);
727 GCPP_get_peer_at_offset (path,
730 /* received message from unexpected direction, ignore! */
739 /* We're just an intermediary peer, route the message along its path */
747 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
749 * @param cls Closure (CadetPeer for neighbor that sent the message).
750 * @param msg Message itself.
753 handle_tunnel_kx_auth (void *cls,
754 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
756 struct CadetPeer *peer = cls;
757 struct CadetConnection *cc;
759 /* First, check if message belongs to a connection that ends here. */
760 cc = GNUNET_CONTAINER_multishortmap_get (connections,
761 &msg->kx.cid.connection_of_tunnel);
764 /* verify message came from the right direction */
765 struct CadetPeerPath *path = GCC_get_path (cc);
768 GCPP_get_peer_at_offset (path,
771 /* received message from unexpected direction, ignore! */
775 GCC_handle_kx_auth (cc,
780 /* We're just an intermediary peer, route the message along its path */
788 * Check if the encrypted message has the appropriate size.
790 * @param cls Closure (unused).
791 * @param msg Message to check.
793 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
796 check_tunnel_encrypted (void *cls,
797 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
804 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
806 * @param cls Closure (CadetPeer for neighbor that sent the message).
807 * @param msg Message itself.
810 handle_tunnel_encrypted (void *cls,
811 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
813 struct CadetPeer *peer = cls;
814 struct CadetConnection *cc;
816 /* First, check if message belongs to a connection that ends here. */
817 cc = GNUNET_CONTAINER_multishortmap_get (connections,
818 &msg->cid.connection_of_tunnel);
821 /* verify message came from the right direction */
822 struct CadetPeerPath *path = GCC_get_path (cc);
825 GCPP_get_peer_at_offset (path,
828 /* received message from unexpected direction, ignore! */
832 GCC_handle_encrypted (cc,
836 /* We're just an intermediary peer, route the message along its path */
844 * Function called after #GNUNET_CORE_connect has succeeded (or failed
845 * for good). Note that the private key of the peer is intentionally
846 * not exposed here; if you need it, your process should try to read
847 * the private key file directly (which should work if you are
848 * authorized...). Implementations of this function must not call
849 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
853 * @param my_identity ID of this peer, NULL if we failed
856 core_init_cb (void *cls,
857 const struct GNUNET_PeerIdentity *my_identity)
859 if (NULL == my_identity)
867 sizeof (struct GNUNET_PeerIdentity)));
872 * Method called whenever a given peer connects.
875 * @param peer peer identity this notification is about
878 core_connect_cb (void *cls,
879 const struct GNUNET_PeerIdentity *peer,
880 struct GNUNET_MQ_Handle *mq)
882 struct CadetPeer *cp;
884 LOG (GNUNET_ERROR_TYPE_DEBUG,
885 "CORE connection to peer %s was established.\n",
896 * Method called whenever a peer disconnects.
899 * @param peer peer identity this notification is about
902 core_disconnect_cb (void *cls,
903 const struct GNUNET_PeerIdentity *peer,
906 struct CadetPeer *cp = peer_cls;
908 LOG (GNUNET_ERROR_TYPE_DEBUG,
909 "CORE connection to peer %s went down.\n",
917 * Initialize the CORE subsystem.
919 * @param c Configuration.
922 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
924 struct GNUNET_MQ_MessageHandler handlers[] = {
925 GNUNET_MQ_hd_var_size (connection_create,
926 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
927 struct GNUNET_CADET_ConnectionCreateMessage,
929 GNUNET_MQ_hd_fixed_size (connection_create_ack,
930 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
931 struct GNUNET_CADET_ConnectionCreateAckMessage,
933 GNUNET_MQ_hd_fixed_size (connection_broken,
934 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
935 struct GNUNET_CADET_ConnectionBrokenMessage,
937 GNUNET_MQ_hd_fixed_size (connection_destroy,
938 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
939 struct GNUNET_CADET_ConnectionDestroyMessage,
941 GNUNET_MQ_hd_fixed_size (tunnel_kx,
942 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
943 struct GNUNET_CADET_TunnelKeyExchangeMessage,
945 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
946 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
947 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
949 GNUNET_MQ_hd_var_size (tunnel_encrypted,
950 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
951 struct GNUNET_CADET_TunnelEncryptedMessage,
953 GNUNET_MQ_handler_end ()
956 routes = GNUNET_CONTAINER_multishortmap_create (1024,
958 core = GNUNET_CORE_connect (c,
968 * Shut down the CORE subsystem.
975 GNUNET_CORE_disconnect (core);
978 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
979 GNUNET_CONTAINER_multishortmap_destroy (routes);
982 /* end of gnunet-cadet-service_core.c */