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_core.h"
34 #include "gnunet-service-cadet_paths.h"
35 #include "gnunet-service-cadet_peer.h"
36 #include "gnunet-service-cadet_connection.h"
37 #include "gnunet-service-cadet_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__)
46 * Information we keep per direction for a route.
48 struct RouteDirection;
52 * Set of CadetRoutes that have exactly the same number of messages
53 * in their buffer. Used so we can efficiently find all of those
54 * routes that have the current maximum of messages in the buffer (in
55 * case we have to purge).
61 * Rung of RouteDirections with one more buffer entry each.
66 * Rung of RouteDirections with one less buffer entry each.
71 * DLL of route directions with a number of buffer entries matching this rung.
73 struct RouteDirection *rd_head;
76 * DLL of route directions with a number of buffer entries matching this rung.
78 struct RouteDirection *rd_tail;
81 * Total number of route directions in this rung.
83 unsigned int num_routes;
86 * Number of messages route directions at this rung have
89 unsigned int rung_off;
94 * Information we keep per direction for a route.
100 * DLL of other route directions within the same `struct Rung`.
102 struct RouteDirection *prev;
105 * DLL of other route directions within the same `struct Rung`.
107 struct RouteDirection *next;
110 * Rung of this route direction (matches length of the buffer DLL).
115 * Head of DLL of envelopes we have in the buffer for this direction.
117 struct GNUNET_MQ_Envelope *env_head;
120 * Tail of DLL of envelopes we have in the buffer for this direction.
122 struct GNUNET_MQ_Envelope *env_tail;
127 struct CadetPeer *hop;
130 * Route this direction is part of.
132 struct CadetRoute *my_route;
135 * Message queue manager for @e hop.
137 struct GCP_MessageQueueManager *mqm;
140 * Is @e mqm currently ready for transmission?
148 * Description of a segment of a `struct CadetConnection` at the
149 * intermediate peers. Routes are basically entries in a peer's
150 * routing table for forwarding traffic. At both endpoints, the
151 * routes are terminated by a `struct CadetConnection`, which knows
152 * the complete `struct CadetPath` that is formed by the individual
159 * Information about the next hop on this route.
161 struct RouteDirection next;
164 * Information about the previous hop on this route.
166 struct RouteDirection prev;
169 * Unique identifier for the connection that uses this route.
171 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
174 * When was this route last in use?
176 struct GNUNET_TIME_Absolute last_use;
179 * Position of this route in the #route_heap.
181 struct GNUNET_CONTAINER_HeapNode *hn;
184 * Options for the route, control buffering.
186 enum GNUNET_CADET_ChannelOption options;
191 * Handle to the CORE service.
193 static struct GNUNET_CORE_Handle *core;
196 * Routes on which this peer is an intermediate.
198 static struct GNUNET_CONTAINER_MultiShortmap *routes;
201 * Heap of routes, MIN-sorted by last activity.
203 static struct GNUNET_CONTAINER_Heap *route_heap;
206 * Rung zero (always pointed to by #rung_head).
208 static struct Rung rung_zero;
211 * DLL of rungs, with the head always point to a rung of
212 * route directions with no messages in the queue.
214 static struct Rung *rung_head = &rung_zero;
217 * Tail of the #rung_head DLL.
219 static struct Rung *rung_tail = &rung_zero;
222 * Maximum number of concurrent routes this peer will support.
224 static unsigned long long max_routes;
227 * Maximum number of envelopes we will buffer at this peer.
229 static unsigned long long max_buffers;
232 * Current number of envelopes we have buffered at this peer.
234 static unsigned long long cur_buffers;
237 * Task to timeout routes.
239 static struct GNUNET_SCHEDULER_Task *timeout_task;
243 * Get the route corresponding to a hash.
245 * @param cid hash generated from the connection identifier
247 static struct CadetRoute *
248 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
250 return GNUNET_CONTAINER_multishortmap_get (routes,
251 &cid->connection_of_tunnel);
256 * Lower the rung in which @a dir is by 1.
258 * @param dir direction to lower in rung.
261 lower_rung (struct RouteDirection *dir)
263 struct Rung *rung = dir->rung;
266 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
270 GNUNET_assert (NULL != prev);
271 if (prev->rung_off != rung->rung_off - 1)
273 prev = GNUNET_new (struct Rung);
274 prev->rung_off = rung->rung_off - 1;
275 GNUNET_CONTAINER_DLL_insert_after (rung_head,
280 GNUNET_assert (NULL != prev);
281 GNUNET_CONTAINER_DLL_insert (prev->rd_head,
289 * Discard the buffer @a env from the route direction @a dir and
290 * move @a dir down a rung.
292 * @param dir direction that contains the @a env in the buffer
293 * @param env envelope to discard
296 discard_buffer (struct RouteDirection *dir,
297 struct GNUNET_MQ_Envelope *env)
299 GNUNET_MQ_dll_remove (&dir->env_head,
303 GNUNET_MQ_discard (env);
305 GNUNET_STATISTICS_set (stats,
313 * Discard all messages from the highest rung, to make space.
316 discard_all_from_rung_tail ()
318 struct Rung *tail = rung_tail;
319 struct RouteDirection *dir;
321 while (NULL != (dir = tail->rd_head))
323 LOG (GNUNET_ERROR_TYPE_DEBUG,
324 "Queue full due new message %s on connection %s, dropping old message\n",
325 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
326 GNUNET_STATISTICS_update (stats,
327 "# messages dropped due to full buffer",
333 GNUNET_CONTAINER_DLL_remove (rung_head,
341 * We message @a msg from @a prev. Find its route by @a cid and
342 * forward to the next hop. Drop and signal broken route if we do not
345 * @param prev previous hop (sender)
346 * @param cid connection identifier, tells us which route to use
347 * @param msg the message to forward
350 route_message (struct CadetPeer *prev,
351 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
352 const struct GNUNET_MessageHeader *msg)
354 struct CadetRoute *route;
355 struct RouteDirection *dir;
358 struct GNUNET_MQ_Envelope *env;
360 route = get_route (cid);
363 struct GNUNET_MQ_Envelope *env;
364 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
366 LOG (GNUNET_ERROR_TYPE_DEBUG,
367 "Failed to route message of type %u from %s on connection %s: no route\n",
370 GNUNET_sh2s (&cid->connection_of_tunnel));
371 switch (ntohs (msg->type))
373 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
374 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
375 /* No need to respond to these! */
378 env = GNUNET_MQ_msg (bm,
379 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
381 bm->peer1 = my_full_id;
386 route->last_use = GNUNET_TIME_absolute_get ();
387 GNUNET_CONTAINER_heap_update_cost (route->hn,
388 route->last_use.abs_value_us);
389 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
390 if (GNUNET_YES == dir->is_ready)
392 LOG (GNUNET_ERROR_TYPE_DEBUG,
393 "Routing message of type %u from %s to %s on connection %s\n",
396 GNUNET_i2s (GCP_get_id (dir->hop)),
397 GNUNET_sh2s (&cid->connection_of_tunnel));
398 dir->is_ready = GNUNET_NO;
400 GNUNET_MQ_msg_copy (msg));
403 /* Check if buffering is disallowed, and if so, make sure we only queue
404 one message per direction. */
405 if ( (0 != (route->options & GNUNET_CADET_OPTION_NOBUFFER)) &&
406 (NULL != dir->env_head) )
410 if (cur_buffers == max_buffers)
412 /* Need to make room. */
413 if (NULL != rung->next)
415 /* Easy case, drop messages from route directions in highest rung */
416 discard_all_from_rung_tail ();
420 /* We are in the highest rung, drop our own! */
421 LOG (GNUNET_ERROR_TYPE_DEBUG,
422 "Queue full due new message %s on connection %s, dropping old message\n",
423 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
424 GNUNET_STATISTICS_update (stats,
425 "# messages dropped due to full buffer",
433 /* remove 'dir' from current rung */
434 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
437 /* make 'nxt' point to the next higher rung, creat if necessary */
439 if ( (NULL == nxt) ||
440 (rung->rung_off + 1 != nxt->rung_off) )
442 nxt = GNUNET_new (struct Rung);
443 nxt->rung_off = rung->rung_off + 1;
444 GNUNET_CONTAINER_DLL_insert_after (rung_head,
449 /* insert 'dir' into next higher rung */
450 GNUNET_CONTAINER_DLL_insert (nxt->rd_head,
455 /* add message into 'dir' buffer */
456 LOG (GNUNET_ERROR_TYPE_DEBUG,
457 "Queueing new message of type %u from %s to %s on connection %s\n",
460 GNUNET_i2s (GCP_get_id (dir->hop)),
461 GNUNET_sh2s (&cid->connection_of_tunnel));
462 env = GNUNET_MQ_msg_copy (msg);
463 GNUNET_MQ_dll_insert_tail (&dir->env_head,
467 GNUNET_STATISTICS_set (stats,
471 /* Clean up 'rung' if now empty (and not head) */
472 if ( (NULL == rung->rd_head) &&
473 (rung != rung_head) )
475 GNUNET_CONTAINER_DLL_remove (rung_head,
484 * Check if the create_connection message has the appropriate size.
486 * @param cls Closure (unused).
487 * @param msg Message to check.
489 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
492 check_connection_create (void *cls,
493 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
495 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
497 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
507 * Free internal data of a route direction.
509 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
512 destroy_direction (struct RouteDirection *dir)
514 struct GNUNET_MQ_Envelope *env;
516 while (NULL != (env = dir->env_head))
518 GNUNET_STATISTICS_update (stats,
519 "# messages dropped due to route destruction",
525 if (NULL != dir->mqm)
527 GCP_request_mq_cancel (dir->mqm,
531 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head,
538 * Destroy our state for @a route.
540 * @param route route to destroy
543 destroy_route (struct CadetRoute *route)
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Destroying route from %s to %s of connection %s\n",
547 GNUNET_i2s (GCP_get_id (route->prev.hop)),
548 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
549 GNUNET_sh2s (&route->cid.connection_of_tunnel));
550 GNUNET_assert (route ==
551 GNUNET_CONTAINER_heap_remove_node (route->hn));
552 GNUNET_assert (GNUNET_YES ==
553 GNUNET_CONTAINER_multishortmap_remove (routes,
554 &route->cid.connection_of_tunnel,
556 GNUNET_STATISTICS_set (stats,
558 GNUNET_CONTAINER_multishortmap_size (routes),
560 destroy_direction (&route->prev);
561 destroy_direction (&route->next);
567 * Send message that a route is broken between @a peer1 and @a peer2.
569 * @param target where to send the message
570 * @param cid connection identifier to use
571 * @param peer1 one of the peers where a link is broken
572 * @param peer2 another one of the peers where a link is broken
575 send_broken (struct RouteDirection *target,
576 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
577 const struct GNUNET_PeerIdentity *peer1,
578 const struct GNUNET_PeerIdentity *peer2)
580 struct GNUNET_MQ_Envelope *env;
581 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
583 if (NULL == target->mqm)
584 return; /* Can't send notification, connection is down! */
585 LOG (GNUNET_ERROR_TYPE_DEBUG,
586 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
587 GCP_2s (target->hop),
590 GNUNET_sh2s (&cid->connection_of_tunnel));
592 env = GNUNET_MQ_msg (bm,
593 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
599 GCP_request_mq_cancel (target->mqm,
606 * Function called to check if any routes have timed out, and if
607 * so, to clean them up. Finally, schedules itself again at the
608 * earliest time where there might be more work.
613 timeout_cb (void *cls)
615 struct CadetRoute *r;
616 struct GNUNET_TIME_Relative linger;
617 struct GNUNET_TIME_Absolute exp;
620 linger = GNUNET_TIME_relative_multiply (keepalive_period,
622 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
624 exp = GNUNET_TIME_absolute_add (r->last_use,
626 if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us)
628 /* Route not yet timed out, wait until it does. */
629 timeout_task = GNUNET_SCHEDULER_add_at (exp,
634 send_broken (&r->prev,
638 send_broken (&r->next,
644 /* No more routes left, so no need for a #timeout_task */
649 * Function called when the message queue to the previous hop
650 * becomes available/unavailable. We expect this function to
651 * be called immediately when we register, and then again
652 * later if the connection ever goes down.
654 * @param cls the `struct RouteDirection`
655 * @param available #GNUNET_YES if sending is now possible,
656 * #GNUNET_NO if sending is no longer possible
657 * #GNUNET_SYSERR if sending is no longer possible
658 * and the last envelope was discarded
661 dir_ready_cb (void *cls,
664 struct RouteDirection *dir = cls;
665 struct CadetRoute *route = dir->my_route;
666 struct RouteDirection *odir;
668 if (GNUNET_YES == ready)
670 struct GNUNET_MQ_Envelope *env;
672 dir->is_ready = GNUNET_YES;
673 if (NULL != (env = dir->env_head))
675 GNUNET_MQ_dll_remove (&dir->env_head,
679 GNUNET_STATISTICS_set (stats,
684 dir->is_ready = GNUNET_NO;
690 odir = (dir == &route->next) ? &route->prev : &route->next;
691 send_broken (&route->next,
693 GCP_get_id (odir->hop),
695 destroy_route (route);
700 * Initialize one of the directions of a route.
702 * @param route route the direction belongs to
703 * @param dir direction to initialize
704 * @param hop next hop on in the @a dir
707 dir_init (struct RouteDirection *dir,
708 struct CadetRoute *route,
709 struct CadetPeer *hop)
712 dir->my_route = route;
713 dir->mqm = GCP_request_mq (hop,
716 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head,
719 dir->rung = rung_head;
720 GNUNET_assert (GNUNET_YES == dir->is_ready);
725 * We could not create the desired route. Send a
726 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
727 * message to @a target.
729 * @param target who should receive the message
730 * @param cid identifier of the connection/route that failed
731 * @param failure_at neighbour with which we failed to route,
735 send_broken_without_mqm (struct CadetPeer *target,
736 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
737 const struct GNUNET_PeerIdentity *failure_at)
739 struct GNUNET_MQ_Envelope *env;
740 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
742 env = GNUNET_MQ_msg (bm,
743 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
745 bm->peer1 = my_full_id;
746 if (NULL != failure_at)
747 bm->peer2 = *failure_at;
748 GCP_send_ooo (target,
754 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
756 * @param cls Closure (CadetPeer for neighbor that sent the message).
757 * @param msg Message itself.
760 handle_connection_create (void *cls,
761 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
763 struct CadetPeer *sender = cls;
764 struct CadetPeer *next;
765 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
766 struct CadetRoute *route;
767 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
768 unsigned int path_length;
770 enum GNUNET_CADET_ChannelOption options;
772 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
773 path_length = size / sizeof (struct GNUNET_PeerIdentity);
774 /* Initiator is at offset 0. */
775 for (off=1;off<path_length;off++)
776 if (0 == memcmp (&my_full_id,
778 sizeof (struct GNUNET_PeerIdentity)))
780 if (off == path_length)
782 /* We are not on the path, bogus request */
786 /* Check previous hop */
787 if (sender != GCP_get (&pids[off - 1],
790 /* sender is not on the path, not allowed */
795 get_route (&msg->cid))
797 /* Duplicate CREATE, pass it on, previous one might have been lost! */
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
800 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
801 route_message (sender,
806 if (off == path_length - 1)
808 /* We are the destination, create connection */
809 struct CadetConnection *cc;
810 struct CadetPeerPath *path;
811 struct CadetPeer *origin;
813 cc = GCC_lookup (&msg->cid);
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
818 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
819 GCC_handle_duplicate_create (cc);
823 origin = GCP_get (&pids[0],
825 LOG (GNUNET_ERROR_TYPE_DEBUG,
826 "Received CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
828 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
829 path = GCPP_get_path_from_route (path_length - 1,
832 GCT_add_inbound_connection (GCP_get_tunnel (origin,
835 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
838 /* Send back BROKEN: duplicate connection on the same path,
839 we will use the other one. */
840 LOG (GNUNET_ERROR_TYPE_DEBUG,
841 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
843 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
845 send_broken_without_mqm (sender,
852 /* We are merely a hop on the way, check if we can support the route */
853 next = GCP_get (&pids[off + 1],
855 if ( (NULL == next) ||
856 (GNUNET_NO == GCP_has_core_connection (next)) )
858 /* unworkable, send back BROKEN notification */
859 LOG (GNUNET_ERROR_TYPE_DEBUG,
860 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
862 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
863 GNUNET_i2s (&pids[off + 1]),
865 send_broken_without_mqm (sender,
870 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
872 LOG (GNUNET_ERROR_TYPE_DEBUG,
873 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
875 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
876 send_broken_without_mqm (sender,
882 /* Workable route, create routing entry */
883 LOG (GNUNET_ERROR_TYPE_DEBUG,
884 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
886 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
887 GNUNET_i2s (&pids[off + 1]),
889 route = GNUNET_new (struct CadetRoute);
890 route->options = options;
891 route->cid = msg->cid;
892 route->last_use = GNUNET_TIME_absolute_get ();
893 dir_init (&route->prev,
896 dir_init (&route->next,
899 GNUNET_assert (GNUNET_OK ==
900 GNUNET_CONTAINER_multishortmap_put (routes,
901 &route->cid.connection_of_tunnel,
903 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
904 GNUNET_STATISTICS_set (stats,
906 GNUNET_CONTAINER_multishortmap_size (routes),
908 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
910 route->last_use.abs_value_us);
911 if (NULL == timeout_task)
912 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
920 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
922 * @param cls Closure (CadetPeer for neighbor that sent the message).
923 * @param msg Message itself.
926 handle_connection_create_ack (void *cls,
927 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
929 struct CadetPeer *peer = cls;
930 struct CadetConnection *cc;
932 /* First, check if ACK belongs to a connection that ends here. */
933 cc = GCC_lookup (&msg->cid);
936 /* verify ACK came from the right direction */
937 struct CadetPeerPath *path = GCC_get_path (cc);
940 GCPP_get_peer_at_offset (path,
943 /* received ACK from unexpected direction, ignore! */
947 LOG (GNUNET_ERROR_TYPE_DEBUG,
948 "Received CONNECTION_CREATE_ACK for connection %s.\n",
949 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
950 GCC_handle_connection_create_ack (cc);
954 /* We're just an intermediary peer, route the message along its path */
962 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
964 * @param cls Closure (CadetPeer for neighbor that sent the message).
965 * @param msg Message itself.
966 * @deprecated duplicate logic with #handle_destroy(); dedup!
969 handle_connection_broken (void *cls,
970 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
972 struct CadetPeer *peer = cls;
973 struct CadetConnection *cc;
974 struct CadetRoute *route;
976 /* First, check if message belongs to a connection that ends here. */
977 cc = GCC_lookup (&msg->cid);
980 /* verify message came from the right direction */
981 struct CadetPeerPath *path = GCC_get_path (cc);
984 GCPP_get_peer_at_offset (path,
987 /* received message from unexpected direction, ignore! */
991 LOG (GNUNET_ERROR_TYPE_DEBUG,
992 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
993 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
994 GCC_destroy_without_core (cc);
996 /* FIXME: also destroy the path up to the specified link! */
1000 /* We're just an intermediary peer, route the message along its path */
1001 route_message (peer,
1004 route = get_route (&msg->cid);
1006 destroy_route (route);
1007 /* FIXME: also destroy paths we MAY have up to the specified link! */
1012 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1014 * @param cls Closure (CadetPeer for neighbor that sent the message).
1015 * @param msg Message itself.
1018 handle_connection_destroy (void *cls,
1019 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1021 struct CadetPeer *peer = cls;
1022 struct CadetConnection *cc;
1023 struct CadetRoute *route;
1025 /* First, check if message belongs to a connection that ends here. */
1026 cc = GCC_lookup (&msg->cid);
1029 /* verify message came from the right direction */
1030 struct CadetPeerPath *path = GCC_get_path (cc);
1033 GCPP_get_peer_at_offset (path,
1036 /* received message from unexpected direction, ignore! */
1037 GNUNET_break_op (0);
1040 LOG (GNUNET_ERROR_TYPE_DEBUG,
1041 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1042 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1044 GCC_destroy_without_core (cc);
1048 /* We're just an intermediary peer, route the message along its path */
1049 LOG (GNUNET_ERROR_TYPE_DEBUG,
1050 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1051 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1052 route_message (peer,
1055 route = get_route (&msg->cid);
1057 destroy_route (route);
1062 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1064 * @param cls Closure (CadetPeer for neighbor that sent the message).
1065 * @param msg Message itself.
1068 handle_tunnel_kx (void *cls,
1069 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1071 struct CadetPeer *peer = cls;
1072 struct CadetConnection *cc;
1074 /* First, check if message belongs to a connection that ends here. */
1075 cc = GCC_lookup (&msg->cid);
1078 /* verify message came from the right direction */
1079 struct CadetPeerPath *path = GCC_get_path (cc);
1082 GCPP_get_peer_at_offset (path,
1085 /* received message from unexpected direction, ignore! */
1086 GNUNET_break_op (0);
1094 /* We're just an intermediary peer, route the message along its path */
1095 route_message (peer,
1102 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1104 * @param cls Closure (CadetPeer for neighbor that sent the message).
1105 * @param msg Message itself.
1108 handle_tunnel_kx_auth (void *cls,
1109 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1111 struct CadetPeer *peer = cls;
1112 struct CadetConnection *cc;
1114 /* First, check if message belongs to a connection that ends here. */
1115 cc = GCC_lookup (&msg->kx.cid);
1118 /* verify message came from the right direction */
1119 struct CadetPeerPath *path = GCC_get_path (cc);
1122 GCPP_get_peer_at_offset (path,
1125 /* received message from unexpected direction, ignore! */
1126 GNUNET_break_op (0);
1129 GCC_handle_kx_auth (cc,
1134 /* We're just an intermediary peer, route the message along its path */
1135 route_message (peer,
1142 * Check if the encrypted message has the appropriate size.
1144 * @param cls Closure (unused).
1145 * @param msg Message to check.
1147 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1150 check_tunnel_encrypted (void *cls,
1151 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1158 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1160 * @param cls Closure (CadetPeer for neighbor that sent the message).
1161 * @param msg Message itself.
1164 handle_tunnel_encrypted (void *cls,
1165 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1167 struct CadetPeer *peer = cls;
1168 struct CadetConnection *cc;
1170 /* First, check if message belongs to a connection that ends here. */
1171 cc = GCC_lookup (&msg->cid);
1174 /* verify message came from the right direction */
1175 struct CadetPeerPath *path = GCC_get_path (cc);
1178 GCPP_get_peer_at_offset (path,
1181 /* received message from unexpected direction, ignore! */
1182 GNUNET_break_op (0);
1185 GCC_handle_encrypted (cc,
1189 /* We're just an intermediary peer, route the message along its path */
1190 route_message (peer,
1197 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1198 * for good). Note that the private key of the peer is intentionally
1199 * not exposed here; if you need it, your process should try to read
1200 * the private key file directly (which should work if you are
1201 * authorized...). Implementations of this function must not call
1202 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1205 * @param cls closure
1206 * @param my_identity ID of this peer, NULL if we failed
1209 core_init_cb (void *cls,
1210 const struct GNUNET_PeerIdentity *my_identity)
1212 if (NULL == my_identity)
1218 memcmp (my_identity,
1220 sizeof (struct GNUNET_PeerIdentity)));
1225 * Method called whenever a given peer connects.
1227 * @param cls closure
1228 * @param peer peer identity this notification is about
1231 core_connect_cb (void *cls,
1232 const struct GNUNET_PeerIdentity *peer,
1233 struct GNUNET_MQ_Handle *mq)
1235 struct CadetPeer *cp;
1237 LOG (GNUNET_ERROR_TYPE_DEBUG,
1238 "CORE connection to peer %s was established.\n",
1249 * Method called whenever a peer disconnects.
1251 * @param cls closure
1252 * @param peer peer identity this notification is about
1255 core_disconnect_cb (void *cls,
1256 const struct GNUNET_PeerIdentity *peer,
1259 struct CadetPeer *cp = peer_cls;
1261 LOG (GNUNET_ERROR_TYPE_DEBUG,
1262 "CORE connection to peer %s went down.\n",
1270 * Initialize the CORE subsystem.
1272 * @param c Configuration.
1275 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1277 struct GNUNET_MQ_MessageHandler handlers[] = {
1278 GNUNET_MQ_hd_var_size (connection_create,
1279 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1280 struct GNUNET_CADET_ConnectionCreateMessage,
1282 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1283 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1284 struct GNUNET_CADET_ConnectionCreateAckMessage,
1286 GNUNET_MQ_hd_fixed_size (connection_broken,
1287 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1288 struct GNUNET_CADET_ConnectionBrokenMessage,
1290 GNUNET_MQ_hd_fixed_size (connection_destroy,
1291 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1292 struct GNUNET_CADET_ConnectionDestroyMessage,
1294 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1295 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1296 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1298 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1299 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1300 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1302 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1303 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1304 struct GNUNET_CADET_TunnelEncryptedMessage,
1306 GNUNET_MQ_handler_end ()
1310 GNUNET_CONFIGURATION_get_value_number (c,
1316 GNUNET_CONFIGURATION_get_value_number (c,
1320 max_buffers = 10000;
1321 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1323 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1324 core = GNUNET_CORE_connect (c,
1328 &core_disconnect_cb,
1334 * Shut down the CORE subsystem.
1341 GNUNET_CORE_disconnect (core);
1344 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1345 GNUNET_CONTAINER_multishortmap_destroy (routes);
1347 GNUNET_CONTAINER_heap_destroy (route_heap);
1349 if (NULL != timeout_task)
1351 GNUNET_SCHEDULER_cancel (timeout_task);
1352 timeout_task = NULL;
1356 /* end of gnunet-cadet-service_core.c */