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_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 #include "gnunet-service-cadet_connection.h"
30 #include "gnunet-service-cadet_channel.h"
31 #include "gnunet-service-cadet_paths.h"
32 #include "gnunet-service-cadet_tunnels.h"
33 #include "gnunet_cadet_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "cadet_protocol.h"
38 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
42 * All the states a connection can be in.
44 enum CadetConnectionState
47 * Uninitialized status, we have not yet even gotten the message queue.
52 * Connection create message in queue, awaiting transmission by CORE.
54 CADET_CONNECTION_SENDING_CREATE,
57 * Connection create message sent, waiting for ACK.
59 CADET_CONNECTION_SENT,
62 * We are an inbound connection, and received a CREATE. Need to
63 * send an CREATE_ACK back.
65 CADET_CONNECTION_CREATE_RECEIVED,
68 * Connection confirmed, ready to carry traffic.
70 CADET_CONNECTION_READY
76 * Low-level connection to a destination.
78 struct CadetConnection
82 * ID of the connection.
84 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
87 * To which peer does this connection go?
89 struct CadetPeer *destination;
92 * Which tunnel is using this connection?
94 struct CadetTConnection *ct;
97 * Path we are using to our destination.
99 struct CadetPeerPath *path;
102 * Pending message, NULL if we are ready to transmit.
104 struct GNUNET_MQ_Envelope *env;
107 * Handle for calling #GCP_request_mq_cancel() once we are finished.
109 struct GCP_MessageQueueManager *mq_man;
112 * Task for connection maintenance.
114 struct GNUNET_SCHEDULER_Task *task;
117 * Queue entry for keepalive messages.
119 struct CadetTunnelQueueEntry *keepalive_qe;
122 * Function to call once we are ready to transmit.
124 GCC_ReadyCallback ready_cb;
127 * Closure for @e ready_cb.
132 * How long do we wait before we try again with a CREATE message?
134 struct GNUNET_TIME_Relative retry_delay;
137 * Performance metrics for this connection.
139 struct CadetConnectionMetrics metrics;
142 * State of the connection.
144 enum CadetConnectionState state;
147 * Options for the route, control buffering.
149 enum GNUNET_CADET_ChannelOption options;
152 * How many latency observations did we make for this connection?
154 unsigned int latency_datapoints;
157 * Offset of our @e destination in @e path.
162 * Are we ready to transmit via @e mq_man right now?
170 * Lookup a connection by its identifier.
172 * @param cid identifier to resolve
173 * @return NULL if connection was not found
175 struct CadetConnection *
176 GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
178 return GNUNET_CONTAINER_multishortmap_get (connections,
179 &cid->connection_of_tunnel);
184 * Update the connection state. Also triggers the necessary
187 * @param cc connection to update the state for
188 * @param new_state new state for @a cc
189 * @param new_mqm_ready new `mqm_ready` state for @a cc
192 update_state (struct CadetConnection *cc,
193 enum CadetConnectionState new_state,
199 if ( (new_state == cc->state) &&
200 (new_mqm_ready == cc->mqm_ready) )
201 return; /* no change, nothing to do */
202 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
203 (GNUNET_YES == cc->mqm_ready) );
204 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
205 (GNUNET_YES == new_mqm_ready) );
206 cc->state = new_state;
207 cc->mqm_ready = new_mqm_ready;
208 if (old_ready != new_ready)
209 cc->ready_cb (cc->ready_cb_cls,
215 * Destroy a connection, part of the internal implementation. Called
216 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
218 * @param cc connection to destroy
221 GCC_destroy (struct CadetConnection *cc)
223 LOG (GNUNET_ERROR_TYPE_DEBUG,
226 if (NULL != cc->mq_man)
228 GCP_request_mq_cancel (cc->mq_man,
232 if (NULL != cc->task)
234 GNUNET_SCHEDULER_cancel (cc->task);
237 if (NULL != cc->keepalive_qe)
239 GCT_send_cancel (cc->keepalive_qe);
240 cc->keepalive_qe = NULL;
242 GCPP_del_connection (cc->path,
245 for (unsigned int i=0;i<cc->off;i++)
246 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
249 GNUNET_assert (GNUNET_YES ==
250 GNUNET_CONTAINER_multishortmap_remove (connections,
251 &GCC_get_id (cc)->connection_of_tunnel,
259 * Destroy a connection, called when the CORE layer is already done
260 * (i.e. has received a BROKEN message), but if we still have to
261 * communicate the destruction of the connection to the tunnel (if one
264 * @param cc connection to destroy
267 GCC_destroy_without_core (struct CadetConnection *cc)
271 GCT_connection_lost (cc->ct);
279 * Destroy a connection, called if the tunnel association with the
280 * connection was already broken, but we still need to notify the CORE
281 * layer about the breakage.
283 * @param cc connection to destroy
286 GCC_destroy_without_tunnel (struct CadetConnection *cc)
289 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
290 (NULL != cc->mq_man) )
292 struct GNUNET_MQ_Envelope *env;
293 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
295 /* Need to notify next hop that we are down. */
296 env = GNUNET_MQ_msg (destroy_msg,
297 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
298 destroy_msg->cid = cc->cid;
299 GCP_request_mq_cancel (cc->mq_man,
308 * Return the tunnel associated with this connection.
310 * @param cc connection to query
311 * @return corresponding entry in the tunnel's connection list
313 struct CadetTConnection *
314 GCC_get_ct (struct CadetConnection *cc)
321 * Obtain performance @a metrics from @a cc.
323 * @param cc connection to query
324 * @return the metrics
326 const struct CadetConnectionMetrics *
327 GCC_get_metrics (struct CadetConnection *cc)
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);
344 * Keepalive was transmitted. Remember this, and possibly
345 * schedule the next one.
347 * @param cls the `struct CadetConnection` to keep alive.
348 * @param cid identifier of the connection within the tunnel, NULL
349 * if transmission failed
352 keepalive_done (void *cls,
353 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
355 struct CadetConnection *cc = cls;
357 cc->keepalive_qe = NULL;
358 if ( (GNUNET_YES == cc->mqm_ready) &&
360 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
367 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
368 * tunnel to prevent it from timing out.
370 * @param cls the `struct CadetConnection` to keep alive.
373 send_keepalive (void *cls)
375 struct CadetConnection *cc = cls;
376 struct GNUNET_MessageHeader msg;
379 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
381 /* Tunnel not yet ready, wait with keepalives... */
382 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
387 GNUNET_assert (NULL != cc->ct);
388 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
389 GNUNET_assert (NULL == cc->keepalive_qe);
390 LOG (GNUNET_ERROR_TYPE_INFO,
391 "Sending KEEPALIVE on behalf of %s via %s\n",
394 GNUNET_STATISTICS_update (stats,
398 msg.size = htons (sizeof (msg));
399 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
402 = GCT_send (cc->ct->t,
410 * We sent a message for which we expect to receive an ACK via
411 * the connection identified by @a cti.
413 * @param cid connection identifier where we expect an ACK
416 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
418 struct CadetConnection *cc;
420 cc = GCC_lookup (cid);
422 return; /* whopise, connection alredy down? */
423 cc->metrics.num_acked_transmissions++;
428 * We observed an ACK for a message that was originally sent via
429 * the connection identified by @a cti.
431 * @param cti connection identifier where we got an ACK for a message
432 * that was originally sent via this connection (the ACK
433 * may have gotten back to us via a different connection).
436 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
438 struct CadetConnection *cc;
440 cc = GCC_lookup (cid);
442 return; /* whopise, connection alredy down? */
443 cc->metrics.num_successes++;
448 * We observed some the given @a latency on the connection
449 * identified by @a cti. (The same connection was taken
450 * in both directions.)
452 * @param cid connection identifier where we measured latency
453 * @param latency the observed latency
456 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
457 struct GNUNET_TIME_Relative latency)
459 struct CadetConnection *cc;
463 cc = GCC_lookup (cid);
465 return; /* whopise, connection alredy down? */
466 GNUNET_STATISTICS_update (stats,
467 "# latencies observed",
470 cc->latency_datapoints++;
471 if (cc->latency_datapoints >= 7)
474 weight = cc->latency_datapoints;
475 /* Compute weighted average, giving at MOST weight 7 to the
476 existing values, or less if that value is based on fewer than 7
478 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
479 result /= (weight + 1.0);
480 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
485 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
486 * that the end-to-end connection is up. Process it.
488 * @param cc the connection that got the ACK.
491 GCC_handle_connection_create_ack (struct CadetConnection *cc)
493 LOG (GNUNET_ERROR_TYPE_DEBUG,
494 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
497 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
498 if (CADET_CONNECTION_READY == cc->state)
499 return; /* Duplicate ACK, ignore */
500 if (NULL != cc->task)
502 GNUNET_SCHEDULER_cancel (cc->task);
505 cc->metrics.age = GNUNET_TIME_absolute_get ();
507 CADET_CONNECTION_READY,
509 if ( (NULL == cc->keepalive_qe) &&
510 (GNUNET_YES == cc->mqm_ready) &&
512 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
521 * @param cc connection that received encrypted message
522 * @param msg the key exchange message
525 GCC_handle_kx (struct CadetConnection *cc,
526 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
528 if (CADET_CONNECTION_SENT == cc->state)
530 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
531 clearly something is working, so pretend we got an ACK. */
532 LOG (GNUNET_ERROR_TYPE_DEBUG,
533 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
535 GCC_handle_connection_create_ack (cc);
537 GCT_handle_kx (cc->ct,
543 * Handle KX_AUTH message.
545 * @param cc connection that received encrypted message
546 * @param msg the key exchange message
549 GCC_handle_kx_auth (struct CadetConnection *cc,
550 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
552 if (CADET_CONNECTION_SENT == cc->state)
554 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
555 clearly something is working, so pretend we got an ACK. */
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
559 GCC_handle_connection_create_ack (cc);
561 GCT_handle_kx_auth (cc->ct,
567 * Handle encrypted message.
569 * @param cc connection that received encrypted message
570 * @param msg the encrypted message to decrypt
573 GCC_handle_encrypted (struct CadetConnection *cc,
574 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
576 if (CADET_CONNECTION_SENT == cc->state)
578 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
579 clearly something is working, so pretend we got an ACK. */
580 LOG (GNUNET_ERROR_TYPE_DEBUG,
581 "Faking connection ACK for %s due to ENCRYPTED payload\n",
583 GCC_handle_connection_create_ack (cc);
585 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
586 GCT_handle_encrypted (cc->ct,
592 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
595 * @param cls the `struct CadetConnection` to initiate
598 send_create (void *cls)
600 struct CadetConnection *cc = cls;
601 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
602 struct GNUNET_PeerIdentity *pids;
603 struct GNUNET_MQ_Envelope *env;
604 unsigned int path_length;
607 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
608 path_length = GCPP_get_length (cc->path);
609 env = GNUNET_MQ_msg_extra (create_msg,
610 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
611 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
612 create_msg->options = htonl ((uint32_t) cc->options);
613 create_msg->cid = cc->cid;
614 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
615 pids[0] = my_full_id;
616 for (unsigned int i=0;i<path_length;i++)
617 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
619 LOG (GNUNET_ERROR_TYPE_DEBUG,
620 "Sending CADET_CONNECTION_CREATE message for %s\n",
624 CADET_CONNECTION_SENT,
626 GCP_send (cc->mq_man,
632 * Send a CREATE_ACK message towards the origin.
634 * @param cls the `struct CadetConnection` to initiate
637 send_create_ack (void *cls)
639 struct CadetConnection *cc = cls;
640 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
641 struct GNUNET_MQ_Envelope *env;
644 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "Sending CONNECTION_CREATE_ACK message for %s\n",
648 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
649 env = GNUNET_MQ_msg (ack_msg,
650 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
651 ack_msg->cid = cc->cid;
654 CADET_CONNECTION_READY,
656 GCP_send (cc->mq_man,
662 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
663 * connection that we already have. Either our ACK got lost
664 * or something is fishy. Consider retransmitting the ACK.
666 * @param cc connection that got the duplicate CREATE
669 GCC_handle_duplicate_create (struct CadetConnection *cc)
671 if (GNUNET_YES == cc->mqm_ready)
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
676 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
677 /* Revert back to the state of having only received the 'CREATE',
678 and immediately proceed to send the CREATE_ACK. */
680 CADET_CONNECTION_CREATE_RECEIVED,
682 if (NULL != cc->task)
683 GNUNET_SCHEDULER_cancel (cc->task);
684 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
689 /* We are currently sending something else back, which
690 can only be an ACK or payload, either of which would
691 do. So actually no need to do anything. */
692 LOG (GNUNET_ERROR_TYPE_DEBUG,
693 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
700 * There has been a change in the message queue existence for our
701 * peer at the first hop. Adjust accordingly.
703 * @param cls the `struct CadetConnection`
704 * @param available #GNUNET_YES if sending is now possible,
705 * #GNUNET_NO if sending is no longer possible
706 * #GNUNET_SYSERR if sending is no longer possible
707 * and the last envelope was discarded
710 manage_first_hop_mq (void *cls,
713 struct CadetConnection *cc = cls;
715 if (GNUNET_YES != available)
717 /* Connection is down, for now... */
718 LOG (GNUNET_ERROR_TYPE_DEBUG,
719 "Core MQ for %s went down\n",
722 CADET_CONNECTION_NEW,
724 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
725 if (NULL != cc->task)
727 GNUNET_SCHEDULER_cancel (cc->task);
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Core MQ for %s became available in state %d\n",
742 case CADET_CONNECTION_NEW:
743 /* Transmit immediately */
744 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
747 case CADET_CONNECTION_SENDING_CREATE:
748 /* Should not be possible to be called in this state. */
751 case CADET_CONNECTION_SENT:
752 /* Retry a bit later... */
753 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
754 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
758 case CADET_CONNECTION_CREATE_RECEIVED:
759 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
760 cc->metrics.age = GNUNET_TIME_absolute_get ();
761 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
764 case CADET_CONNECTION_READY:
765 if ( (NULL == cc->keepalive_qe) &&
766 (GNUNET_YES == cc->mqm_ready) &&
769 LOG (GNUNET_ERROR_TYPE_DEBUG,
770 "Scheduling keepalive for %s in %s\n",
772 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
774 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
784 * Create a connection to @a destination via @a path and notify @a cb
785 * whenever we are ready for more data. Shared logic independent of
786 * who is initiating the connection.
788 * @param destination where to go
789 * @param path which path to take (may not be the full path)
790 * @param off offset of @a destination on @a path
791 * @param options options for the connection
792 * @param ct which tunnel uses this connection
793 * @param init_state initial state for the connection
794 * @param ready_cb function to call when ready to transmit
795 * @param ready_cb_cls closure for @a cb
796 * @return handle to the connection
798 static struct CadetConnection *
799 connection_create (struct CadetPeer *destination,
800 struct CadetPeerPath *path,
802 enum GNUNET_CADET_ChannelOption options,
803 struct CadetTConnection *ct,
804 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
805 enum CadetConnectionState init_state,
806 GCC_ReadyCallback ready_cb,
809 struct CadetConnection *cc;
810 struct CadetPeer *first_hop;
812 cc = GNUNET_new (struct CadetConnection);
813 cc->options = options;
814 cc->state = init_state;
817 GNUNET_assert (GNUNET_OK ==
818 GNUNET_CONTAINER_multishortmap_put (connections,
819 &GCC_get_id (cc)->connection_of_tunnel,
821 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
822 cc->ready_cb = ready_cb;
823 cc->ready_cb_cls = ready_cb_cls;
826 LOG (GNUNET_ERROR_TYPE_DEBUG,
827 "Creating %s using path %s\n",
830 GCPP_add_connection (path,
833 for (unsigned int i=0;i<off;i++)
834 GCP_add_connection (GCPP_get_peer_at_offset (path,
838 first_hop = GCPP_get_peer_at_offset (path,
840 cc->mq_man = GCP_request_mq (first_hop,
841 &manage_first_hop_mq,
848 * Create a connection to @a destination via @a path and
849 * notify @a cb whenever we are ready for more data. This
850 * is an inbound tunnel, so we must use the existing @a cid
852 * @param destination where to go
853 * @param path which path to take (may not be the full path)
854 * @param options options for the connection
855 * @param ct which tunnel uses this connection
856 * @param ready_cb function to call when ready to transmit
857 * @param ready_cb_cls closure for @a cb
858 * @return handle to the connection, NULL if we already have
859 * a connection that takes precedence on @a path
861 struct CadetConnection *
862 GCC_create_inbound (struct CadetPeer *destination,
863 struct CadetPeerPath *path,
864 enum GNUNET_CADET_ChannelOption options,
865 struct CadetTConnection *ct,
866 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
867 GCC_ReadyCallback ready_cb,
870 struct CadetConnection *cc;
873 off = GCPP_find_peer (path,
875 GNUNET_assert (UINT_MAX != off);
876 cc = GCPP_get_connection (path,
888 /* Two peers picked the SAME random connection identifier at the
889 same time for the same path? Must be malicious. Drop
890 connection (existing and inbound), even if it is the only
893 GCT_connection_lost (cc->ct);
894 GCC_destroy_without_tunnel (cc);
900 LOG (GNUNET_ERROR_TYPE_DEBUG,
901 "Got two connections on %s, dropping my existing %s\n",
904 GCT_connection_lost (cc->ct);
905 GCC_destroy_without_tunnel (cc);
910 LOG (GNUNET_ERROR_TYPE_DEBUG,
911 "Got two connections on %s, keeping my existing %s\n",
918 return connection_create (destination,
924 CADET_CONNECTION_CREATE_RECEIVED,
931 * Create a connection to @a destination via @a path and
932 * notify @a cb whenever we are ready for more data.
934 * @param destination where to go
935 * @param path which path to take (may not be the full path)
936 * @param off offset of @a destination on @a path
937 * @param options options for the connection
938 * @param ct tunnel that uses the connection
939 * @param ready_cb function to call when ready to transmit
940 * @param ready_cb_cls closure for @a cb
941 * @return handle to the connection
943 struct CadetConnection *
944 GCC_create (struct CadetPeer *destination,
945 struct CadetPeerPath *path,
947 enum GNUNET_CADET_ChannelOption options,
948 struct CadetTConnection *ct,
949 GCC_ReadyCallback ready_cb,
952 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
954 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
957 return connection_create (destination,
963 CADET_CONNECTION_NEW,
970 * Transmit message @a msg via connection @a cc. Must only be called
971 * (once) after the connection has signalled that it is ready via the
972 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
973 * connection is right now ready for transmission.
975 * @param cc connection identification
976 * @param env envelope with message to transmit; must NOT
977 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
980 GCC_transmit (struct CadetConnection *cc,
981 struct GNUNET_MQ_Envelope *env)
983 LOG (GNUNET_ERROR_TYPE_DEBUG,
984 "Scheduling message for transmission on %s\n",
986 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
987 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
988 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
989 cc->mqm_ready = GNUNET_NO;
990 if (NULL != cc->task)
992 GNUNET_SCHEDULER_cancel (cc->task);
995 GCP_send (cc->mq_man,
1001 * Obtain the path used by this connection.
1003 * @param cc connection
1004 * @return path to @a cc
1006 struct CadetPeerPath *
1007 GCC_get_path (struct CadetConnection *cc)
1014 * Obtain unique ID for the connection.
1016 * @param cc connection.
1017 * @return unique number of the connection
1019 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1020 GCC_get_id (struct CadetConnection *cc)
1027 * Get a (static) string for a connection.
1029 * @param cc Connection.
1032 GCC_2s (const struct CadetConnection *cc)
1034 static char buf[128];
1037 return "Connection(NULL)";
1041 GNUNET_snprintf (buf,
1043 "Connection %s (%s)",
1044 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1045 GCT_2s (cc->ct->t));
1048 GNUNET_snprintf (buf,
1051 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1056 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1060 * Log connection info.
1062 * @param cc connection
1063 * @param level Debug level to use.
1066 GCC_debug (struct CadetConnection *cc,
1067 enum GNUNET_ErrorType level)
1069 #if !defined(GNUNET_CULL_LOGGING)
1072 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1074 __FILE__, __FUNCTION__, __LINE__);
1080 "Connection (NULL)\n");
1084 "%s to %s via path %s in state %d is %s\n",
1086 GCP_2s (cc->destination),
1089 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1093 /* end of gnunet-service-cadet_connection.c */