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 == memcmp (&my_full_id,
848 sizeof (struct GNUNET_PeerIdentity)))
850 if (off == path_length)
852 LOG (GNUNET_ERROR_TYPE_DEBUG,
853 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
857 /* Check previous hop */
858 if (sender != GCP_get (&pids[off - 1],
861 LOG (GNUNET_ERROR_TYPE_DEBUG,
862 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
867 (route = get_route (&msg->cid)))
869 /* Duplicate CREATE, pass it on, previous one might have been lost! */
871 LOG (GNUNET_ERROR_TYPE_DEBUG,
872 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
873 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
874 route_message (sender,
879 if (off == path_length - 1)
881 /* We are the destination, create connection */
882 struct CadetConnection *cc;
883 struct CadetPeerPath *path;
884 struct CadetPeer *origin;
886 cc = GCC_lookup (&msg->cid);
889 LOG (GNUNET_ERROR_TYPE_DEBUG,
890 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
891 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
892 GCC_handle_duplicate_create (cc);
896 origin = GCP_get (&pids[0],
898 LOG (GNUNET_ERROR_TYPE_DEBUG,
899 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
901 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
902 path = GCPP_get_path_from_route (path_length - 1,
905 GCT_add_inbound_connection (GCP_get_tunnel (origin,
908 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
911 /* Send back BROKEN: duplicate connection on the same path,
912 we will use the other one. */
913 LOG (GNUNET_ERROR_TYPE_DEBUG,
914 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
916 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
918 send_broken_without_mqm (sender,
925 /* We are merely a hop on the way, check if we can support the route */
926 next = GCP_get (&pids[off + 1],
928 if ( (NULL == next) ||
929 (GNUNET_NO == GCP_has_core_connection (next)) )
931 /* unworkable, send back BROKEN notification */
932 LOG (GNUNET_ERROR_TYPE_DEBUG,
933 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
935 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
936 GNUNET_i2s (&pids[off + 1]),
938 send_broken_without_mqm (sender,
943 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
945 LOG (GNUNET_ERROR_TYPE_DEBUG,
946 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
948 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
949 send_broken_without_mqm (sender,
955 /* Workable route, create routing entry */
956 LOG (GNUNET_ERROR_TYPE_DEBUG,
957 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
959 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
960 GNUNET_i2s (&pids[off + 1]),
962 route = GNUNET_new (struct CadetRoute);
963 route->options = options;
964 route->cid = msg->cid;
965 route->last_use = GNUNET_TIME_absolute_get ();
966 dir_init (&route->prev,
969 dir_init (&route->next,
972 GNUNET_assert (GNUNET_OK ==
973 GNUNET_CONTAINER_multishortmap_put (routes,
974 &route->cid.connection_of_tunnel,
976 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
977 GNUNET_STATISTICS_set (stats,
979 GNUNET_CONTAINER_multishortmap_size (routes),
981 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
983 route->last_use.abs_value_us);
984 if (NULL == timeout_task)
985 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
989 /* also pass CREATE message along to next hop */
990 route_message (sender,
997 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
999 * @param cls Closure (CadetPeer for neighbor that sent the message).
1000 * @param msg Message itself.
1003 handle_connection_create_ack (void *cls,
1004 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
1006 struct CadetPeer *peer = cls;
1007 struct CadetConnection *cc;
1009 /* First, check if ACK belongs to a connection that ends here. */
1010 cc = GCC_lookup (&msg->cid);
1013 /* verify ACK came from the right direction */
1015 struct CadetPeerPath *path = GCC_get_path (cc,
1019 GCPP_get_peer_at_offset (path,
1022 /* received ACK from unexpected direction, ignore! */
1023 GNUNET_break_op (0);
1026 LOG (GNUNET_ERROR_TYPE_DEBUG,
1027 "Received CONNECTION_CREATE_ACK for connection %s.\n",
1028 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1029 GCC_handle_connection_create_ack (cc);
1033 /* We're just an intermediary peer, route the message along its path */
1034 route_message (peer,
1041 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
1043 * @param cls Closure (CadetPeer for neighbor that sent the message).
1044 * @param msg Message itself.
1045 * @deprecated duplicate logic with #handle_destroy(); dedup!
1048 handle_connection_broken (void *cls,
1049 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
1051 struct CadetPeer *peer = cls;
1052 struct CadetConnection *cc;
1053 struct CadetRoute *route;
1055 /* First, check if message belongs to a connection that ends here. */
1056 cc = GCC_lookup (&msg->cid);
1059 /* verify message came from the right direction */
1061 struct CadetPeerPath *path = GCC_get_path (cc,
1065 GCPP_get_peer_at_offset (path,
1068 /* received message from unexpected direction, ignore! */
1069 GNUNET_break_op (0);
1072 LOG (GNUNET_ERROR_TYPE_DEBUG,
1073 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
1074 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1075 GCC_destroy_without_core (cc);
1077 /* FIXME: also destroy the path up to the specified link! */
1081 /* We're just an intermediary peer, route the message along its path */
1082 route_message (peer,
1085 route = get_route (&msg->cid);
1087 destroy_route (route);
1088 /* FIXME: also destroy paths we MAY have up to the specified link! */
1093 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1095 * @param cls Closure (CadetPeer for neighbor that sent the message).
1096 * @param msg Message itself.
1099 handle_connection_destroy (void *cls,
1100 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1102 struct CadetPeer *peer = cls;
1103 struct CadetConnection *cc;
1104 struct CadetRoute *route;
1106 /* First, check if message belongs to a connection that ends here. */
1107 cc = GCC_lookup (&msg->cid);
1110 /* verify message came from the right direction */
1112 struct CadetPeerPath *path = GCC_get_path (cc,
1116 GCPP_get_peer_at_offset (path,
1119 /* received message from unexpected direction, ignore! */
1120 GNUNET_break_op (0);
1123 LOG (GNUNET_ERROR_TYPE_DEBUG,
1124 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1125 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1127 GCC_destroy_without_core (cc);
1131 /* We're just an intermediary peer, route the message along its path */
1132 LOG (GNUNET_ERROR_TYPE_DEBUG,
1133 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1134 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1135 route_message (peer,
1138 route = get_route (&msg->cid);
1140 destroy_route (route);
1145 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1147 * @param cls Closure (CadetPeer for neighbor that sent the message).
1148 * @param msg Message itself.
1151 handle_tunnel_kx (void *cls,
1152 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1154 struct CadetPeer *peer = cls;
1155 struct CadetConnection *cc;
1157 /* First, check if message belongs to a connection that ends here. */
1158 LOG (GNUNET_ERROR_TYPE_DEBUG,
1159 "Routing KX with ephemeral %s on CID %s\n",
1160 GNUNET_e2s (&msg->ephemeral_key),
1161 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1164 cc = GCC_lookup (&msg->cid);
1167 /* verify message came from the right direction */
1169 struct CadetPeerPath *path = GCC_get_path (cc,
1173 GCPP_get_peer_at_offset (path,
1176 /* received message from unexpected direction, ignore! */
1177 GNUNET_break_op (0);
1185 /* We're just an intermediary peer, route the message along its path */
1186 route_message (peer,
1193 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1195 * @param cls Closure (CadetPeer for neighbor that sent the message).
1196 * @param msg Message itself.
1199 handle_tunnel_kx_auth (void *cls,
1200 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1202 struct CadetPeer *peer = cls;
1203 struct CadetConnection *cc;
1205 /* First, check if message belongs to a connection that ends here. */
1206 cc = GCC_lookup (&msg->kx.cid);
1209 /* verify message came from the right direction */
1211 struct CadetPeerPath *path = GCC_get_path (cc,
1215 GCPP_get_peer_at_offset (path,
1218 /* received message from unexpected direction, ignore! */
1219 GNUNET_break_op (0);
1222 GCC_handle_kx_auth (cc,
1227 /* We're just an intermediary peer, route the message along its path */
1228 route_message (peer,
1235 * Check if the encrypted message has the appropriate size.
1237 * @param cls Closure (unused).
1238 * @param msg Message to check.
1240 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1243 check_tunnel_encrypted (void *cls,
1244 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1251 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1253 * @param cls Closure (CadetPeer for neighbor that sent the message).
1254 * @param msg Message itself.
1257 handle_tunnel_encrypted (void *cls,
1258 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1260 struct CadetPeer *peer = cls;
1261 struct CadetConnection *cc;
1263 /* First, check if message belongs to a connection that ends here. */
1264 cc = GCC_lookup (&msg->cid);
1267 /* verify message came from the right direction */
1269 struct CadetPeerPath *path = GCC_get_path (cc,
1273 GCPP_get_peer_at_offset (path,
1276 /* received message from unexpected direction, ignore! */
1277 GNUNET_break_op (0);
1280 GCC_handle_encrypted (cc,
1284 /* We're just an intermediary peer, route the message along its path */
1285 route_message (peer,
1292 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1293 * for good). Note that the private key of the peer is intentionally
1294 * not exposed here; if you need it, your process should try to read
1295 * the private key file directly (which should work if you are
1296 * authorized...). Implementations of this function must not call
1297 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1300 * @param cls closure
1301 * @param my_identity ID of this peer, NULL if we failed
1304 core_init_cb (void *cls,
1305 const struct GNUNET_PeerIdentity *my_identity)
1307 if (NULL == my_identity)
1313 memcmp (my_identity,
1315 sizeof (struct GNUNET_PeerIdentity)));
1320 * Method called whenever a given peer connects.
1322 * @param cls closure
1323 * @param peer peer identity this notification is about
1326 core_connect_cb (void *cls,
1327 const struct GNUNET_PeerIdentity *peer,
1328 struct GNUNET_MQ_Handle *mq)
1330 struct CadetPeer *cp;
1332 LOG (GNUNET_ERROR_TYPE_DEBUG,
1333 "CORE connection to peer %s was established.\n",
1344 * Method called whenever a peer disconnects.
1346 * @param cls closure
1347 * @param peer peer identity this notification is about
1350 core_disconnect_cb (void *cls,
1351 const struct GNUNET_PeerIdentity *peer,
1354 struct CadetPeer *cp = peer_cls;
1356 LOG (GNUNET_ERROR_TYPE_DEBUG,
1357 "CORE connection to peer %s went down.\n",
1365 * Initialize the CORE subsystem.
1367 * @param c Configuration.
1370 GCO_init (const struct GNUNET_CONFIGURATION_Handle *c)
1372 struct GNUNET_MQ_MessageHandler handlers[] = {
1373 GNUNET_MQ_hd_var_size (connection_create,
1374 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
1375 struct GNUNET_CADET_ConnectionCreateMessage,
1377 GNUNET_MQ_hd_fixed_size (connection_create_ack,
1378 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
1379 struct GNUNET_CADET_ConnectionCreateAckMessage,
1381 GNUNET_MQ_hd_fixed_size (connection_broken,
1382 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
1383 struct GNUNET_CADET_ConnectionBrokenMessage,
1385 GNUNET_MQ_hd_fixed_size (connection_destroy,
1386 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
1387 struct GNUNET_CADET_ConnectionDestroyMessage,
1389 GNUNET_MQ_hd_fixed_size (tunnel_kx,
1390 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
1391 struct GNUNET_CADET_TunnelKeyExchangeMessage,
1393 GNUNET_MQ_hd_fixed_size (tunnel_kx_auth,
1394 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH,
1395 struct GNUNET_CADET_TunnelKeyExchangeAuthMessage,
1397 GNUNET_MQ_hd_var_size (tunnel_encrypted,
1398 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
1399 struct GNUNET_CADET_TunnelEncryptedMessage,
1401 GNUNET_MQ_handler_end ()
1405 GNUNET_CONFIGURATION_get_value_number (c,
1411 GNUNET_CONFIGURATION_get_value_number (c,
1415 max_buffers = 10000;
1416 routes = GNUNET_CONTAINER_multishortmap_create (1024,
1418 route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1419 core = GNUNET_CORE_connect (c,
1423 &core_disconnect_cb,
1429 * Shut down the CORE subsystem.
1436 GNUNET_CORE_disconnect (core);
1439 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes));
1440 GNUNET_CONTAINER_multishortmap_destroy (routes);
1442 GNUNET_CONTAINER_heap_destroy (route_heap);
1444 if (NULL != timeout_task)
1446 GNUNET_SCHEDULER_cancel (timeout_task);
1447 timeout_task = NULL;
1451 /* end of gnunet-cadet-service_core.c */