3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
23 * @file cadet/gnunet-service-cadet-new_connection.c
24 * @brief management of CORE-level end-to-end connections; establishes
25 * end-to-end routes and transmits messages along the route
26 * @author Bartlomiej Polot
27 * @author Christian Grothoff
30 * - Optimization: keep per-connection performance metrics (?)
33 #include "gnunet-service-cadet-new.h"
34 #include "gnunet-service-cadet-new_channel.h"
35 #include "gnunet-service-cadet-new_connection.h"
36 #include "gnunet-service-cadet-new_paths.h"
37 #include "gnunet-service-cadet-new_peer.h"
38 #include "gnunet-service-cadet-new_tunnels.h"
39 #include "gnunet_cadet_service.h"
40 #include "gnunet_statistics_service.h"
41 #include "cadet_protocol.h"
44 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
48 * All the states a connection can be in.
50 enum CadetConnectionState
53 * Uninitialized status, we have not yet even gotten the message queue.
58 * Connection create message in queue, awaiting transmission by CORE.
60 CADET_CONNECTION_SENDING_CREATE,
63 * Connection create message sent, waiting for ACK.
65 CADET_CONNECTION_SENT,
68 * We are an inbound connection, and received a CREATE. Need to
69 * send an CREATE_ACK back.
71 CADET_CONNECTION_CREATE_RECEIVED,
74 * Connection confirmed, ready to carry traffic.
76 CADET_CONNECTION_READY
82 * Low-level connection to a destination.
84 struct CadetConnection
88 * ID of the connection.
90 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
93 * To which peer does this connection go?
95 struct CadetPeer *destination;
98 * Which tunnel is using this connection?
100 struct CadetTConnection *ct;
103 * Path we are using to our destination.
105 struct CadetPeerPath *path;
108 * Pending message, NULL if we are ready to transmit.
110 struct GNUNET_MQ_Envelope *env;
113 * Handle for calling #GCP_request_mq_cancel() once we are finished.
115 struct GCP_MessageQueueManager *mq_man;
118 * Task for connection maintenance.
120 struct GNUNET_SCHEDULER_Task *task;
123 * Queue entry for keepalive messages.
125 struct CadetTunnelQueueEntry *keepalive_qe;
128 * Function to call once we are ready to transmit.
130 GCC_ReadyCallback ready_cb;
133 * Closure for @e ready_cb.
138 * How long do we wait before we try again with a CREATE message?
140 struct GNUNET_TIME_Relative retry_delay;
143 * State of the connection.
145 enum CadetConnectionState state;
148 * Offset of our @e destination in @e path.
153 * Are we ready to transmit via @e mq_man right now?
161 * Destroy a connection, part of the internal implementation. Called
162 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
164 * @param cc connection to destroy
167 GCC_destroy (struct CadetConnection *cc)
169 LOG (GNUNET_ERROR_TYPE_DEBUG,
172 if (NULL != cc->mq_man)
174 GCP_request_mq_cancel (cc->mq_man,
178 if (NULL != cc->task)
180 GNUNET_SCHEDULER_cancel (cc->task);
183 if (NULL != cc->keepalive_qe)
185 GCT_send_cancel (cc->keepalive_qe);
186 cc->keepalive_qe = NULL;
188 GCPP_del_connection (cc->path,
191 GNUNET_assert (GNUNET_YES ==
192 GNUNET_CONTAINER_multishortmap_remove (connections,
193 &GCC_get_id (cc)->connection_of_tunnel,
201 * Destroy a connection, called when the CORE layer is already done
202 * (i.e. has received a BROKEN message), but if we still have to
203 * communicate the destruction of the connection to the tunnel (if one
206 * @param cc connection to destroy
209 GCC_destroy_without_core (struct CadetConnection *cc)
213 GCT_connection_lost (cc->ct);
221 * Destroy a connection, called if the tunnel association with the
222 * connection was already broken, but we still need to notify the CORE
223 * layer about the breakage.
225 * @param cc connection to destroy
228 GCC_destroy_without_tunnel (struct CadetConnection *cc)
231 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
232 (NULL != cc->mq_man) )
234 struct GNUNET_MQ_Envelope *env;
235 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
237 /* Need to notify next hop that we are down. */
238 env = GNUNET_MQ_msg (destroy_msg,
239 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
240 destroy_msg->cid = cc->cid;
241 GCP_request_mq_cancel (cc->mq_man,
250 * Return the tunnel associated with this connection.
252 * @param cc connection to query
253 * @return corresponding entry in the tunnel's connection list
255 struct CadetTConnection *
256 GCC_get_ct (struct CadetConnection *cc)
263 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
264 * tunnel to prevent it from timing out.
266 * @param cls the `struct CadetConnection` to keep alive.
269 send_keepalive (void *cls);
273 * Keepalive was transmitted. Remember this, and possibly
274 * schedule the next one.
276 * @param cls the `struct CadetConnection` to keep alive.
279 keepalive_done (void *cls)
281 struct CadetConnection *cc = cls;
283 cc->keepalive_qe = NULL;
284 if ( (GNUNET_YES == cc->mqm_ready) &&
286 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
293 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
294 * tunnel to prevent it from timing out.
296 * @param cls the `struct CadetConnection` to keep alive.
299 send_keepalive (void *cls)
301 struct CadetConnection *cc = cls;
302 struct GNUNET_MessageHeader msg;
305 GNUNET_assert (NULL != cc->ct);
306 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
307 GNUNET_assert (NULL == cc->keepalive_qe);
308 LOG (GNUNET_ERROR_TYPE_INFO,
309 "Sending KEEPALIVE on behalf of %s via %s\n",
312 GNUNET_STATISTICS_update (stats,
316 msg.size = htons (sizeof (msg));
317 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
320 = GCT_send (cc->ct->t,
328 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
329 * that the end-to-end connection is up. Process it.
331 * @param cc the connection that got the ACK.
334 GCC_handle_connection_create_ack (struct CadetConnection *cc)
336 LOG (GNUNET_ERROR_TYPE_DEBUG,
337 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
340 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
341 if (NULL != cc->task)
343 GNUNET_SCHEDULER_cancel (cc->task);
346 cc->state = CADET_CONNECTION_READY;
347 if (GNUNET_YES == cc->mqm_ready)
349 cc->ready_cb (cc->ready_cb_cls,
351 if ( (NULL == cc->keepalive_qe) &&
352 (GNUNET_YES == cc->mqm_ready) &&
354 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
364 * @param cc connection that received encrypted message
365 * @param msg the key exchange message
368 GCC_handle_kx (struct CadetConnection *cc,
369 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
371 if (CADET_CONNECTION_SENT == cc->state)
373 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
374 clearly something is working, so pretend we got an ACK. */
375 LOG (GNUNET_ERROR_TYPE_DEBUG,
376 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
378 GCC_handle_connection_create_ack (cc);
380 GCT_handle_kx (cc->ct,
386 * Handle encrypted message.
388 * @param cc connection that received encrypted message
389 * @param msg the encrypted message to decrypt
392 GCC_handle_encrypted (struct CadetConnection *cc,
393 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
395 if (CADET_CONNECTION_SENT == cc->state)
397 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
398 clearly something is working, so pretend we got an ACK. */
399 LOG (GNUNET_ERROR_TYPE_DEBUG,
400 "Faking connection ACK for %s due to ENCRYPTED payload\n",
402 GCC_handle_connection_create_ack (cc);
404 GCT_handle_encrypted (cc->ct,
410 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
413 * @param cls the `struct CadetConnection` to initiate
416 send_create (void *cls)
418 struct CadetConnection *cc = cls;
419 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
420 struct GNUNET_PeerIdentity *pids;
421 struct GNUNET_MQ_Envelope *env;
422 unsigned int path_length;
425 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
426 path_length = GCPP_get_length (cc->path);
427 env = GNUNET_MQ_msg_extra (create_msg,
428 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
429 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
430 create_msg->cid = cc->cid;
431 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
432 pids[0] = my_full_id;
433 for (unsigned int i=0;i<path_length;i++)
434 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
436 LOG (GNUNET_ERROR_TYPE_DEBUG,
437 "Sending CADET_CONNECTION_CREATE message for %s\n",
440 cc->mqm_ready = GNUNET_NO;
441 cc->state = CADET_CONNECTION_SENT;
442 GCP_send (cc->mq_man,
448 * Send a CREATE_ACK message towards the origin.
450 * @param cls the `struct CadetConnection` to initiate
453 send_create_ack (void *cls)
455 struct CadetConnection *cc = cls;
456 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
457 struct GNUNET_MQ_Envelope *env;
460 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
461 LOG (GNUNET_ERROR_TYPE_DEBUG,
462 "Sending CONNECTION_CREATE_ACK message for %s\n",
464 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
465 env = GNUNET_MQ_msg (ack_msg,
466 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
467 ack_msg->cid = cc->cid;
469 cc->mqm_ready = GNUNET_NO;
470 cc->state = CADET_CONNECTION_READY;
471 GCP_send (cc->mq_man,
477 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
478 * connection that we already have. Either our ACK got lost
479 * or something is fishy. Consider retransmitting the ACK.
481 * @param cc connection that got the duplicate CREATE
484 GCC_handle_duplicate_create (struct CadetConnection *cc)
486 if (GNUNET_YES == cc->mqm_ready)
488 LOG (GNUNET_ERROR_TYPE_DEBUG,
489 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
491 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
492 /* Tell tunnel that we are not ready for transmission anymore
493 (until CREATE_ACK is done) */
494 cc->ready_cb (cc->ready_cb_cls,
496 /* Revert back to the state of having only received the 'CREATE',
497 and immediately proceed to send the CREATE_ACK. */
498 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
499 if (NULL != cc->task)
500 GNUNET_SCHEDULER_cancel (cc->task);
501 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
506 /* We are currently sending something else back, which
507 can only be an ACK or payload, either of which would
508 do. So actually no need to do anything. */
509 LOG (GNUNET_ERROR_TYPE_DEBUG,
510 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
517 * There has been a change in the message queue existence for our
518 * peer at the first hop. Adjust accordingly.
520 * @param cls the `struct CadetConnection`
521 * @param available #GNUNET_YES if sending is now possible,
522 * #GNUNET_NO if sending is no longer possible
523 * #GNUNET_SYSERR if sending is no longer possible
524 * and the last envelope was discarded
527 manage_first_hop_mq (void *cls,
530 struct CadetConnection *cc = cls;
532 if (GNUNET_YES != available)
534 /* Connection is down, for now... */
535 LOG (GNUNET_ERROR_TYPE_DEBUG,
536 "Core MQ for %s went down\n",
538 cc->mqm_ready = GNUNET_NO;
539 cc->state = CADET_CONNECTION_NEW;
540 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
541 if (NULL != cc->task)
543 GNUNET_SCHEDULER_cancel (cc->task);
546 cc->ready_cb (cc->ready_cb_cls,
551 cc->mqm_ready = GNUNET_YES;
552 LOG (GNUNET_ERROR_TYPE_DEBUG,
553 "Core MQ for %s became available in state %d\n",
558 case CADET_CONNECTION_NEW:
559 /* Transmit immediately */
560 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
563 case CADET_CONNECTION_SENDING_CREATE:
564 /* Should not be possible to be called in this state. */
567 case CADET_CONNECTION_SENT:
568 /* Retry a bit later... */
569 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
570 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
574 case CADET_CONNECTION_CREATE_RECEIVED:
575 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
576 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
579 case CADET_CONNECTION_READY:
580 cc->ready_cb (cc->ready_cb_cls,
582 if ( (NULL == cc->keepalive_qe) &&
583 (GNUNET_YES == cc->mqm_ready) &&
586 LOG (GNUNET_ERROR_TYPE_DEBUG,
587 "Scheduling keepalive for %s in %s\n",
589 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
591 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
601 * Create a connection to @a destination via @a path and notify @a cb
602 * whenever we are ready for more data. Shared logic independent of
603 * who is initiating the connection.
605 * @param destination where to go
606 * @param path which path to take (may not be the full path)
607 * @param ct which tunnel uses this connection
608 * @param init_state initial state for the connection
609 * @param ready_cb function to call when ready to transmit
610 * @param ready_cb_cls closure for @a cb
611 * @return handle to the connection
613 static struct CadetConnection *
614 connection_create (struct CadetPeer *destination,
615 struct CadetPeerPath *path,
616 struct CadetTConnection *ct,
617 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
618 enum CadetConnectionState init_state,
619 GCC_ReadyCallback ready_cb,
622 struct CadetConnection *cc;
623 struct CadetPeer *first_hop;
626 off = GCPP_find_peer (path,
628 GNUNET_assert (UINT_MAX > off);
629 cc = GNUNET_new (struct CadetConnection);
630 cc->state = init_state;
633 GNUNET_assert (GNUNET_OK ==
634 GNUNET_CONTAINER_multishortmap_put (connections,
635 &GCC_get_id (cc)->connection_of_tunnel,
637 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
638 cc->ready_cb = ready_cb;
639 cc->ready_cb_cls = ready_cb_cls;
642 LOG (GNUNET_ERROR_TYPE_DEBUG,
643 "Creating %s using path %s\n",
646 GCPP_add_connection (path,
649 for (unsigned int i=0;i<off;i++)
650 GCP_add_connection (GCPP_get_peer_at_offset (path,
654 first_hop = GCPP_get_peer_at_offset (path,
656 cc->mq_man = GCP_request_mq (first_hop,
657 &manage_first_hop_mq,
664 * Create a connection to @a destination via @a path and
665 * notify @a cb whenever we are ready for more data. This
666 * is an inbound tunnel, so we must use the existing @a cid
668 * @param destination where to go
669 * @param path which path to take (may not be the full path)
670 * @param ct which tunnel uses this connection
671 * @param ready_cb function to call when ready to transmit
672 * @param ready_cb_cls closure for @a cb
673 * @return handle to the connection, NULL if we already have
674 * a connection that takes precedence on @a path
676 struct CadetConnection *
677 GCC_create_inbound (struct CadetPeer *destination,
678 struct CadetPeerPath *path,
679 struct CadetTConnection *ct,
680 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
681 GCC_ReadyCallback ready_cb,
684 struct CadetConnection *cc;
687 off = GCPP_find_peer (path,
689 GNUNET_assert (UINT_MAX != off);
690 cc = GCPP_get_connection (path,
702 /* Two peers picked the SAME random connection identifier at the
703 same time for the same path? Must be malicious. Drop
704 connection (existing and inbound), even if it is the only
707 GCT_connection_lost (cc->ct);
708 GCC_destroy_without_tunnel (cc);
714 LOG (GNUNET_ERROR_TYPE_DEBUG,
715 "Got two connections on %s, dropping my existing %s\n",
718 GCT_connection_lost (cc->ct);
719 GCC_destroy_without_tunnel (cc);
724 LOG (GNUNET_ERROR_TYPE_DEBUG,
725 "Got two connections on %s, keeping my existing %s\n",
732 return connection_create (destination,
736 CADET_CONNECTION_CREATE_RECEIVED,
743 * Create a connection to @a destination via @a path and
744 * notify @a cb whenever we are ready for more data.
746 * @param destination where to go
747 * @param path which path to take (may not be the full path)
748 * @param ct tunnel that uses the connection
749 * @param ready_cb function to call when ready to transmit
750 * @param ready_cb_cls closure for @a cb
751 * @return handle to the connection
753 struct CadetConnection *
754 GCC_create (struct CadetPeer *destination,
755 struct CadetPeerPath *path,
756 struct CadetTConnection *ct,
757 GCC_ReadyCallback ready_cb,
760 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
762 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
765 return connection_create (destination,
769 CADET_CONNECTION_NEW,
776 * Transmit message @a msg via connection @a cc. Must only be called
777 * (once) after the connection has signalled that it is ready via the
778 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
779 * connection is right now ready for transmission.
781 * @param cc connection identification
782 * @param env envelope with message to transmit; must NOT
783 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
786 GCC_transmit (struct CadetConnection *cc,
787 struct GNUNET_MQ_Envelope *env)
789 LOG (GNUNET_ERROR_TYPE_DEBUG,
790 "Scheduling message for transmission on %s\n",
792 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
793 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
794 cc->mqm_ready = GNUNET_NO;
795 if (NULL != cc->task)
797 GNUNET_SCHEDULER_cancel (cc->task);
800 GCP_send (cc->mq_man,
806 * Obtain the path used by this connection.
808 * @param cc connection
809 * @return path to @a cc
811 struct CadetPeerPath *
812 GCC_get_path (struct CadetConnection *cc)
819 * Obtain unique ID for the connection.
821 * @param cc connection.
822 * @return unique number of the connection
824 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
825 GCC_get_id (struct CadetConnection *cc)
832 * Get a (static) string for a connection.
834 * @param cc Connection.
837 GCC_2s (const struct CadetConnection *cc)
839 static char buf[128];
842 return "Connection(NULL)";
846 GNUNET_snprintf (buf,
848 "Connection %s (%s)",
849 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
853 GNUNET_snprintf (buf,
856 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
861 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
865 * Log connection info.
867 * @param cc connection
868 * @param level Debug level to use.
871 GCC_debug (struct CadetConnection *cc,
872 enum GNUNET_ErrorType level)
876 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
878 __FILE__, __FUNCTION__, __LINE__);
884 "Connection (NULL)\n");
888 "%s to %s via path %s in state %d is %s\n",
890 GCP_2s (cc->destination),
893 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
896 /* end of gnunet-service-cadet-new_connection.c */