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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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 * How long do we wait initially before retransmitting the KX?
43 * TODO: replace by 2 RTT if/once we have connection-level RTT data!
45 #define INITIAL_CONNECTION_CREATE_RETRY_DELAY \
46 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200)
50 * All the states a connection can be in.
52 enum CadetConnectionState
55 * Uninitialized status, we have not yet even gotten the message queue.
60 * Connection create message in queue, awaiting transmission by CORE.
62 CADET_CONNECTION_SENDING_CREATE,
65 * Connection create message sent, waiting for ACK.
67 CADET_CONNECTION_SENT,
70 * We are an inbound connection, and received a CREATE. Need to
71 * send an CREATE_ACK back.
73 CADET_CONNECTION_CREATE_RECEIVED,
76 * Connection confirmed, ready to carry traffic.
78 CADET_CONNECTION_READY
84 * Low-level connection to a destination.
86 struct CadetConnection
90 * ID of the connection.
92 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
95 * To which peer does this connection go?
97 struct CadetPeer *destination;
100 * Which tunnel is using this connection?
102 struct CadetTConnection *ct;
105 * Path we are using to our destination.
107 struct CadetPeerPath *path;
110 * Pending message, NULL if we are ready to transmit.
112 struct GNUNET_MQ_Envelope *env;
115 * Handle for calling #GCP_request_mq_cancel() once we are finished.
117 struct GCP_MessageQueueManager *mq_man;
120 * Task for connection maintenance.
122 struct GNUNET_SCHEDULER_Task *task;
125 * Queue entry for keepalive messages.
127 struct CadetTunnelQueueEntry *keepalive_qe;
130 * Function to call once we are ready to transmit.
132 GCC_ReadyCallback ready_cb;
135 * Closure for @e ready_cb.
140 * How long do we wait before we try again with a CREATE message?
142 struct GNUNET_TIME_Relative retry_delay;
145 * Earliest time for re-trying CREATE
147 struct GNUNET_TIME_Absolute create_at;
150 * Earliest time for re-trying CREATE_ACK
152 struct GNUNET_TIME_Absolute create_ack_at;
155 * Performance metrics for this connection.
157 struct CadetConnectionMetrics metrics;
160 * State of the connection.
162 enum CadetConnectionState state;
165 * How many latency observations did we make for this connection?
167 unsigned int latency_datapoints;
170 * Offset of our @e destination in @e path.
175 * Are we ready to transmit via @e mq_man right now?
182 * Lookup a connection by its identifier.
184 * @param cid identifier to resolve
185 * @return NULL if connection was not found
187 struct CadetConnection *
188 GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
190 return GNUNET_CONTAINER_multishortmap_get (connections,
191 &cid->connection_of_tunnel);
196 * Update the connection state. Also triggers the necessary
199 * @param cc connection to update the state for
200 * @param new_state new state for @a cc
201 * @param new_mqm_ready new `mqm_ready` state for @a cc
204 update_state (struct CadetConnection *cc,
205 enum CadetConnectionState new_state,
211 if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
212 return; /* no change, nothing to do */
214 ((CADET_CONNECTION_READY == cc->state) && (GNUNET_YES == cc->mqm_ready));
216 ((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
217 cc->state = new_state;
218 cc->mqm_ready = new_mqm_ready;
219 if (old_ready != new_ready)
220 cc->ready_cb (cc->ready_cb_cls, new_ready);
225 * Destroy a connection, part of the internal implementation. Called
226 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
228 * @param cc connection to destroy
231 GCC_destroy (struct CadetConnection *cc)
233 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying %s\n", GCC_2s (cc));
234 if (NULL != cc->mq_man)
236 GCP_request_mq_cancel (cc->mq_man, NULL);
239 if (NULL != cc->task)
241 GNUNET_SCHEDULER_cancel (cc->task);
244 if (NULL != cc->keepalive_qe)
246 GCT_send_cancel (cc->keepalive_qe);
247 cc->keepalive_qe = NULL;
249 GCPP_del_connection (cc->path, cc->off, cc);
250 for (unsigned int i = 0; i < cc->off; i++)
251 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, i), cc);
254 GNUNET_CONTAINER_multishortmap_remove (connections,
256 ->connection_of_tunnel,
263 * Destroy a connection, called when the CORE layer is already done
264 * (i.e. has received a BROKEN message), but if we still have to
265 * communicate the destruction of the connection to the tunnel (if one
268 * @param cc connection to destroy
271 GCC_destroy_without_core (struct CadetConnection *cc)
275 GCT_connection_lost (cc->ct);
283 * Destroy a connection, called if the tunnel association with the
284 * connection was already broken, but we still need to notify the CORE
285 * layer about the breakage.
287 * @param cc connection to destroy
290 GCC_destroy_without_tunnel (struct CadetConnection *cc)
293 if ((CADET_CONNECTION_SENDING_CREATE != cc->state) && (NULL != cc->mq_man))
295 struct GNUNET_MQ_Envelope *env;
296 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
298 /* Need to notify next hop that we are down. */
300 GNUNET_MQ_msg (destroy_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
301 destroy_msg->cid = cc->cid;
302 GCP_request_mq_cancel (cc->mq_man, env);
310 * Return the tunnel associated with this connection.
312 * @param cc connection to query
313 * @return corresponding entry in the tunnel's connection list
315 struct CadetTConnection *
316 GCC_get_ct (struct CadetConnection *cc)
323 * Obtain performance @a metrics from @a cc.
325 * @param cc connection to query
326 * @return the metrics
328 const struct CadetConnectionMetrics *
329 GCC_get_metrics (struct CadetConnection *cc)
336 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
337 * tunnel to prevent it from timing out.
339 * @param cls the `struct CadetConnection` to keep alive.
342 send_keepalive (void *cls);
346 * Keepalive was transmitted. Remember this, and possibly
347 * schedule the next one.
349 * @param cls the `struct CadetConnection` to keep alive.
350 * @param cid identifier of the connection within the tunnel, NULL
351 * if transmission failed
354 keepalive_done (void *cls,
355 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
357 struct CadetConnection *cc = cls;
359 cc->keepalive_qe = NULL;
360 if ((GNUNET_YES == cc->mqm_ready) && (NULL == cc->task))
362 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
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... */
383 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
386 GNUNET_assert (NULL != cc->ct);
387 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
388 GNUNET_assert (NULL == cc->keepalive_qe);
389 LOG (GNUNET_ERROR_TYPE_INFO,
390 "Sending KEEPALIVE on behalf of %s via %s\n",
393 GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
394 msg.size = htons (sizeof (msg));
395 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
397 cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc);
402 * We sent a message for which we expect to receive an ACK via
403 * the connection identified by @a cti.
405 * @param cid connection identifier where we expect an ACK
408 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
410 struct CadetConnection *cc;
412 cc = GCC_lookup (cid);
414 return; /* whopise, connection alredy down? */
415 cc->metrics.num_acked_transmissions++;
420 * We observed an ACK for a message that was originally sent via
421 * the connection identified by @a cti.
423 * @param cti connection identifier where we got an ACK for a message
424 * that was originally sent via this connection (the ACK
425 * may have gotten back to us via a different connection).
428 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
430 struct CadetConnection *cc;
432 cc = GCC_lookup (cid);
434 return; /* whopise, connection alredy down? */
435 cc->metrics.num_successes++;
440 * We observed some the given @a latency on the connection
441 * identified by @a cti. (The same connection was taken
442 * in both directions.)
444 * @param cid connection identifier where we measured latency
445 * @param latency the observed latency
448 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
449 struct GNUNET_TIME_Relative latency)
451 struct CadetConnection *cc;
455 cc = GCC_lookup (cid);
457 return; /* whopise, connection alredy down? */
458 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
459 cc->latency_datapoints++;
460 if (cc->latency_datapoints >= 7)
463 weight = cc->latency_datapoints;
464 /* Compute weighted average, giving at MOST weight 7 to the
465 existing values, or less if that value is based on fewer than 7
467 result = (weight * cc->metrics.aged_latency.rel_value_us) +
468 1.0 * latency.rel_value_us;
469 result /= (weight + 1.0);
470 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
475 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
476 * this connection, implying that the end-to-end connection is up.
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 ();
497 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
498 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
501 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
508 * @param cc connection that received encrypted message
509 * @param msg the key exchange message
512 GCC_handle_kx (struct CadetConnection *cc,
513 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
515 LOG (GNUNET_ERROR_TYPE_DEBUG,
516 "Received KX message with ephermal %s on CC %s in state %d\n",
517 GNUNET_e2s (&msg->ephemeral_key),
518 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
520 if (CADET_CONNECTION_SENT == cc->state)
522 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
523 clearly something is working, so pretend we got an ACK. */
524 LOG (GNUNET_ERROR_TYPE_DEBUG,
525 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
527 GCC_handle_connection_create_ack (cc);
529 GCT_handle_kx (cc->ct, msg);
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 LOG (GNUNET_ERROR_TYPE_DEBUG,
544 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
545 GNUNET_e2s (&msg->kx.ephemeral_key),
546 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
548 if (CADET_CONNECTION_SENT == cc->state)
550 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
551 clearly something is working, so pretend we got an ACK. */
552 LOG (GNUNET_ERROR_TYPE_DEBUG,
553 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
555 GCC_handle_connection_create_ack (cc);
557 GCT_handle_kx_auth (cc->ct, msg);
562 * Handle encrypted message.
564 * @param cc connection that received encrypted message
565 * @param msg the encrypted message to decrypt
568 GCC_handle_encrypted (struct CadetConnection *cc,
569 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
571 if (CADET_CONNECTION_SENT == cc->state)
573 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
574 clearly something is working, so pretend we got an ACK. */
575 LOG (GNUNET_ERROR_TYPE_DEBUG,
576 "Faking connection ACK for %s due to ENCRYPTED payload\n",
578 GCC_handle_connection_create_ack (cc);
580 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
581 GCT_handle_encrypted (cc->ct, msg);
586 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
589 * @param cls the `struct CadetConnection` to initiate
592 send_create (void *cls)
594 struct CadetConnection *cc = cls;
595 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
596 struct GNUNET_PeerIdentity *pids;
597 struct GNUNET_MQ_Envelope *env;
600 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
602 GNUNET_MQ_msg_extra (create_msg,
603 (2 + cc->off) * sizeof (struct GNUNET_PeerIdentity),
604 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
605 //TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed.
606 create_msg->options = 2;
607 create_msg->cid = cc->cid;
608 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
609 pids[0] = my_full_id;
610 for (unsigned int i = 0; i <= cc->off; i++)
611 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
612 LOG (GNUNET_ERROR_TYPE_DEBUG,
613 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
617 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
618 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
619 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
620 GCP_send (cc->mq_man, env);
625 * Send a CREATE_ACK message towards the origin.
627 * @param cls the `struct CadetConnection` to initiate
630 send_create_ack (void *cls)
632 struct CadetConnection *cc = cls;
633 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
634 struct GNUNET_MQ_Envelope *env;
637 LOG (GNUNET_ERROR_TYPE_DEBUG,
638 "Sending CONNECTION_CREATE_ACK message for %s\n",
640 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
642 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
643 ack_msg->cid = cc->cid;
645 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
646 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
647 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
648 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
649 if (CADET_CONNECTION_READY == cc->state)
651 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
652 GCP_send (cc->mq_man, env);
657 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
658 * connection that we already have. Either our ACK got lost
659 * or something is fishy. Consider retransmitting the ACK.
661 * @param cc connection that got the duplicate CREATE
664 GCC_handle_duplicate_create (struct CadetConnection *cc)
666 if (GNUNET_YES == cc->mqm_ready)
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
671 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
672 /* Revert back to the state of having only received the 'CREATE',
673 and immediately proceed to send the CREATE_ACK. */
674 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
675 if (NULL != cc->task)
676 GNUNET_SCHEDULER_cancel (cc->task);
678 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
682 /* We are currently sending something else back, which
683 can only be an ACK or payload, either of which would
684 do. So actually no need to do anything. */
685 LOG (GNUNET_ERROR_TYPE_DEBUG,
686 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
693 * There has been a change in the message queue existence for our
694 * peer at the first hop. Adjust accordingly.
696 * @param cls the `struct CadetConnection`
697 * @param available #GNUNET_YES if sending is now possible,
698 * #GNUNET_NO if sending is no longer possible
699 * #GNUNET_SYSERR if sending is no longer possible
700 * and the last envelope was discarded
703 manage_first_hop_mq (void *cls, int available)
705 struct CadetConnection *cc = cls;
707 if (GNUNET_YES != available)
709 /* Connection is down, for now... */
710 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
711 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
712 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
713 if (NULL != cc->task)
715 GNUNET_SCHEDULER_cancel (cc->task);
721 update_state (cc, cc->state, GNUNET_YES);
722 LOG (GNUNET_ERROR_TYPE_DEBUG,
723 "Core MQ for %s became available in state %d\n",
728 case CADET_CONNECTION_NEW:
729 /* Transmit immediately */
730 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
732 case CADET_CONNECTION_SENDING_CREATE:
733 /* Should not be possible to be called in this state. */
736 case CADET_CONNECTION_SENT:
737 /* Retry a bit later... */
738 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
740 case CADET_CONNECTION_CREATE_RECEIVED:
741 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
742 cc->metrics.age = GNUNET_TIME_absolute_get ();
744 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
746 case CADET_CONNECTION_READY:
747 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
750 LOG (GNUNET_ERROR_TYPE_DEBUG,
751 "Scheduling keepalive for %s in %s\n",
753 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
756 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
764 * Create a connection to @a destination via @a path and notify @a cb
765 * whenever we are ready for more data. Shared logic independent of
766 * who is initiating the connection.
768 * @param destination where to go
769 * @param path which path to take (may not be the full path)
770 * @param off offset of @a destination on @a path
771 * @param ct which tunnel uses this connection
772 * @param init_state initial state for the connection
773 * @param ready_cb function to call when ready to transmit
774 * @param ready_cb_cls closure for @a cb
775 * @return handle to the connection
777 static struct CadetConnection *
778 connection_create (struct CadetPeer *destination,
779 struct CadetPeerPath *path,
781 struct CadetTConnection *ct,
782 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
783 enum CadetConnectionState init_state,
784 GCC_ReadyCallback ready_cb,
787 struct CadetConnection *cc;
788 struct CadetPeer *first_hop;
790 cc = GNUNET_new (struct CadetConnection);
791 cc->state = init_state;
795 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
796 GNUNET_assert (GNUNET_OK ==
797 GNUNET_CONTAINER_multishortmap_put (
799 &GCC_get_id (cc)->connection_of_tunnel,
801 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
802 cc->ready_cb = ready_cb;
803 cc->ready_cb_cls = ready_cb_cls;
806 LOG (GNUNET_ERROR_TYPE_DEBUG,
807 "Creating %s using path %s (offset: %u)\n",
811 GCPP_add_connection (path, off, cc);
812 for (unsigned int i = 0; i < off; i++)
813 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
814 first_hop = GCPP_get_peer_at_offset (path, 0);
815 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
821 * Create a connection to @a destination via @a path and
822 * notify @a cb whenever we are ready for more data. This
823 * is an inbound tunnel, so we must use the existing @a cid
825 * @param destination where to go
826 * @param path which path to take (may not be the full path)
827 * @param ct which tunnel uses this connection
828 * @param ready_cb function to call when ready to transmit
829 * @param ready_cb_cls closure for @a cb
830 * @return handle to the connection, NULL if we already have
831 * a connection that takes precedence on @a path
833 struct CadetConnection *
834 GCC_create_inbound (struct CadetPeer *destination,
835 struct CadetPeerPath *path,
836 struct CadetTConnection *ct,
837 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
838 GCC_ReadyCallback ready_cb,
841 struct CadetConnection *cc;
844 off = GCPP_find_peer (path, destination);
845 GNUNET_assert (UINT_MAX != off);
846 cc = GCPP_get_connection (path, destination, off);
851 cmp = GNUNET_memcmp (cid, &cc->cid);
854 /* Two peers picked the SAME random connection identifier at the
855 same time for the same path? Must be malicious. Drop
856 connection (existing and inbound), even if it is the only
859 GCT_connection_lost (cc->ct);
860 GCC_destroy_without_tunnel (cc);
866 LOG (GNUNET_ERROR_TYPE_DEBUG,
867 "Got two connections on %s, dropping my existing %s\n",
870 GCT_connection_lost (cc->ct);
871 GCC_destroy_without_tunnel (cc);
876 LOG (GNUNET_ERROR_TYPE_DEBUG,
877 "Got two connections on %s, keeping my existing %s\n",
884 return connection_create (destination,
889 CADET_CONNECTION_CREATE_RECEIVED,
896 * Create a connection to @a destination via @a path and
897 * notify @a cb whenever we are ready for more data.
899 * @param destination where to go
900 * @param path which path to take (may not be the full path)
901 * @param off offset of @a destination on @a path
902 * @param ct tunnel that uses the connection
903 * @param ready_cb function to call when ready to transmit
904 * @param ready_cb_cls closure for @a cb
905 * @return handle to the connection
907 struct CadetConnection *
908 GCC_create (struct CadetPeer *destination,
909 struct CadetPeerPath *path,
911 struct CadetTConnection *ct,
912 GCC_ReadyCallback ready_cb,
915 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
917 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid));
918 return connection_create (destination,
923 CADET_CONNECTION_NEW,
930 * Transmit message @a msg via connection @a cc. Must only be called
931 * (once) after the connection has signalled that it is ready via the
932 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
933 * connection is right now ready for transmission.
935 * @param cc connection identification
936 * @param env envelope with message to transmit; must NOT
937 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
940 GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
942 LOG (GNUNET_ERROR_TYPE_DEBUG,
943 "Scheduling message for transmission on %s\n",
945 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
946 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
947 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
948 cc->mqm_ready = GNUNET_NO;
949 if (NULL != cc->task)
951 GNUNET_SCHEDULER_cancel (cc->task);
954 GCP_send (cc->mq_man, env);
959 * Obtain the path used by this connection.
961 * @param cc connection
962 * @param off[out] set to the length of the path we use
963 * @return path to @a cc
965 struct CadetPeerPath *
966 GCC_get_path (struct CadetConnection *cc, unsigned int *off)
974 * Obtain unique ID for the connection.
976 * @param cc connection.
977 * @return unique number of the connection
979 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
980 GCC_get_id (struct CadetConnection *cc)
987 * Get a (static) string for a connection.
989 * @param cc Connection.
992 GCC_2s (const struct CadetConnection *cc)
994 static char buf[128];
997 return "Connection(NULL)";
1001 GNUNET_snprintf (buf,
1003 "Connection %s (%s)",
1004 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1005 GCT_2s (cc->ct->t));
1008 GNUNET_snprintf (buf,
1011 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1016 #define LOG2(level, ...) \
1017 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1021 * Log connection info.
1023 * @param cc connection
1024 * @param level Debug level to use.
1027 GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1029 #if ! defined(GNUNET_CULL_LOGGING)
1032 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1041 LOG2 (level, "Connection (NULL)\n");
1045 "%s to %s via path %s in state %d is %s\n",
1047 GCP_2s (cc->destination),
1050 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1054 /* end of gnunet-service-cadet_connection.c */