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 * - Implement: keepalive messages / timeout (timeout to be done @ peer level!)
31 * - Optimization: keep performance metrics (?)
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 * Offset of our @e destination in @e path.
154 * Are we ready to transmit via @e mq_man right now?
162 * Destroy a connection.
164 * @param cc connection to destroy
167 GCC_destroy (struct CadetConnection *cc)
169 struct GNUNET_MQ_Envelope *env = NULL;
171 LOG (GNUNET_ERROR_TYPE_DEBUG,
174 if (CADET_CONNECTION_SENDING_CREATE != cc->state)
176 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
178 /* Need to notify next hop that we are down. */
179 env = GNUNET_MQ_msg (destroy_msg,
180 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
181 destroy_msg->cid = cc->cid;
183 if (NULL != cc->mq_man)
185 GCP_request_mq_cancel (cc->mq_man,
189 if (NULL != cc->task)
191 GNUNET_SCHEDULER_cancel (cc->task);
194 if (NULL != cc->keepalive_qe)
196 GCT_send_cancel (cc->keepalive_qe);
197 cc->keepalive_qe = NULL;
199 GCPP_del_connection (cc->path,
202 GNUNET_assert (GNUNET_YES ==
203 GNUNET_CONTAINER_multishortmap_remove (connections,
204 &GCC_get_id (cc)->connection_of_tunnel,
211 * Return the tunnel associated with this connection.
213 * @param cc connection to query
214 * @return corresponding entry in the tunnel's connection list
216 struct CadetTConnection *
217 GCC_get_ct (struct CadetConnection *cc)
224 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
225 * tunnel to prevent it from timing out.
227 * @param cls the `struct CadetConnection` to keep alive.
230 send_keepalive (void *cls);
234 * Keepalive was transmitted. Remember this, and possibly
235 * schedule the next one.
237 * @param cls the `struct CadetConnection` to keep alive.
240 keepalive_done (void *cls)
242 struct CadetConnection *cc = cls;
244 cc->keepalive_qe = NULL;
245 if ( (GNUNET_YES == cc->mqm_ready) &&
247 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
254 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
255 * tunnel to prevent it from timing out.
257 * @param cls the `struct CadetConnection` to keep alive.
260 send_keepalive (void *cls)
262 struct CadetConnection *cc = cls;
263 struct GNUNET_MessageHeader msg;
266 GNUNET_assert (NULL != cc->ct);
267 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
268 GNUNET_assert (NULL == cc->keepalive_qe);
269 LOG (GNUNET_ERROR_TYPE_INFO,
270 "Sending KEEPALIVE on behalf of %s via %s\n",
273 GNUNET_STATISTICS_update (stats,
277 msg.size = htons (sizeof (msg));
278 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
281 = GCT_send (cc->ct->t,
289 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
290 * that the end-to-end connection is up. Process it.
292 * @param cc the connection that got the ACK.
295 GCC_handle_connection_create_ack (struct CadetConnection *cc)
297 LOG (GNUNET_ERROR_TYPE_DEBUG,
298 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
301 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
302 if (NULL != cc->task)
304 GNUNET_SCHEDULER_cancel (cc->task);
307 cc->state = CADET_CONNECTION_READY;
308 if (GNUNET_YES == cc->mqm_ready)
310 cc->ready_cb (cc->ready_cb_cls,
312 if ( (NULL == cc->keepalive_qe) &&
313 (GNUNET_YES == cc->mqm_ready) &&
315 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
325 * @param cc connection that received encrypted message
326 * @param msg the key exchange message
329 GCC_handle_kx (struct CadetConnection *cc,
330 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
332 if (CADET_CONNECTION_SENT == cc->state)
334 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
335 clearly something is working, so pretend we got an ACK. */
336 LOG (GNUNET_ERROR_TYPE_DEBUG,
337 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
339 GCC_handle_connection_create_ack (cc);
341 GCT_handle_kx (cc->ct,
347 * Handle encrypted message.
349 * @param cc connection that received encrypted message
350 * @param msg the encrypted message to decrypt
353 GCC_handle_encrypted (struct CadetConnection *cc,
354 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
356 if (CADET_CONNECTION_SENT == cc->state)
358 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
359 clearly something is working, so pretend we got an ACK. */
360 LOG (GNUNET_ERROR_TYPE_DEBUG,
361 "Faking connection ACK for %s due to ENCRYPTED payload\n",
363 GCC_handle_connection_create_ack (cc);
365 GCT_handle_encrypted (cc->ct,
371 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
374 * @param cls the `struct CadetConnection` to initiate
377 send_create (void *cls)
379 struct CadetConnection *cc = cls;
380 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
381 struct GNUNET_PeerIdentity *pids;
382 struct GNUNET_MQ_Envelope *env;
383 unsigned int path_length;
386 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
387 path_length = GCPP_get_length (cc->path);
388 env = GNUNET_MQ_msg_extra (create_msg,
389 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
390 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
391 create_msg->cid = cc->cid;
392 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
393 pids[0] = my_full_id;
394 for (unsigned int i=0;i<path_length;i++)
395 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
397 LOG (GNUNET_ERROR_TYPE_DEBUG,
398 "Sending CADET_CONNECTION_CREATE message for %s\n",
401 cc->mqm_ready = GNUNET_NO;
402 cc->state = CADET_CONNECTION_SENT;
403 GCP_send (cc->mq_man,
409 * Send a CREATE_ACK message towards the origin.
411 * @param cls the `struct CadetConnection` to initiate
414 send_create_ack (void *cls)
416 struct CadetConnection *cc = cls;
417 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
418 struct GNUNET_MQ_Envelope *env;
421 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
422 LOG (GNUNET_ERROR_TYPE_DEBUG,
423 "Sending CONNECTION_CREATE_ACK message for %s\n",
425 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
426 env = GNUNET_MQ_msg (ack_msg,
427 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
428 ack_msg->cid = cc->cid;
430 cc->mqm_ready = GNUNET_NO;
431 cc->state = CADET_CONNECTION_READY;
432 GCP_send (cc->mq_man,
438 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
439 * connection that we already have. Either our ACK got lost
440 * or something is fishy. Consider retransmitting the ACK.
442 * @param cc connection that got the duplicate CREATE
445 GCC_handle_duplicate_create (struct CadetConnection *cc)
447 if (GNUNET_YES == cc->mqm_ready)
449 LOG (GNUNET_ERROR_TYPE_DEBUG,
450 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
452 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
453 /* Tell tunnel that we are not ready for transmission anymore
454 (until CREATE_ACK is done) */
455 cc->ready_cb (cc->ready_cb_cls,
457 /* Revert back to the state of having only received the 'CREATE',
458 and immediately proceed to send the CREATE_ACK. */
459 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
460 if (NULL != cc->task)
461 GNUNET_SCHEDULER_cancel (cc->task);
462 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
467 /* We are currently sending something else back, which
468 can only be an ACK or payload, either of which would
469 do. So actually no need to do anything. */
470 LOG (GNUNET_ERROR_TYPE_DEBUG,
471 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
478 * There has been a change in the message queue existence for our
479 * peer at the first hop. Adjust accordingly.
481 * @param cls the `struct CadetConnection`
482 * @param available #GNUNET_YES if sending is now possible,
483 * #GNUNET_NO if sending is no longer possible
484 * #GNUNET_SYSERR if sending is no longer possible
485 * and the last envelope was discarded
488 manage_first_hop_mq (void *cls,
491 struct CadetConnection *cc = cls;
493 if (GNUNET_YES != available)
495 /* Connection is down, for now... */
496 LOG (GNUNET_ERROR_TYPE_DEBUG,
497 "Core MQ for %s went down\n",
499 cc->mqm_ready = GNUNET_NO;
500 cc->state = CADET_CONNECTION_NEW;
501 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
502 if (NULL != cc->task)
504 GNUNET_SCHEDULER_cancel (cc->task);
507 cc->ready_cb (cc->ready_cb_cls,
512 cc->mqm_ready = GNUNET_YES;
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Core MQ for %s became available in state %d\n",
519 case CADET_CONNECTION_NEW:
520 /* Transmit immediately */
521 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
524 case CADET_CONNECTION_SENDING_CREATE:
525 /* Should not be possible to be called in this state. */
528 case CADET_CONNECTION_SENT:
529 /* Retry a bit later... */
530 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
531 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
535 case CADET_CONNECTION_CREATE_RECEIVED:
536 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
537 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
540 case CADET_CONNECTION_READY:
541 cc->ready_cb (cc->ready_cb_cls,
543 if ( (NULL == cc->keepalive_qe) &&
544 (GNUNET_YES == cc->mqm_ready) &&
547 LOG (GNUNET_ERROR_TYPE_DEBUG,
548 "Scheduling keepalive for %s in %s\n",
550 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
552 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
562 * Create a connection to @a destination via @a path and notify @a cb
563 * whenever we are ready for more data. Shared logic independent of
564 * who is initiating the connection.
566 * @param destination where to go
567 * @param path which path to take (may not be the full path)
568 * @param ct which tunnel uses this connection
569 * @param init_state initial state for the connection
570 * @param ready_cb function to call when ready to transmit
571 * @param ready_cb_cls closure for @a cb
572 * @return handle to the connection
574 static struct CadetConnection *
575 connection_create (struct CadetPeer *destination,
576 struct CadetPeerPath *path,
577 struct CadetTConnection *ct,
578 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
579 enum CadetConnectionState init_state,
580 GCC_ReadyCallback ready_cb,
583 struct CadetConnection *cc;
584 struct CadetPeer *first_hop;
587 off = GCPP_find_peer (path,
589 GNUNET_assert (UINT_MAX > off);
590 cc = GNUNET_new (struct CadetConnection);
591 cc->state = init_state;
594 GNUNET_assert (GNUNET_OK ==
595 GNUNET_CONTAINER_multishortmap_put (connections,
596 &GCC_get_id (cc)->connection_of_tunnel,
598 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
599 cc->ready_cb = ready_cb;
600 cc->ready_cb_cls = ready_cb_cls;
603 LOG (GNUNET_ERROR_TYPE_DEBUG,
604 "Creating %s using path %s\n",
607 GCPP_add_connection (path,
610 for (unsigned int i=0;i<off;i++)
611 GCP_add_connection (GCPP_get_peer_at_offset (path,
615 first_hop = GCPP_get_peer_at_offset (path,
617 cc->mq_man = GCP_request_mq (first_hop,
618 &manage_first_hop_mq,
625 * Create a connection to @a destination via @a path and
626 * notify @a cb whenever we are ready for more data. This
627 * is an inbound tunnel, so we must use the existing @a cid
629 * @param destination where to go
630 * @param path which path to take (may not be the full path)
631 * @param ct which tunnel uses this connection
632 * @param ready_cb function to call when ready to transmit
633 * @param ready_cb_cls closure for @a cb
634 * @return handle to the connection
636 struct CadetConnection *
637 GCC_create_inbound (struct CadetPeer *destination,
638 struct CadetPeerPath *path,
639 struct CadetTConnection *ct,
640 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
641 GCC_ReadyCallback ready_cb,
644 return connection_create (destination,
648 CADET_CONNECTION_CREATE_RECEIVED,
655 * Create a connection to @a destination via @a path and
656 * notify @a cb whenever we are ready for more data.
658 * @param destination where to go
659 * @param path which path to take (may not be the full path)
660 * @param ct tunnel that uses the connection
661 * @param ready_cb function to call when ready to transmit
662 * @param ready_cb_cls closure for @a cb
663 * @return handle to the connection
665 struct CadetConnection *
666 GCC_create (struct CadetPeer *destination,
667 struct CadetPeerPath *path,
668 struct CadetTConnection *ct,
669 GCC_ReadyCallback ready_cb,
672 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
674 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
677 return connection_create (destination,
681 CADET_CONNECTION_NEW,
688 * Transmit message @a msg via connection @a cc. Must only be called
689 * (once) after the connection has signalled that it is ready via the
690 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
691 * connection is right now ready for transmission.
693 * @param cc connection identification
694 * @param env envelope with message to transmit; must NOT
695 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
698 GCC_transmit (struct CadetConnection *cc,
699 struct GNUNET_MQ_Envelope *env)
701 LOG (GNUNET_ERROR_TYPE_DEBUG,
702 "Scheduling message for transmission on %s\n",
704 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
705 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
706 cc->mqm_ready = GNUNET_NO;
707 if (NULL != cc->task)
709 GNUNET_SCHEDULER_cancel (cc->task);
712 GCP_send (cc->mq_man,
718 * Obtain the path used by this connection.
720 * @param cc connection
721 * @return path to @a cc
723 struct CadetPeerPath *
724 GCC_get_path (struct CadetConnection *cc)
731 * Obtain unique ID for the connection.
733 * @param cc connection.
734 * @return unique number of the connection
736 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
737 GCC_get_id (struct CadetConnection *cc)
744 * Get a (static) string for a connection.
746 * @param cc Connection.
749 GCC_2s (const struct CadetConnection *cc)
751 static char buf[128];
754 return "Connection(NULL)";
758 GNUNET_snprintf (buf,
760 "Connection %s (%s)",
761 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
765 GNUNET_snprintf (buf,
768 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
773 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
777 * Log connection info.
779 * @param cc connection
780 * @param level Debug level to use.
783 GCC_debug (struct CadetConnection *cc,
784 enum GNUNET_ErrorType level)
788 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
790 __FILE__, __FUNCTION__, __LINE__);
796 "Connection (NULL)\n");
800 "%s to %s via path %s in state %d is %s\n",
802 GCP_2s (cc->destination),
805 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
808 /* end of gnunet-service-cadet-new_connection.c */