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
83 * Low-level connection to a destination.
85 struct CadetConnection
88 * ID of the connection.
90 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
93 * To which peer does this connection go?
95 struct CadetPeer *destination;
98 * Which tunnel is using this connection?
100 struct CadetTConnection *ct;
103 * Path we are using to our destination.
105 struct CadetPeerPath *path;
108 * Pending message, NULL if we are ready to transmit.
110 struct GNUNET_MQ_Envelope *env;
113 * Handle for calling #GCP_request_mq_cancel() once we are finished.
115 struct GCP_MessageQueueManager *mq_man;
118 * Task for connection maintenance.
120 struct GNUNET_SCHEDULER_Task *task;
123 * Queue entry for keepalive messages.
125 struct CadetTunnelQueueEntry *keepalive_qe;
128 * Function to call once we are ready to transmit.
130 GCC_ReadyCallback ready_cb;
133 * Closure for @e ready_cb.
138 * How long do we wait before we try again with a CREATE message?
140 struct GNUNET_TIME_Relative retry_delay;
143 * Earliest time for re-trying CREATE
145 struct GNUNET_TIME_Absolute create_at;
148 * Earliest time for re-trying CREATE_ACK
150 struct GNUNET_TIME_Absolute create_ack_at;
153 * Performance metrics for this connection.
155 struct CadetConnectionMetrics metrics;
158 * State of the connection.
160 enum CadetConnectionState state;
163 * How many latency observations did we make for this connection?
165 unsigned int latency_datapoints;
168 * Offset of our @e destination in @e path.
173 * Are we ready to transmit via @e mq_man right now?
180 * Lookup a connection by its identifier.
182 * @param cid identifier to resolve
183 * @return NULL if connection was not found
185 struct CadetConnection *
186 GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
188 return GNUNET_CONTAINER_multishortmap_get (connections,
189 &cid->connection_of_tunnel);
194 * Update the connection state. Also triggers the necessary
197 * @param cc connection to update the state for
198 * @param new_state new state for @a cc
199 * @param new_mqm_ready new `mqm_ready` state for @a cc
202 update_state (struct CadetConnection *cc,
203 enum CadetConnectionState new_state,
209 if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
210 return; /* no change, nothing to do */
212 ((CADET_CONNECTION_READY == cc->state) && (GNUNET_YES == cc->mqm_ready));
214 ((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
215 cc->state = new_state;
216 cc->mqm_ready = new_mqm_ready;
217 if (old_ready != new_ready)
218 cc->ready_cb (cc->ready_cb_cls, new_ready);
223 * Destroy a connection, part of the internal implementation. Called
224 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
226 * @param cc connection to destroy
229 GCC_destroy (struct CadetConnection *cc)
231 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying %s\n", GCC_2s (cc));
232 if (NULL != cc->mq_man)
234 GCP_request_mq_cancel (cc->mq_man, NULL);
237 if (NULL != cc->task)
239 GNUNET_SCHEDULER_cancel (cc->task);
242 if (NULL != cc->keepalive_qe)
244 GCT_send_cancel (cc->keepalive_qe);
245 cc->keepalive_qe = NULL;
247 GCPP_del_connection (cc->path, cc->off, cc);
248 for (unsigned int i = 0; i < cc->off; i++)
249 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, i), cc);
252 GNUNET_CONTAINER_multishortmap_remove (connections,
254 ->connection_of_tunnel,
261 * Destroy a connection, called when the CORE layer is already done
262 * (i.e. has received a BROKEN message), but if we still have to
263 * communicate the destruction of the connection to the tunnel (if one
266 * @param cc connection to destroy
269 GCC_destroy_without_core (struct CadetConnection *cc)
273 GCT_connection_lost (cc->ct);
281 * Destroy a connection, called if the tunnel association with the
282 * connection was already broken, but we still need to notify the CORE
283 * layer about the breakage.
285 * @param cc connection to destroy
288 GCC_destroy_without_tunnel (struct CadetConnection *cc)
291 if ((CADET_CONNECTION_SENDING_CREATE != cc->state) && (NULL != cc->mq_man))
293 struct GNUNET_MQ_Envelope *env;
294 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
296 /* Need to notify next hop that we are down. */
298 GNUNET_MQ_msg (destroy_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
299 destroy_msg->cid = cc->cid;
300 GCP_request_mq_cancel (cc->mq_man, env);
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) && (NULL == cc->task))
360 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
365 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
366 * tunnel to prevent it from timing out.
368 * @param cls the `struct CadetConnection` to keep alive.
371 send_keepalive (void *cls)
373 struct CadetConnection *cc = cls;
374 struct GNUNET_MessageHeader msg;
377 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
379 /* Tunnel not yet ready, wait with keepalives... */
381 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
384 GNUNET_assert (NULL != cc->ct);
385 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
386 GNUNET_assert (NULL == cc->keepalive_qe);
387 LOG (GNUNET_ERROR_TYPE_INFO,
388 "Sending KEEPALIVE on behalf of %s via %s\n",
391 GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
392 msg.size = htons (sizeof(msg));
393 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
395 cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc);
400 * We sent a message for which we expect to receive an ACK via
401 * the connection identified by @a cti.
403 * @param cid connection identifier where we expect an ACK
406 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
408 struct CadetConnection *cc;
410 cc = GCC_lookup (cid);
412 return; /* whopise, connection alredy down? */
413 cc->metrics.num_acked_transmissions++;
418 * We observed an ACK for a message that was originally sent via
419 * the connection identified by @a cti.
421 * @param cti connection identifier where we got an ACK for a message
422 * that was originally sent via this connection (the ACK
423 * may have gotten back to us via a different connection).
426 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
428 struct CadetConnection *cc;
430 cc = GCC_lookup (cid);
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 = GCC_lookup (cid);
455 return; /* whopise, connection alredy down? */
456 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
457 cc->latency_datapoints++;
458 if (cc->latency_datapoints >= 7)
461 weight = cc->latency_datapoints;
462 /* Compute weighted average, giving at MOST weight 7 to the
463 existing values, or less if that value is based on fewer than 7
465 result = (weight * cc->metrics.aged_latency.rel_value_us)
466 + 1.0 * latency.rel_value_us;
467 result /= (weight + 1.0);
468 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
473 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
474 * this connection, implying that the end-to-end connection is up.
477 * @param cc the connection that got the ACK.
480 GCC_handle_connection_create_ack (struct CadetConnection *cc)
482 LOG (GNUNET_ERROR_TYPE_DEBUG,
483 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
486 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
487 if (CADET_CONNECTION_READY == cc->state)
488 return; /* Duplicate ACK, ignore */
489 if (NULL != cc->task)
491 GNUNET_SCHEDULER_cancel (cc->task);
494 cc->metrics.age = GNUNET_TIME_absolute_get ();
495 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
496 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
499 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
506 * @param cc connection that received encrypted message
507 * @param msg the key exchange message
510 GCC_handle_kx (struct CadetConnection *cc,
511 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
513 LOG (GNUNET_ERROR_TYPE_DEBUG,
514 "Received KX message with ephermal %s on CC %s in state %d\n",
515 GNUNET_e2s (&msg->ephemeral_key),
516 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
518 if (CADET_CONNECTION_SENT == cc->state)
520 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
521 clearly something is working, so pretend we got an ACK. */
522 LOG (GNUNET_ERROR_TYPE_DEBUG,
523 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
525 GCC_handle_connection_create_ack (cc);
527 GCT_handle_kx (cc->ct, msg);
532 * Handle KX_AUTH message.
534 * @param cc connection that received encrypted message
535 * @param msg the key exchange message
538 GCC_handle_kx_auth (struct CadetConnection *cc,
539 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
541 LOG (GNUNET_ERROR_TYPE_DEBUG,
542 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
543 GNUNET_e2s (&msg->kx.ephemeral_key),
544 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
546 if (CADET_CONNECTION_SENT == cc->state)
548 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
549 clearly something is working, so pretend we got an ACK. */
550 LOG (GNUNET_ERROR_TYPE_DEBUG,
551 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
553 GCC_handle_connection_create_ack (cc);
555 GCT_handle_kx_auth (cc->ct, msg);
560 * Handle encrypted message.
562 * @param cc connection that received encrypted message
563 * @param msg the encrypted message to decrypt
566 GCC_handle_encrypted (struct CadetConnection *cc,
567 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
569 if (CADET_CONNECTION_SENT == cc->state)
571 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
572 clearly something is working, so pretend we got an ACK. */
573 LOG (GNUNET_ERROR_TYPE_DEBUG,
574 "Faking connection ACK for %s due to ENCRYPTED payload\n",
576 GCC_handle_connection_create_ack (cc);
578 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
579 GCT_handle_encrypted (cc->ct, msg);
584 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
587 * @param cls the `struct CadetConnection` to initiate
590 send_create (void *cls)
592 struct CadetConnection *cc = cls;
593 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
594 struct GNUNET_PeerIdentity *pids;
595 struct GNUNET_MQ_Envelope *env;
598 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
600 GNUNET_MQ_msg_extra (create_msg,
601 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
602 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
603 // 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.
604 create_msg->options = 2;
605 create_msg->cid = cc->cid;
606 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
607 pids[0] = my_full_id;
608 for (unsigned int i = 0; i <= cc->off; i++)
609 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
610 LOG (GNUNET_ERROR_TYPE_DEBUG,
611 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
615 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
616 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
617 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
618 GCP_send (cc->mq_man, env);
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 LOG (GNUNET_ERROR_TYPE_DEBUG,
636 "Sending CONNECTION_CREATE_ACK message for %s\n",
638 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
640 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
641 ack_msg->cid = cc->cid;
643 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
644 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
645 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
646 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
647 if (CADET_CONNECTION_READY == cc->state)
649 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
650 GCP_send (cc->mq_man, env);
655 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
656 * connection that we already have. Either our ACK got lost
657 * or something is fishy. Consider retransmitting the ACK.
659 * @param cc connection that got the duplicate CREATE
662 GCC_handle_duplicate_create (struct CadetConnection *cc)
664 if (GNUNET_YES == cc->mqm_ready)
666 LOG (GNUNET_ERROR_TYPE_DEBUG,
667 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
669 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
670 /* Revert back to the state of having only received the 'CREATE',
671 and immediately proceed to send the CREATE_ACK. */
672 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
673 if (NULL != cc->task)
674 GNUNET_SCHEDULER_cancel (cc->task);
676 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
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, int available)
703 struct CadetConnection *cc = cls;
705 if (GNUNET_YES != available)
707 /* Connection is down, for now... */
708 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
709 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
710 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
711 if (NULL != cc->task)
713 GNUNET_SCHEDULER_cancel (cc->task);
719 update_state (cc, cc->state, GNUNET_YES);
720 LOG (GNUNET_ERROR_TYPE_DEBUG,
721 "Core MQ for %s became available in state %d\n",
726 case CADET_CONNECTION_NEW:
727 /* Transmit immediately */
728 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
731 case CADET_CONNECTION_SENDING_CREATE:
732 /* 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);
741 case CADET_CONNECTION_CREATE_RECEIVED:
742 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
743 cc->metrics.age = GNUNET_TIME_absolute_get ();
745 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
748 case CADET_CONNECTION_READY:
749 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Scheduling keepalive for %s in %s\n",
755 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
758 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
766 * Create a connection to @a destination via @a path and notify @a cb
767 * whenever we are ready for more data. Shared logic independent of
768 * who is initiating the connection.
770 * @param destination where to go
771 * @param path which path to take (may not be the full path)
772 * @param off offset of @a destination on @a path
773 * @param ct which tunnel uses this connection
774 * @param init_state initial state for the connection
775 * @param ready_cb function to call when ready to transmit
776 * @param ready_cb_cls closure for @a cb
777 * @return handle to the connection
779 static struct CadetConnection *
780 connection_create (struct CadetPeer *destination,
781 struct CadetPeerPath *path,
783 struct CadetTConnection *ct,
784 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
785 enum CadetConnectionState init_state,
786 GCC_ReadyCallback ready_cb,
789 struct CadetConnection *cc;
790 struct CadetPeer *first_hop;
792 cc = GNUNET_new (struct CadetConnection);
793 cc->state = init_state;
797 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
798 GNUNET_assert (GNUNET_OK ==
799 GNUNET_CONTAINER_multishortmap_put (
801 &GCC_get_id (cc)->connection_of_tunnel,
803 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
804 cc->ready_cb = ready_cb;
805 cc->ready_cb_cls = ready_cb_cls;
808 LOG (GNUNET_ERROR_TYPE_DEBUG,
809 "Creating %s using path %s (offset: %u)\n",
813 GCPP_add_connection (path, off, cc);
814 for (unsigned int i = 0; i < off; i++)
815 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
816 first_hop = GCPP_get_peer_at_offset (path, 0);
817 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
823 * Create a connection to @a destination via @a path and
824 * notify @a cb whenever we are ready for more data. This
825 * is an inbound tunnel, so we must use the existing @a cid
827 * @param destination where to go
828 * @param path which path to take (may not be the full path)
829 * @param ct which tunnel uses this connection
830 * @param ready_cb function to call when ready to transmit
831 * @param ready_cb_cls closure for @a cb
832 * @return handle to the connection, NULL if we already have
833 * a connection that takes precedence on @a path
835 struct CadetConnection *
836 GCC_create_inbound (struct CadetPeer *destination,
837 struct CadetPeerPath *path,
838 struct CadetTConnection *ct,
839 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
840 GCC_ReadyCallback ready_cb,
843 struct CadetConnection *cc;
846 off = GCPP_find_peer (path, destination);
847 GNUNET_assert (UINT_MAX != off);
848 cc = GCPP_get_connection (path, destination, off);
853 cmp = GNUNET_memcmp (cid, &cc->cid);
856 /* Two peers picked the SAME random connection identifier at the
857 same time for the same path? Must be malicious. Drop
858 connection (existing and inbound), even if it is the only
861 GCT_connection_lost (cc->ct);
862 GCC_destroy_without_tunnel (cc);
868 LOG (GNUNET_ERROR_TYPE_DEBUG,
869 "Got two connections on %s, dropping my existing %s\n",
872 GCT_connection_lost (cc->ct);
873 GCC_destroy_without_tunnel (cc);
878 LOG (GNUNET_ERROR_TYPE_DEBUG,
879 "Got two connections on %s, keeping my existing %s\n",
886 return connection_create (destination,
891 CADET_CONNECTION_CREATE_RECEIVED,
898 * Create a connection to @a destination via @a path and
899 * notify @a cb whenever we are ready for more data.
901 * @param destination where to go
902 * @param path which path to take (may not be the full path)
903 * @param off offset of @a destination on @a path
904 * @param ct tunnel that uses the connection
905 * @param ready_cb function to call when ready to transmit
906 * @param ready_cb_cls closure for @a cb
907 * @return handle to the connection
909 struct CadetConnection *
910 GCC_create (struct CadetPeer *destination,
911 struct CadetPeerPath *path,
913 struct CadetTConnection *ct,
914 GCC_ReadyCallback ready_cb,
917 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
919 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
920 return connection_create (destination,
925 CADET_CONNECTION_NEW,
932 * Transmit message @a msg via connection @a cc. Must only be called
933 * (once) after the connection has signalled that it is ready via the
934 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
935 * connection is right now ready for transmission.
937 * @param cc connection identification
938 * @param env envelope with message to transmit; must NOT
939 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
942 GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
944 LOG (GNUNET_ERROR_TYPE_DEBUG,
945 "Scheduling message for transmission on %s\n",
947 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
948 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
949 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
950 cc->mqm_ready = GNUNET_NO;
951 if (NULL != cc->task)
953 GNUNET_SCHEDULER_cancel (cc->task);
956 GCP_send (cc->mq_man, env);
961 * Obtain the path used by this connection.
963 * @param cc connection
964 * @param off[out] set to the length of the path we use
965 * @return path to @a cc
967 struct CadetPeerPath *
968 GCC_get_path (struct CadetConnection *cc, unsigned int *off)
976 * Obtain unique ID for the connection.
978 * @param cc connection.
979 * @return unique number of the connection
981 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
982 GCC_get_id (struct CadetConnection *cc)
989 * Get a (static) string for a connection.
991 * @param cc Connection.
994 GCC_2s (const struct CadetConnection *cc)
996 static char buf[128];
999 return "Connection(NULL)";
1003 GNUNET_snprintf (buf,
1005 "Connection %s (%s)",
1006 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1007 GCT_2s (cc->ct->t));
1010 GNUNET_snprintf (buf,
1013 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1018 #define LOG2(level, ...) \
1019 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1023 * Log connection info.
1025 * @param cc connection
1026 * @param level Debug level to use.
1029 GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1031 #if ! defined(GNUNET_CULL_LOGGING)
1034 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1043 LOG2 (level, "Connection (NULL)\n");
1047 "%s to %s via path %s in state %d is %s\n",
1049 GCP_2s (cc->destination),
1052 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1057 /* end of gnunet-service-cadet_connection.c */