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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
17 * @file cadet/gnunet-service-cadet_core.c
18 * @brief cadet service; interaction with CORE service
19 * @author Bartlomiej Polot
20 * @author Christian Grothoff
22 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
25 * - Optimization: given BROKEN messages, destroy paths (?)
28 #include "gnunet-service-cadet_core.h"
29 #include "gnunet-service-cadet_paths.h"
30 #include "gnunet-service-cadet_peer.h"
31 #include "gnunet-service-cadet_connection.h"
32 #include "gnunet-service-cadet_tunnels.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "cadet_protocol.h"
38 #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__)
41 * Information we keep per direction for a route.
43 struct RouteDirection;
47 * Set of CadetRoutes that have exactly the same number of messages
48 * in their buffer. Used so we can efficiently find all of those
49 * routes that have the current maximum of messages in the buffer (in
50 * case we have to purge).
56 * Rung of RouteDirections with one more buffer entry each.
61 * Rung of RouteDirections with one less buffer entry each.
66 * DLL of route directions with a number of buffer entries matching this rung.
68 struct RouteDirection *rd_head;
71 * DLL of route directions with a number of buffer entries matching this rung.
73 struct RouteDirection *rd_tail;
76 * Total number of route directions in this rung.
78 unsigned int num_routes;
81 * Number of messages route directions at this rung have
84 unsigned int rung_off;
89 * Information we keep per direction for a route.
95 * DLL of other route directions within the same `struct Rung`.
97 struct RouteDirection *prev;
100 * DLL of other route directions within the same `struct Rung`.
102 struct RouteDirection *next;
105 * Rung of this route direction (matches length of the buffer DLL).
110 * Head of DLL of envelopes we have in the buffer for this direction.
112 struct GNUNET_MQ_Envelope *env_head;
115 * Tail of DLL of envelopes we have in the buffer for this direction.
117 struct GNUNET_MQ_Envelope *env_tail;
122 struct CadetPeer *hop;
125 * Route this direction is part of.
127 struct CadetRoute *my_route;
130 * Message queue manager for @e hop.
132 struct GCP_MessageQueueManager *mqm;
135 * Is @e mqm currently ready for transmission?
143 * Description of a segment of a `struct CadetConnection` at the
144 * intermediate peers. Routes are basically entries in a peer's
145 * routing table for forwarding traffic. At both endpoints, the
146 * routes are terminated by a `struct CadetConnection`, which knows
147 * the complete `struct CadetPath` that is formed by the individual
154 * Information about the next hop on this route.
156 struct RouteDirection next;
159 * Information about the previous hop on this route.
161 struct RouteDirection prev;
164 * Unique identifier for the connection that uses this route.
166 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
169 * When was this route last in use?
171 struct GNUNET_TIME_Absolute last_use;
174 * Position of this route in the #route_heap.
176 struct GNUNET_CONTAINER_HeapNode *hn;
179 * Options for the route, control buffering.
181 enum GNUNET_CADET_ChannelOption options;
186 * Handle to the CORE service.
188 static struct GNUNET_CORE_Handle *core;
191 * Routes on which this peer is an intermediate.
193 static struct GNUNET_CONTAINER_MultiShortmap *routes;
196 * Heap of routes, MIN-sorted by last activity.
198 static struct GNUNET_CONTAINER_Heap *route_heap;
201 * Rung zero (always pointed to by #rung_head).
203 static struct Rung rung_zero;
206 * DLL of rungs, with the head always point to a rung of
207 * route directions with no messages in the queue.
209 static struct Rung *rung_head = &rung_zero;
212 * Tail of the #rung_head DLL.
214 static struct Rung *rung_tail = &rung_zero;
217 * Maximum number of concurrent routes this peer will support.
219 static unsigned long long max_routes;
222 * Maximum number of envelopes we will buffer at this peer.
224 static unsigned long long max_buffers;
227 * Current number of envelopes we have buffered at this peer.
229 static unsigned long long cur_buffers;
232 * Task to timeout routes.
234 static struct GNUNET_SCHEDULER_Task *timeout_task;
238 * Get the route corresponding to a hash.
240 * @param cid hash generated from the connection identifier
242 static struct CadetRoute *
243 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
245 return GNUNET_CONTAINER_multishortmap_get (routes,
246 &cid->connection_of_tunnel);
251 * Lower the rung in which @a dir is by 1.
253 * @param dir direction to lower in rung.
256 lower_rung (struct RouteDirection *dir)
258 struct Rung *rung = dir->rung;
261 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
265 GNUNET_assert (NULL != prev);
266 if (prev->rung_off != rung->rung_off - 1)
268 prev = GNUNET_new (struct Rung);
269 prev->rung_off = rung->rung_off - 1;
270 GNUNET_CONTAINER_DLL_insert_after (rung_head,
275 GNUNET_assert (NULL != prev);
276 GNUNET_CONTAINER_DLL_insert (prev->rd_head,
284 * Discard the buffer @a env from the route direction @a dir and
285 * move @a dir down a rung.
287 * @param dir direction that contains the @a env in the buffer
288 * @param env envelope to discard
291 discard_buffer (struct RouteDirection *dir,
292 struct GNUNET_MQ_Envelope *env)
294 GNUNET_MQ_dll_remove (&dir->env_head,
298 GNUNET_MQ_discard (env);
300 GNUNET_STATISTICS_set (stats,
308 * Discard all messages from the highest rung, to make space.
311 discard_all_from_rung_tail ()
313 struct Rung *tail = rung_tail;
314 struct RouteDirection *dir;
316 while (NULL != (dir = tail->rd_head))
318 LOG (GNUNET_ERROR_TYPE_DEBUG,
319 "Queue full due new message %s on connection %s, dropping old message\n",
320 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
321 GNUNET_STATISTICS_update (stats,
322 "# messages dropped due to full buffer",
328 GNUNET_CONTAINER_DLL_remove (rung_head,
336 * We message @a msg from @a prev. Find its route by @a cid and
337 * forward to the next hop. Drop and signal broken route if we do not
340 * @param prev previous hop (sender)
341 * @param cid connection identifier, tells us which route to use
342 * @param msg the message to forward
345 route_message (struct CadetPeer *prev,
346 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
347 const struct GNUNET_MessageHeader *msg)
349 struct CadetRoute *route;
350 struct RouteDirection *dir;
353 struct GNUNET_MQ_Envelope *env;
355 route = get_route (cid);
358 struct GNUNET_MQ_Envelope *env;
359 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
361 LOG (GNUNET_ERROR_TYPE_DEBUG,
362 "Failed to route message of type %u from %s on connection %s: no route\n",
365 GNUNET_sh2s (&cid->connection_of_tunnel));
366 switch (ntohs (msg->type))
368 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
369 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
370 /* No need to respond to these! */
373 env = GNUNET_MQ_msg (bm,
374 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
376 bm->peer1 = my_full_id;
381 route->last_use = GNUNET_TIME_absolute_get ();
382 GNUNET_CONTAINER_heap_update_cost (route->hn,
383 route->last_use.abs_value_us);
384 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
385 if (GNUNET_YES == dir->is_ready)
387 LOG (GNUNET_ERROR_TYPE_DEBUG,
388 "Routing message of type %u from %s to %s on connection %s\n",
391 GNUNET_i2s (GCP_get_id (dir->hop)),
392 GNUNET_sh2s (&cid->connection_of_tunnel));
393 dir->is_ready = GNUNET_NO;
395 GNUNET_MQ_msg_copy (msg));
398 /* Check if buffering is disallowed, and if so, make sure we only queue
399 one message per direction. */
400 if ( (0 != (route->options & GNUNET_CADET_OPTION_NOBUFFER)) &&
401 (NULL != dir->env_head) )
404 /* Check for duplicates */
405 for (const struct GNUNET_MQ_Envelope *env = dir->env_head;
407 env = GNUNET_MQ_env_next (env))
409 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
411 if ( (hdr->size == msg->size) &&
414 ntohs (msg->size))) )
416 LOG (GNUNET_ERROR_TYPE_DEBUG,
417 "Received duplicate of message already in buffer, dropping\n");
418 GNUNET_STATISTICS_update (stats,
419 "# messages dropped due to duplicate in buffer",
427 if (cur_buffers == max_buffers)
429 /* Need to make room. */
430 if (NULL != rung->next)
432 /* Easy case, drop messages from route directions in highest rung */
433 discard_all_from_rung_tail ();
437 /* We are in the highest rung, drop our own! */
438 LOG (GNUNET_ERROR_TYPE_DEBUG,
439 "Queue full due new message %s on connection %s, dropping old message\n",
440 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
441 GNUNET_STATISTICS_update (stats,
442 "# messages dropped due to full buffer",
450 /* remove 'dir' from current rung */
451 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
454 /* make 'nxt' point to the next higher rung, create if necessary */
456 if ( (NULL == nxt) ||
457 (rung->rung_off + 1 != nxt->rung_off) )
459 nxt = GNUNET_new (struct Rung);
460 nxt->rung_off = rung->rung_off + 1;
461 GNUNET_CONTAINER_DLL_insert_after (rung_head,
466 /* insert 'dir' into next higher rung */
467 GNUNET_CONTAINER_DLL_insert (nxt->rd_head,
472 /* add message into 'dir' buffer */
473 LOG (GNUNET_ERROR_TYPE_DEBUG,
474 "Queueing new message of type %u from %s to %s on connection %s\n",
477 GNUNET_i2s (GCP_get_id (dir->hop)),
478 GNUNET_sh2s (&cid->connection_of_tunnel));
479 env = GNUNET_MQ_msg_copy (msg);
480 GNUNET_MQ_dll_insert_tail (&dir->env_head,
484 GNUNET_STATISTICS_set (stats,
488 /* Clean up 'rung' if now empty (and not head) */
489 if ( (NULL == rung->rd_head) &&
490 (rung != rung_head) )
492 GNUNET_CONTAINER_DLL_remove (rung_head,
501 * Check if the create_connection message has the appropriate size.
503 * @param cls Closure (unused).
504 * @param msg Message to check.
506 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
509 check_connection_create (void *cls,
510 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
512 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
514 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
524 * Free internal data of a route direction.
526 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
529 destroy_direction (struct RouteDirection *dir)
531 struct GNUNET_MQ_Envelope *env;
533 while (NULL != (env = dir->env_head))
535 GNUNET_STATISTICS_update (stats,
536 "# messages dropped due to route destruction",
542 if (NULL != dir->mqm)
544 GCP_request_mq_cancel (dir->mqm,
548 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head,
555 * Destroy our state for @a route.
557 * @param route route to destroy
560 destroy_route (struct CadetRoute *route)
562 LOG (GNUNET_ERROR_TYPE_DEBUG,
563 "Destroying route from %s to %s of connection %s\n",
564 GNUNET_i2s (GCP_get_id (route->prev.hop)),
565 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
566 GNUNET_sh2s (&route->cid.connection_of_tunnel));
567 GNUNET_assert (route ==
568 GNUNET_CONTAINER_heap_remove_node (route->hn));
569 GNUNET_assert (GNUNET_YES ==
570 GNUNET_CONTAINER_multishortmap_remove (routes,
571 &route->cid.connection_of_tunnel,
573 GNUNET_STATISTICS_set (stats,
575 GNUNET_CONTAINER_multishortmap_size (routes),
577 destroy_direction (&route->prev);
578 destroy_direction (&route->next);
584 * Send message that a route is broken between @a peer1 and @a peer2.
586 * @param target where to send the message
587 * @param cid connection identifier to use
588 * @param peer1 one of the peers where a link is broken
589 * @param peer2 another one of the peers where a link is broken
592 send_broken (struct RouteDirection *target,
593 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
594 const struct GNUNET_PeerIdentity *peer1,
595 const struct GNUNET_PeerIdentity *peer2)
597 struct GNUNET_MQ_Envelope *env;
598 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
600 if (NULL == target->mqm)
601 return; /* Can't send notification, connection is down! */
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
604 GCP_2s (target->hop),
607 GNUNET_sh2s (&cid->connection_of_tunnel));
609 env = GNUNET_MQ_msg (bm,
610 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
616 GCP_request_mq_cancel (target->mqm,
623 * Function called to check if any routes have timed out, and if
624 * so, to clean them up. Finally, schedules itself again at the
625 * earliest time where there might be more work.
630 timeout_cb (void *cls)
632 struct CadetRoute *r;
633 struct GNUNET_TIME_Relative linger;
634 struct GNUNET_TIME_Absolute exp;
637 linger = GNUNET_TIME_relative_multiply (keepalive_period,
639 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
641 exp = GNUNET_TIME_absolute_add (r->last_use,
643 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
645 /* Route not yet timed out, wait until it does. */
646 timeout_task = GNUNET_SCHEDULER_add_at (exp,
651 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
652 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
653 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
654 GNUNET_STRINGS_relative_time_to_string (linger,
656 send_broken (&r->prev,
660 send_broken (&r->next,
666 /* No more routes left, so no need for a #timeout_task */
671 * Function called when the message queue to the previous hop
672 * becomes available/unavailable. We expect this function to
673 * be called immediately when we register, and then again
674 * later if the connection ever goes down.
676 * @param cls the `struct RouteDirection`
677 * @param available #GNUNET_YES if sending is now possible,
678 * #GNUNET_NO if sending is no longer possible
679 * #GNUNET_SYSERR if sending is no longer possible
680 * and the last envelope was discarded
683 dir_ready_cb (void *cls,
686 struct RouteDirection *dir = cls;
687 struct CadetRoute *route = dir->my_route;
688 struct RouteDirection *odir;
690 if (GNUNET_YES == ready)
692 struct GNUNET_MQ_Envelope *env;
694 dir->is_ready = GNUNET_YES;
695 if (NULL != (env = dir->env_head))
697 GNUNET_MQ_dll_remove (&dir->env_head,
701 GNUNET_STATISTICS_set (stats,
706 dir->is_ready = GNUNET_NO;
712 odir = (dir == &route->next) ? &route->prev : &route->next;
713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
714 "Sending BROKEN due to MQ going down\n");
715 send_broken (&route->next,
717 GCP_get_id (odir->hop),
719 destroy_route (route);
724 * Initialize one of the directions of a route.
726 * @param route route the direction belongs to
727 * @param dir direction to initialize
728 * @param hop next hop on in the @a dir
731 dir_init (struct RouteDirection *dir,
732 struct CadetRoute *route,
733 struct CadetPeer *hop)
736 dir->my_route = route;
737 dir->mqm = GCP_request_mq (hop,
740 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head,
743 dir->rung = rung_head;
744 GNUNET_assert (GNUNET_YES == dir->is_ready);
749 * We could not create the desired route. Send a
750 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
751 * message to @a target.
753 * @param target who should receive the message
754 * @param cid identifier of the connection/route that failed
755 * @param failure_at neighbour with which we failed to route,
759 send_broken_without_mqm (struct CadetPeer *target,
760 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
761 const struct GNUNET_PeerIdentity *failure_at)
763 struct GNUNET_MQ_Envelope *env;
764 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
766 env = GNUNET_MQ_msg (bm,
767 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
769 bm->peer1 = my_full_id;
770 if (NULL != failure_at)
771 bm->peer2 = *failure_at;
772 GCP_send_ooo (target,
778 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
780 * @param cls Closure (CadetPeer for neighbor that sent the message).
781 * @param msg Message itself.
784 handle_connection_create (void *cls,
785 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
787 struct CadetPeer *sender = cls;
788 struct CadetPeer *next;
789 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
790 struct CadetRoute *route;
791 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
792 unsigned int path_length;
794 enum GNUNET_CADET_ChannelOption options;
796 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
797 path_length = size / sizeof (struct GNUNET_PeerIdentity);
798 if (0 == path_length)
800 LOG (GNUNET_ERROR_TYPE_DEBUG,
801 "Dropping CADET_CONNECTION_CREATE with empty path\n");
805 LOG (GNUNET_ERROR_TYPE_DEBUG,
806 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
808 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
810 /* Check for loops */
812 struct GNUNET_CONTAINER_MultiPeerMap *map;
814 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
816 GNUNET_assert (NULL != map);
817 for (unsigned int i=0;i<path_length;i++)
819 LOG (GNUNET_ERROR_TYPE_DEBUG,
820 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
821 GNUNET_i2s (&pids[i]),
824 GNUNET_CONTAINER_multipeermap_put (map,
827 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
830 GNUNET_CONTAINER_multipeermap_destroy (map);
831 LOG (GNUNET_ERROR_TYPE_DEBUG,
832 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
837 GNUNET_CONTAINER_multipeermap_destroy (map);
839 /* Initiator is at offset 0, find us */
840 for (off=1;off<path_length;off++)
841 if (0 == memcmp (&my_full_id,
843 sizeof (struct GNUNET_PeerIdentity)))
845 if (off == path_length)
847 LOG (GNUNET_ERROR_TYPE_DEBUG,
848 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
852 /* Check previous hop */
853 if (sender != GCP_get (&pids[off - 1],
856 LOG (GNUNET_ERROR_TYPE_DEBUG,
857 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
862 (route = get_route (&msg->cid)))
864 /* Duplicate CREATE, pass it on, previous one might have been lost! */
866 LOG (GNUNET_ERROR_TYPE_DEBUG,
867 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
868 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
869 route_message (sender,
874 if (off == path_length - 1)
876 /* We are the destination, create connection */
877 struct CadetConnection *cc;
878 struct CadetPeerPath *path;
879 struct CadetPeer *origin;
881 cc = GCC_lookup (&msg->cid);
884 LOG (GNUNET_ERROR_TYPE_DEBUG,
885 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
886 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
887 GCC_handle_duplicate_create (cc);
891 origin = GCP_get (&pids[0],
893 LOG (GNUNET_ERROR_TYPE_DEBUG,
894 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
896 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
897 path = GCPP_get_path_from_route (path_length - 1,
900 GCT_add_inbound_connection (GCP_get_tunnel (origin,
903 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
906 /* Send back BROKEN: duplicate connection on the same path,
907 we will use the other one. */
908 LOG (GNUNET_ERROR_TYPE_DEBUG,
909 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
911 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
913 send_broken_without_mqm (sender,
920 /* We are merely a hop on the way, check if we can support the route */
921 next = GCP_get (&pids[off + 1],
923 if ( (NULL == next) ||
924 (GNUNET_NO == GCP_has_core_connection (next)) )
926 /* unworkable, send back BROKEN notification */
927 LOG (GNUNET_ERROR_TYPE_DEBUG,
928 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
930 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
931 GNUNET_i2s (&pids[off + 1]),
933 send_broken_without_mqm (sender,
938 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
940 LOG (GNUNET_ERROR_TYPE_DEBUG,
941 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
943 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
944 send_broken_without_mqm (sender,
950 /* Workable route, create routing entry */
951 LOG (GNUNET_ERROR_TYPE_DEBUG,
952 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
954 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
955 GNUNET_i2s (&pids[off + 1]),
957 route = GNUNET_new (struct CadetRoute);
958 route->options = options;
959 route->cid = msg->cid;
960 route->last_use = GNUNET_TIME_absolute_get ();
961 dir_init (&route->prev,
964 dir_init (&route->next,
967 GNUNET_assert (GNUNET_OK ==
968 GNUNET_CONTAINER_multishortmap_put (routes,
969 &route->cid.connection_of_tunnel,
971 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
972 GNUNET_STATISTICS_set (stats,
974 GNUNET_CONTAINER_multishortmap_size (routes),
976 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
978 route->last_use.abs_value_us);
979 if (NULL == timeout_task)
980 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
984 /* also pass CREATE message along to next hop */
985 route_message (sender,
992 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
994 * @param cls Closure (CadetPeer for neighbor that sent the message).
995 * @param msg Message itself.
998 handle_connection_create_ack (void *cls,
999 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
1001 struct CadetPeer *peer = cls;
1002 struct CadetConnection *cc;
1004 /* First, check if ACK belongs to a connection that ends here. */
1005 cc = GCC_lookup (&msg->cid);
1008 /* verify ACK came from the right direction */
1010 struct CadetPeerPath *path = GCC_get_path (cc,
1014 GCPP_get_peer_at_offset (path,
1017 /* received ACK from unexpected direction, ignore! */
1018 GNUNET_break_op (0);
1021 LOG (GNUNET_ERROR_TYPE_DEBUG,
1022 "Received CONNECTION_CREATE_ACK for connection %s.\n",
1023 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1024 GCC_handle_connection_create_ack (cc);
1028 /* We're just an intermediary peer, route the message along its path */
1029 route_message (peer,
1036 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
1038 * @param cls Closure (CadetPeer for neighbor that sent the message).
1039 * @param msg Message itself.
1040 * @deprecated duplicate logic with #handle_destroy(); dedup!
1043 handle_connection_broken (void *cls,
1044 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
1046 struct CadetPeer *peer = cls;
1047 struct CadetConnection *cc;
1048 struct CadetRoute *route;
1050 /* First, check if message belongs to a connection that ends here. */
1051 cc = GCC_lookup (&msg->cid);
1054 /* verify message came from the right direction */
1056 struct CadetPeerPath *path = GCC_get_path (cc,
1060 GCPP_get_peer_at_offset (path,
1063 /* received message from unexpected direction, ignore! */
1064 GNUNET_break_op (0);
1067 LOG (GNUNET_ERROR_TYPE_DEBUG,
1068 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
1069 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1070 GCC_destroy_without_core (cc);
1072 /* FIXME: also destroy the path up to the specified link! */
1076 /* We're just an intermediary peer, route the message along its path */
1077 route_message (peer,
1080 route = get_route (&msg->cid);
1082 destroy_route (route);
1083 /* FIXME: also destroy paths we MAY have up to the specified link! */
1088 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1090 * @param cls Closure (CadetPeer for neighbor that sent the message).
1091 * @param msg Message itself.
1094 handle_connection_destroy (void *cls,
1095 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1097 struct CadetPeer *peer = cls;
1098 struct CadetConnection *cc;
1099 struct CadetRoute *route;
1101 /* First, check if message belongs to a connection that ends here. */
1102 cc = GCC_lookup (&msg->cid);
1105 /* verify message came from the right direction */
1107 struct CadetPeerPath *path = GCC_get_path (cc,
1111 GCPP_get_peer_at_offset (path,
1114 /* received message from unexpected direction, ignore! */
1115 GNUNET_break_op (0);
1118 LOG (GNUNET_ERROR_TYPE_DEBUG,
1119 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1120 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1122 GCC_destroy_without_core (cc);
1126 /* We're just an intermediary peer, route the message along its path */
1127 LOG (GNUNET_ERROR_TYPE_DEBUG,
1128 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1129 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1130 route_message (peer,
1133 route = get_route (&msg->cid);
1135 destroy_route (route);
1140 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1142 * @param cls Closure (CadetPeer for neighbor that sent the message).
1143 * @param msg Message itself.
1146 handle_tunnel_kx (void *cls,
1147 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1149 struct CadetPeer *peer = cls;
1150 struct CadetConnection *cc;
1152 /* First, check if message belongs to a connection that ends here. */
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Routing KX with ephemeral %s on CID %s\n",
1155 GNUNET_e2s (&msg->ephemeral_key),
1156 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1159 cc = GCC_lookup (&msg->cid);
1162 /* verify message came from the right direction */
1164 struct CadetPeerPath *path = GCC_get_path (cc,
1168 GCPP_get_peer_at_offset (path,
1171 /* received message from unexpected direction, ignore! */
1172 GNUNET_break_op (0);
1180 /* We're just an intermediary peer, route the message along its path */
1181 route_message (peer,
1188 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1190 * @param cls Closure (CadetPeer for neighbor that sent the message).
1191 * @param msg Message itself.
1194 handle_tunnel_kx_auth (void *cls,
1195 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1197 struct CadetPeer *peer = cls;
1198 struct CadetConnection *cc;
1200 /* First, check if message belongs to a connection that ends here. */
1201 cc = GCC_lookup (&msg->kx.cid);
1204 /* verify message came from the right direction */
1206 struct CadetPeerPath *path = GCC_get_path (cc,
1210 GCPP_get_peer_at_offset (path,
1213 /* received message from unexpected direction, ignore! */
1214 GNUNET_break_op (0);
1217 GCC_handle_kx_auth (cc,
1222 /* We're just an intermediary peer, route the message along its path */
1223 route_message (peer,
1230 * Check if the encrypted message has the appropriate size.
1232 * @param cls Closure (unused).
1233 * @param msg Message to check.
1235 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1238 check_tunnel_encrypted (void *cls,
1239 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1246 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1248 * @param cls Closure (CadetPeer for neighbor that sent the message).
1249 * @param msg Message itself.
1252 handle_tunnel_encrypted (void *cls,
1253 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1255 struct CadetPeer *peer = cls;
1256 struct CadetConnection *cc;
1258 /* First, check if message belongs to a connection that ends here. */
1259 cc = GCC_lookup (&msg->cid);
1262 /* verify message came from the right direction */
1264 struct CadetPeerPath *path = GCC_get_path (cc,
1268 GCPP_get_peer_at_offset (path,
1271 /* received message from unexpected direction, ignore! */
1272 GNUNET_break_op (0);
1275 GCC_handle_encrypted (cc,
1279 /* We're just an intermediary peer, route the message along its path */
1280 route_message (peer,
1287 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1288 * for good). Note that the private key of the peer is intentionally
1289 * not exposed here; if you need it, your process should try to read
1290 * the private key file directly (which should work if you are
1291 * authorized...). Implementations of this function must not call
1292 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1295 * @param cls closure
1296 * @param my_identity ID of this peer, NULL if we failed
1299 core_init_cb (void *cls,
1300 const struct GNUNET_PeerIdentity *my_identity)
1302 if (NULL == my_identity)
1308 memcmp (my_identity,
1310 sizeof (struct GNUNET_PeerIdentity)));
1315 * Method called whenever a given peer connects.
1317 * @param cls closure
1318 * @param peer peer identity this notification is about
1321 core_connect_cb (void *cls,
1322 const struct GNUNET_PeerIdentity *peer,
1323 struct GNUNET_MQ_Handle *mq)
1325 struct CadetPeer *cp;
1327 LOG (GNUNET_ERROR_TYPE_DEBUG,
1328 "CORE connection to peer %s was established.\n",
1339 * Method called whenever a peer disconnects.
1341 * @param cls closure
1342 * @param peer peer identity this notification is about
1345 core_disconnect_cb (void *cls,
1346 const struct GNUNET_PeerIdentity *peer,
1349 struct CadetPeer *cp = peer_cls;
1351 LOG (GNUNET_ERROR_TYPE_DEBUG,
1352 "CORE connection to peer %s went down.\n",
1360 * Initialize the CORE subsystem.
1362 * @param c Configuration.
1365 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1367 struct GNUNET_MQ_MessageHandler handlers[] = {
1368 GNUNET_MQ_hd_var_size (connection_create,
1369 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1370 struct GNUNET_CADET_ConnectionCreateMessage,
1372 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1373 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1374 struct GNUNET_CADET_ConnectionCreateAckMessage,
1376 GNUNET_MQ_hd_fixed_size (connection_broken,
1377 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1378 struct GNUNET_CADET_ConnectionBrokenMessage,
1380 GNUNET_MQ_hd_fixed_size (connection_destroy,
1381 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1382 struct GNUNET_CADET_ConnectionDestroyMessage,
1384 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1385 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1386 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1388 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1389 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1390 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1392 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1393 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1394 struct GNUNET_CADET_TunnelEncryptedMessage,
1396 GNUNET_MQ_handler_end ()
1400 GNUNET_CONFIGURATION_get_value_number (c,
1406 GNUNET_CONFIGURATION_get_value_number (c,
1410 max_buffers = 10000;
1411 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1413 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1414 core = GNUNET_CORE_connect (c,
1418 &core_disconnect_cb,
1424 * Shut down the CORE subsystem.
1431 GNUNET_CORE_disconnect (core);
1434 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1435 GNUNET_CONTAINER_multishortmap_destroy (routes);
1437 GNUNET_CONTAINER_heap_destroy (route_heap);
1439 if (NULL != timeout_task)
1441 GNUNET_SCHEDULER_cancel (timeout_task);
1442 timeout_task = NULL;
1446 /* end of gnunet-cadet-service_core.c */