2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file cadet/gnunet-service-cadet-new_connection.c
23 * @brief management of CORE-level end-to-end connections; establishes
24 * end-to-end routes and transmits messages along the route
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
29 * - Optimization: keep per-connection performance metrics (?)
32 #include "gnunet-service-cadet-new.h"
33 #include "gnunet-service-cadet-new_channel.h"
34 #include "gnunet-service-cadet-new_connection.h"
35 #include "gnunet-service-cadet-new_paths.h"
36 #include "gnunet-service-cadet-new_peer.h"
37 #include "gnunet-service-cadet-new_tunnels.h"
38 #include "gnunet_cadet_service.h"
39 #include "gnunet_statistics_service.h"
40 #include "cadet_protocol.h"
43 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
47 * All the states a connection can be in.
49 enum CadetConnectionState
52 * Uninitialized status, we have not yet even gotten the message queue.
57 * Connection create message in queue, awaiting transmission by CORE.
59 CADET_CONNECTION_SENDING_CREATE,
62 * Connection create message sent, waiting for ACK.
64 CADET_CONNECTION_SENT,
67 * We are an inbound connection, and received a CREATE. Need to
68 * send an CREATE_ACK back.
70 CADET_CONNECTION_CREATE_RECEIVED,
73 * Connection confirmed, ready to carry traffic.
75 CADET_CONNECTION_READY
81 * Low-level connection to a destination.
83 struct CadetConnection
87 * ID of the connection.
89 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
92 * To which peer does this connection go?
94 struct CadetPeer *destination;
97 * Which tunnel is using this connection?
99 struct CadetTConnection *ct;
102 * Path we are using to our destination.
104 struct CadetPeerPath *path;
107 * Pending message, NULL if we are ready to transmit.
109 struct GNUNET_MQ_Envelope *env;
112 * Handle for calling #GCP_request_mq_cancel() once we are finished.
114 struct GCP_MessageQueueManager *mq_man;
117 * Task for connection maintenance.
119 struct GNUNET_SCHEDULER_Task *task;
122 * Queue entry for keepalive messages.
124 struct CadetTunnelQueueEntry *keepalive_qe;
127 * Function to call once we are ready to transmit.
129 GCC_ReadyCallback ready_cb;
132 * Closure for @e ready_cb.
137 * How long do we wait before we try again with a CREATE message?
139 struct GNUNET_TIME_Relative retry_delay;
142 * State of the connection.
144 enum CadetConnectionState state;
147 * Offset of our @e destination in @e path.
152 * Are we ready to transmit via @e mq_man right now?
160 * Destroy a connection, part of the internal implementation. Called
161 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
163 * @param cc connection to destroy
166 GCC_destroy (struct CadetConnection *cc)
168 LOG (GNUNET_ERROR_TYPE_DEBUG,
171 if (NULL != cc->mq_man)
173 GCP_request_mq_cancel (cc->mq_man,
177 if (NULL != cc->task)
179 GNUNET_SCHEDULER_cancel (cc->task);
182 if (NULL != cc->keepalive_qe)
184 GCT_send_cancel (cc->keepalive_qe);
185 cc->keepalive_qe = NULL;
187 GCPP_del_connection (cc->path,
190 GNUNET_assert (GNUNET_YES ==
191 GNUNET_CONTAINER_multishortmap_remove (connections,
192 &GCC_get_id (cc)->connection_of_tunnel,
200 * Destroy a connection, called when the CORE layer is already done
201 * (i.e. has received a BROKEN message), but if we still have to
202 * communicate the destruction of the connection to the tunnel (if one
205 * @param cc connection to destroy
208 GCC_destroy_without_core (struct CadetConnection *cc)
212 GCT_connection_lost (cc->ct);
220 * Destroy a connection, called if the tunnel association with the
221 * connection was already broken, but we still need to notify the CORE
222 * layer about the breakage.
224 * @param cc connection to destroy
227 GCC_destroy_without_tunnel (struct CadetConnection *cc)
230 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
231 (NULL != cc->mq_man) )
233 struct GNUNET_MQ_Envelope *env;
234 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
236 /* Need to notify next hop that we are down. */
237 env = GNUNET_MQ_msg (destroy_msg,
238 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
239 destroy_msg->cid = cc->cid;
240 GCP_request_mq_cancel (cc->mq_man,
249 * Return the tunnel associated with this connection.
251 * @param cc connection to query
252 * @return corresponding entry in the tunnel's connection list
254 struct CadetTConnection *
255 GCC_get_ct (struct CadetConnection *cc)
262 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
263 * tunnel to prevent it from timing out.
265 * @param cls the `struct CadetConnection` to keep alive.
268 send_keepalive (void *cls);
272 * Keepalive was transmitted. Remember this, and possibly
273 * schedule the next one.
275 * @param cls the `struct CadetConnection` to keep alive.
278 keepalive_done (void *cls)
280 struct CadetConnection *cc = cls;
282 cc->keepalive_qe = NULL;
283 if ( (GNUNET_YES == cc->mqm_ready) &&
285 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
292 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
293 * tunnel to prevent it from timing out.
295 * @param cls the `struct CadetConnection` to keep alive.
298 send_keepalive (void *cls)
300 struct CadetConnection *cc = cls;
301 struct GNUNET_MessageHeader msg;
304 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
306 /* Tunnel not yet ready, wait with keepalives... */
307 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
312 GNUNET_assert (NULL != cc->ct);
313 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
314 GNUNET_assert (NULL == cc->keepalive_qe);
315 LOG (GNUNET_ERROR_TYPE_INFO,
316 "Sending KEEPALIVE on behalf of %s via %s\n",
319 GNUNET_STATISTICS_update (stats,
323 msg.size = htons (sizeof (msg));
324 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
327 = GCT_send (cc->ct->t,
335 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
336 * that the end-to-end connection is up. Process it.
338 * @param cc the connection that got the ACK.
341 GCC_handle_connection_create_ack (struct CadetConnection *cc)
343 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
347 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
348 if (CADET_CONNECTION_READY == cc->state)
349 return; /* Duplicate ACK, ignore */
350 if (NULL != cc->task)
352 GNUNET_SCHEDULER_cancel (cc->task);
355 cc->state = CADET_CONNECTION_READY;
356 if (GNUNET_YES == cc->mqm_ready)
358 cc->ready_cb (cc->ready_cb_cls,
360 if ( (NULL == cc->keepalive_qe) &&
361 (GNUNET_YES == cc->mqm_ready) &&
363 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
373 * @param cc connection that received encrypted message
374 * @param msg the key exchange message
377 GCC_handle_kx (struct CadetConnection *cc,
378 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
380 if (CADET_CONNECTION_SENT == cc->state)
382 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
383 clearly something is working, so pretend we got an ACK. */
384 LOG (GNUNET_ERROR_TYPE_DEBUG,
385 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
387 GCC_handle_connection_create_ack (cc);
389 GCT_handle_kx (cc->ct,
395 * Handle KX_AUTH message.
397 * @param cc connection that received encrypted message
398 * @param msg the key exchange message
401 GCC_handle_kx_auth (struct CadetConnection *cc,
402 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
404 if (CADET_CONNECTION_SENT == cc->state)
406 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
407 clearly something is working, so pretend we got an ACK. */
408 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
411 GCC_handle_connection_create_ack (cc);
413 GCT_handle_kx_auth (cc->ct,
419 * Handle encrypted message.
421 * @param cc connection that received encrypted message
422 * @param msg the encrypted message to decrypt
425 GCC_handle_encrypted (struct CadetConnection *cc,
426 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
428 if (CADET_CONNECTION_SENT == cc->state)
430 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
431 clearly something is working, so pretend we got an ACK. */
432 LOG (GNUNET_ERROR_TYPE_DEBUG,
433 "Faking connection ACK for %s due to ENCRYPTED payload\n",
435 GCC_handle_connection_create_ack (cc);
437 GCT_handle_encrypted (cc->ct,
443 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
446 * @param cls the `struct CadetConnection` to initiate
449 send_create (void *cls)
451 struct CadetConnection *cc = cls;
452 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
453 struct GNUNET_PeerIdentity *pids;
454 struct GNUNET_MQ_Envelope *env;
455 unsigned int path_length;
458 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
459 path_length = GCPP_get_length (cc->path);
460 env = GNUNET_MQ_msg_extra (create_msg,
461 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
462 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
463 create_msg->cid = cc->cid;
464 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
465 pids[0] = my_full_id;
466 for (unsigned int i=0;i<path_length;i++)
467 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
469 LOG (GNUNET_ERROR_TYPE_DEBUG,
470 "Sending CADET_CONNECTION_CREATE message for %s\n",
473 cc->mqm_ready = GNUNET_NO;
474 cc->state = CADET_CONNECTION_SENT;
475 GCP_send (cc->mq_man,
481 * Send a CREATE_ACK message towards the origin.
483 * @param cls the `struct CadetConnection` to initiate
486 send_create_ack (void *cls)
488 struct CadetConnection *cc = cls;
489 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
490 struct GNUNET_MQ_Envelope *env;
493 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
494 LOG (GNUNET_ERROR_TYPE_DEBUG,
495 "Sending CONNECTION_CREATE_ACK message for %s\n",
497 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
498 env = GNUNET_MQ_msg (ack_msg,
499 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
500 ack_msg->cid = cc->cid;
502 cc->mqm_ready = GNUNET_NO;
503 cc->state = CADET_CONNECTION_READY;
504 GCP_send (cc->mq_man,
510 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
511 * connection that we already have. Either our ACK got lost
512 * or something is fishy. Consider retransmitting the ACK.
514 * @param cc connection that got the duplicate CREATE
517 GCC_handle_duplicate_create (struct CadetConnection *cc)
519 if (GNUNET_YES == cc->mqm_ready)
521 LOG (GNUNET_ERROR_TYPE_DEBUG,
522 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
524 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
525 /* Tell tunnel that we are not ready for transmission anymore
526 (until CREATE_ACK is done) */
527 if (CADET_CONNECTION_READY == cc->state)
528 cc->ready_cb (cc->ready_cb_cls,
530 /* Revert back to the state of having only received the 'CREATE',
531 and immediately proceed to send the CREATE_ACK. */
532 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
533 if (NULL != cc->task)
534 GNUNET_SCHEDULER_cancel (cc->task);
535 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
540 /* We are currently sending something else back, which
541 can only be an ACK or payload, either of which would
542 do. So actually no need to do anything. */
543 LOG (GNUNET_ERROR_TYPE_DEBUG,
544 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
551 * There has been a change in the message queue existence for our
552 * peer at the first hop. Adjust accordingly.
554 * @param cls the `struct CadetConnection`
555 * @param available #GNUNET_YES if sending is now possible,
556 * #GNUNET_NO if sending is no longer possible
557 * #GNUNET_SYSERR if sending is no longer possible
558 * and the last envelope was discarded
561 manage_first_hop_mq (void *cls,
564 struct CadetConnection *cc = cls;
566 if (GNUNET_YES != available)
568 /* Connection is down, for now... */
569 LOG (GNUNET_ERROR_TYPE_DEBUG,
570 "Core MQ for %s went down\n",
572 cc->state = CADET_CONNECTION_NEW;
573 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
574 if (NULL != cc->task)
576 GNUNET_SCHEDULER_cancel (cc->task);
579 if (GNUNET_YES == cc->mqm_ready)
581 cc->mqm_ready = GNUNET_NO;
582 if (CADET_CONNECTION_READY == cc->state)
583 cc->ready_cb (cc->ready_cb_cls,
589 cc->mqm_ready = GNUNET_YES;
590 LOG (GNUNET_ERROR_TYPE_DEBUG,
591 "Core MQ for %s became available in state %d\n",
596 case CADET_CONNECTION_NEW:
597 /* Transmit immediately */
598 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
601 case CADET_CONNECTION_SENDING_CREATE:
602 /* Should not be possible to be called in this state. */
605 case CADET_CONNECTION_SENT:
606 /* Retry a bit later... */
607 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
608 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
612 case CADET_CONNECTION_CREATE_RECEIVED:
613 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
614 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
617 case CADET_CONNECTION_READY:
618 cc->ready_cb (cc->ready_cb_cls,
620 if ( (NULL == cc->keepalive_qe) &&
621 (GNUNET_YES == cc->mqm_ready) &&
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Scheduling keepalive for %s in %s\n",
627 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
629 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
639 * Create a connection to @a destination via @a path and notify @a cb
640 * whenever we are ready for more data. Shared logic independent of
641 * who is initiating the connection.
643 * @param destination where to go
644 * @param path which path to take (may not be the full path)
645 * @param ct which tunnel uses this connection
646 * @param init_state initial state for the connection
647 * @param ready_cb function to call when ready to transmit
648 * @param ready_cb_cls closure for @a cb
649 * @return handle to the connection
651 static struct CadetConnection *
652 connection_create (struct CadetPeer *destination,
653 struct CadetPeerPath *path,
654 struct CadetTConnection *ct,
655 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
656 enum CadetConnectionState init_state,
657 GCC_ReadyCallback ready_cb,
660 struct CadetConnection *cc;
661 struct CadetPeer *first_hop;
664 off = GCPP_find_peer (path,
666 GNUNET_assert (UINT_MAX > off);
667 cc = GNUNET_new (struct CadetConnection);
668 cc->state = init_state;
671 GNUNET_assert (GNUNET_OK ==
672 GNUNET_CONTAINER_multishortmap_put (connections,
673 &GCC_get_id (cc)->connection_of_tunnel,
675 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
676 cc->ready_cb = ready_cb;
677 cc->ready_cb_cls = ready_cb_cls;
680 LOG (GNUNET_ERROR_TYPE_DEBUG,
681 "Creating %s using path %s\n",
684 GCPP_add_connection (path,
687 for (unsigned int i=0;i<off;i++)
688 GCP_add_connection (GCPP_get_peer_at_offset (path,
692 first_hop = GCPP_get_peer_at_offset (path,
694 cc->mq_man = GCP_request_mq (first_hop,
695 &manage_first_hop_mq,
702 * Create a connection to @a destination via @a path and
703 * notify @a cb whenever we are ready for more data. This
704 * is an inbound tunnel, so we must use the existing @a cid
706 * @param destination where to go
707 * @param path which path to take (may not be the full path)
708 * @param ct which tunnel uses this connection
709 * @param ready_cb function to call when ready to transmit
710 * @param ready_cb_cls closure for @a cb
711 * @return handle to the connection, NULL if we already have
712 * a connection that takes precedence on @a path
714 struct CadetConnection *
715 GCC_create_inbound (struct CadetPeer *destination,
716 struct CadetPeerPath *path,
717 struct CadetTConnection *ct,
718 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
719 GCC_ReadyCallback ready_cb,
722 struct CadetConnection *cc;
725 off = GCPP_find_peer (path,
727 GNUNET_assert (UINT_MAX != off);
728 cc = GCPP_get_connection (path,
740 /* Two peers picked the SAME random connection identifier at the
741 same time for the same path? Must be malicious. Drop
742 connection (existing and inbound), even if it is the only
745 GCT_connection_lost (cc->ct);
746 GCC_destroy_without_tunnel (cc);
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Got two connections on %s, dropping my existing %s\n",
756 GCT_connection_lost (cc->ct);
757 GCC_destroy_without_tunnel (cc);
762 LOG (GNUNET_ERROR_TYPE_DEBUG,
763 "Got two connections on %s, keeping my existing %s\n",
770 return connection_create (destination,
774 CADET_CONNECTION_CREATE_RECEIVED,
781 * Create a connection to @a destination via @a path and
782 * notify @a cb whenever we are ready for more data.
784 * @param destination where to go
785 * @param path which path to take (may not be the full path)
786 * @param ct tunnel that uses the connection
787 * @param ready_cb function to call when ready to transmit
788 * @param ready_cb_cls closure for @a cb
789 * @return handle to the connection
791 struct CadetConnection *
792 GCC_create (struct CadetPeer *destination,
793 struct CadetPeerPath *path,
794 struct CadetTConnection *ct,
795 GCC_ReadyCallback ready_cb,
798 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
800 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
803 return connection_create (destination,
807 CADET_CONNECTION_NEW,
814 * Transmit message @a msg via connection @a cc. Must only be called
815 * (once) after the connection has signalled that it is ready via the
816 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
817 * connection is right now ready for transmission.
819 * @param cc connection identification
820 * @param env envelope with message to transmit; must NOT
821 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
824 GCC_transmit (struct CadetConnection *cc,
825 struct GNUNET_MQ_Envelope *env)
827 LOG (GNUNET_ERROR_TYPE_DEBUG,
828 "Scheduling message for transmission on %s\n",
830 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
831 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
832 cc->mqm_ready = GNUNET_NO;
833 if (NULL != cc->task)
835 GNUNET_SCHEDULER_cancel (cc->task);
838 GCP_send (cc->mq_man,
844 * Obtain the path used by this connection.
846 * @param cc connection
847 * @return path to @a cc
849 struct CadetPeerPath *
850 GCC_get_path (struct CadetConnection *cc)
857 * Obtain unique ID for the connection.
859 * @param cc connection.
860 * @return unique number of the connection
862 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
863 GCC_get_id (struct CadetConnection *cc)
870 * Get a (static) string for a connection.
872 * @param cc Connection.
875 GCC_2s (const struct CadetConnection *cc)
877 static char buf[128];
880 return "Connection(NULL)";
884 GNUNET_snprintf (buf,
886 "Connection %s (%s)",
887 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
891 GNUNET_snprintf (buf,
894 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
899 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
903 * Log connection info.
905 * @param cc connection
906 * @param level Debug level to use.
909 GCC_debug (struct CadetConnection *cc,
910 enum GNUNET_ErrorType level)
914 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
916 __FILE__, __FUNCTION__, __LINE__);
922 "Connection (NULL)\n");
926 "%s to %s via path %s in state %d is %s\n",
928 GCP_2s (cc->destination),
931 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
934 /* end of gnunet-service-cadet-new_connection.c */