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_signatures.h"
30 #include "gnunet-service-cadet_connection.h"
31 #include "gnunet-service-cadet_channel.h"
32 #include "gnunet-service-cadet_paths.h"
33 #include "gnunet-service-cadet_tunnels.h"
34 #include "gnunet_cadet_service.h"
35 #include "gnunet_statistics_service.h"
36 #include "cadet_protocol.h"
39 #define LOG(level, ...) GNUNET_log_from (level, "cadet-con", __VA_ARGS__)
43 * How long do we wait initially before retransmitting the KX?
44 * TODO: replace by 2 RTT if/once we have connection-level RTT data!
46 #define INITIAL_CONNECTION_CREATE_RETRY_DELAY \
47 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200)
51 * All the states a connection can be in.
53 enum CadetConnectionState
56 * Uninitialized status, we have not yet even gotten the message queue.
61 * Connection create message in queue, awaiting transmission by CORE.
63 CADET_CONNECTION_SENDING_CREATE,
66 * Connection create message sent, waiting for ACK.
68 CADET_CONNECTION_SENT,
71 * We are an inbound connection, and received a CREATE. Need to
72 * send an CREATE_ACK back.
74 CADET_CONNECTION_CREATE_RECEIVED,
77 * Connection confirmed, ready to carry traffic.
79 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 LOG (GNUNET_ERROR_TYPE_DEBUG,
210 "Trying to update connection state for %s having old state %d to new %d and mqm_ready old %d to mqm_ready new %d\n",
217 if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
218 return; /* no change, nothing to do */
220 ((CADET_CONNECTION_READY == cc->state) && (GNUNET_YES == cc->mqm_ready));
222 ((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
223 cc->state = new_state;
224 cc->mqm_ready = new_mqm_ready;
226 LOG (GNUNET_ERROR_TYPE_DEBUG,
227 "Updating connection state for %s having old_ready %d and new_rady %d\n",
232 if (old_ready != new_ready)
233 cc->ready_cb (cc->ready_cb_cls, new_ready);
238 * Destroy a connection, part of the internal implementation. Called
239 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
241 * @param cc connection to destroy
244 GCC_destroy (struct CadetConnection *cc)
246 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying %s\n", GCC_2s (cc));
247 if (NULL != cc->mq_man)
249 GCP_request_mq_cancel (cc->mq_man, NULL);
252 if (NULL != cc->task)
254 GNUNET_SCHEDULER_cancel (cc->task);
257 if (NULL != cc->keepalive_qe)
259 GCT_send_cancel (cc->keepalive_qe);
260 cc->keepalive_qe = NULL;
262 GCPP_del_connection (cc->path, cc->off, cc);
263 for (unsigned int i = 0; i < cc->off; i++)
264 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, i), cc);
267 GNUNET_CONTAINER_multishortmap_remove (connections,
269 ->connection_of_tunnel,
276 * Destroy a connection, called when the CORE layer is already done
277 * (i.e. has received a BROKEN message), but if we still have to
278 * communicate the destruction of the connection to the tunnel (if one
281 * @param cc connection to destroy
284 GCC_destroy_without_core (struct CadetConnection *cc)
288 GCT_connection_lost (cc->ct);
296 * Destroy a connection, called if the tunnel association with the
297 * connection was already broken, but we still need to notify the CORE
298 * layer about the breakage.
300 * @param cc connection to destroy
303 GCC_destroy_without_tunnel (struct CadetConnection *cc)
306 if ((CADET_CONNECTION_SENDING_CREATE != cc->state) && (NULL != cc->mq_man))
308 struct GNUNET_MQ_Envelope *env;
309 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
311 /* Need to notify next hop that we are down. */
313 GNUNET_MQ_msg (destroy_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
314 destroy_msg->cid = cc->cid;
315 GCP_request_mq_cancel (cc->mq_man, env);
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) && (NULL == cc->task))
375 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
380 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
381 * tunnel to prevent it from timing out.
383 * @param cls the `struct CadetConnection` to keep alive.
386 send_keepalive (void *cls)
388 struct CadetConnection *cc = cls;
389 struct GNUNET_MessageHeader msg;
392 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
394 /* Tunnel not yet ready, wait with keepalives... */
396 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
399 GNUNET_assert (NULL != cc->ct);
400 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
401 GNUNET_assert (NULL == cc->keepalive_qe);
402 LOG (GNUNET_ERROR_TYPE_INFO,
403 "Sending KEEPALIVE on behalf of %s via %s\n",
406 GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
407 msg.size = htons (sizeof(msg));
408 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
410 cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc, NULL);
415 * We sent a message for which we expect to receive an ACK via
416 * the connection identified by @a cti.
418 * @param cid connection identifier where we expect an ACK
421 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
423 struct CadetConnection *cc;
425 cc = GCC_lookup (cid);
427 return; /* whopise, connection alredy down? */
428 cc->metrics.num_acked_transmissions++;
433 * We observed an ACK for a message that was originally sent via
434 * the connection identified by @a cti.
436 * @param cti connection identifier where we got an ACK for a message
437 * that was originally sent via this connection (the ACK
438 * may have gotten back to us via a different connection).
441 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
443 struct CadetConnection *cc;
445 cc = GCC_lookup (cid);
447 return; /* whopise, connection alredy down? */
448 cc->metrics.num_successes++;
453 * We observed some the given @a latency on the connection
454 * identified by @a cti. (The same connection was taken
455 * in both directions.)
457 * @param cid connection identifier where we measured latency
458 * @param latency the observed latency
461 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
462 struct GNUNET_TIME_Relative latency)
464 struct CadetConnection *cc;
468 cc = GCC_lookup (cid);
470 return; /* whopise, connection alredy down? */
471 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
472 cc->latency_datapoints++;
473 if (cc->latency_datapoints >= 7)
476 weight = cc->latency_datapoints;
477 /* Compute weighted average, giving at MOST weight 7 to the
478 existing values, or less if that value is based on fewer than 7
480 result = (weight * cc->metrics.aged_latency.rel_value_us)
481 + 1.0 * latency.rel_value_us;
482 result /= (weight + 1.0);
483 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
488 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
489 * this connection, implying that the end-to-end connection is up.
492 * @param cc the connection that got the ACK.
495 GCC_handle_connection_create_ack (struct CadetConnection *cc)
497 LOG (GNUNET_ERROR_TYPE_DEBUG,
498 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
501 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
502 if (CADET_CONNECTION_READY == cc->state)
503 return; /* Duplicate ACK, ignore */
504 if (NULL != cc->task)
506 GNUNET_SCHEDULER_cancel (cc->task);
509 cc->metrics.age = GNUNET_TIME_absolute_get ();
510 update_state (cc, CADET_CONNECTION_READY, cc->mqm_ready);
511 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
514 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
521 * @param cc connection that received encrypted message
522 * @param msg the key exchange message
525 GCC_handle_kx (struct CadetConnection *cc,
526 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
528 LOG (GNUNET_ERROR_TYPE_DEBUG,
529 "Received KX message with ephermal %s on CC %s in state %d\n",
530 GNUNET_e2s (&msg->ephemeral_key),
531 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
533 if (CADET_CONNECTION_SENT == cc->state)
535 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
536 clearly something is working, so pretend we got an ACK. */
537 LOG (GNUNET_ERROR_TYPE_DEBUG,
538 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
540 GCC_handle_connection_create_ack (cc);
542 GCT_handle_kx (cc->ct, msg);
547 * Handle KX_AUTH message.
549 * @param cc connection that received encrypted message
550 * @param msg the key exchange message
553 GCC_handle_kx_auth (struct CadetConnection *cc,
554 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
556 LOG (GNUNET_ERROR_TYPE_DEBUG,
557 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
558 GNUNET_e2s (&msg->kx.ephemeral_key),
559 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
561 if (CADET_CONNECTION_SENT == cc->state)
563 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
564 clearly something is working, so pretend we got an ACK. */
565 LOG (GNUNET_ERROR_TYPE_DEBUG,
566 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
568 GCC_handle_connection_create_ack (cc);
570 GCT_handle_kx_auth (cc->ct, msg);
575 * Handle encrypted message.
577 * @param cc connection that received encrypted message
578 * @param msg the encrypted message to decrypt
581 GCC_handle_encrypted (struct CadetConnection *cc,
582 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
584 if (CADET_CONNECTION_SENT == cc->state)
586 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
587 clearly something is working, so pretend we got an ACK. */
588 LOG (GNUNET_ERROR_TYPE_DEBUG,
589 "Faking connection ACK for %s due to ENCRYPTED payload\n",
591 GCC_handle_connection_create_ack (cc);
593 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
594 GCT_handle_encrypted (cc->ct, msg);
599 * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage.
601 * @param msg The GNUNET_CADET_ConnectionCreateMessage.
604 set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
607 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
608 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
609 .purpose.size = htonl (sizeof(cp)),
610 .monotonic_time = msg->monotime};
612 GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
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;
630 struct CadetTunnel *t;
633 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
635 GNUNET_MQ_msg_extra (create_msg,
636 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
637 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
638 // 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.
639 create_msg->options = 2;
640 create_msg->cid = cc->cid;
642 // check for tunnel state and set signed monotime (xrs,t3ss)
643 t = GCP_get_tunnel (cc->destination, GNUNET_YES);
644 if ((NULL != t)&& (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
645 (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
647 create_msg->has_monotime = GNUNET_YES;
648 create_msg->monotime = GNUNET_TIME_absolute_hton (
649 GNUNET_TIME_absolute_get_monotonic (cfg));
650 set_monotime_sig (create_msg);
653 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
654 pids[0] = my_full_id;
655 for (unsigned int i = 0; i <= cc->off; i++)
656 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
657 LOG (GNUNET_ERROR_TYPE_DEBUG,
658 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
662 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
663 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
664 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
665 GCP_send (cc->mq_man, env);
670 * Send a CREATE_ACK message towards the origin.
672 * @param cls the `struct CadetConnection` to initiate
675 send_create_ack (void *cls)
677 struct CadetConnection *cc = cls;
678 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
679 struct GNUNET_MQ_Envelope *env;
682 LOG (GNUNET_ERROR_TYPE_DEBUG,
683 "Sending CONNECTION_CREATE_ACK message for %s\n",
685 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
687 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
688 ack_msg->cid = cc->cid;
690 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
691 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
692 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
693 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
694 if (CADET_CONNECTION_READY == cc->state)
696 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
697 GCP_send (cc->mq_man, env);
702 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
703 * connection that we already have. Either our ACK got lost
704 * or something is fishy. Consider retransmitting the ACK.
706 * @param cc connection that got the duplicate CREATE
709 GCC_handle_duplicate_create (struct CadetConnection *cc)
711 if (GNUNET_YES == cc->mqm_ready)
713 LOG (GNUNET_ERROR_TYPE_DEBUG,
714 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
716 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
717 /* Revert back to the state of having only received the 'CREATE',
718 and immediately proceed to send the CREATE_ACK. */
719 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
720 if (NULL != cc->task)
721 GNUNET_SCHEDULER_cancel (cc->task);
723 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
727 /* We are currently sending something else back, which
728 can only be an ACK or payload, either of which would
729 do. So actually no need to do anything. */
730 LOG (GNUNET_ERROR_TYPE_DEBUG,
731 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
738 * There has been a change in the message queue existence for our
739 * peer at the first hop. Adjust accordingly.
741 * @param cls the `struct CadetConnection`
742 * @param available #GNUNET_YES if sending is now possible,
743 * #GNUNET_NO if sending is no longer possible
744 * #GNUNET_SYSERR if sending is no longer possible
745 * and the last envelope was discarded
748 manage_first_hop_mq (void *cls, int available)
750 struct CadetConnection *cc = cls;
752 if (GNUNET_YES != available)
754 /* Connection is down, for now... */
755 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
756 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
757 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
758 if (NULL != cc->task)
760 GNUNET_SCHEDULER_cancel (cc->task);
766 update_state (cc, cc->state, GNUNET_YES);
767 LOG (GNUNET_ERROR_TYPE_DEBUG,
768 "Core MQ for %s became available in state %d\n",
773 case CADET_CONNECTION_NEW:
774 /* Transmit immediately */
775 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
778 case CADET_CONNECTION_SENDING_CREATE:
779 /* Should not be possible to be called in this state. */
783 case CADET_CONNECTION_SENT:
784 /* Retry a bit later... */
785 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
788 case CADET_CONNECTION_CREATE_RECEIVED:
789 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
790 cc->metrics.age = GNUNET_TIME_absolute_get ();
792 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
795 case CADET_CONNECTION_READY:
796 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
799 LOG (GNUNET_ERROR_TYPE_DEBUG,
800 "Scheduling keepalive for %s in %s\n",
802 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
805 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
813 * Create a connection to @a destination via @a path and notify @a cb
814 * whenever we are ready for more data. Shared logic independent of
815 * who is initiating the connection.
817 * @param destination where to go
818 * @param path which path to take (may not be the full path)
819 * @param off offset of @a destination on @a path
820 * @param ct which tunnel uses this connection
821 * @param init_state initial state for the connection
822 * @param ready_cb function to call when ready to transmit
823 * @param ready_cb_cls closure for @a cb
824 * @return handle to the connection
826 static struct CadetConnection *
827 connection_create (struct CadetPeer *destination,
828 struct CadetPeerPath *path,
830 struct CadetTConnection *ct,
831 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
832 enum CadetConnectionState init_state,
833 GCC_ReadyCallback ready_cb,
836 struct CadetConnection *cc;
837 struct CadetPeer *first_hop;
839 cc = GNUNET_new (struct CadetConnection);
840 cc->state = init_state;
842 cc->destination = destination; /* xrs,t3ss,lurchi*/
845 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
846 GNUNET_assert (GNUNET_OK ==
847 GNUNET_CONTAINER_multishortmap_put (
849 &GCC_get_id (cc)->connection_of_tunnel,
851 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
852 cc->ready_cb = ready_cb;
853 cc->ready_cb_cls = ready_cb_cls;
856 LOG (GNUNET_ERROR_TYPE_DEBUG,
857 "Creating %s using path %s (offset: %u)\n",
861 GCPP_add_connection (path, off, cc);
862 for (unsigned int i = 0; i < off; i++)
863 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
864 first_hop = GCPP_get_peer_at_offset (path, 0);
865 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
871 * Create a connection to @a destination via @a path and
872 * notify @a cb whenever we are ready for more data. This
873 * is an inbound tunnel, so we must use the existing @a cid
875 * @param destination where to go
876 * @param path which path to take (may not be the full path)
877 * @param ct which tunnel uses this connection
878 * @param ready_cb function to call when ready to transmit
879 * @param ready_cb_cls closure for @a cb
880 * @return handle to the connection, NULL if we already have
881 * a connection that takes precedence on @a path
883 struct CadetConnection *
884 GCC_create_inbound (struct CadetPeer *destination,
885 struct CadetPeerPath *path,
886 struct CadetTConnection *ct,
887 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
888 GCC_ReadyCallback ready_cb,
891 struct CadetConnection *cc;
894 off = GCPP_find_peer (path, destination);
895 GNUNET_assert (UINT_MAX != off);
896 cc = GCPP_get_connection (path, destination, off);
901 cmp = GNUNET_memcmp (cid, &cc->cid);
904 /* Two peers picked the SAME random connection identifier at the
905 same time for the same path? Must be malicious. Drop
906 connection (existing and inbound), even if it is the only
909 GCT_connection_lost (cc->ct);
910 GCC_destroy_without_tunnel (cc);
916 LOG (GNUNET_ERROR_TYPE_DEBUG,
917 "Got two connections on %s, dropping my existing %s\n",
920 GCT_connection_lost (cc->ct);
921 GCC_destroy_without_tunnel (cc);
926 LOG (GNUNET_ERROR_TYPE_DEBUG,
927 "Got two connections on %s, keeping my existing %s\n",
934 return connection_create (destination,
939 CADET_CONNECTION_CREATE_RECEIVED,
946 * Create a connection to @a destination via @a path and
947 * notify @a cb whenever we are ready for more data.
949 * @param destination where to go
950 * @param path which path to take (may not be the full path)
951 * @param off offset of @a destination on @a path
952 * @param ct tunnel that uses the connection
953 * @param ready_cb function to call when ready to transmit
954 * @param ready_cb_cls closure for @a cb
955 * @return handle to the connection
957 struct CadetConnection *
958 GCC_create (struct CadetPeer *destination,
959 struct CadetPeerPath *path,
961 struct CadetTConnection *ct,
962 GCC_ReadyCallback ready_cb,
965 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
967 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
968 return connection_create (destination,
973 CADET_CONNECTION_NEW,
980 * Transmit message @a msg via connection @a cc. Must only be called
981 * (once) after the connection has signalled that it is ready via the
982 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
983 * connection is right now ready for transmission.
985 * @param cc connection identification
986 * @param env envelope with message to transmit; must NOT
987 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
990 GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
992 LOG (GNUNET_ERROR_TYPE_DEBUG,
993 "Scheduling message for transmission on %s\n",
995 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
996 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
997 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
998 cc->mqm_ready = GNUNET_NO;
999 if (NULL != cc->task)
1001 GNUNET_SCHEDULER_cancel (cc->task);
1004 GCP_send (cc->mq_man, env);
1009 * Obtain the path used by this connection.
1011 * @param cc connection
1012 * @param off[out] set to the length of the path we use
1013 * @return path to @a cc
1015 struct CadetPeerPath *
1016 GCC_get_path (struct CadetConnection *cc, unsigned int *off)
1024 * Obtain unique ID for the connection.
1026 * @param cc connection.
1027 * @return unique number of the connection
1029 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1030 GCC_get_id (struct CadetConnection *cc)
1037 * Get a (static) string for a connection.
1039 * @param cc Connection.
1042 GCC_2s (const struct CadetConnection *cc)
1044 static char buf[128];
1047 return "Connection(NULL)";
1051 GNUNET_snprintf (buf,
1053 "Connection %s (%s)",
1054 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1055 GCT_2s (cc->ct->t));
1058 GNUNET_snprintf (buf,
1061 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1066 #define LOG2(level, ...) \
1067 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1071 * Log connection info.
1073 * @param cc connection
1074 * @param level Debug level to use.
1077 GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1079 #if ! defined(GNUNET_CULL_LOGGING)
1082 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1091 LOG2 (level, "Connection (NULL)\n");
1095 "%s to %s via path %s in state %d is %s\n",
1097 GCP_2s (cc->destination),
1100 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1105 /* end of gnunet-service-cadet_connection.c */