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 GNUNET_assert (GNUNET_YES ==
330 GNUNET_CONTAINER_multishortmap_remove (routes,
331 &route->cid.connection_of_tunnel,
333 destroy_direction (&route->prev);
334 destroy_direction (&route->next);
340 * Send message that a route is broken between @a peer1 and @a peer2.
342 * @param target where to send the message
343 * @param cid connection identifier to use
344 * @param peer1 one of the peers where a link is broken
345 * @param peer2 another one of the peers where a link is broken
348 send_broken (struct RouteDirection *target,
349 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
350 const struct GNUNET_PeerIdentity *peer1,
351 const struct GNUNET_PeerIdentity *peer2)
353 struct GNUNET_MQ_Envelope *env;
354 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
356 if (NULL == target->mqm)
357 return; /* Can't send notification, connection is down! */
358 LOG (GNUNET_ERROR_TYPE_DEBUG,
359 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
360 GCP_2s (target->hop),
363 GNUNET_sh2s (&cid->connection_of_tunnel));
365 env = GNUNET_MQ_msg (bm,
366 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
373 GCP_request_mq_cancel (target->mqm,
380 * Function called to check if any routes have timed out, and if
381 * so, to clean them up. Finally, schedules itself again at the
382 * earliest time where there might be more work.
387 timeout_cb (void *cls)
389 struct CadetRoute *r;
390 struct GNUNET_TIME_Relative linger;
391 struct GNUNET_TIME_Absolute exp;
394 linger = GNUNET_TIME_relative_multiply (keepalive_period,
396 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
398 exp = GNUNET_TIME_absolute_add (r->last_use,
400 if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
402 /* Route not yet timed out, wait until it does. */
403 timeout_task = GNUNET_SCHEDULER_add_at (exp,
408 send_broken (&r->prev,
412 send_broken (&r->next,
418 /* No more routes left, so no need for a #timeout_task */
423 * Function called when the message queue to the previous hop
424 * becomes available/unavailable. We expect this function to
425 * be called immediately when we register, and then again
426 * later if the connection ever goes down.
428 * @param cls the `struct RouteDirection`
429 * @param available #GNUNET_YES if sending is now possible,
430 * #GNUNET_NO if sending is no longer possible
431 * #GNUNET_SYSERR if sending is no longer possible
432 * and the last envelope was discarded
435 dir_ready_cb (void *cls,
438 struct RouteDirection *dir = cls;
439 struct CadetRoute *route = dir->my_route;
440 struct RouteDirection *odir;
442 if (GNUNET_YES == ready)
444 struct GNUNET_MQ_Envelope *env;
446 dir->is_ready = GNUNET_YES;
447 if (NULL != (env = dir->out_buffer[dir->out_rpos]))
449 dir->out_buffer[dir->out_rpos] = NULL;
451 if (ROUTE_BUFFER_SIZE == dir->out_rpos)
453 dir->is_ready = GNUNET_NO;
459 odir = (dir == &route->next) ? &route->prev : &route->next;
460 send_broken (&route->next,
462 GCP_get_id (odir->hop),
464 destroy_route (route);
469 * Initialize one of the directions of a route.
471 * @param route route the direction belongs to
472 * @param dir direction to initialize
473 * @param hop next hop on in the @a dir
476 dir_init (struct RouteDirection *dir,
477 struct CadetRoute *route,
478 struct CadetPeer *hop)
481 dir->my_route = route;
482 dir->mqm = GCP_request_mq (hop,
485 GNUNET_assert (GNUNET_YES == dir->is_ready);
490 * We could not create the desired route. Send a
491 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
492 * message to @a target.
494 * @param target who should receive the message
495 * @param cid identifier of the connection/route that failed
496 * @param failure_at neighbour with which we failed to route,
500 send_broken_without_mqm (struct CadetPeer *target,
501 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
502 const struct GNUNET_PeerIdentity *failure_at)
504 struct GNUNET_MQ_Envelope *env;
505 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
507 env = GNUNET_MQ_msg (bm,
508 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
510 bm->peer1 = my_full_id;
511 if (NULL != failure_at)
512 bm->peer2 = *failure_at;
513 GCP_send_ooo (target,
519 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
521 * @param cls Closure (CadetPeer for neighbor that sent the message).
522 * @param msg Message itself.
525 handle_connection_create (void *cls,
526 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
528 struct CadetPeer *sender = cls;
529 struct CadetPeer *next;
530 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
531 struct CadetRoute *route;
532 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
533 unsigned int path_length;
535 enum GNUNET_CADET_ChannelOption options;
537 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
538 path_length = size / sizeof (struct GNUNET_PeerIdentity);
539 /* Initiator is at offset 0. */
540 for (off=1;off<path_length;off++)
541 if (0 == memcmp (&my_full_id,
543 sizeof (struct GNUNET_PeerIdentity)))
545 if (off == path_length)
547 /* We are not on the path, bogus request */
551 /* Check previous hop */
552 if (sender != GCP_get (&pids[off - 1],
555 /* sender is not on the path, not allowed */
560 get_route (&msg->cid))
562 /* Duplicate CREATE, pass it on, previous one might have been lost! */
563 LOG (GNUNET_ERROR_TYPE_DEBUG,
564 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
565 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
566 route_message (sender,
571 if (off == path_length - 1)
573 /* We are the destination, create connection */
574 struct CadetConnection *cc;
575 struct CadetPeerPath *path;
576 struct CadetPeer *origin;
578 cc = GNUNET_CONTAINER_multishortmap_get (connections,
579 &msg->cid.connection_of_tunnel);
582 LOG (GNUNET_ERROR_TYPE_DEBUG,
583 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
584 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
585 GCC_handle_duplicate_create (cc);
589 origin = GCP_get (&pids[0],
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
594 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
595 path = GCPP_get_path_from_route (path_length - 1,
598 GCT_add_inbound_connection (GCP_get_tunnel (origin,
601 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
604 /* Send back BROKEN: duplicate connection on the same path,
605 we will use the other one. */
606 LOG (GNUNET_ERROR_TYPE_DEBUG,
607 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
609 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
611 send_broken_without_mqm (sender,
618 /* We are merely a hop on the way, check if we can support the route */
619 next = GCP_get (&pids[off + 1],
621 if ( (NULL == next) ||
622 (GNUNET_NO == GCP_has_core_connection (next)) )
624 /* unworkable, send back BROKEN notification */
625 LOG (GNUNET_ERROR_TYPE_DEBUG,
626 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
628 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
629 GNUNET_i2s (&pids[off + 1]),
631 send_broken_without_mqm (sender,
636 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
638 LOG (GNUNET_ERROR_TYPE_DEBUG,
639 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
641 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
642 send_broken_without_mqm (sender,
648 /* Workable route, create routing entry */
649 LOG (GNUNET_ERROR_TYPE_DEBUG,
650 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
652 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
653 GNUNET_i2s (&pids[off + 1]),
655 route = GNUNET_new (struct CadetRoute);
656 route->options = options;
657 route->cid = msg->cid;
658 route->last_use = GNUNET_TIME_absolute_get ();
659 dir_init (&route->prev,
662 dir_init (&route->next,
665 GNUNET_assert (GNUNET_OK ==
666 GNUNET_CONTAINER_multishortmap_put (routes,
667 &route->cid.connection_of_tunnel,
669 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
670 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
672 route->last_use.abs_value_us);
673 if (NULL == timeout_task)
674 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
682 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
684 * @param cls Closure (CadetPeer for neighbor that sent the message).
685 * @param msg Message itself.
688 handle_connection_create_ack (void *cls,
689 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
691 struct CadetPeer *peer = cls;
692 struct CadetConnection *cc;
694 /* First, check if ACK belongs to a connection that ends here. */
695 cc = GNUNET_CONTAINER_multishortmap_get (connections,
696 &msg->cid.connection_of_tunnel);
699 /* verify ACK came from the right direction */
700 struct CadetPeerPath *path = GCC_get_path (cc);
703 GCPP_get_peer_at_offset (path,
706 /* received ACK from unexpected direction, ignore! */
710 LOG (GNUNET_ERROR_TYPE_DEBUG,
711 "Received CONNECTION_CREATE_ACK for connection %s.\n",
712 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
713 GCC_handle_connection_create_ack (cc);
717 /* We're just an intermediary peer, route the message along its path */
725 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
727 * @param cls Closure (CadetPeer for neighbor that sent the message).
728 * @param msg Message itself.
729 * @deprecated duplicate logic with #handle_destroy(); dedup!
732 handle_connection_broken (void *cls,
733 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
735 struct CadetPeer *peer = cls;
736 struct CadetConnection *cc;
737 struct CadetRoute *route;
739 /* First, check if message belongs to a connection that ends here. */
740 cc = GNUNET_CONTAINER_multishortmap_get (connections,
741 &msg->cid.connection_of_tunnel);
744 /* verify message came from the right direction */
745 struct CadetPeerPath *path = GCC_get_path (cc);
748 GCPP_get_peer_at_offset (path,
751 /* received message from unexpected direction, ignore! */
755 LOG (GNUNET_ERROR_TYPE_DEBUG,
756 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
757 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
758 GCC_destroy_without_core (cc);
760 /* FIXME: also destroy the path up to the specified link! */
764 /* We're just an intermediary peer, route the message along its path */
768 route = get_route (&msg->cid);
770 destroy_route (route);
771 /* FIXME: also destroy paths we MAY have up to the specified link! */
776 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
778 * @param cls Closure (CadetPeer for neighbor that sent the message).
779 * @param msg Message itself.
782 handle_connection_destroy (void *cls,
783 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
785 struct CadetPeer *peer = cls;
786 struct CadetConnection *cc;
787 struct CadetRoute *route;
789 /* First, check if message belongs to a connection that ends here. */
790 cc = GNUNET_CONTAINER_multishortmap_get (connections,
791 &msg->cid.connection_of_tunnel);
794 /* verify message came from the right direction */
795 struct CadetPeerPath *path = GCC_get_path (cc);
798 GCPP_get_peer_at_offset (path,
801 /* received message from unexpected direction, ignore! */
805 LOG (GNUNET_ERROR_TYPE_DEBUG,
806 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
807 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
809 GCC_destroy_without_core (cc);
813 /* We're just an intermediary peer, route the message along its path */
814 LOG (GNUNET_ERROR_TYPE_DEBUG,
815 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
816 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
820 route = get_route (&msg->cid);
822 destroy_route (route);
827 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
829 * @param cls Closure (CadetPeer for neighbor that sent the message).
830 * @param msg Message itself.
833 handle_tunnel_kx (void *cls,
834 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
836 struct CadetPeer *peer = cls;
837 struct CadetConnection *cc;
839 /* First, check if message belongs to a connection that ends here. */
840 cc = GNUNET_CONTAINER_multishortmap_get (connections,
841 &msg->cid.connection_of_tunnel);
844 /* verify message came from the right direction */
845 struct CadetPeerPath *path = GCC_get_path (cc);
848 GCPP_get_peer_at_offset (path,
851 /* received message from unexpected direction, ignore! */
860 /* We're just an intermediary peer, route the message along its path */
868 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
870 * @param cls Closure (CadetPeer for neighbor that sent the message).
871 * @param msg Message itself.
874 handle_tunnel_kx_auth (void *cls,
875 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
877 struct CadetPeer *peer = cls;
878 struct CadetConnection *cc;
880 /* First, check if message belongs to a connection that ends here. */
881 cc = GNUNET_CONTAINER_multishortmap_get (connections,
882 &msg->kx.cid.connection_of_tunnel);
885 /* verify message came from the right direction */
886 struct CadetPeerPath *path = GCC_get_path (cc);
889 GCPP_get_peer_at_offset (path,
892 /* received message from unexpected direction, ignore! */
896 GCC_handle_kx_auth (cc,
901 /* We're just an intermediary peer, route the message along its path */
909 * Check if the encrypted message has the appropriate size.
911 * @param cls Closure (unused).
912 * @param msg Message to check.
914 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
917 check_tunnel_encrypted (void *cls,
918 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
925 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
927 * @param cls Closure (CadetPeer for neighbor that sent the message).
928 * @param msg Message itself.
931 handle_tunnel_encrypted (void *cls,
932 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
934 struct CadetPeer *peer = cls;
935 struct CadetConnection *cc;
937 /* First, check if message belongs to a connection that ends here. */
938 cc = GNUNET_CONTAINER_multishortmap_get (connections,
939 &msg->cid.connection_of_tunnel);
942 /* verify message came from the right direction */
943 struct CadetPeerPath *path = GCC_get_path (cc);
946 GCPP_get_peer_at_offset (path,
949 /* received message from unexpected direction, ignore! */
953 GCC_handle_encrypted (cc,
957 /* We're just an intermediary peer, route the message along its path */
965 * Function called after #GNUNET_CORE_connect has succeeded (or failed
966 * for good). Note that the private key of the peer is intentionally
967 * not exposed here; if you need it, your process should try to read
968 * the private key file directly (which should work if you are
969 * authorized...). Implementations of this function must not call
970 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
974 * @param my_identity ID of this peer, NULL if we failed
977 core_init_cb (void *cls,
978 const struct GNUNET_PeerIdentity *my_identity)
980 if (NULL == my_identity)
988 sizeof (struct GNUNET_PeerIdentity)));
993 * Method called whenever a given peer connects.
996 * @param peer peer identity this notification is about
999 core_connect_cb (void *cls,
1000 const struct GNUNET_PeerIdentity *peer,
1001 struct GNUNET_MQ_Handle *mq)
1003 struct CadetPeer *cp;
1005 LOG (GNUNET_ERROR_TYPE_DEBUG,
1006 "CORE connection to peer %s was established.\n",
1017 * Method called whenever a peer disconnects.
1019 * @param cls closure
1020 * @param peer peer identity this notification is about
1023 core_disconnect_cb (void *cls,
1024 const struct GNUNET_PeerIdentity *peer,
1027 struct CadetPeer *cp = peer_cls;
1029 LOG (GNUNET_ERROR_TYPE_DEBUG,
1030 "CORE connection to peer %s went down.\n",
1038 * Initialize the CORE subsystem.
1040 * @param c Configuration.
1043 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1045 struct GNUNET_MQ_MessageHandler handlers[] = {
1046 GNUNET_MQ_hd_var_size (connection_create,
1047 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1048 struct GNUNET_CADET_ConnectionCreateMessage,
1050 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1051 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1052 struct GNUNET_CADET_ConnectionCreateAckMessage,
1054 GNUNET_MQ_hd_fixed_size (connection_broken,
1055 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1056 struct GNUNET_CADET_ConnectionBrokenMessage,
1058 GNUNET_MQ_hd_fixed_size (connection_destroy,
1059 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1060 struct GNUNET_CADET_ConnectionDestroyMessage,
1062 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1063 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1064 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1066 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1067 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1068 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1070 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1071 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1072 struct GNUNET_CADET_TunnelEncryptedMessage,
1074 GNUNET_MQ_handler_end ()
1078 GNUNET_CONFIGURATION_get_value_number (c,
1083 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1085 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1086 core = GNUNET_CORE_connect (c,
1090 &core_disconnect_cb,
1096 * Shut down the CORE subsystem.
1103 GNUNET_CORE_disconnect (core);
1106 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1107 GNUNET_CONTAINER_multishortmap_destroy (routes);
1109 GNUNET_CONTAINER_heap_destroy (route_heap);
1111 if (NULL != timeout_task)
1113 GNUNET_SCHEDULER_cancel (timeout_task);
1114 timeout_task = NULL;
1118 /* end of gnunet-cadet-service_core.c */