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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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) )
409 /* Check for duplicates */
410 for (const struct GNUNET_MQ_Envelope *env = dir->env_head;
412 env = GNUNET_MQ_env_next (env))
414 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
416 if ( (hdr->size == msg->size) &&
419 ntohs (msg->size))) )
421 LOG (GNUNET_ERROR_TYPE_DEBUG,
422 "Received duplicate of message already in buffer, dropping\n");
423 GNUNET_STATISTICS_update (stats,
424 "# messages dropped due to duplicate in buffer",
432 if (cur_buffers == max_buffers)
434 /* Need to make room. */
435 if (NULL != rung->next)
437 /* Easy case, drop messages from route directions in highest rung */
438 discard_all_from_rung_tail ();
442 /* We are in the highest rung, drop our own! */
443 LOG (GNUNET_ERROR_TYPE_DEBUG,
444 "Queue full due new message %s on connection %s, dropping old message\n",
445 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
446 GNUNET_STATISTICS_update (stats,
447 "# messages dropped due to full buffer",
455 /* remove 'dir' from current rung */
456 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
459 /* make 'nxt' point to the next higher rung, create if necessary */
461 if ( (NULL == nxt) ||
462 (rung->rung_off + 1 != nxt->rung_off) )
464 nxt = GNUNET_new (struct Rung);
465 nxt->rung_off = rung->rung_off + 1;
466 GNUNET_CONTAINER_DLL_insert_after (rung_head,
471 /* insert 'dir' into next higher rung */
472 GNUNET_CONTAINER_DLL_insert (nxt->rd_head,
477 /* add message into 'dir' buffer */
478 LOG (GNUNET_ERROR_TYPE_DEBUG,
479 "Queueing new message of type %u from %s to %s on connection %s\n",
482 GNUNET_i2s (GCP_get_id (dir->hop)),
483 GNUNET_sh2s (&cid->connection_of_tunnel));
484 env = GNUNET_MQ_msg_copy (msg);
485 GNUNET_MQ_dll_insert_tail (&dir->env_head,
489 GNUNET_STATISTICS_set (stats,
493 /* Clean up 'rung' if now empty (and not head) */
494 if ( (NULL == rung->rd_head) &&
495 (rung != rung_head) )
497 GNUNET_CONTAINER_DLL_remove (rung_head,
506 * Check if the create_connection message has the appropriate size.
508 * @param cls Closure (unused).
509 * @param msg Message to check.
511 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
514 check_connection_create (void *cls,
515 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
517 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
519 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
529 * Free internal data of a route direction.
531 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
534 destroy_direction (struct RouteDirection *dir)
536 struct GNUNET_MQ_Envelope *env;
538 while (NULL != (env = dir->env_head))
540 GNUNET_STATISTICS_update (stats,
541 "# messages dropped due to route destruction",
547 if (NULL != dir->mqm)
549 GCP_request_mq_cancel (dir->mqm,
553 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head,
560 * Destroy our state for @a route.
562 * @param route route to destroy
565 destroy_route (struct CadetRoute *route)
567 LOG (GNUNET_ERROR_TYPE_DEBUG,
568 "Destroying route from %s to %s of connection %s\n",
569 GNUNET_i2s (GCP_get_id (route->prev.hop)),
570 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
571 GNUNET_sh2s (&route->cid.connection_of_tunnel));
572 GNUNET_assert (route ==
573 GNUNET_CONTAINER_heap_remove_node (route->hn));
574 GNUNET_assert (GNUNET_YES ==
575 GNUNET_CONTAINER_multishortmap_remove (routes,
576 &route->cid.connection_of_tunnel,
578 GNUNET_STATISTICS_set (stats,
580 GNUNET_CONTAINER_multishortmap_size (routes),
582 destroy_direction (&route->prev);
583 destroy_direction (&route->next);
589 * Send message that a route is broken between @a peer1 and @a peer2.
591 * @param target where to send the message
592 * @param cid connection identifier to use
593 * @param peer1 one of the peers where a link is broken
594 * @param peer2 another one of the peers where a link is broken
597 send_broken (struct RouteDirection *target,
598 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
599 const struct GNUNET_PeerIdentity *peer1,
600 const struct GNUNET_PeerIdentity *peer2)
602 struct GNUNET_MQ_Envelope *env;
603 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
605 if (NULL == target->mqm)
606 return; /* Can't send notification, connection is down! */
607 LOG (GNUNET_ERROR_TYPE_DEBUG,
608 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
609 GCP_2s (target->hop),
612 GNUNET_sh2s (&cid->connection_of_tunnel));
614 env = GNUNET_MQ_msg (bm,
615 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
621 GCP_request_mq_cancel (target->mqm,
628 * Function called to check if any routes have timed out, and if
629 * so, to clean them up. Finally, schedules itself again at the
630 * earliest time where there might be more work.
635 timeout_cb (void *cls)
637 struct CadetRoute *r;
638 struct GNUNET_TIME_Relative linger;
639 struct GNUNET_TIME_Absolute exp;
642 linger = GNUNET_TIME_relative_multiply (keepalive_period,
644 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
646 exp = GNUNET_TIME_absolute_add (r->last_use,
648 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
650 /* Route not yet timed out, wait until it does. */
651 timeout_task = GNUNET_SCHEDULER_add_at (exp,
656 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
657 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
658 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
659 GNUNET_STRINGS_relative_time_to_string (linger,
661 send_broken (&r->prev,
665 send_broken (&r->next,
671 /* No more routes left, so no need for a #timeout_task */
676 * Function called when the message queue to the previous hop
677 * becomes available/unavailable. We expect this function to
678 * be called immediately when we register, and then again
679 * later if the connection ever goes down.
681 * @param cls the `struct RouteDirection`
682 * @param available #GNUNET_YES if sending is now possible,
683 * #GNUNET_NO if sending is no longer possible
684 * #GNUNET_SYSERR if sending is no longer possible
685 * and the last envelope was discarded
688 dir_ready_cb (void *cls,
691 struct RouteDirection *dir = cls;
692 struct CadetRoute *route = dir->my_route;
693 struct RouteDirection *odir;
695 if (GNUNET_YES == ready)
697 struct GNUNET_MQ_Envelope *env;
699 dir->is_ready = GNUNET_YES;
700 if (NULL != (env = dir->env_head))
702 GNUNET_MQ_dll_remove (&dir->env_head,
706 GNUNET_STATISTICS_set (stats,
711 dir->is_ready = GNUNET_NO;
717 odir = (dir == &route->next) ? &route->prev : &route->next;
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719 "Sending BROKEN due to MQ going down\n");
720 send_broken (&route->next,
722 GCP_get_id (odir->hop),
724 destroy_route (route);
729 * Initialize one of the directions of a route.
731 * @param route route the direction belongs to
732 * @param dir direction to initialize
733 * @param hop next hop on in the @a dir
736 dir_init (struct RouteDirection *dir,
737 struct CadetRoute *route,
738 struct CadetPeer *hop)
741 dir->my_route = route;
742 dir->mqm = GCP_request_mq (hop,
745 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head,
748 dir->rung = rung_head;
749 GNUNET_assert (GNUNET_YES == dir->is_ready);
754 * We could not create the desired route. Send a
755 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
756 * message to @a target.
758 * @param target who should receive the message
759 * @param cid identifier of the connection/route that failed
760 * @param failure_at neighbour with which we failed to route,
764 send_broken_without_mqm (struct CadetPeer *target,
765 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
766 const struct GNUNET_PeerIdentity *failure_at)
768 struct GNUNET_MQ_Envelope *env;
769 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
771 env = GNUNET_MQ_msg (bm,
772 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
774 bm->peer1 = my_full_id;
775 if (NULL != failure_at)
776 bm->peer2 = *failure_at;
777 GCP_send_ooo (target,
783 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
785 * @param cls Closure (CadetPeer for neighbor that sent the message).
786 * @param msg Message itself.
789 handle_connection_create (void *cls,
790 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
792 struct CadetPeer *sender = cls;
793 struct CadetPeer *next;
794 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
795 struct CadetRoute *route;
796 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
797 unsigned int path_length;
799 enum GNUNET_CADET_ChannelOption options;
801 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
802 path_length = size / sizeof (struct GNUNET_PeerIdentity);
803 if (0 == path_length)
805 LOG (GNUNET_ERROR_TYPE_DEBUG,
806 "Dropping CADET_CONNECTION_CREATE with empty path\n");
810 LOG (GNUNET_ERROR_TYPE_DEBUG,
811 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
813 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
815 /* Check for loops */
817 struct GNUNET_CONTAINER_MultiPeerMap *map;
819 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
821 GNUNET_assert (NULL != map);
822 for (unsigned int i=0;i<path_length;i++)
824 LOG (GNUNET_ERROR_TYPE_DEBUG,
825 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
826 GNUNET_i2s (&pids[i]),
829 GNUNET_CONTAINER_multipeermap_put (map,
832 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
835 GNUNET_CONTAINER_multipeermap_destroy (map);
836 LOG (GNUNET_ERROR_TYPE_DEBUG,
837 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
842 GNUNET_CONTAINER_multipeermap_destroy (map);
844 /* Initiator is at offset 0, find us */
845 for (off=1;off<path_length;off++)
846 if (0 == GNUNET_memcmp (&my_full_id,
849 if (off == path_length)
851 LOG (GNUNET_ERROR_TYPE_DEBUG,
852 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
856 /* Check previous hop */
857 if (sender != GCP_get (&pids[off - 1],
860 LOG (GNUNET_ERROR_TYPE_DEBUG,
861 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
866 (route = get_route (&msg->cid)))
868 /* Duplicate CREATE, pass it on, previous one might have been lost! */
870 LOG (GNUNET_ERROR_TYPE_DEBUG,
871 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
872 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
873 route_message (sender,
878 if (off == path_length - 1)
880 /* We are the destination, create connection */
881 struct CadetConnection *cc;
882 struct CadetPeerPath *path;
883 struct CadetPeer *origin;
885 cc = GCC_lookup (&msg->cid);
888 LOG (GNUNET_ERROR_TYPE_DEBUG,
889 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
890 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
891 GCC_handle_duplicate_create (cc);
895 origin = GCP_get (&pids[0],
897 LOG (GNUNET_ERROR_TYPE_DEBUG,
898 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
900 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
901 path = GCPP_get_path_from_route (path_length - 1,
904 GCT_add_inbound_connection (GCP_get_tunnel (origin,
907 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
910 /* Send back BROKEN: duplicate connection on the same path,
911 we will use the other one. */
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
915 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
917 send_broken_without_mqm (sender,
924 /* We are merely a hop on the way, check if we can support the route */
925 next = GCP_get (&pids[off + 1],
927 if ( (NULL == next) ||
928 (GNUNET_NO == GCP_has_core_connection (next)) )
930 /* unworkable, send back BROKEN notification */
931 LOG (GNUNET_ERROR_TYPE_DEBUG,
932 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
934 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
935 GNUNET_i2s (&pids[off + 1]),
937 send_broken_without_mqm (sender,
942 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
944 LOG (GNUNET_ERROR_TYPE_DEBUG,
945 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
947 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
948 send_broken_without_mqm (sender,
954 /* Workable route, create routing entry */
955 LOG (GNUNET_ERROR_TYPE_DEBUG,
956 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
958 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
959 GNUNET_i2s (&pids[off + 1]),
961 route = GNUNET_new (struct CadetRoute);
962 route->options = options;
963 route->cid = msg->cid;
964 route->last_use = GNUNET_TIME_absolute_get ();
965 dir_init (&route->prev,
968 dir_init (&route->next,
971 GNUNET_assert (GNUNET_OK ==
972 GNUNET_CONTAINER_multishortmap_put (routes,
973 &route->cid.connection_of_tunnel,
975 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
976 GNUNET_STATISTICS_set (stats,
978 GNUNET_CONTAINER_multishortmap_size (routes),
980 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
982 route->last_use.abs_value_us);
983 if (NULL == timeout_task)
984 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
988 /* also pass CREATE message along to next hop */
989 route_message (sender,
996 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
998 * @param cls Closure (CadetPeer for neighbor that sent the message).
999 * @param msg Message itself.
1002 handle_connection_create_ack (void *cls,
1003 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
1005 struct CadetPeer *peer = cls;
1006 struct CadetConnection *cc;
1008 /* First, check if ACK belongs to a connection that ends here. */
1009 cc = GCC_lookup (&msg->cid);
1012 /* verify ACK came from the right direction */
1014 struct CadetPeerPath *path = GCC_get_path (cc,
1018 GCPP_get_peer_at_offset (path,
1021 /* received ACK from unexpected direction, ignore! */
1022 GNUNET_break_op (0);
1025 LOG (GNUNET_ERROR_TYPE_DEBUG,
1026 "Received CONNECTION_CREATE_ACK for connection %s.\n",
1027 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1028 GCC_handle_connection_create_ack (cc);
1032 /* We're just an intermediary peer, route the message along its path */
1033 route_message (peer,
1040 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
1042 * @param cls Closure (CadetPeer for neighbor that sent the message).
1043 * @param msg Message itself.
1044 * @deprecated duplicate logic with #handle_destroy(); dedup!
1047 handle_connection_broken (void *cls,
1048 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
1050 struct CadetPeer *peer = cls;
1051 struct CadetConnection *cc;
1052 struct CadetRoute *route;
1054 /* First, check if message belongs to a connection that ends here. */
1055 cc = GCC_lookup (&msg->cid);
1058 /* verify message came from the right direction */
1060 struct CadetPeerPath *path = GCC_get_path (cc,
1064 GCPP_get_peer_at_offset (path,
1067 /* received message from unexpected direction, ignore! */
1068 GNUNET_break_op (0);
1071 LOG (GNUNET_ERROR_TYPE_DEBUG,
1072 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
1073 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1074 GCC_destroy_without_core (cc);
1076 /* FIXME: also destroy the path up to the specified link! */
1080 /* We're just an intermediary peer, route the message along its path */
1081 route_message (peer,
1084 route = get_route (&msg->cid);
1086 destroy_route (route);
1087 /* FIXME: also destroy paths we MAY have up to the specified link! */
1092 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1094 * @param cls Closure (CadetPeer for neighbor that sent the message).
1095 * @param msg Message itself.
1098 handle_connection_destroy (void *cls,
1099 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1101 struct CadetPeer *peer = cls;
1102 struct CadetConnection *cc;
1103 struct CadetRoute *route;
1105 /* First, check if message belongs to a connection that ends here. */
1106 cc = GCC_lookup (&msg->cid);
1109 /* verify message came from the right direction */
1111 struct CadetPeerPath *path = GCC_get_path (cc,
1115 GCPP_get_peer_at_offset (path,
1118 /* received message from unexpected direction, ignore! */
1119 GNUNET_break_op (0);
1122 LOG (GNUNET_ERROR_TYPE_DEBUG,
1123 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1124 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1126 GCC_destroy_without_core (cc);
1130 /* We're just an intermediary peer, route the message along its path */
1131 LOG (GNUNET_ERROR_TYPE_DEBUG,
1132 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1133 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1134 route_message (peer,
1137 route = get_route (&msg->cid);
1139 destroy_route (route);
1144 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1146 * @param cls Closure (CadetPeer for neighbor that sent the message).
1147 * @param msg Message itself.
1150 handle_tunnel_kx (void *cls,
1151 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1153 struct CadetPeer *peer = cls;
1154 struct CadetConnection *cc;
1156 /* First, check if message belongs to a connection that ends here. */
1157 LOG (GNUNET_ERROR_TYPE_DEBUG,
1158 "Routing KX with ephemeral %s on CID %s\n",
1159 GNUNET_e2s (&msg->ephemeral_key),
1160 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1163 cc = GCC_lookup (&msg->cid);
1166 /* verify message came from the right direction */
1168 struct CadetPeerPath *path = GCC_get_path (cc,
1172 GCPP_get_peer_at_offset (path,
1175 /* received message from unexpected direction, ignore! */
1176 GNUNET_break_op (0);
1184 /* We're just an intermediary peer, route the message along its path */
1185 route_message (peer,
1192 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1194 * @param cls Closure (CadetPeer for neighbor that sent the message).
1195 * @param msg Message itself.
1198 handle_tunnel_kx_auth (void *cls,
1199 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1201 struct CadetPeer *peer = cls;
1202 struct CadetConnection *cc;
1204 /* First, check if message belongs to a connection that ends here. */
1205 cc = GCC_lookup (&msg->kx.cid);
1208 /* verify message came from the right direction */
1210 struct CadetPeerPath *path = GCC_get_path (cc,
1214 GCPP_get_peer_at_offset (path,
1217 /* received message from unexpected direction, ignore! */
1218 GNUNET_break_op (0);
1221 GCC_handle_kx_auth (cc,
1226 /* We're just an intermediary peer, route the message along its path */
1227 route_message (peer,
1234 * Check if the encrypted message has the appropriate size.
1236 * @param cls Closure (unused).
1237 * @param msg Message to check.
1239 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1242 check_tunnel_encrypted (void *cls,
1243 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1250 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1252 * @param cls Closure (CadetPeer for neighbor that sent the message).
1253 * @param msg Message itself.
1256 handle_tunnel_encrypted (void *cls,
1257 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1259 struct CadetPeer *peer = cls;
1260 struct CadetConnection *cc;
1262 /* First, check if message belongs to a connection that ends here. */
1263 cc = GCC_lookup (&msg->cid);
1266 /* verify message came from the right direction */
1268 struct CadetPeerPath *path = GCC_get_path (cc,
1272 GCPP_get_peer_at_offset (path,
1275 /* received message from unexpected direction, ignore! */
1276 GNUNET_break_op (0);
1279 GCC_handle_encrypted (cc,
1283 /* We're just an intermediary peer, route the message along its path */
1284 route_message (peer,
1291 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1292 * for good). Note that the private key of the peer is intentionally
1293 * not exposed here; if you need it, your process should try to read
1294 * the private key file directly (which should work if you are
1295 * authorized...). Implementations of this function must not call
1296 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1299 * @param cls closure
1300 * @param my_identity ID of this peer, NULL if we failed
1303 core_init_cb (void *cls,
1304 const struct GNUNET_PeerIdentity *my_identity)
1306 if (NULL == my_identity)
1312 GNUNET_memcmp (my_identity,
1318 * Method called whenever a given peer connects.
1320 * @param cls closure
1321 * @param peer peer identity this notification is about
1324 core_connect_cb (void *cls,
1325 const struct GNUNET_PeerIdentity *peer,
1326 struct GNUNET_MQ_Handle *mq)
1328 struct CadetPeer *cp;
1330 LOG (GNUNET_ERROR_TYPE_DEBUG,
1331 "CORE connection to peer %s was established.\n",
1342 * Method called whenever a peer disconnects.
1344 * @param cls closure
1345 * @param peer peer identity this notification is about
1348 core_disconnect_cb (void *cls,
1349 const struct GNUNET_PeerIdentity *peer,
1352 struct CadetPeer *cp = peer_cls;
1354 LOG (GNUNET_ERROR_TYPE_DEBUG,
1355 "CORE connection to peer %s went down.\n",
1363 * Initialize the CORE subsystem.
1365 * @param c Configuration.
1368 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1370 struct GNUNET_MQ_MessageHandler handlers[] = {
1371 GNUNET_MQ_hd_var_size (connection_create,
1372 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1373 struct GNUNET_CADET_ConnectionCreateMessage,
1375 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1376 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1377 struct GNUNET_CADET_ConnectionCreateAckMessage,
1379 GNUNET_MQ_hd_fixed_size (connection_broken,
1380 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1381 struct GNUNET_CADET_ConnectionBrokenMessage,
1383 GNUNET_MQ_hd_fixed_size (connection_destroy,
1384 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1385 struct GNUNET_CADET_ConnectionDestroyMessage,
1387 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1388 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1389 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1391 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1392 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1393 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1395 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1396 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1397 struct GNUNET_CADET_TunnelEncryptedMessage,
1399 GNUNET_MQ_handler_end ()
1403 GNUNET_CONFIGURATION_get_value_number (c,
1409 GNUNET_CONFIGURATION_get_value_number (c,
1413 max_buffers = 10000;
1414 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1416 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1417 core = GNUNET_CORE_connect (c,
1421 &core_disconnect_cb,
1427 * Shut down the CORE subsystem.
1434 GNUNET_CORE_disconnect (core);
1437 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1438 GNUNET_CONTAINER_multishortmap_destroy (routes);
1440 GNUNET_CONTAINER_heap_destroy (route_heap);
1442 if (NULL != timeout_task)
1444 GNUNET_SCHEDULER_cancel (timeout_task);
1445 timeout_task = NULL;
1449 /* end of gnunet-cadet-service_core.c */