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 * - keep per-connection performance metrics
30 * - in particular, interact with channel (!) to see
31 * if we get ACKs indicating successful payload delivery.
34 #include "gnunet-service-cadet-new.h"
35 #include "gnunet-service-cadet-new_channel.h"
36 #include "gnunet-service-cadet-new_connection.h"
37 #include "gnunet-service-cadet-new_paths.h"
38 #include "gnunet-service-cadet-new_peer.h"
39 #include "gnunet-service-cadet-new_tunnels.h"
40 #include "gnunet_cadet_service.h"
41 #include "gnunet_statistics_service.h"
42 #include "cadet_protocol.h"
45 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
49 * All the states a connection can be in.
51 enum CadetConnectionState
54 * Uninitialized status, we have not yet even gotten the message queue.
59 * Connection create message in queue, awaiting transmission by CORE.
61 CADET_CONNECTION_SENDING_CREATE,
64 * Connection create message sent, waiting for ACK.
66 CADET_CONNECTION_SENT,
69 * We are an inbound connection, and received a CREATE. Need to
70 * send an CREATE_ACK back.
72 CADET_CONNECTION_CREATE_RECEIVED,
75 * Connection confirmed, ready to carry traffic.
77 CADET_CONNECTION_READY
83 * Low-level connection to a destination.
85 struct CadetConnection
89 * ID of the connection.
91 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
94 * To which peer does this connection go?
96 struct CadetPeer *destination;
99 * Which tunnel is using this connection?
101 struct CadetTConnection *ct;
104 * Path we are using to our destination.
106 struct CadetPeerPath *path;
109 * Pending message, NULL if we are ready to transmit.
111 struct GNUNET_MQ_Envelope *env;
114 * Handle for calling #GCP_request_mq_cancel() once we are finished.
116 struct GCP_MessageQueueManager *mq_man;
119 * Task for connection maintenance.
121 struct GNUNET_SCHEDULER_Task *task;
124 * Queue entry for keepalive messages.
126 struct CadetTunnelQueueEntry *keepalive_qe;
129 * Function to call once we are ready to transmit.
131 GCC_ReadyCallback ready_cb;
134 * Closure for @e ready_cb.
139 * How long do we wait before we try again with a CREATE message?
141 struct GNUNET_TIME_Relative retry_delay;
144 * State of the connection.
146 enum CadetConnectionState state;
149 * Options for the route, control buffering.
151 enum GNUNET_CADET_ChannelOption options;
154 * Offset of our @e destination in @e path.
159 * Are we ready to transmit via @e mq_man right now?
167 * Update the connection state. Also triggers the necessary
170 * @param cc connection to update the state for
171 * @param new_state new state for @a cc
172 * @param new_mqm_ready new `mqm_ready` state for @a cc
175 update_state (struct CadetConnection *cc,
176 enum CadetConnectionState new_state,
182 if ( (new_state == cc->state) &&
183 (new_mqm_ready == cc->mqm_ready) )
184 return; /* no change, nothing to do */
185 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
186 (GNUNET_YES == cc->mqm_ready) );
187 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
188 (GNUNET_YES == new_mqm_ready) );
189 cc->state = new_state;
190 cc->mqm_ready = new_mqm_ready;
191 if (old_ready != new_ready)
192 cc->ready_cb (cc->ready_cb_cls,
198 * Destroy a connection, part of the internal implementation. Called
199 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
201 * @param cc connection to destroy
204 GCC_destroy (struct CadetConnection *cc)
206 LOG (GNUNET_ERROR_TYPE_DEBUG,
209 if (NULL != cc->mq_man)
211 GCP_request_mq_cancel (cc->mq_man,
215 if (NULL != cc->task)
217 GNUNET_SCHEDULER_cancel (cc->task);
220 if (NULL != cc->keepalive_qe)
222 GCT_send_cancel (cc->keepalive_qe);
223 cc->keepalive_qe = NULL;
225 GCPP_del_connection (cc->path,
228 for (unsigned int i=0;i<cc->off;i++)
229 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
232 GNUNET_assert (GNUNET_YES ==
233 GNUNET_CONTAINER_multishortmap_remove (connections,
234 &GCC_get_id (cc)->connection_of_tunnel,
242 * Destroy a connection, called when the CORE layer is already done
243 * (i.e. has received a BROKEN message), but if we still have to
244 * communicate the destruction of the connection to the tunnel (if one
247 * @param cc connection to destroy
250 GCC_destroy_without_core (struct CadetConnection *cc)
254 GCT_connection_lost (cc->ct);
262 * Destroy a connection, called if the tunnel association with the
263 * connection was already broken, but we still need to notify the CORE
264 * layer about the breakage.
266 * @param cc connection to destroy
269 GCC_destroy_without_tunnel (struct CadetConnection *cc)
272 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
273 (NULL != cc->mq_man) )
275 struct GNUNET_MQ_Envelope *env;
276 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
278 /* Need to notify next hop that we are down. */
279 env = GNUNET_MQ_msg (destroy_msg,
280 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
281 destroy_msg->cid = cc->cid;
282 GCP_request_mq_cancel (cc->mq_man,
291 * Return the tunnel associated with this connection.
293 * @param cc connection to query
294 * @return corresponding entry in the tunnel's connection list
296 struct CadetTConnection *
297 GCC_get_ct (struct CadetConnection *cc)
304 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
305 * tunnel to prevent it from timing out.
307 * @param cls the `struct CadetConnection` to keep alive.
310 send_keepalive (void *cls);
314 * Keepalive was transmitted. Remember this, and possibly
315 * schedule the next one.
317 * @param cls the `struct CadetConnection` to keep alive.
320 keepalive_done (void *cls)
322 struct CadetConnection *cc = cls;
324 cc->keepalive_qe = NULL;
325 if ( (GNUNET_YES == cc->mqm_ready) &&
327 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
334 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
335 * tunnel to prevent it from timing out.
337 * @param cls the `struct CadetConnection` to keep alive.
340 send_keepalive (void *cls)
342 struct CadetConnection *cc = cls;
343 struct GNUNET_MessageHeader msg;
346 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
348 /* Tunnel not yet ready, wait with keepalives... */
349 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
354 GNUNET_assert (NULL != cc->ct);
355 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
356 GNUNET_assert (NULL == cc->keepalive_qe);
357 LOG (GNUNET_ERROR_TYPE_INFO,
358 "Sending KEEPALIVE on behalf of %s via %s\n",
361 GNUNET_STATISTICS_update (stats,
365 msg.size = htons (sizeof (msg));
366 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
369 = GCT_send (cc->ct->t,
377 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
378 * that the end-to-end connection is up. Process it.
380 * @param cc the connection that got the ACK.
383 GCC_handle_connection_create_ack (struct CadetConnection *cc)
385 LOG (GNUNET_ERROR_TYPE_DEBUG,
386 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
389 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
390 if (CADET_CONNECTION_READY == cc->state)
391 return; /* Duplicate ACK, ignore */
392 if (NULL != cc->task)
394 GNUNET_SCHEDULER_cancel (cc->task);
398 CADET_CONNECTION_READY,
400 if ( (NULL == cc->keepalive_qe) &&
401 (GNUNET_YES == cc->mqm_ready) &&
403 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
412 * @param cc connection that received encrypted message
413 * @param msg the key exchange message
416 GCC_handle_kx (struct CadetConnection *cc,
417 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
419 if (CADET_CONNECTION_SENT == cc->state)
421 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
422 clearly something is working, so pretend we got an ACK. */
423 LOG (GNUNET_ERROR_TYPE_DEBUG,
424 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
426 GCC_handle_connection_create_ack (cc);
428 GCT_handle_kx (cc->ct,
434 * Handle KX_AUTH message.
436 * @param cc connection that received encrypted message
437 * @param msg the key exchange message
440 GCC_handle_kx_auth (struct CadetConnection *cc,
441 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
443 if (CADET_CONNECTION_SENT == cc->state)
445 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
446 clearly something is working, so pretend we got an ACK. */
447 LOG (GNUNET_ERROR_TYPE_DEBUG,
448 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
450 GCC_handle_connection_create_ack (cc);
452 GCT_handle_kx_auth (cc->ct,
458 * Handle encrypted message.
460 * @param cc connection that received encrypted message
461 * @param msg the encrypted message to decrypt
464 GCC_handle_encrypted (struct CadetConnection *cc,
465 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
467 if (CADET_CONNECTION_SENT == cc->state)
469 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
470 clearly something is working, so pretend we got an ACK. */
471 LOG (GNUNET_ERROR_TYPE_DEBUG,
472 "Faking connection ACK for %s due to ENCRYPTED payload\n",
474 GCC_handle_connection_create_ack (cc);
476 GCT_handle_encrypted (cc->ct,
482 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
485 * @param cls the `struct CadetConnection` to initiate
488 send_create (void *cls)
490 struct CadetConnection *cc = cls;
491 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
492 struct GNUNET_PeerIdentity *pids;
493 struct GNUNET_MQ_Envelope *env;
494 unsigned int path_length;
497 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
498 path_length = GCPP_get_length (cc->path);
499 env = GNUNET_MQ_msg_extra (create_msg,
500 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
501 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
502 create_msg->options = htonl ((uint32_t) cc->options);
503 create_msg->cid = cc->cid;
504 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
505 pids[0] = my_full_id;
506 for (unsigned int i=0;i<path_length;i++)
507 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
509 LOG (GNUNET_ERROR_TYPE_DEBUG,
510 "Sending CADET_CONNECTION_CREATE message for %s\n",
514 CADET_CONNECTION_SENT,
516 GCP_send (cc->mq_man,
522 * Send a CREATE_ACK message towards the origin.
524 * @param cls the `struct CadetConnection` to initiate
527 send_create_ack (void *cls)
529 struct CadetConnection *cc = cls;
530 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
531 struct GNUNET_MQ_Envelope *env;
534 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
535 LOG (GNUNET_ERROR_TYPE_DEBUG,
536 "Sending CONNECTION_CREATE_ACK message for %s\n",
538 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
539 env = GNUNET_MQ_msg (ack_msg,
540 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
541 ack_msg->cid = cc->cid;
544 CADET_CONNECTION_READY,
546 GCP_send (cc->mq_man,
552 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
553 * connection that we already have. Either our ACK got lost
554 * or something is fishy. Consider retransmitting the ACK.
556 * @param cc connection that got the duplicate CREATE
559 GCC_handle_duplicate_create (struct CadetConnection *cc)
561 if (GNUNET_YES == cc->mqm_ready)
563 LOG (GNUNET_ERROR_TYPE_DEBUG,
564 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
566 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
567 /* Revert back to the state of having only received the 'CREATE',
568 and immediately proceed to send the CREATE_ACK. */
570 CADET_CONNECTION_CREATE_RECEIVED,
572 if (NULL != cc->task)
573 GNUNET_SCHEDULER_cancel (cc->task);
574 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
579 /* We are currently sending something else back, which
580 can only be an ACK or payload, either of which would
581 do. So actually no need to do anything. */
582 LOG (GNUNET_ERROR_TYPE_DEBUG,
583 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
590 * There has been a change in the message queue existence for our
591 * peer at the first hop. Adjust accordingly.
593 * @param cls the `struct CadetConnection`
594 * @param available #GNUNET_YES if sending is now possible,
595 * #GNUNET_NO if sending is no longer possible
596 * #GNUNET_SYSERR if sending is no longer possible
597 * and the last envelope was discarded
600 manage_first_hop_mq (void *cls,
603 struct CadetConnection *cc = cls;
605 if (GNUNET_YES != available)
607 /* Connection is down, for now... */
608 LOG (GNUNET_ERROR_TYPE_DEBUG,
609 "Core MQ for %s went down\n",
612 CADET_CONNECTION_NEW,
614 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
615 if (NULL != cc->task)
617 GNUNET_SCHEDULER_cancel (cc->task);
626 LOG (GNUNET_ERROR_TYPE_DEBUG,
627 "Core MQ for %s became available in state %d\n",
632 case CADET_CONNECTION_NEW:
633 /* Transmit immediately */
634 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
637 case CADET_CONNECTION_SENDING_CREATE:
638 /* Should not be possible to be called in this state. */
641 case CADET_CONNECTION_SENT:
642 /* Retry a bit later... */
643 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
644 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
648 case CADET_CONNECTION_CREATE_RECEIVED:
649 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
650 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
653 case CADET_CONNECTION_READY:
654 if ( (NULL == cc->keepalive_qe) &&
655 (GNUNET_YES == cc->mqm_ready) &&
658 LOG (GNUNET_ERROR_TYPE_DEBUG,
659 "Scheduling keepalive for %s in %s\n",
661 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
663 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
673 * Create a connection to @a destination via @a path and notify @a cb
674 * whenever we are ready for more data. Shared logic independent of
675 * who is initiating the connection.
677 * @param destination where to go
678 * @param path which path to take (may not be the full path)
679 * @param options options for the connection
680 * @param ct which tunnel uses this connection
681 * @param init_state initial state for the connection
682 * @param ready_cb function to call when ready to transmit
683 * @param ready_cb_cls closure for @a cb
684 * @return handle to the connection
686 static struct CadetConnection *
687 connection_create (struct CadetPeer *destination,
688 struct CadetPeerPath *path,
689 enum GNUNET_CADET_ChannelOption options,
690 struct CadetTConnection *ct,
691 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
692 enum CadetConnectionState init_state,
693 GCC_ReadyCallback ready_cb,
696 struct CadetConnection *cc;
697 struct CadetPeer *first_hop;
700 off = GCPP_find_peer (path,
702 GNUNET_assert (UINT_MAX > off);
703 cc = GNUNET_new (struct CadetConnection);
704 cc->options = options;
705 cc->state = init_state;
708 GNUNET_assert (GNUNET_OK ==
709 GNUNET_CONTAINER_multishortmap_put (connections,
710 &GCC_get_id (cc)->connection_of_tunnel,
712 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
713 cc->ready_cb = ready_cb;
714 cc->ready_cb_cls = ready_cb_cls;
717 LOG (GNUNET_ERROR_TYPE_DEBUG,
718 "Creating %s using path %s\n",
721 GCPP_add_connection (path,
724 for (unsigned int i=0;i<off;i++)
725 GCP_add_connection (GCPP_get_peer_at_offset (path,
729 first_hop = GCPP_get_peer_at_offset (path,
731 cc->mq_man = GCP_request_mq (first_hop,
732 &manage_first_hop_mq,
739 * Create a connection to @a destination via @a path and
740 * notify @a cb whenever we are ready for more data. This
741 * is an inbound tunnel, so we must use the existing @a cid
743 * @param destination where to go
744 * @param path which path to take (may not be the full path)
745 * @param options options for the connection
746 * @param ct which tunnel uses this connection
747 * @param ready_cb function to call when ready to transmit
748 * @param ready_cb_cls closure for @a cb
749 * @return handle to the connection, NULL if we already have
750 * a connection that takes precedence on @a path
752 struct CadetConnection *
753 GCC_create_inbound (struct CadetPeer *destination,
754 struct CadetPeerPath *path,
755 enum GNUNET_CADET_ChannelOption options,
756 struct CadetTConnection *ct,
757 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
758 GCC_ReadyCallback ready_cb,
761 struct CadetConnection *cc;
764 off = GCPP_find_peer (path,
766 GNUNET_assert (UINT_MAX != off);
767 cc = GCPP_get_connection (path,
779 /* Two peers picked the SAME random connection identifier at the
780 same time for the same path? Must be malicious. Drop
781 connection (existing and inbound), even if it is the only
784 GCT_connection_lost (cc->ct);
785 GCC_destroy_without_tunnel (cc);
791 LOG (GNUNET_ERROR_TYPE_DEBUG,
792 "Got two connections on %s, dropping my existing %s\n",
795 GCT_connection_lost (cc->ct);
796 GCC_destroy_without_tunnel (cc);
801 LOG (GNUNET_ERROR_TYPE_DEBUG,
802 "Got two connections on %s, keeping my existing %s\n",
809 return connection_create (destination,
814 CADET_CONNECTION_CREATE_RECEIVED,
821 * Create a connection to @a destination via @a path and
822 * notify @a cb whenever we are ready for more data.
824 * @param destination where to go
825 * @param path which path to take (may not be the full path)
826 * @param options options for the connection
827 * @param ct tunnel that uses the connection
828 * @param ready_cb function to call when ready to transmit
829 * @param ready_cb_cls closure for @a cb
830 * @return handle to the connection
832 struct CadetConnection *
833 GCC_create (struct CadetPeer *destination,
834 struct CadetPeerPath *path,
835 enum GNUNET_CADET_ChannelOption options,
836 struct CadetTConnection *ct,
837 GCC_ReadyCallback ready_cb,
840 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
842 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
845 return connection_create (destination,
850 CADET_CONNECTION_NEW,
857 * Transmit message @a msg via connection @a cc. Must only be called
858 * (once) after the connection has signalled that it is ready via the
859 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
860 * connection is right now ready for transmission.
862 * @param cc connection identification
863 * @param env envelope with message to transmit; must NOT
864 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
867 GCC_transmit (struct CadetConnection *cc,
868 struct GNUNET_MQ_Envelope *env)
870 LOG (GNUNET_ERROR_TYPE_DEBUG,
871 "Scheduling message for transmission on %s\n",
873 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
874 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
875 cc->mqm_ready = GNUNET_NO;
876 if (NULL != cc->task)
878 GNUNET_SCHEDULER_cancel (cc->task);
881 GCP_send (cc->mq_man,
887 * Obtain the path used by this connection.
889 * @param cc connection
890 * @return path to @a cc
892 struct CadetPeerPath *
893 GCC_get_path (struct CadetConnection *cc)
900 * Obtain unique ID for the connection.
902 * @param cc connection.
903 * @return unique number of the connection
905 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
906 GCC_get_id (struct CadetConnection *cc)
913 * Get a (static) string for a connection.
915 * @param cc Connection.
918 GCC_2s (const struct CadetConnection *cc)
920 static char buf[128];
923 return "Connection(NULL)";
927 GNUNET_snprintf (buf,
929 "Connection %s (%s)",
930 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
934 GNUNET_snprintf (buf,
937 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
942 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
946 * Log connection info.
948 * @param cc connection
949 * @param level Debug level to use.
952 GCC_debug (struct CadetConnection *cc,
953 enum GNUNET_ErrorType level)
957 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
959 __FILE__, __FUNCTION__, __LINE__);
965 "Connection (NULL)\n");
969 "%s to %s via path %s in state %d is %s\n",
971 GCP_2s (cc->destination),
974 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
977 /* end of gnunet-service-cadet-new_connection.c */