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/>.
20 * @file cadet/gnunet-service-cadet_core.c
21 * @brief cadet service; interaction with CORE service
22 * @author Bartlomiej Polot
23 * @author Christian Grothoff
25 * All functions in this file should use the prefix GCO (Gnunet Cadet cOre (bottom))
28 * - Optimization: given BROKEN messages, destroy paths (?)
31 #include "gnunet-service-cadet_core.h"
32 #include "gnunet-service-cadet_paths.h"
33 #include "gnunet-service-cadet_peer.h"
34 #include "gnunet-service-cadet_connection.h"
35 #include "gnunet-service-cadet_tunnels.h"
36 #include "gnunet_core_service.h"
37 #include "gnunet_statistics_service.h"
38 #include "cadet_protocol.h"
41 #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__)
44 * Information we keep per direction for a route.
46 struct RouteDirection;
50 * Set of CadetRoutes that have exactly the same number of messages
51 * in their buffer. Used so we can efficiently find all of those
52 * routes that have the current maximum of messages in the buffer (in
53 * case we have to purge).
59 * Rung of RouteDirections with one more buffer entry each.
64 * Rung of RouteDirections with one less buffer entry each.
69 * DLL of route directions with a number of buffer entries matching this rung.
71 struct RouteDirection *rd_head;
74 * DLL of route directions with a number of buffer entries matching this rung.
76 struct RouteDirection *rd_tail;
79 * Total number of route directions in this rung.
81 unsigned int num_routes;
84 * Number of messages route directions at this rung have
87 unsigned int rung_off;
92 * Information we keep per direction for a route.
98 * DLL of other route directions within the same `struct Rung`.
100 struct RouteDirection *prev;
103 * DLL of other route directions within the same `struct Rung`.
105 struct RouteDirection *next;
108 * Rung of this route direction (matches length of the buffer DLL).
113 * Head of DLL of envelopes we have in the buffer for this direction.
115 struct GNUNET_MQ_Envelope *env_head;
118 * Tail of DLL of envelopes we have in the buffer for this direction.
120 struct GNUNET_MQ_Envelope *env_tail;
125 struct CadetPeer *hop;
128 * Route this direction is part of.
130 struct CadetRoute *my_route;
133 * Message queue manager for @e hop.
135 struct GCP_MessageQueueManager *mqm;
138 * Is @e mqm currently ready for transmission?
146 * Description of a segment of a `struct CadetConnection` at the
147 * intermediate peers. Routes are basically entries in a peer's
148 * routing table for forwarding traffic. At both endpoints, the
149 * routes are terminated by a `struct CadetConnection`, which knows
150 * the complete `struct CadetPath` that is formed by the individual
157 * Information about the next hop on this route.
159 struct RouteDirection next;
162 * Information about the previous hop on this route.
164 struct RouteDirection prev;
167 * Unique identifier for the connection that uses this route.
169 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
172 * When was this route last in use?
174 struct GNUNET_TIME_Absolute last_use;
177 * Position of this route in the #route_heap.
179 struct GNUNET_CONTAINER_HeapNode *hn;
182 * Options for the route, control buffering.
184 enum GNUNET_CADET_ChannelOption options;
189 * Handle to the CORE service.
191 static struct GNUNET_CORE_Handle *core;
194 * Routes on which this peer is an intermediate.
196 static struct GNUNET_CONTAINER_MultiShortmap *routes;
199 * Heap of routes, MIN-sorted by last activity.
201 static struct GNUNET_CONTAINER_Heap *route_heap;
204 * Rung zero (always pointed to by #rung_head).
206 static struct Rung rung_zero;
209 * DLL of rungs, with the head always point to a rung of
210 * route directions with no messages in the queue.
212 static struct Rung *rung_head = &rung_zero;
215 * Tail of the #rung_head DLL.
217 static struct Rung *rung_tail = &rung_zero;
220 * Maximum number of concurrent routes this peer will support.
222 static unsigned long long max_routes;
225 * Maximum number of envelopes we will buffer at this peer.
227 static unsigned long long max_buffers;
230 * Current number of envelopes we have buffered at this peer.
232 static unsigned long long cur_buffers;
235 * Task to timeout routes.
237 static struct GNUNET_SCHEDULER_Task *timeout_task;
241 * Get the route corresponding to a hash.
243 * @param cid hash generated from the connection identifier
245 static struct CadetRoute *
246 get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
248 return GNUNET_CONTAINER_multishortmap_get (routes,
249 &cid->connection_of_tunnel);
254 * Lower the rung in which @a dir is by 1.
256 * @param dir direction to lower in rung.
259 lower_rung (struct RouteDirection *dir)
261 struct Rung *rung = dir->rung;
264 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
268 GNUNET_assert (NULL != prev);
269 if (prev->rung_off != rung->rung_off - 1)
271 prev = GNUNET_new (struct Rung);
272 prev->rung_off = rung->rung_off - 1;
273 GNUNET_CONTAINER_DLL_insert_after (rung_head,
278 GNUNET_assert (NULL != prev);
279 GNUNET_CONTAINER_DLL_insert (prev->rd_head,
287 * Discard the buffer @a env from the route direction @a dir and
288 * move @a dir down a rung.
290 * @param dir direction that contains the @a env in the buffer
291 * @param env envelope to discard
294 discard_buffer (struct RouteDirection *dir,
295 struct GNUNET_MQ_Envelope *env)
297 GNUNET_MQ_dll_remove (&dir->env_head,
301 GNUNET_MQ_discard (env);
303 GNUNET_STATISTICS_set (stats,
311 * Discard all messages from the highest rung, to make space.
314 discard_all_from_rung_tail ()
316 struct Rung *tail = rung_tail;
317 struct RouteDirection *dir;
319 while (NULL != (dir = tail->rd_head))
321 LOG (GNUNET_ERROR_TYPE_DEBUG,
322 "Queue full due new message %s on connection %s, dropping old message\n",
323 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
324 GNUNET_STATISTICS_update (stats,
325 "# messages dropped due to full buffer",
331 GNUNET_CONTAINER_DLL_remove (rung_head,
339 * We message @a msg from @a prev. Find its route by @a cid and
340 * forward to the next hop. Drop and signal broken route if we do not
343 * @param prev previous hop (sender)
344 * @param cid connection identifier, tells us which route to use
345 * @param msg the message to forward
348 route_message (struct CadetPeer *prev,
349 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
350 const struct GNUNET_MessageHeader *msg)
352 struct CadetRoute *route;
353 struct RouteDirection *dir;
356 struct GNUNET_MQ_Envelope *env;
358 route = get_route (cid);
361 struct GNUNET_MQ_Envelope *env;
362 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
364 LOG (GNUNET_ERROR_TYPE_DEBUG,
365 "Failed to route message of type %u from %s on connection %s: no route\n",
368 GNUNET_sh2s (&cid->connection_of_tunnel));
369 switch (ntohs (msg->type))
371 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
372 case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
373 /* No need to respond to these! */
376 env = GNUNET_MQ_msg (bm,
377 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
379 bm->peer1 = my_full_id;
384 route->last_use = GNUNET_TIME_absolute_get ();
385 GNUNET_CONTAINER_heap_update_cost (route->hn,
386 route->last_use.abs_value_us);
387 dir = (prev == route->prev.hop) ? &route->next : &route->prev;
388 if (GNUNET_YES == dir->is_ready)
390 LOG (GNUNET_ERROR_TYPE_DEBUG,
391 "Routing message of type %u from %s to %s on connection %s\n",
394 GNUNET_i2s (GCP_get_id (dir->hop)),
395 GNUNET_sh2s (&cid->connection_of_tunnel));
396 dir->is_ready = GNUNET_NO;
398 GNUNET_MQ_msg_copy (msg));
401 /* Check if buffering is disallowed, and if so, make sure we only queue
402 one message per direction. */
403 if ( (0 != (route->options & GNUNET_CADET_OPTION_NOBUFFER)) &&
404 (NULL != dir->env_head) )
407 /* Check for duplicates */
408 for (const struct GNUNET_MQ_Envelope *env = dir->env_head;
410 env = GNUNET_MQ_env_next (env))
412 const struct GNUNET_MessageHeader *hdr = GNUNET_MQ_env_get_msg (env);
414 if ( (hdr->size == msg->size) &&
417 ntohs (msg->size))) )
419 LOG (GNUNET_ERROR_TYPE_DEBUG,
420 "Received duplicate of message already in buffer, dropping\n");
421 GNUNET_STATISTICS_update (stats,
422 "# messages dropped due to duplicate in buffer",
430 if (cur_buffers == max_buffers)
432 /* Need to make room. */
433 if (NULL != rung->next)
435 /* Easy case, drop messages from route directions in highest rung */
436 discard_all_from_rung_tail ();
440 /* We are in the highest rung, drop our own! */
441 LOG (GNUNET_ERROR_TYPE_DEBUG,
442 "Queue full due new message %s on connection %s, dropping old message\n",
443 GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel));
444 GNUNET_STATISTICS_update (stats,
445 "# messages dropped due to full buffer",
453 /* remove 'dir' from current rung */
454 GNUNET_CONTAINER_DLL_remove (rung->rd_head,
457 /* make 'nxt' point to the next higher rung, create if necessary */
459 if ( (NULL == nxt) ||
460 (rung->rung_off + 1 != nxt->rung_off) )
462 nxt = GNUNET_new (struct Rung);
463 nxt->rung_off = rung->rung_off + 1;
464 GNUNET_CONTAINER_DLL_insert_after (rung_head,
469 /* insert 'dir' into next higher rung */
470 GNUNET_CONTAINER_DLL_insert (nxt->rd_head,
475 /* add message into 'dir' buffer */
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Queueing new message of type %u from %s to %s on connection %s\n",
480 GNUNET_i2s (GCP_get_id (dir->hop)),
481 GNUNET_sh2s (&cid->connection_of_tunnel));
482 env = GNUNET_MQ_msg_copy (msg);
483 GNUNET_MQ_dll_insert_tail (&dir->env_head,
487 GNUNET_STATISTICS_set (stats,
491 /* Clean up 'rung' if now empty (and not head) */
492 if ( (NULL == rung->rd_head) &&
493 (rung != rung_head) )
495 GNUNET_CONTAINER_DLL_remove (rung_head,
504 * Check if the create_connection message has the appropriate size.
506 * @param cls Closure (unused).
507 * @param msg Message to check.
509 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
512 check_connection_create (void *cls,
513 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
515 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
517 if (0 != (size % sizeof (struct GNUNET_PeerIdentity)))
527 * Free internal data of a route direction.
529 * @param dir direction to destroy (do NOT free memory of 'dir' itself)
532 destroy_direction (struct RouteDirection *dir)
534 struct GNUNET_MQ_Envelope *env;
536 while (NULL != (env = dir->env_head))
538 GNUNET_STATISTICS_update (stats,
539 "# messages dropped due to route destruction",
545 if (NULL != dir->mqm)
547 GCP_request_mq_cancel (dir->mqm,
551 GNUNET_CONTAINER_DLL_remove (rung_head->rd_head,
558 * Destroy our state for @a route.
560 * @param route route to destroy
563 destroy_route (struct CadetRoute *route)
565 LOG (GNUNET_ERROR_TYPE_DEBUG,
566 "Destroying route from %s to %s of connection %s\n",
567 GNUNET_i2s (GCP_get_id (route->prev.hop)),
568 GNUNET_i2s2 (GCP_get_id (route->next.hop)),
569 GNUNET_sh2s (&route->cid.connection_of_tunnel));
570 GNUNET_assert (route ==
571 GNUNET_CONTAINER_heap_remove_node (route->hn));
572 GNUNET_assert (GNUNET_YES ==
573 GNUNET_CONTAINER_multishortmap_remove (routes,
574 &route->cid.connection_of_tunnel,
576 GNUNET_STATISTICS_set (stats,
578 GNUNET_CONTAINER_multishortmap_size (routes),
580 destroy_direction (&route->prev);
581 destroy_direction (&route->next);
587 * Send message that a route is broken between @a peer1 and @a peer2.
589 * @param target where to send the message
590 * @param cid connection identifier to use
591 * @param peer1 one of the peers where a link is broken
592 * @param peer2 another one of the peers where a link is broken
595 send_broken (struct RouteDirection *target,
596 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
597 const struct GNUNET_PeerIdentity *peer1,
598 const struct GNUNET_PeerIdentity *peer2)
600 struct GNUNET_MQ_Envelope *env;
601 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
603 if (NULL == target->mqm)
604 return; /* Can't send notification, connection is down! */
605 LOG (GNUNET_ERROR_TYPE_DEBUG,
606 "Notifying %s about BROKEN route at %s-%s of connection %s\n",
607 GCP_2s (target->hop),
610 GNUNET_sh2s (&cid->connection_of_tunnel));
612 env = GNUNET_MQ_msg (bm,
613 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
619 GCP_request_mq_cancel (target->mqm,
626 * Function called to check if any routes have timed out, and if
627 * so, to clean them up. Finally, schedules itself again at the
628 * earliest time where there might be more work.
633 timeout_cb (void *cls)
635 struct CadetRoute *r;
636 struct GNUNET_TIME_Relative linger;
637 struct GNUNET_TIME_Absolute exp;
640 linger = GNUNET_TIME_relative_multiply (keepalive_period,
642 while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap)))
644 exp = GNUNET_TIME_absolute_add (r->last_use,
646 if (0 != GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
648 /* Route not yet timed out, wait until it does. */
649 timeout_task = GNUNET_SCHEDULER_add_at (exp,
654 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
655 "Sending BROKEN due to timeout (%s was last use, %s linger)\n",
656 GNUNET_STRINGS_absolute_time_to_string (r->last_use),
657 GNUNET_STRINGS_relative_time_to_string (linger,
659 send_broken (&r->prev,
663 send_broken (&r->next,
669 /* No more routes left, so no need for a #timeout_task */
674 * Function called when the message queue to the previous hop
675 * becomes available/unavailable. We expect this function to
676 * be called immediately when we register, and then again
677 * later if the connection ever goes down.
679 * @param cls the `struct RouteDirection`
680 * @param available #GNUNET_YES if sending is now possible,
681 * #GNUNET_NO if sending is no longer possible
682 * #GNUNET_SYSERR if sending is no longer possible
683 * and the last envelope was discarded
686 dir_ready_cb (void *cls,
689 struct RouteDirection *dir = cls;
690 struct CadetRoute *route = dir->my_route;
691 struct RouteDirection *odir;
693 if (GNUNET_YES == ready)
695 struct GNUNET_MQ_Envelope *env;
697 dir->is_ready = GNUNET_YES;
698 if (NULL != (env = dir->env_head))
700 GNUNET_MQ_dll_remove (&dir->env_head,
704 GNUNET_STATISTICS_set (stats,
709 dir->is_ready = GNUNET_NO;
715 odir = (dir == &route->next) ? &route->prev : &route->next;
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717 "Sending BROKEN due to MQ going down\n");
718 send_broken (&route->next,
720 GCP_get_id (odir->hop),
722 destroy_route (route);
727 * Initialize one of the directions of a route.
729 * @param route route the direction belongs to
730 * @param dir direction to initialize
731 * @param hop next hop on in the @a dir
734 dir_init (struct RouteDirection *dir,
735 struct CadetRoute *route,
736 struct CadetPeer *hop)
739 dir->my_route = route;
740 dir->mqm = GCP_request_mq (hop,
743 GNUNET_CONTAINER_DLL_insert (rung_head->rd_head,
746 dir->rung = rung_head;
747 GNUNET_assert (GNUNET_YES == dir->is_ready);
752 * We could not create the desired route. Send a
753 * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
754 * message to @a target.
756 * @param target who should receive the message
757 * @param cid identifier of the connection/route that failed
758 * @param failure_at neighbour with which we failed to route,
762 send_broken_without_mqm (struct CadetPeer *target,
763 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
764 const struct GNUNET_PeerIdentity *failure_at)
766 struct GNUNET_MQ_Envelope *env;
767 struct GNUNET_CADET_ConnectionBrokenMessage *bm;
769 env = GNUNET_MQ_msg (bm,
770 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
772 bm->peer1 = my_full_id;
773 if (NULL != failure_at)
774 bm->peer2 = *failure_at;
775 GCP_send_ooo (target,
781 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
783 * @param cls Closure (CadetPeer for neighbor that sent the message).
784 * @param msg Message itself.
787 handle_connection_create (void *cls,
788 const struct GNUNET_CADET_ConnectionCreateMessage *msg)
790 struct CadetPeer *sender = cls;
791 struct CadetPeer *next;
792 const struct GNUNET_PeerIdentity *pids = (const struct GNUNET_PeerIdentity *) &msg[1];
793 struct CadetRoute *route;
794 uint16_t size = ntohs (msg->header.size) - sizeof (*msg);
795 unsigned int path_length;
797 enum GNUNET_CADET_ChannelOption options;
799 options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options);
800 path_length = size / sizeof (struct GNUNET_PeerIdentity);
801 if (0 == path_length)
803 LOG (GNUNET_ERROR_TYPE_DEBUG,
804 "Dropping CADET_CONNECTION_CREATE with empty path\n");
808 LOG (GNUNET_ERROR_TYPE_DEBUG,
809 "Handling CADET_CONNECTION_CREATE from %s for CID %s with %u hops\n",
811 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
813 /* Check for loops */
815 struct GNUNET_CONTAINER_MultiPeerMap *map;
817 map = GNUNET_CONTAINER_multipeermap_create (path_length * 2,
819 GNUNET_assert (NULL != map);
820 for (unsigned int i=0;i<path_length;i++)
822 LOG (GNUNET_ERROR_TYPE_DEBUG,
823 "CADET_CONNECTION_CREATE has peer %s at offset %u\n",
824 GNUNET_i2s (&pids[i]),
827 GNUNET_CONTAINER_multipeermap_put (map,
830 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
833 GNUNET_CONTAINER_multipeermap_destroy (map);
834 LOG (GNUNET_ERROR_TYPE_DEBUG,
835 "Dropping CADET_CONNECTION_CREATE with cyclic path\n");
840 GNUNET_CONTAINER_multipeermap_destroy (map);
842 /* Initiator is at offset 0, find us */
843 for (off=1;off<path_length;off++)
844 if (0 == memcmp (&my_full_id,
846 sizeof (struct GNUNET_PeerIdentity)))
848 if (off == path_length)
850 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "Dropping CADET_CONNECTION_CREATE without us in the path\n");
855 /* Check previous hop */
856 if (sender != GCP_get (&pids[off - 1],
859 LOG (GNUNET_ERROR_TYPE_DEBUG,
860 "Dropping CADET_CONNECTION_CREATE without sender at previous hop in the path\n");
865 (route = get_route (&msg->cid)))
867 /* Duplicate CREATE, pass it on, previous one might have been lost! */
869 LOG (GNUNET_ERROR_TYPE_DEBUG,
870 "Passing on duplicate CADET_CONNECTION_CREATE message on connection %s\n",
871 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
872 route_message (sender,
877 if (off == path_length - 1)
879 /* We are the destination, create connection */
880 struct CadetConnection *cc;
881 struct CadetPeerPath *path;
882 struct CadetPeer *origin;
884 cc = GCC_lookup (&msg->cid);
887 LOG (GNUNET_ERROR_TYPE_DEBUG,
888 "Received duplicate CADET_CONNECTION_CREATE message on connection %s\n",
889 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
890 GCC_handle_duplicate_create (cc);
894 origin = GCP_get (&pids[0],
896 LOG (GNUNET_ERROR_TYPE_DEBUG,
897 "I am destination for CADET_CONNECTION_CREATE message from %s for connection %s, building inverse path\n",
899 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
900 path = GCPP_get_path_from_route (path_length - 1,
903 GCT_add_inbound_connection (GCP_get_tunnel (origin,
906 (enum GNUNET_CADET_ChannelOption) ntohl (msg->options),
909 /* Send back BROKEN: duplicate connection on the same path,
910 we will use the other one. */
911 LOG (GNUNET_ERROR_TYPE_DEBUG,
912 "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n",
914 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
916 send_broken_without_mqm (sender,
923 /* We are merely a hop on the way, check if we can support the route */
924 next = GCP_get (&pids[off + 1],
926 if ( (NULL == next) ||
927 (GNUNET_NO == GCP_has_core_connection (next)) )
929 /* unworkable, send back BROKEN notification */
930 LOG (GNUNET_ERROR_TYPE_DEBUG,
931 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n",
933 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
934 GNUNET_i2s (&pids[off + 1]),
936 send_broken_without_mqm (sender,
941 if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes))
943 LOG (GNUNET_ERROR_TYPE_DEBUG,
944 "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n",
946 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
947 send_broken_without_mqm (sender,
953 /* Workable route, create routing entry */
954 LOG (GNUNET_ERROR_TYPE_DEBUG,
955 "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is up. Creating route\n",
957 GNUNET_sh2s (&msg->cid.connection_of_tunnel),
958 GNUNET_i2s (&pids[off + 1]),
960 route = GNUNET_new (struct CadetRoute);
961 route->options = options;
962 route->cid = msg->cid;
963 route->last_use = GNUNET_TIME_absolute_get ();
964 dir_init (&route->prev,
967 dir_init (&route->next,
970 GNUNET_assert (GNUNET_OK ==
971 GNUNET_CONTAINER_multishortmap_put (routes,
972 &route->cid.connection_of_tunnel,
974 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
975 GNUNET_STATISTICS_set (stats,
977 GNUNET_CONTAINER_multishortmap_size (routes),
979 route->hn = GNUNET_CONTAINER_heap_insert (route_heap,
981 route->last_use.abs_value_us);
982 if (NULL == timeout_task)
983 timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period,
987 /* also pass CREATE message along to next hop */
988 route_message (sender,
995 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
997 * @param cls Closure (CadetPeer for neighbor that sent the message).
998 * @param msg Message itself.
1001 handle_connection_create_ack (void *cls,
1002 const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
1004 struct CadetPeer *peer = cls;
1005 struct CadetConnection *cc;
1007 /* First, check if ACK belongs to a connection that ends here. */
1008 cc = GCC_lookup (&msg->cid);
1011 /* verify ACK came from the right direction */
1013 struct CadetPeerPath *path = GCC_get_path (cc,
1017 GCPP_get_peer_at_offset (path,
1020 /* received ACK from unexpected direction, ignore! */
1021 GNUNET_break_op (0);
1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1025 "Received CONNECTION_CREATE_ACK for connection %s.\n",
1026 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1027 GCC_handle_connection_create_ack (cc);
1031 /* We're just an intermediary peer, route the message along its path */
1032 route_message (peer,
1039 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
1041 * @param cls Closure (CadetPeer for neighbor that sent the message).
1042 * @param msg Message itself.
1043 * @deprecated duplicate logic with #handle_destroy(); dedup!
1046 handle_connection_broken (void *cls,
1047 const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
1049 struct CadetPeer *peer = cls;
1050 struct CadetConnection *cc;
1051 struct CadetRoute *route;
1053 /* First, check if message belongs to a connection that ends here. */
1054 cc = GCC_lookup (&msg->cid);
1057 /* verify message came from the right direction */
1059 struct CadetPeerPath *path = GCC_get_path (cc,
1063 GCPP_get_peer_at_offset (path,
1066 /* received message from unexpected direction, ignore! */
1067 GNUNET_break_op (0);
1070 LOG (GNUNET_ERROR_TYPE_DEBUG,
1071 "Received CONNECTION_BROKEN for connection %s. Destroying it.\n",
1072 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1073 GCC_destroy_without_core (cc);
1075 /* FIXME: also destroy the path up to the specified link! */
1079 /* We're just an intermediary peer, route the message along its path */
1080 route_message (peer,
1083 route = get_route (&msg->cid);
1085 destroy_route (route);
1086 /* FIXME: also destroy paths we MAY have up to the specified link! */
1091 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
1093 * @param cls Closure (CadetPeer for neighbor that sent the message).
1094 * @param msg Message itself.
1097 handle_connection_destroy (void *cls,
1098 const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
1100 struct CadetPeer *peer = cls;
1101 struct CadetConnection *cc;
1102 struct CadetRoute *route;
1104 /* First, check if message belongs to a connection that ends here. */
1105 cc = GCC_lookup (&msg->cid);
1108 /* verify message came from the right direction */
1110 struct CadetPeerPath *path = GCC_get_path (cc,
1114 GCPP_get_peer_at_offset (path,
1117 /* received message from unexpected direction, ignore! */
1118 GNUNET_break_op (0);
1121 LOG (GNUNET_ERROR_TYPE_DEBUG,
1122 "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n",
1123 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1125 GCC_destroy_without_core (cc);
1129 /* We're just an intermediary peer, route the message along its path */
1130 LOG (GNUNET_ERROR_TYPE_DEBUG,
1131 "Received CONNECTION_DESTROY for connection %s. Destroying route.\n",
1132 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1133 route_message (peer,
1136 route = get_route (&msg->cid);
1138 destroy_route (route);
1143 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
1145 * @param cls Closure (CadetPeer for neighbor that sent the message).
1146 * @param msg Message itself.
1149 handle_tunnel_kx (void *cls,
1150 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
1152 struct CadetPeer *peer = cls;
1153 struct CadetConnection *cc;
1155 /* First, check if message belongs to a connection that ends here. */
1156 LOG (GNUNET_ERROR_TYPE_DEBUG,
1157 "Routing KX with ephemeral %s on CID %s\n",
1158 GNUNET_e2s (&msg->ephemeral_key),
1159 GNUNET_sh2s (&msg->cid.connection_of_tunnel));
1162 cc = GCC_lookup (&msg->cid);
1165 /* verify message came from the right direction */
1167 struct CadetPeerPath *path = GCC_get_path (cc,
1171 GCPP_get_peer_at_offset (path,
1174 /* received message from unexpected direction, ignore! */
1175 GNUNET_break_op (0);
1183 /* We're just an intermediary peer, route the message along its path */
1184 route_message (peer,
1191 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH
1193 * @param cls Closure (CadetPeer for neighbor that sent the message).
1194 * @param msg Message itself.
1197 handle_tunnel_kx_auth (void *cls,
1198 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
1200 struct CadetPeer *peer = cls;
1201 struct CadetConnection *cc;
1203 /* First, check if message belongs to a connection that ends here. */
1204 cc = GCC_lookup (&msg->kx.cid);
1207 /* verify message came from the right direction */
1209 struct CadetPeerPath *path = GCC_get_path (cc,
1213 GCPP_get_peer_at_offset (path,
1216 /* received message from unexpected direction, ignore! */
1217 GNUNET_break_op (0);
1220 GCC_handle_kx_auth (cc,
1225 /* We're just an intermediary peer, route the message along its path */
1226 route_message (peer,
1233 * Check if the encrypted message has the appropriate size.
1235 * @param cls Closure (unused).
1236 * @param msg Message to check.
1238 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
1241 check_tunnel_encrypted (void *cls,
1242 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1249 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
1251 * @param cls Closure (CadetPeer for neighbor that sent the message).
1252 * @param msg Message itself.
1255 handle_tunnel_encrypted (void *cls,
1256 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
1258 struct CadetPeer *peer = cls;
1259 struct CadetConnection *cc;
1261 /* First, check if message belongs to a connection that ends here. */
1262 cc = GCC_lookup (&msg->cid);
1265 /* verify message came from the right direction */
1267 struct CadetPeerPath *path = GCC_get_path (cc,
1271 GCPP_get_peer_at_offset (path,
1274 /* received message from unexpected direction, ignore! */
1275 GNUNET_break_op (0);
1278 GCC_handle_encrypted (cc,
1282 /* We're just an intermediary peer, route the message along its path */
1283 route_message (peer,
1290 * Function called after #GNUNET_CORE_connect has succeeded (or failed
1291 * for good). Note that the private key of the peer is intentionally
1292 * not exposed here; if you need it, your process should try to read
1293 * the private key file directly (which should work if you are
1294 * authorized...). Implementations of this function must not call
1295 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
1298 * @param cls closure
1299 * @param my_identity ID of this peer, NULL if we failed
1302 core_init_cb (void *cls,
1303 const struct GNUNET_PeerIdentity *my_identity)
1305 if (NULL == my_identity)
1311 memcmp (my_identity,
1313 sizeof (struct GNUNET_PeerIdentity)));
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 */