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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file cadet/gnunet-service-cadet_connection.c
21 * @brief management of CORE-level end-to-end connections; establishes
22 * end-to-end routes and transmits messages along the route
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
27 #include "gnunet-service-cadet_connection.h"
28 #include "gnunet-service-cadet_channel.h"
29 #include "gnunet-service-cadet_paths.h"
30 #include "gnunet-service-cadet_tunnels.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_statistics_service.h"
33 #include "cadet_protocol.h"
36 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
40 * How long do we wait initially before retransmitting the KX?
41 * TODO: replace by 2 RTT if/once we have connection-level RTT data!
43 #define INITIAL_CONNECTION_CREATE_RETRY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 200)
47 * All the states a connection can be in.
49 enum CadetConnectionState
52 * Uninitialized status, we have not yet even gotten the message queue.
57 * Connection create message in queue, awaiting transmission by CORE.
59 CADET_CONNECTION_SENDING_CREATE,
62 * Connection create message sent, waiting for ACK.
64 CADET_CONNECTION_SENT,
67 * We are an inbound connection, and received a CREATE. Need to
68 * send an CREATE_ACK back.
70 CADET_CONNECTION_CREATE_RECEIVED,
73 * Connection confirmed, ready to carry traffic.
75 CADET_CONNECTION_READY
81 * Low-level connection to a destination.
83 struct CadetConnection
87 * ID of the connection.
89 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
92 * To which peer does this connection go?
94 struct CadetPeer *destination;
97 * Which tunnel is using this connection?
99 struct CadetTConnection *ct;
102 * Path we are using to our destination.
104 struct CadetPeerPath *path;
107 * Pending message, NULL if we are ready to transmit.
109 struct GNUNET_MQ_Envelope *env;
112 * Handle for calling #GCP_request_mq_cancel() once we are finished.
114 struct GCP_MessageQueueManager *mq_man;
117 * Task for connection maintenance.
119 struct GNUNET_SCHEDULER_Task *task;
122 * Queue entry for keepalive messages.
124 struct CadetTunnelQueueEntry *keepalive_qe;
127 * Function to call once we are ready to transmit.
129 GCC_ReadyCallback ready_cb;
132 * Closure for @e ready_cb.
137 * How long do we wait before we try again with a CREATE message?
139 struct GNUNET_TIME_Relative retry_delay;
142 * Earliest time for re-trying CREATE
144 struct GNUNET_TIME_Absolute create_at;
147 * Earliest time for re-trying CREATE_ACK
149 struct GNUNET_TIME_Absolute create_ack_at;
152 * Performance metrics for this connection.
154 struct CadetConnectionMetrics metrics;
157 * State of the connection.
159 enum CadetConnectionState state;
162 * Options for the route, control buffering.
164 enum GNUNET_CADET_ChannelOption options;
167 * How many latency observations did we make for this connection?
169 unsigned int latency_datapoints;
172 * Offset of our @e destination in @e path.
177 * Are we ready to transmit via @e mq_man right now?
185 * Lookup a connection by its identifier.
187 * @param cid identifier to resolve
188 * @return NULL if connection was not found
190 struct CadetConnection *
191 GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
193 return GNUNET_CONTAINER_multishortmap_get (connections,
194 &cid->connection_of_tunnel);
199 * Update the connection state. Also triggers the necessary
202 * @param cc connection to update the state for
203 * @param new_state new state for @a cc
204 * @param new_mqm_ready new `mqm_ready` state for @a cc
207 update_state (struct CadetConnection *cc,
208 enum CadetConnectionState new_state,
214 if ( (new_state == cc->state) &&
215 (new_mqm_ready == cc->mqm_ready) )
216 return; /* no change, nothing to do */
217 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
218 (GNUNET_YES == cc->mqm_ready) );
219 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
220 (GNUNET_YES == new_mqm_ready) );
221 cc->state = new_state;
222 cc->mqm_ready = new_mqm_ready;
223 if (old_ready != new_ready)
224 cc->ready_cb (cc->ready_cb_cls,
230 * Destroy a connection, part of the internal implementation. Called
231 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
233 * @param cc connection to destroy
236 GCC_destroy (struct CadetConnection *cc)
238 LOG (GNUNET_ERROR_TYPE_DEBUG,
241 if (NULL != cc->mq_man)
243 GCP_request_mq_cancel (cc->mq_man,
247 if (NULL != cc->task)
249 GNUNET_SCHEDULER_cancel (cc->task);
252 if (NULL != cc->keepalive_qe)
254 GCT_send_cancel (cc->keepalive_qe);
255 cc->keepalive_qe = NULL;
257 GCPP_del_connection (cc->path,
260 for (unsigned int i=0;i<cc->off;i++)
261 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
264 GNUNET_assert (GNUNET_YES ==
265 GNUNET_CONTAINER_multishortmap_remove (connections,
266 &GCC_get_id (cc)->connection_of_tunnel,
274 * Destroy a connection, called when the CORE layer is already done
275 * (i.e. has received a BROKEN message), but if we still have to
276 * communicate the destruction of the connection to the tunnel (if one
279 * @param cc connection to destroy
282 GCC_destroy_without_core (struct CadetConnection *cc)
286 GCT_connection_lost (cc->ct);
294 * Destroy a connection, called if the tunnel association with the
295 * connection was already broken, but we still need to notify the CORE
296 * layer about the breakage.
298 * @param cc connection to destroy
301 GCC_destroy_without_tunnel (struct CadetConnection *cc)
304 if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) &&
305 (NULL != cc->mq_man) )
307 struct GNUNET_MQ_Envelope *env;
308 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
310 /* Need to notify next hop that we are down. */
311 env = GNUNET_MQ_msg (destroy_msg,
312 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
313 destroy_msg->cid = cc->cid;
314 GCP_request_mq_cancel (cc->mq_man,
323 * Return the tunnel associated with this connection.
325 * @param cc connection to query
326 * @return corresponding entry in the tunnel's connection list
328 struct CadetTConnection *
329 GCC_get_ct (struct CadetConnection *cc)
336 * Obtain performance @a metrics from @a cc.
338 * @param cc connection to query
339 * @return the metrics
341 const struct CadetConnectionMetrics *
342 GCC_get_metrics (struct CadetConnection *cc)
349 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
350 * tunnel to prevent it from timing out.
352 * @param cls the `struct CadetConnection` to keep alive.
355 send_keepalive (void *cls);
359 * Keepalive was transmitted. Remember this, and possibly
360 * schedule the next one.
362 * @param cls the `struct CadetConnection` to keep alive.
363 * @param cid identifier of the connection within the tunnel, NULL
364 * if transmission failed
367 keepalive_done (void *cls,
368 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
370 struct CadetConnection *cc = cls;
372 cc->keepalive_qe = NULL;
373 if ( (GNUNET_YES == cc->mqm_ready) &&
375 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
382 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
383 * tunnel to prevent it from timing out.
385 * @param cls the `struct CadetConnection` to keep alive.
388 send_keepalive (void *cls)
390 struct CadetConnection *cc = cls;
391 struct GNUNET_MessageHeader msg;
394 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
396 /* Tunnel not yet ready, wait with keepalives... */
397 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
402 GNUNET_assert (NULL != cc->ct);
403 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
404 GNUNET_assert (NULL == cc->keepalive_qe);
405 LOG (GNUNET_ERROR_TYPE_INFO,
406 "Sending KEEPALIVE on behalf of %s via %s\n",
409 GNUNET_STATISTICS_update (stats,
413 msg.size = htons (sizeof (msg));
414 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
417 = GCT_send (cc->ct->t,
425 * We sent a message for which we expect to receive an ACK via
426 * the connection identified by @a cti.
428 * @param cid connection identifier where we expect an ACK
431 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
433 struct CadetConnection *cc;
435 cc = GCC_lookup (cid);
437 return; /* whopise, connection alredy down? */
438 cc->metrics.num_acked_transmissions++;
443 * We observed an ACK for a message that was originally sent via
444 * the connection identified by @a cti.
446 * @param cti connection identifier where we got an ACK for a message
447 * that was originally sent via this connection (the ACK
448 * may have gotten back to us via a different connection).
451 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
453 struct CadetConnection *cc;
455 cc = GCC_lookup (cid);
457 return; /* whopise, connection alredy down? */
458 cc->metrics.num_successes++;
463 * We observed some the given @a latency on the connection
464 * identified by @a cti. (The same connection was taken
465 * in both directions.)
467 * @param cid connection identifier where we measured latency
468 * @param latency the observed latency
471 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
472 struct GNUNET_TIME_Relative latency)
474 struct CadetConnection *cc;
478 cc = GCC_lookup (cid);
480 return; /* whopise, connection alredy down? */
481 GNUNET_STATISTICS_update (stats,
482 "# latencies observed",
485 cc->latency_datapoints++;
486 if (cc->latency_datapoints >= 7)
489 weight = cc->latency_datapoints;
490 /* Compute weighted average, giving at MOST weight 7 to the
491 existing values, or less if that value is based on fewer than 7
493 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
494 result /= (weight + 1.0);
495 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
500 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
501 * this connection, implying that the end-to-end connection is up.
504 * @param cc the connection that got the ACK.
507 GCC_handle_connection_create_ack (struct CadetConnection *cc)
509 LOG (GNUNET_ERROR_TYPE_DEBUG,
510 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
513 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
514 if (CADET_CONNECTION_READY == cc->state)
515 return; /* Duplicate ACK, ignore */
516 if (NULL != cc->task)
518 GNUNET_SCHEDULER_cancel (cc->task);
521 cc->metrics.age = GNUNET_TIME_absolute_get ();
523 CADET_CONNECTION_READY,
525 if ( (NULL == cc->keepalive_qe) &&
526 (GNUNET_YES == cc->mqm_ready) &&
528 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
537 * @param cc connection that received encrypted message
538 * @param msg the key exchange message
541 GCC_handle_kx (struct CadetConnection *cc,
542 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
544 LOG (GNUNET_ERROR_TYPE_DEBUG,
545 "Received KX message with ephermal %s on CC %s in state %d\n",
546 GNUNET_e2s (&msg->ephemeral_key),
547 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
549 if (CADET_CONNECTION_SENT == cc->state)
551 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
552 clearly something is working, so pretend we got an ACK. */
553 LOG (GNUNET_ERROR_TYPE_DEBUG,
554 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
556 GCC_handle_connection_create_ack (cc);
558 GCT_handle_kx (cc->ct,
564 * Handle KX_AUTH message.
566 * @param cc connection that received encrypted message
567 * @param msg the key exchange message
570 GCC_handle_kx_auth (struct CadetConnection *cc,
571 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
573 LOG (GNUNET_ERROR_TYPE_DEBUG,
574 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
575 GNUNET_e2s (&msg->kx.ephemeral_key),
576 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
578 if (CADET_CONNECTION_SENT == cc->state)
580 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
581 clearly something is working, so pretend we got an ACK. */
582 LOG (GNUNET_ERROR_TYPE_DEBUG,
583 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
585 GCC_handle_connection_create_ack (cc);
587 GCT_handle_kx_auth (cc->ct,
593 * Handle encrypted message.
595 * @param cc connection that received encrypted message
596 * @param msg the encrypted message to decrypt
599 GCC_handle_encrypted (struct CadetConnection *cc,
600 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
602 if (CADET_CONNECTION_SENT == cc->state)
604 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
605 clearly something is working, so pretend we got an ACK. */
606 LOG (GNUNET_ERROR_TYPE_DEBUG,
607 "Faking connection ACK for %s due to ENCRYPTED payload\n",
609 GCC_handle_connection_create_ack (cc);
611 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
612 GCT_handle_encrypted (cc->ct,
618 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
621 * @param cls the `struct CadetConnection` to initiate
624 send_create (void *cls)
626 struct CadetConnection *cc = cls;
627 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
628 struct GNUNET_PeerIdentity *pids;
629 struct GNUNET_MQ_Envelope *env;
632 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
633 env = GNUNET_MQ_msg_extra (create_msg,
634 (2 + cc->off) * sizeof (struct GNUNET_PeerIdentity),
635 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
636 create_msg->options = htonl ((uint32_t) cc->options);
637 create_msg->cid = cc->cid;
638 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
639 pids[0] = my_full_id;
640 for (unsigned int i=0;i<=cc->off;i++)
641 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
648 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
649 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
651 CADET_CONNECTION_SENT,
653 GCP_send (cc->mq_man,
659 * Send a CREATE_ACK message towards the origin.
661 * @param cls the `struct CadetConnection` to initiate
664 send_create_ack (void *cls)
666 struct CadetConnection *cc = cls;
667 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
668 struct GNUNET_MQ_Envelope *env;
671 LOG (GNUNET_ERROR_TYPE_DEBUG,
672 "Sending CONNECTION_CREATE_ACK message for %s\n",
674 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
675 env = GNUNET_MQ_msg (ack_msg,
676 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
677 ack_msg->cid = cc->cid;
679 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
680 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
681 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
683 CADET_CONNECTION_READY,
685 if (CADET_CONNECTION_READY == cc->state)
686 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
689 GCP_send (cc->mq_man,
695 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
696 * connection that we already have. Either our ACK got lost
697 * or something is fishy. Consider retransmitting the ACK.
699 * @param cc connection that got the duplicate CREATE
702 GCC_handle_duplicate_create (struct CadetConnection *cc)
704 if (GNUNET_YES == cc->mqm_ready)
706 LOG (GNUNET_ERROR_TYPE_DEBUG,
707 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
709 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
710 /* Revert back to the state of having only received the 'CREATE',
711 and immediately proceed to send the CREATE_ACK. */
713 CADET_CONNECTION_CREATE_RECEIVED,
715 if (NULL != cc->task)
716 GNUNET_SCHEDULER_cancel (cc->task);
717 cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at,
723 /* We are currently sending something else back, which
724 can only be an ACK or payload, either of which would
725 do. So actually no need to do anything. */
726 LOG (GNUNET_ERROR_TYPE_DEBUG,
727 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
734 * There has been a change in the message queue existence for our
735 * peer at the first hop. Adjust accordingly.
737 * @param cls the `struct CadetConnection`
738 * @param available #GNUNET_YES if sending is now possible,
739 * #GNUNET_NO if sending is no longer possible
740 * #GNUNET_SYSERR if sending is no longer possible
741 * and the last envelope was discarded
744 manage_first_hop_mq (void *cls,
747 struct CadetConnection *cc = cls;
749 if (GNUNET_YES != available)
751 /* Connection is down, for now... */
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Core MQ for %s went down\n",
756 CADET_CONNECTION_NEW,
758 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
759 if (NULL != cc->task)
761 GNUNET_SCHEDULER_cancel (cc->task);
770 LOG (GNUNET_ERROR_TYPE_DEBUG,
771 "Core MQ for %s became available in state %d\n",
776 case CADET_CONNECTION_NEW:
777 /* Transmit immediately */
778 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at,
782 case CADET_CONNECTION_SENDING_CREATE:
783 /* Should not be possible to be called in this state. */
786 case CADET_CONNECTION_SENT:
787 /* Retry a bit later... */
788 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at,
792 case CADET_CONNECTION_CREATE_RECEIVED:
793 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
794 cc->metrics.age = GNUNET_TIME_absolute_get ();
795 cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at,
799 case CADET_CONNECTION_READY:
800 if ( (NULL == cc->keepalive_qe) &&
801 (GNUNET_YES == cc->mqm_ready) &&
804 LOG (GNUNET_ERROR_TYPE_DEBUG,
805 "Scheduling keepalive for %s in %s\n",
807 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
809 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
819 * Create a connection to @a destination via @a path and notify @a cb
820 * whenever we are ready for more data. Shared logic independent of
821 * who is initiating the connection.
823 * @param destination where to go
824 * @param path which path to take (may not be the full path)
825 * @param off offset of @a destination on @a path
826 * @param options options for the connection
827 * @param ct which tunnel uses this connection
828 * @param init_state initial state for the connection
829 * @param ready_cb function to call when ready to transmit
830 * @param ready_cb_cls closure for @a cb
831 * @return handle to the connection
833 static struct CadetConnection *
834 connection_create (struct CadetPeer *destination,
835 struct CadetPeerPath *path,
837 enum GNUNET_CADET_ChannelOption options,
838 struct CadetTConnection *ct,
839 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
840 enum CadetConnectionState init_state,
841 GCC_ReadyCallback ready_cb,
844 struct CadetConnection *cc;
845 struct CadetPeer *first_hop;
847 cc = GNUNET_new (struct CadetConnection);
848 cc->options = options;
849 cc->state = init_state;
852 cc->retry_delay = GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY,
854 GNUNET_assert (GNUNET_OK ==
855 GNUNET_CONTAINER_multishortmap_put (connections,
856 &GCC_get_id (cc)->connection_of_tunnel,
858 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
859 cc->ready_cb = ready_cb;
860 cc->ready_cb_cls = ready_cb_cls;
863 LOG (GNUNET_ERROR_TYPE_DEBUG,
864 "Creating %s using path %s (offset: %u)\n",
868 GCPP_add_connection (path,
871 for (unsigned int i=0;i<off;i++)
872 GCP_add_connection (GCPP_get_peer_at_offset (path,
875 first_hop = GCPP_get_peer_at_offset (path,
877 cc->mq_man = GCP_request_mq (first_hop,
878 &manage_first_hop_mq,
885 * Create a connection to @a destination via @a path and
886 * notify @a cb whenever we are ready for more data. This
887 * is an inbound tunnel, so we must use the existing @a cid
889 * @param destination where to go
890 * @param path which path to take (may not be the full path)
891 * @param options options for the connection
892 * @param ct which tunnel uses this connection
893 * @param ready_cb function to call when ready to transmit
894 * @param ready_cb_cls closure for @a cb
895 * @return handle to the connection, NULL if we already have
896 * a connection that takes precedence on @a path
898 struct CadetConnection *
899 GCC_create_inbound (struct CadetPeer *destination,
900 struct CadetPeerPath *path,
901 enum GNUNET_CADET_ChannelOption options,
902 struct CadetTConnection *ct,
903 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
904 GCC_ReadyCallback ready_cb,
907 struct CadetConnection *cc;
910 off = GCPP_find_peer (path,
912 GNUNET_assert (UINT_MAX != off);
913 cc = GCPP_get_connection (path,
925 /* Two peers picked the SAME random connection identifier at the
926 same time for the same path? Must be malicious. Drop
927 connection (existing and inbound), even if it is the only
930 GCT_connection_lost (cc->ct);
931 GCC_destroy_without_tunnel (cc);
937 LOG (GNUNET_ERROR_TYPE_DEBUG,
938 "Got two connections on %s, dropping my existing %s\n",
941 GCT_connection_lost (cc->ct);
942 GCC_destroy_without_tunnel (cc);
947 LOG (GNUNET_ERROR_TYPE_DEBUG,
948 "Got two connections on %s, keeping my existing %s\n",
955 return connection_create (destination,
961 CADET_CONNECTION_CREATE_RECEIVED,
968 * Create a connection to @a destination via @a path and
969 * notify @a cb whenever we are ready for more data.
971 * @param destination where to go
972 * @param path which path to take (may not be the full path)
973 * @param off offset of @a destination on @a path
974 * @param options options for the connection
975 * @param ct tunnel that uses the connection
976 * @param ready_cb function to call when ready to transmit
977 * @param ready_cb_cls closure for @a cb
978 * @return handle to the connection
980 struct CadetConnection *
981 GCC_create (struct CadetPeer *destination,
982 struct CadetPeerPath *path,
984 enum GNUNET_CADET_ChannelOption options,
985 struct CadetTConnection *ct,
986 GCC_ReadyCallback ready_cb,
989 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
991 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
994 return connection_create (destination,
1000 CADET_CONNECTION_NEW,
1007 * Transmit message @a msg via connection @a cc. Must only be called
1008 * (once) after the connection has signalled that it is ready via the
1009 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
1010 * connection is right now ready for transmission.
1012 * @param cc connection identification
1013 * @param env envelope with message to transmit; must NOT
1014 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
1017 GCC_transmit (struct CadetConnection *cc,
1018 struct GNUNET_MQ_Envelope *env)
1020 LOG (GNUNET_ERROR_TYPE_DEBUG,
1021 "Scheduling message for transmission on %s\n",
1023 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
1024 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
1025 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
1026 cc->mqm_ready = GNUNET_NO;
1027 if (NULL != cc->task)
1029 GNUNET_SCHEDULER_cancel (cc->task);
1032 GCP_send (cc->mq_man,
1038 * Obtain the path used by this connection.
1040 * @param cc connection
1041 * @param off[out] set to the length of the path we use
1042 * @return path to @a cc
1044 struct CadetPeerPath *
1045 GCC_get_path (struct CadetConnection *cc,
1054 * Obtain unique ID for the connection.
1056 * @param cc connection.
1057 * @return unique number of the connection
1059 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1060 GCC_get_id (struct CadetConnection *cc)
1067 * Get a (static) string for a connection.
1069 * @param cc Connection.
1072 GCC_2s (const struct CadetConnection *cc)
1074 static char buf[128];
1077 return "Connection(NULL)";
1081 GNUNET_snprintf (buf,
1083 "Connection %s (%s)",
1084 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1085 GCT_2s (cc->ct->t));
1088 GNUNET_snprintf (buf,
1091 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1096 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1100 * Log connection info.
1102 * @param cc connection
1103 * @param level Debug level to use.
1106 GCC_debug (struct CadetConnection *cc,
1107 enum GNUNET_ErrorType level)
1109 #if !defined(GNUNET_CULL_LOGGING)
1112 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1114 __FILE__, __FUNCTION__, __LINE__);
1120 "Connection (NULL)\n");
1124 "%s to %s via path %s in state %d is %s\n",
1126 GCP_2s (cc->destination),
1129 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1133 /* end of gnunet-service-cadet_connection.c */