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 #include "gnunet-service-cadet-new.h"
30 #include "gnunet-service-cadet-new_channel.h"
31 #include "gnunet-service-cadet-new_connection.h"
32 #include "gnunet-service-cadet-new_paths.h"
33 #include "gnunet-service-cadet-new_peer.h"
34 #include "gnunet-service-cadet-new_tunnels.h"
35 #include "gnunet_cadet_service.h"
36 #include "gnunet_statistics_service.h"
37 #include "cadet_protocol.h"
40 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
44 * All the states a connection can be in.
46 enum CadetConnectionState
49 * Uninitialized status, we have not yet even gotten the message queue.
54 * Connection create message in queue, awaiting transmission by CORE.
56 CADET_CONNECTION_SENDING_CREATE,
59 * Connection create message sent, waiting for ACK.
61 CADET_CONNECTION_SENT,
64 * We are an inbound connection, and received a CREATE. Need to
65 * send an CREATE_ACK back.
67 CADET_CONNECTION_CREATE_RECEIVED,
70 * Connection confirmed, ready to carry traffic.
72 CADET_CONNECTION_READY
78 * Low-level connection to a destination.
80 struct CadetConnection
84 * ID of the connection.
86 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
89 * To which peer does this connection go?
91 struct CadetPeer *destination;
94 * Which tunnel is using this connection?
96 struct CadetTConnection *ct;
99 * Path we are using to our destination.
101 struct CadetPeerPath *path;
104 * Pending message, NULL if we are ready to transmit.
106 struct GNUNET_MQ_Envelope *env;
109 * Handle for calling #GCP_request_mq_cancel() once we are finished.
111 struct GCP_MessageQueueManager *mq_man;
114 * Task for connection maintenance.
116 struct GNUNET_SCHEDULER_Task *task;
119 * Queue entry for keepalive messages.
121 struct CadetTunnelQueueEntry *keepalive_qe;
124 * Function to call once we are ready to transmit.
126 GCC_ReadyCallback ready_cb;
129 * Closure for @e ready_cb.
134 * How long do we wait before we try again with a CREATE message?
136 struct GNUNET_TIME_Relative retry_delay;
139 * Performance metrics for this connection.
141 struct CadetConnectionMetrics metrics;
144 * State of the connection.
146 enum CadetConnectionState state;
149 * Options for the route, control buffering.
151 enum GNUNET_CADET_ChannelOption options;
154 * How many latency observations did we make for this connection?
156 unsigned int latency_datapoints;
159 * Offset of our @e destination in @e path.
164 * Are we ready to transmit via @e mq_man right now?
172 * Update the connection state. Also triggers the necessary
175 * @param cc connection to update the state for
176 * @param new_state new state for @a cc
177 * @param new_mqm_ready new `mqm_ready` state for @a cc
180 update_state (struct CadetConnection *cc,
181 enum CadetConnectionState new_state,
187 if ( (new_state == cc->state) &&
188 (new_mqm_ready == cc->mqm_ready) )
189 return; /* no change, nothing to do */
190 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
191 (GNUNET_YES == cc->mqm_ready) );
192 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
193 (GNUNET_YES == new_mqm_ready) );
194 cc->state = new_state;
195 cc->mqm_ready = new_mqm_ready;
196 if (old_ready != new_ready)
197 cc->ready_cb (cc->ready_cb_cls,
203 * Destroy a connection, part of the internal implementation. Called
204 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
206 * @param cc connection to destroy
209 GCC_destroy (struct CadetConnection *cc)
211 LOG (GNUNET_ERROR_TYPE_DEBUG,
214 if (NULL != cc->mq_man)
216 GCP_request_mq_cancel (cc->mq_man,
220 if (NULL != cc->task)
222 GNUNET_SCHEDULER_cancel (cc->task);
225 if (NULL != cc->keepalive_qe)
227 GCT_send_cancel (cc->keepalive_qe);
228 cc->keepalive_qe = NULL;
230 GCPP_del_connection (cc->path,
233 for (unsigned int i=0;i<cc->off;i++)
234 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
237 GNUNET_assert (GNUNET_YES ==
238 GNUNET_CONTAINER_multishortmap_remove (connections,
239 &GCC_get_id (cc)->connection_of_tunnel,
247 * Destroy a connection, called when the CORE layer is already done
248 * (i.e. has received a BROKEN message), but if we still have to
249 * communicate the destruction of the connection to the tunnel (if one
252 * @param cc connection to destroy
255 GCC_destroy_without_core (struct CadetConnection *cc)
259 GCT_connection_lost (cc->ct);
267 * Destroy a connection, called if the tunnel association with the
268 * connection was already broken, but we still need to notify the CORE
269 * layer about the breakage.
271 * @param cc connection to destroy
274 GCC_destroy_without_tunnel (struct CadetConnection *cc)
277 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
278 (NULL != cc->mq_man) )
280 struct GNUNET_MQ_Envelope *env;
281 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
283 /* Need to notify next hop that we are down. */
284 env = GNUNET_MQ_msg (destroy_msg,
285 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
286 destroy_msg->cid = cc->cid;
287 GCP_request_mq_cancel (cc->mq_man,
296 * Return the tunnel associated with this connection.
298 * @param cc connection to query
299 * @return corresponding entry in the tunnel's connection list
301 struct CadetTConnection *
302 GCC_get_ct (struct CadetConnection *cc)
309 * Obtain performance @a metrics from @a cc.
311 * @param cc connection to query
312 * @return the metrics
314 const struct CadetConnectionMetrics *
315 GCC_get_metrics (struct CadetConnection *cc)
322 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
323 * tunnel to prevent it from timing out.
325 * @param cls the `struct CadetConnection` to keep alive.
328 send_keepalive (void *cls);
332 * Keepalive was transmitted. Remember this, and possibly
333 * schedule the next one.
335 * @param cls the `struct CadetConnection` to keep alive.
336 * @param cid identifier of the connection within the tunnel, NULL
337 * if transmission failed
340 keepalive_done (void *cls,
341 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
343 struct CadetConnection *cc = cls;
345 cc->keepalive_qe = NULL;
346 if ( (GNUNET_YES == cc->mqm_ready) &&
348 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
355 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
356 * tunnel to prevent it from timing out.
358 * @param cls the `struct CadetConnection` to keep alive.
361 send_keepalive (void *cls)
363 struct CadetConnection *cc = cls;
364 struct GNUNET_MessageHeader msg;
367 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
369 /* Tunnel not yet ready, wait with keepalives... */
370 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
375 GNUNET_assert (NULL != cc->ct);
376 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
377 GNUNET_assert (NULL == cc->keepalive_qe);
378 LOG (GNUNET_ERROR_TYPE_INFO,
379 "Sending KEEPALIVE on behalf of %s via %s\n",
382 GNUNET_STATISTICS_update (stats,
386 msg.size = htons (sizeof (msg));
387 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
390 = GCT_send (cc->ct->t,
398 * We sent a message for which we expect to receive an ACK via
399 * the connection identified by @a cti.
401 * @param cid connection identifier where we expect an ACK
404 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
406 struct CadetConnection *cc;
408 cc = GNUNET_CONTAINER_multishortmap_get (connections,
409 &cid->connection_of_tunnel);
411 return; /* whopise, connection alredy down? */
412 cc->metrics.num_acked_transmissions++;
417 * We observed an ACK for a message that was originally sent via
418 * the connection identified by @a cti.
420 * @param cti connection identifier where we got an ACK for a message
421 * that was originally sent via this connection (the ACK
422 * may have gotten back to us via a different connection).
425 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
427 struct CadetConnection *cc;
429 cc = GNUNET_CONTAINER_multishortmap_get (connections,
430 &cid->connection_of_tunnel);
432 return; /* whopise, connection alredy down? */
433 cc->metrics.num_successes++;
438 * We observed some the given @a latency on the connection
439 * identified by @a cti. (The same connection was taken
440 * in both directions.)
442 * @param cid connection identifier where we measured latency
443 * @param latency the observed latency
446 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
447 struct GNUNET_TIME_Relative latency)
449 struct CadetConnection *cc;
453 cc = GNUNET_CONTAINER_multishortmap_get (connections,
454 &cid->connection_of_tunnel);
456 return; /* whopise, connection alredy down? */
457 GNUNET_STATISTICS_update (stats,
458 "# latencies observed",
461 cc->latency_datapoints++;
462 if (cc->latency_datapoints >= 7)
465 weight = cc->latency_datapoints;
466 /* Compute weighted average, giving at MOST weight 7 to the
467 existing values, or less if that value is based on fewer than 7
469 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
470 result /= (weight + 1.0);
471 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
476 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
477 * that the end-to-end connection is up. Process it.
479 * @param cc the connection that got the ACK.
482 GCC_handle_connection_create_ack (struct CadetConnection *cc)
484 LOG (GNUNET_ERROR_TYPE_DEBUG,
485 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
488 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
489 if (CADET_CONNECTION_READY == cc->state)
490 return; /* Duplicate ACK, ignore */
491 if (NULL != cc->task)
493 GNUNET_SCHEDULER_cancel (cc->task);
496 cc->metrics.age = GNUNET_TIME_absolute_get ();
498 CADET_CONNECTION_READY,
500 if ( (NULL == cc->keepalive_qe) &&
501 (GNUNET_YES == cc->mqm_ready) &&
503 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
512 * @param cc connection that received encrypted message
513 * @param msg the key exchange message
516 GCC_handle_kx (struct CadetConnection *cc,
517 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
519 if (CADET_CONNECTION_SENT == cc->state)
521 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
522 clearly something is working, so pretend we got an ACK. */
523 LOG (GNUNET_ERROR_TYPE_DEBUG,
524 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
526 GCC_handle_connection_create_ack (cc);
528 GCT_handle_kx (cc->ct,
534 * Handle KX_AUTH message.
536 * @param cc connection that received encrypted message
537 * @param msg the key exchange message
540 GCC_handle_kx_auth (struct CadetConnection *cc,
541 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
543 if (CADET_CONNECTION_SENT == cc->state)
545 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
546 clearly something is working, so pretend we got an ACK. */
547 LOG (GNUNET_ERROR_TYPE_DEBUG,
548 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
550 GCC_handle_connection_create_ack (cc);
552 GCT_handle_kx_auth (cc->ct,
558 * Handle encrypted message.
560 * @param cc connection that received encrypted message
561 * @param msg the encrypted message to decrypt
564 GCC_handle_encrypted (struct CadetConnection *cc,
565 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
567 if (CADET_CONNECTION_SENT == cc->state)
569 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
570 clearly something is working, so pretend we got an ACK. */
571 LOG (GNUNET_ERROR_TYPE_DEBUG,
572 "Faking connection ACK for %s due to ENCRYPTED payload\n",
574 GCC_handle_connection_create_ack (cc);
576 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
577 GCT_handle_encrypted (cc->ct,
583 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
586 * @param cls the `struct CadetConnection` to initiate
589 send_create (void *cls)
591 struct CadetConnection *cc = cls;
592 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
593 struct GNUNET_PeerIdentity *pids;
594 struct GNUNET_MQ_Envelope *env;
595 unsigned int path_length;
598 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
599 path_length = GCPP_get_length (cc->path);
600 env = GNUNET_MQ_msg_extra (create_msg,
601 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
602 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
603 create_msg->options = htonl ((uint32_t) cc->options);
604 create_msg->cid = cc->cid;
605 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
606 pids[0] = my_full_id;
607 for (unsigned int i=0;i<path_length;i++)
608 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
610 LOG (GNUNET_ERROR_TYPE_DEBUG,
611 "Sending CADET_CONNECTION_CREATE message for %s\n",
615 CADET_CONNECTION_SENT,
617 GCP_send (cc->mq_man,
623 * Send a CREATE_ACK message towards the origin.
625 * @param cls the `struct CadetConnection` to initiate
628 send_create_ack (void *cls)
630 struct CadetConnection *cc = cls;
631 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
632 struct GNUNET_MQ_Envelope *env;
635 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
636 LOG (GNUNET_ERROR_TYPE_DEBUG,
637 "Sending CONNECTION_CREATE_ACK message for %s\n",
639 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
640 env = GNUNET_MQ_msg (ack_msg,
641 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
642 ack_msg->cid = cc->cid;
645 CADET_CONNECTION_READY,
647 GCP_send (cc->mq_man,
653 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
654 * connection that we already have. Either our ACK got lost
655 * or something is fishy. Consider retransmitting the ACK.
657 * @param cc connection that got the duplicate CREATE
660 GCC_handle_duplicate_create (struct CadetConnection *cc)
662 if (GNUNET_YES == cc->mqm_ready)
664 LOG (GNUNET_ERROR_TYPE_DEBUG,
665 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
667 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
668 /* Revert back to the state of having only received the 'CREATE',
669 and immediately proceed to send the CREATE_ACK. */
671 CADET_CONNECTION_CREATE_RECEIVED,
673 if (NULL != cc->task)
674 GNUNET_SCHEDULER_cancel (cc->task);
675 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
680 /* We are currently sending something else back, which
681 can only be an ACK or payload, either of which would
682 do. So actually no need to do anything. */
683 LOG (GNUNET_ERROR_TYPE_DEBUG,
684 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
691 * There has been a change in the message queue existence for our
692 * peer at the first hop. Adjust accordingly.
694 * @param cls the `struct CadetConnection`
695 * @param available #GNUNET_YES if sending is now possible,
696 * #GNUNET_NO if sending is no longer possible
697 * #GNUNET_SYSERR if sending is no longer possible
698 * and the last envelope was discarded
701 manage_first_hop_mq (void *cls,
704 struct CadetConnection *cc = cls;
706 if (GNUNET_YES != available)
708 /* Connection is down, for now... */
709 LOG (GNUNET_ERROR_TYPE_DEBUG,
710 "Core MQ for %s went down\n",
713 CADET_CONNECTION_NEW,
715 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
716 if (NULL != cc->task)
718 GNUNET_SCHEDULER_cancel (cc->task);
727 LOG (GNUNET_ERROR_TYPE_DEBUG,
728 "Core MQ for %s became available in state %d\n",
733 case CADET_CONNECTION_NEW:
734 /* Transmit immediately */
735 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
738 case CADET_CONNECTION_SENDING_CREATE:
739 /* Should not be possible to be called in this state. */
742 case CADET_CONNECTION_SENT:
743 /* Retry a bit later... */
744 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
745 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
749 case CADET_CONNECTION_CREATE_RECEIVED:
750 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
751 cc->metrics.age = GNUNET_TIME_absolute_get ();
752 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
755 case CADET_CONNECTION_READY:
756 if ( (NULL == cc->keepalive_qe) &&
757 (GNUNET_YES == cc->mqm_ready) &&
760 LOG (GNUNET_ERROR_TYPE_DEBUG,
761 "Scheduling keepalive for %s in %s\n",
763 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
765 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
775 * Create a connection to @a destination via @a path and notify @a cb
776 * whenever we are ready for more data. Shared logic independent of
777 * who is initiating the connection.
779 * @param destination where to go
780 * @param path which path to take (may not be the full path)
781 * @param off offset of @a destination on @a path
782 * @param options options for the connection
783 * @param ct which tunnel uses this connection
784 * @param init_state initial state for the connection
785 * @param ready_cb function to call when ready to transmit
786 * @param ready_cb_cls closure for @a cb
787 * @return handle to the connection
789 static struct CadetConnection *
790 connection_create (struct CadetPeer *destination,
791 struct CadetPeerPath *path,
793 enum GNUNET_CADET_ChannelOption options,
794 struct CadetTConnection *ct,
795 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
796 enum CadetConnectionState init_state,
797 GCC_ReadyCallback ready_cb,
800 struct CadetConnection *cc;
801 struct CadetPeer *first_hop;
803 cc = GNUNET_new (struct CadetConnection);
804 cc->options = options;
805 cc->state = init_state;
808 GNUNET_assert (GNUNET_OK ==
809 GNUNET_CONTAINER_multishortmap_put (connections,
810 &GCC_get_id (cc)->connection_of_tunnel,
812 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
813 cc->ready_cb = ready_cb;
814 cc->ready_cb_cls = ready_cb_cls;
817 LOG (GNUNET_ERROR_TYPE_DEBUG,
818 "Creating %s using path %s\n",
821 GCPP_add_connection (path,
824 for (unsigned int i=0;i<off;i++)
825 GCP_add_connection (GCPP_get_peer_at_offset (path,
829 first_hop = GCPP_get_peer_at_offset (path,
831 cc->mq_man = GCP_request_mq (first_hop,
832 &manage_first_hop_mq,
839 * Create a connection to @a destination via @a path and
840 * notify @a cb whenever we are ready for more data. This
841 * is an inbound tunnel, so we must use the existing @a cid
843 * @param destination where to go
844 * @param path which path to take (may not be the full path)
845 * @param options options for the connection
846 * @param ct which tunnel uses this connection
847 * @param ready_cb function to call when ready to transmit
848 * @param ready_cb_cls closure for @a cb
849 * @return handle to the connection, NULL if we already have
850 * a connection that takes precedence on @a path
852 struct CadetConnection *
853 GCC_create_inbound (struct CadetPeer *destination,
854 struct CadetPeerPath *path,
855 enum GNUNET_CADET_ChannelOption options,
856 struct CadetTConnection *ct,
857 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
858 GCC_ReadyCallback ready_cb,
861 struct CadetConnection *cc;
864 off = GCPP_find_peer (path,
866 GNUNET_assert (UINT_MAX != off);
867 cc = GCPP_get_connection (path,
879 /* Two peers picked the SAME random connection identifier at the
880 same time for the same path? Must be malicious. Drop
881 connection (existing and inbound), even if it is the only
884 GCT_connection_lost (cc->ct);
885 GCC_destroy_without_tunnel (cc);
891 LOG (GNUNET_ERROR_TYPE_DEBUG,
892 "Got two connections on %s, dropping my existing %s\n",
895 GCT_connection_lost (cc->ct);
896 GCC_destroy_without_tunnel (cc);
901 LOG (GNUNET_ERROR_TYPE_DEBUG,
902 "Got two connections on %s, keeping my existing %s\n",
909 return connection_create (destination,
915 CADET_CONNECTION_CREATE_RECEIVED,
922 * Create a connection to @a destination via @a path and
923 * notify @a cb whenever we are ready for more data.
925 * @param destination where to go
926 * @param path which path to take (may not be the full path)
927 * @param off offset of @a destination on @a path
928 * @param options options for the connection
929 * @param ct tunnel that uses the connection
930 * @param ready_cb function to call when ready to transmit
931 * @param ready_cb_cls closure for @a cb
932 * @return handle to the connection
934 struct CadetConnection *
935 GCC_create (struct CadetPeer *destination,
936 struct CadetPeerPath *path,
938 enum GNUNET_CADET_ChannelOption options,
939 struct CadetTConnection *ct,
940 GCC_ReadyCallback ready_cb,
943 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
945 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
948 return connection_create (destination,
954 CADET_CONNECTION_NEW,
961 * Transmit message @a msg via connection @a cc. Must only be called
962 * (once) after the connection has signalled that it is ready via the
963 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
964 * connection is right now ready for transmission.
966 * @param cc connection identification
967 * @param env envelope with message to transmit; must NOT
968 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
971 GCC_transmit (struct CadetConnection *cc,
972 struct GNUNET_MQ_Envelope *env)
974 LOG (GNUNET_ERROR_TYPE_DEBUG,
975 "Scheduling message for transmission on %s\n",
977 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
978 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
979 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
980 cc->mqm_ready = GNUNET_NO;
981 if (NULL != cc->task)
983 GNUNET_SCHEDULER_cancel (cc->task);
986 GCP_send (cc->mq_man,
992 * Obtain the path used by this connection.
994 * @param cc connection
995 * @return path to @a cc
997 struct CadetPeerPath *
998 GCC_get_path (struct CadetConnection *cc)
1005 * Obtain unique ID for the connection.
1007 * @param cc connection.
1008 * @return unique number of the connection
1010 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1011 GCC_get_id (struct CadetConnection *cc)
1018 * Get a (static) string for a connection.
1020 * @param cc Connection.
1023 GCC_2s (const struct CadetConnection *cc)
1025 static char buf[128];
1028 return "Connection(NULL)";
1032 GNUNET_snprintf (buf,
1034 "Connection %s (%s)",
1035 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1036 GCT_2s (cc->ct->t));
1039 GNUNET_snprintf (buf,
1042 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1047 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1051 * Log connection info.
1053 * @param cc connection
1054 * @param level Debug level to use.
1057 GCC_debug (struct CadetConnection *cc,
1058 enum GNUNET_ErrorType level)
1062 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1064 __FILE__, __FUNCTION__, __LINE__);
1070 "Connection (NULL)\n");
1074 "%s to %s via path %s in state %d is %s\n",
1076 GCP_2s (cc->destination),
1079 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1082 /* end of gnunet-service-cadet-new_connection.c */