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.
163 * @param cc connection to destroy
166 GCC_destroy (struct CadetConnection *cc)
168 struct GNUNET_MQ_Envelope *env = NULL;
170 LOG (GNUNET_ERROR_TYPE_DEBUG,
173 if (CADET_CONNECTION_SENDING_CREATE != cc->state)
175 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
177 /* Need to notify next hop that we are down. */
178 env = GNUNET_MQ_msg (destroy_msg,
179 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
180 destroy_msg->cid = cc->cid;
182 if (NULL != cc->mq_man)
184 GCP_request_mq_cancel (cc->mq_man,
188 if (NULL != cc->task)
190 GNUNET_SCHEDULER_cancel (cc->task);
193 if (NULL != cc->keepalive_qe)
195 GCT_send_cancel (cc->keepalive_qe);
196 cc->keepalive_qe = NULL;
198 GCPP_del_connection (cc->path,
201 GNUNET_assert (GNUNET_YES ==
202 GNUNET_CONTAINER_multishortmap_remove (connections,
203 &GCC_get_id (cc)->connection_of_tunnel,
210 * Return the tunnel associated with this connection.
212 * @param cc connection to query
213 * @return corresponding entry in the tunnel's connection list
215 struct CadetTConnection *
216 GCC_get_ct (struct CadetConnection *cc)
223 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
224 * tunnel to prevent it from timing out.
226 * @param cls the `struct CadetConnection` to keep alive.
229 send_keepalive (void *cls);
233 * Keepalive was transmitted. Remember this, and possibly
234 * schedule the next one.
236 * @param cls the `struct CadetConnection` to keep alive.
239 keepalive_done (void *cls)
241 struct CadetConnection *cc = cls;
243 cc->keepalive_qe = NULL;
244 if ( (GNUNET_YES == cc->mqm_ready) &&
246 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
253 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
254 * tunnel to prevent it from timing out.
256 * @param cls the `struct CadetConnection` to keep alive.
259 send_keepalive (void *cls)
261 struct CadetConnection *cc = cls;
262 struct GNUNET_MessageHeader msg;
265 GNUNET_assert (NULL != cc->ct);
266 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
267 GNUNET_assert (NULL == cc->keepalive_qe);
268 LOG (GNUNET_ERROR_TYPE_INFO,
269 "Sending KEEPALIVE on behalf of %s via %s\n",
272 GNUNET_STATISTICS_update (stats,
276 msg.size = htons (sizeof (msg));
277 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
280 = GCT_send (cc->ct->t,
288 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
289 * that the end-to-end connection is up. Process it.
291 * @param cc the connection that got the ACK.
294 GCC_handle_connection_create_ack (struct CadetConnection *cc)
296 LOG (GNUNET_ERROR_TYPE_DEBUG,
297 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
300 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
301 if (NULL != cc->task)
303 GNUNET_SCHEDULER_cancel (cc->task);
306 cc->state = CADET_CONNECTION_READY;
307 if (GNUNET_YES == cc->mqm_ready)
309 cc->ready_cb (cc->ready_cb_cls,
311 if ( (NULL == cc->keepalive_qe) &&
312 (GNUNET_YES == cc->mqm_ready) &&
314 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
324 * @param cc connection that received encrypted message
325 * @param msg the key exchange message
328 GCC_handle_kx (struct CadetConnection *cc,
329 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
331 if (CADET_CONNECTION_SENT == cc->state)
333 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
334 clearly something is working, so pretend we got an ACK. */
335 LOG (GNUNET_ERROR_TYPE_DEBUG,
336 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
338 GCC_handle_connection_create_ack (cc);
340 GCT_handle_kx (cc->ct,
346 * Handle encrypted message.
348 * @param cc connection that received encrypted message
349 * @param msg the encrypted message to decrypt
352 GCC_handle_encrypted (struct CadetConnection *cc,
353 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
355 if (CADET_CONNECTION_SENT == cc->state)
357 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
358 clearly something is working, so pretend we got an ACK. */
359 LOG (GNUNET_ERROR_TYPE_DEBUG,
360 "Faking connection ACK for %s due to ENCRYPTED payload\n",
362 GCC_handle_connection_create_ack (cc);
364 GCT_handle_encrypted (cc->ct,
370 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
373 * @param cls the `struct CadetConnection` to initiate
376 send_create (void *cls)
378 struct CadetConnection *cc = cls;
379 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
380 struct GNUNET_PeerIdentity *pids;
381 struct GNUNET_MQ_Envelope *env;
382 unsigned int path_length;
385 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
386 path_length = GCPP_get_length (cc->path);
387 env = GNUNET_MQ_msg_extra (create_msg,
388 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
389 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
390 create_msg->cid = cc->cid;
391 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
392 pids[0] = my_full_id;
393 for (unsigned int i=0;i<path_length;i++)
394 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
396 LOG (GNUNET_ERROR_TYPE_DEBUG,
397 "Sending CADET_CONNECTION_CREATE message for %s\n",
400 cc->mqm_ready = GNUNET_NO;
401 cc->state = CADET_CONNECTION_SENT;
402 GCP_send (cc->mq_man,
408 * Send a CREATE_ACK message towards the origin.
410 * @param cls the `struct CadetConnection` to initiate
413 send_create_ack (void *cls)
415 struct CadetConnection *cc = cls;
416 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
417 struct GNUNET_MQ_Envelope *env;
420 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
421 LOG (GNUNET_ERROR_TYPE_DEBUG,
422 "Sending CONNECTION_CREATE_ACK message for %s\n",
424 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
425 env = GNUNET_MQ_msg (ack_msg,
426 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
427 ack_msg->cid = cc->cid;
429 cc->mqm_ready = GNUNET_NO;
430 cc->state = CADET_CONNECTION_READY;
431 GCP_send (cc->mq_man,
437 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
438 * connection that we already have. Either our ACK got lost
439 * or something is fishy. Consider retransmitting the ACK.
441 * @param cc connection that got the duplicate CREATE
444 GCC_handle_duplicate_create (struct CadetConnection *cc)
446 if (GNUNET_YES == cc->mqm_ready)
448 LOG (GNUNET_ERROR_TYPE_DEBUG,
449 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
451 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
452 /* Tell tunnel that we are not ready for transmission anymore
453 (until CREATE_ACK is done) */
454 cc->ready_cb (cc->ready_cb_cls,
456 /* Revert back to the state of having only received the 'CREATE',
457 and immediately proceed to send the CREATE_ACK. */
458 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
459 if (NULL != cc->task)
460 GNUNET_SCHEDULER_cancel (cc->task);
461 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
466 /* We are currently sending something else back, which
467 can only be an ACK or payload, either of which would
468 do. So actually no need to do anything. */
469 LOG (GNUNET_ERROR_TYPE_DEBUG,
470 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
477 * There has been a change in the message queue existence for our
478 * peer at the first hop. Adjust accordingly.
480 * @param cls the `struct CadetConnection`
481 * @param available #GNUNET_YES if sending is now possible,
482 * #GNUNET_NO if sending is no longer possible
483 * #GNUNET_SYSERR if sending is no longer possible
484 * and the last envelope was discarded
487 manage_first_hop_mq (void *cls,
490 struct CadetConnection *cc = cls;
492 if (GNUNET_YES != available)
494 /* Connection is down, for now... */
495 LOG (GNUNET_ERROR_TYPE_DEBUG,
496 "Core MQ for %s went down\n",
498 cc->mqm_ready = GNUNET_NO;
499 cc->state = CADET_CONNECTION_NEW;
500 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
501 if (NULL != cc->task)
503 GNUNET_SCHEDULER_cancel (cc->task);
506 cc->ready_cb (cc->ready_cb_cls,
511 cc->mqm_ready = GNUNET_YES;
512 LOG (GNUNET_ERROR_TYPE_DEBUG,
513 "Core MQ for %s became available in state %d\n",
518 case CADET_CONNECTION_NEW:
519 /* Transmit immediately */
520 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
523 case CADET_CONNECTION_SENDING_CREATE:
524 /* Should not be possible to be called in this state. */
527 case CADET_CONNECTION_SENT:
528 /* Retry a bit later... */
529 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
530 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
534 case CADET_CONNECTION_CREATE_RECEIVED:
535 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
536 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
539 case CADET_CONNECTION_READY:
540 cc->ready_cb (cc->ready_cb_cls,
542 if ( (NULL == cc->keepalive_qe) &&
543 (GNUNET_YES == cc->mqm_ready) &&
546 LOG (GNUNET_ERROR_TYPE_DEBUG,
547 "Scheduling keepalive for %s in %s\n",
549 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
551 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
561 * Create a connection to @a destination via @a path and notify @a cb
562 * whenever we are ready for more data. Shared logic independent of
563 * who is initiating the connection.
565 * @param destination where to go
566 * @param path which path to take (may not be the full path)
567 * @param ct which tunnel uses this connection
568 * @param init_state initial state for the connection
569 * @param ready_cb function to call when ready to transmit
570 * @param ready_cb_cls closure for @a cb
571 * @return handle to the connection
573 static struct CadetConnection *
574 connection_create (struct CadetPeer *destination,
575 struct CadetPeerPath *path,
576 struct CadetTConnection *ct,
577 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
578 enum CadetConnectionState init_state,
579 GCC_ReadyCallback ready_cb,
582 struct CadetConnection *cc;
583 struct CadetPeer *first_hop;
586 off = GCPP_find_peer (path,
588 GNUNET_assert (UINT_MAX > off);
589 cc = GNUNET_new (struct CadetConnection);
590 cc->state = init_state;
593 GNUNET_assert (GNUNET_OK ==
594 GNUNET_CONTAINER_multishortmap_put (connections,
595 &GCC_get_id (cc)->connection_of_tunnel,
597 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
598 cc->ready_cb = ready_cb;
599 cc->ready_cb_cls = ready_cb_cls;
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Creating %s using path %s\n",
606 GCPP_add_connection (path,
609 for (unsigned int i=0;i<off;i++)
610 GCP_add_connection (GCPP_get_peer_at_offset (path,
614 first_hop = GCPP_get_peer_at_offset (path,
616 cc->mq_man = GCP_request_mq (first_hop,
617 &manage_first_hop_mq,
624 * Create a connection to @a destination via @a path and
625 * notify @a cb whenever we are ready for more data. This
626 * is an inbound tunnel, so we must use the existing @a cid
628 * @param destination where to go
629 * @param path which path to take (may not be the full path)
630 * @param ct which tunnel uses this connection
631 * @param ready_cb function to call when ready to transmit
632 * @param ready_cb_cls closure for @a cb
633 * @return handle to the connection
635 struct CadetConnection *
636 GCC_create_inbound (struct CadetPeer *destination,
637 struct CadetPeerPath *path,
638 struct CadetTConnection *ct,
639 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
640 GCC_ReadyCallback ready_cb,
643 return connection_create (destination,
647 CADET_CONNECTION_CREATE_RECEIVED,
654 * Create a connection to @a destination via @a path and
655 * notify @a cb whenever we are ready for more data.
657 * @param destination where to go
658 * @param path which path to take (may not be the full path)
659 * @param ct tunnel that uses the connection
660 * @param ready_cb function to call when ready to transmit
661 * @param ready_cb_cls closure for @a cb
662 * @return handle to the connection
664 struct CadetConnection *
665 GCC_create (struct CadetPeer *destination,
666 struct CadetPeerPath *path,
667 struct CadetTConnection *ct,
668 GCC_ReadyCallback ready_cb,
671 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
673 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
676 return connection_create (destination,
680 CADET_CONNECTION_NEW,
687 * Transmit message @a msg via connection @a cc. Must only be called
688 * (once) after the connection has signalled that it is ready via the
689 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
690 * connection is right now ready for transmission.
692 * @param cc connection identification
693 * @param env envelope with message to transmit; must NOT
694 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
697 GCC_transmit (struct CadetConnection *cc,
698 struct GNUNET_MQ_Envelope *env)
700 LOG (GNUNET_ERROR_TYPE_DEBUG,
701 "Scheduling message for transmission on %s\n",
703 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
704 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
705 cc->mqm_ready = GNUNET_NO;
706 if (NULL != cc->task)
708 GNUNET_SCHEDULER_cancel (cc->task);
711 GCP_send (cc->mq_man,
717 * Obtain the path used by this connection.
719 * @param cc connection
720 * @return path to @a cc
722 struct CadetPeerPath *
723 GCC_get_path (struct CadetConnection *cc)
730 * Obtain unique ID for the connection.
732 * @param cc connection.
733 * @return unique number of the connection
735 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
736 GCC_get_id (struct CadetConnection *cc)
743 * Get a (static) string for a connection.
745 * @param cc Connection.
748 GCC_2s (const struct CadetConnection *cc)
750 static char buf[128];
753 return "Connection(NULL)";
757 GNUNET_snprintf (buf,
759 "Connection %s (%s)",
760 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
764 GNUNET_snprintf (buf,
767 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
772 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
776 * Log connection info.
778 * @param cc connection
779 * @param level Debug level to use.
782 GCC_debug (struct CadetConnection *cc,
783 enum GNUNET_ErrorType level)
787 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
789 __FILE__, __FUNCTION__, __LINE__);
795 "Connection (NULL)\n");
799 "%s to %s via path %s in state %d is %s\n",
801 GCP_2s (cc->destination),
804 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
807 /* end of gnunet-service-cadet-new_connection.c */