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 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 200)
49 * All the states a connection can be in.
51 enum CadetConnectionState
54 * Uninitialized status, we have not yet even gotten the message queue.
59 * Connection create message in queue, awaiting transmission by CORE.
61 CADET_CONNECTION_SENDING_CREATE,
64 * Connection create message sent, waiting for ACK.
66 CADET_CONNECTION_SENT,
69 * We are an inbound connection, and received a CREATE. Need to
70 * send an CREATE_ACK back.
72 CADET_CONNECTION_CREATE_RECEIVED,
75 * Connection confirmed, ready to carry traffic.
77 CADET_CONNECTION_READY
83 * Low-level connection to a destination.
85 struct CadetConnection
89 * ID of the connection.
91 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
94 * To which peer does this connection go?
96 struct CadetPeer *destination;
99 * Which tunnel is using this connection?
101 struct CadetTConnection *ct;
104 * Path we are using to our destination.
106 struct CadetPeerPath *path;
109 * Pending message, NULL if we are ready to transmit.
111 struct GNUNET_MQ_Envelope *env;
114 * Handle for calling #GCP_request_mq_cancel() once we are finished.
116 struct GCP_MessageQueueManager *mq_man;
119 * Task for connection maintenance.
121 struct GNUNET_SCHEDULER_Task *task;
124 * Queue entry for keepalive messages.
126 struct CadetTunnelQueueEntry *keepalive_qe;
129 * Function to call once we are ready to transmit.
131 GCC_ReadyCallback ready_cb;
134 * Closure for @e ready_cb.
139 * How long do we wait before we try again with a CREATE message?
141 struct GNUNET_TIME_Relative retry_delay;
144 * Earliest time for re-trying CREATE
146 struct GNUNET_TIME_Absolute create_at;
149 * Earliest time for re-trying CREATE_ACK
151 struct GNUNET_TIME_Absolute create_ack_at;
154 * Performance metrics for this connection.
156 struct CadetConnectionMetrics metrics;
159 * State of the connection.
161 enum CadetConnectionState state;
164 * Options for the route, control buffering.
166 enum GNUNET_CADET_ChannelOption options;
169 * How many latency observations did we make for this connection?
171 unsigned int latency_datapoints;
174 * Offset of our @e destination in @e path.
179 * Are we ready to transmit via @e mq_man right now?
187 * Lookup a connection by its identifier.
189 * @param cid identifier to resolve
190 * @return NULL if connection was not found
192 struct CadetConnection *
193 GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
195 return GNUNET_CONTAINER_multishortmap_get (connections,
196 &cid->connection_of_tunnel);
201 * Update the connection state. Also triggers the necessary
204 * @param cc connection to update the state for
205 * @param new_state new state for @a cc
206 * @param new_mqm_ready new `mqm_ready` state for @a cc
209 update_state (struct CadetConnection *cc,
210 enum CadetConnectionState new_state,
216 if ( (new_state == cc->state) &&
217 (new_mqm_ready == cc->mqm_ready) )
218 return; /* no change, nothing to do */
219 old_ready = ( (CADET_CONNECTION_READY == cc->state) &&
220 (GNUNET_YES == cc->mqm_ready) );
221 new_ready = ( (CADET_CONNECTION_READY == new_state) &&
222 (GNUNET_YES == new_mqm_ready) );
223 cc->state = new_state;
224 cc->mqm_ready = new_mqm_ready;
225 if (old_ready != new_ready)
226 cc->ready_cb (cc->ready_cb_cls,
232 * Destroy a connection, part of the internal implementation. Called
233 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
235 * @param cc connection to destroy
238 GCC_destroy (struct CadetConnection *cc)
240 LOG (GNUNET_ERROR_TYPE_DEBUG,
243 if (NULL != cc->mq_man)
245 GCP_request_mq_cancel (cc->mq_man,
249 if (NULL != cc->task)
251 GNUNET_SCHEDULER_cancel (cc->task);
254 if (NULL != cc->keepalive_qe)
256 GCT_send_cancel (cc->keepalive_qe);
257 cc->keepalive_qe = NULL;
259 GCPP_del_connection (cc->path,
262 for (unsigned int i=0;i<cc->off;i++)
263 GCP_remove_connection (GCPP_get_peer_at_offset (cc->path,
266 GNUNET_assert (GNUNET_YES ==
267 GNUNET_CONTAINER_multishortmap_remove (connections,
268 &GCC_get_id (cc)->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) &&
307 (NULL != cc->mq_man) )
309 struct GNUNET_MQ_Envelope *env;
310 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
312 /* Need to notify next hop that we are down. */
313 env = GNUNET_MQ_msg (destroy_msg,
314 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
315 destroy_msg->cid = cc->cid;
316 GCP_request_mq_cancel (cc->mq_man,
325 * Return the tunnel associated with this connection.
327 * @param cc connection to query
328 * @return corresponding entry in the tunnel's connection list
330 struct CadetTConnection *
331 GCC_get_ct (struct CadetConnection *cc)
338 * Obtain performance @a metrics from @a cc.
340 * @param cc connection to query
341 * @return the metrics
343 const struct CadetConnectionMetrics *
344 GCC_get_metrics (struct CadetConnection *cc)
351 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
352 * tunnel to prevent it from timing out.
354 * @param cls the `struct CadetConnection` to keep alive.
357 send_keepalive (void *cls);
361 * Keepalive was transmitted. Remember this, and possibly
362 * schedule the next one.
364 * @param cls the `struct CadetConnection` to keep alive.
365 * @param cid identifier of the connection within the tunnel, NULL
366 * if transmission failed
369 keepalive_done (void *cls,
370 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
372 struct CadetConnection *cc = cls;
374 cc->keepalive_qe = NULL;
375 if ( (GNUNET_YES == cc->mqm_ready) &&
377 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
384 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
385 * tunnel to prevent it from timing out.
387 * @param cls the `struct CadetConnection` to keep alive.
390 send_keepalive (void *cls)
392 struct CadetConnection *cc = cls;
393 struct GNUNET_MessageHeader msg;
396 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
398 /* Tunnel not yet ready, wait with keepalives... */
399 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
404 GNUNET_assert (NULL != cc->ct);
405 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
406 GNUNET_assert (NULL == cc->keepalive_qe);
407 LOG (GNUNET_ERROR_TYPE_INFO,
408 "Sending KEEPALIVE on behalf of %s via %s\n",
411 GNUNET_STATISTICS_update (stats,
415 msg.size = htons (sizeof (msg));
416 msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
419 = GCT_send (cc->ct->t,
427 * We sent a message for which we expect to receive an ACK via
428 * the connection identified by @a cti.
430 * @param cid connection identifier where we expect an ACK
433 GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
435 struct CadetConnection *cc;
437 cc = GCC_lookup (cid);
439 return; /* whopise, connection alredy down? */
440 cc->metrics.num_acked_transmissions++;
445 * We observed an ACK for a message that was originally sent via
446 * the connection identified by @a cti.
448 * @param cti connection identifier where we got an ACK for a message
449 * that was originally sent via this connection (the ACK
450 * may have gotten back to us via a different connection).
453 GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
455 struct CadetConnection *cc;
457 cc = GCC_lookup (cid);
459 return; /* whopise, connection alredy down? */
460 cc->metrics.num_successes++;
465 * We observed some the given @a latency on the connection
466 * identified by @a cti. (The same connection was taken
467 * in both directions.)
469 * @param cid connection identifier where we measured latency
470 * @param latency the observed latency
473 GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
474 struct GNUNET_TIME_Relative latency)
476 struct CadetConnection *cc;
480 cc = GCC_lookup (cid);
482 return; /* whopise, connection alredy down? */
483 GNUNET_STATISTICS_update (stats,
484 "# latencies observed",
487 cc->latency_datapoints++;
488 if (cc->latency_datapoints >= 7)
491 weight = cc->latency_datapoints;
492 /* Compute weighted average, giving at MOST weight 7 to the
493 existing values, or less if that value is based on fewer than 7
495 result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us;
496 result /= (weight + 1.0);
497 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
502 * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for
503 * this connection, implying that the end-to-end connection is up.
506 * @param cc the connection that got the ACK.
509 GCC_handle_connection_create_ack (struct CadetConnection *cc)
511 LOG (GNUNET_ERROR_TYPE_DEBUG,
512 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
515 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
516 if (CADET_CONNECTION_READY == cc->state)
517 return; /* Duplicate ACK, ignore */
518 if (NULL != cc->task)
520 GNUNET_SCHEDULER_cancel (cc->task);
523 cc->metrics.age = GNUNET_TIME_absolute_get ();
525 CADET_CONNECTION_READY,
527 if ( (NULL == cc->keepalive_qe) &&
528 (GNUNET_YES == cc->mqm_ready) &&
530 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
539 * @param cc connection that received encrypted message
540 * @param msg the key exchange message
543 GCC_handle_kx (struct CadetConnection *cc,
544 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
546 LOG (GNUNET_ERROR_TYPE_DEBUG,
547 "Received KX message with ephermal %s on CC %s in state %d\n",
548 GNUNET_e2s (&msg->ephemeral_key),
549 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
551 if (CADET_CONNECTION_SENT == cc->state)
553 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
554 clearly something is working, so pretend we got an ACK. */
555 LOG (GNUNET_ERROR_TYPE_DEBUG,
556 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
558 GCC_handle_connection_create_ack (cc);
560 GCT_handle_kx (cc->ct,
566 * Handle KX_AUTH message.
568 * @param cc connection that received encrypted message
569 * @param msg the key exchange message
572 GCC_handle_kx_auth (struct CadetConnection *cc,
573 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
575 LOG (GNUNET_ERROR_TYPE_DEBUG,
576 "Received KX AUTH message with ephermal %s on CC %s in state %d\n",
577 GNUNET_e2s (&msg->kx.ephemeral_key),
578 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
580 if (CADET_CONNECTION_SENT == cc->state)
582 /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
583 clearly something is working, so pretend we got an ACK. */
584 LOG (GNUNET_ERROR_TYPE_DEBUG,
585 "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
587 GCC_handle_connection_create_ack (cc);
589 GCT_handle_kx_auth (cc->ct,
595 * Handle encrypted message.
597 * @param cc connection that received encrypted message
598 * @param msg the encrypted message to decrypt
601 GCC_handle_encrypted (struct CadetConnection *cc,
602 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
604 if (CADET_CONNECTION_SENT == cc->state)
606 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
607 clearly something is working, so pretend we got an ACK. */
608 LOG (GNUNET_ERROR_TYPE_DEBUG,
609 "Faking connection ACK for %s due to ENCRYPTED payload\n",
611 GCC_handle_connection_create_ack (cc);
613 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
614 GCT_handle_encrypted (cc->ct,
620 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
623 * @param cls the `struct CadetConnection` to initiate
626 send_create (void *cls)
628 struct CadetConnection *cc = cls;
629 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
630 struct GNUNET_PeerIdentity *pids;
631 struct GNUNET_MQ_Envelope *env;
634 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
635 env = GNUNET_MQ_msg_extra (create_msg,
636 (2 + cc->off) * sizeof (struct GNUNET_PeerIdentity),
637 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
638 create_msg->options = htonl ((uint32_t) cc->options);
639 create_msg->cid = cc->cid;
640 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
641 pids[0] = my_full_id;
642 for (unsigned int i=0;i<=cc->off;i++)
643 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
650 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
651 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
653 CADET_CONNECTION_SENT,
655 GCP_send (cc->mq_man,
661 * Send a CREATE_ACK message towards the origin.
663 * @param cls the `struct CadetConnection` to initiate
666 send_create_ack (void *cls)
668 struct CadetConnection *cc = cls;
669 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
670 struct GNUNET_MQ_Envelope *env;
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Sending CONNECTION_CREATE_ACK message for %s\n",
676 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
677 env = GNUNET_MQ_msg (ack_msg,
678 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
679 ack_msg->cid = cc->cid;
681 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
682 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
683 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
685 CADET_CONNECTION_READY,
687 if (CADET_CONNECTION_READY == cc->state)
688 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
691 GCP_send (cc->mq_man,
697 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
698 * connection that we already have. Either our ACK got lost
699 * or something is fishy. Consider retransmitting the ACK.
701 * @param cc connection that got the duplicate CREATE
704 GCC_handle_duplicate_create (struct CadetConnection *cc)
706 if (GNUNET_YES == cc->mqm_ready)
708 LOG (GNUNET_ERROR_TYPE_DEBUG,
709 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
711 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
712 /* Revert back to the state of having only received the 'CREATE',
713 and immediately proceed to send the CREATE_ACK. */
715 CADET_CONNECTION_CREATE_RECEIVED,
717 if (NULL != cc->task)
718 GNUNET_SCHEDULER_cancel (cc->task);
719 cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at,
725 /* We are currently sending something else back, which
726 can only be an ACK or payload, either of which would
727 do. So actually no need to do anything. */
728 LOG (GNUNET_ERROR_TYPE_DEBUG,
729 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
736 * There has been a change in the message queue existence for our
737 * peer at the first hop. Adjust accordingly.
739 * @param cls the `struct CadetConnection`
740 * @param available #GNUNET_YES if sending is now possible,
741 * #GNUNET_NO if sending is no longer possible
742 * #GNUNET_SYSERR if sending is no longer possible
743 * and the last envelope was discarded
746 manage_first_hop_mq (void *cls,
749 struct CadetConnection *cc = cls;
751 if (GNUNET_YES != available)
753 /* Connection is down, for now... */
754 LOG (GNUNET_ERROR_TYPE_DEBUG,
755 "Core MQ for %s went down\n",
758 CADET_CONNECTION_NEW,
760 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
761 if (NULL != cc->task)
763 GNUNET_SCHEDULER_cancel (cc->task);
772 LOG (GNUNET_ERROR_TYPE_DEBUG,
773 "Core MQ for %s became available in state %d\n",
778 case CADET_CONNECTION_NEW:
779 /* Transmit immediately */
780 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at,
784 case CADET_CONNECTION_SENDING_CREATE:
785 /* Should not be possible to be called in this state. */
788 case CADET_CONNECTION_SENT:
789 /* Retry a bit later... */
790 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at,
794 case CADET_CONNECTION_CREATE_RECEIVED:
795 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
796 cc->metrics.age = GNUNET_TIME_absolute_get ();
797 cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at,
801 case CADET_CONNECTION_READY:
802 if ( (NULL == cc->keepalive_qe) &&
803 (GNUNET_YES == cc->mqm_ready) &&
806 LOG (GNUNET_ERROR_TYPE_DEBUG,
807 "Scheduling keepalive for %s in %s\n",
809 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
811 cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
821 * Create a connection to @a destination via @a path and notify @a cb
822 * whenever we are ready for more data. Shared logic independent of
823 * who is initiating the connection.
825 * @param destination where to go
826 * @param path which path to take (may not be the full path)
827 * @param off offset of @a destination on @a path
828 * @param options options for the connection
829 * @param ct which tunnel uses this connection
830 * @param init_state initial state for the connection
831 * @param ready_cb function to call when ready to transmit
832 * @param ready_cb_cls closure for @a cb
833 * @return handle to the connection
835 static struct CadetConnection *
836 connection_create (struct CadetPeer *destination,
837 struct CadetPeerPath *path,
839 enum GNUNET_CADET_ChannelOption options,
840 struct CadetTConnection *ct,
841 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
842 enum CadetConnectionState init_state,
843 GCC_ReadyCallback ready_cb,
846 struct CadetConnection *cc;
847 struct CadetPeer *first_hop;
849 cc = GNUNET_new (struct CadetConnection);
850 cc->options = options;
851 cc->state = init_state;
854 cc->retry_delay = GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY,
856 GNUNET_assert (GNUNET_OK ==
857 GNUNET_CONTAINER_multishortmap_put (connections,
858 &GCC_get_id (cc)->connection_of_tunnel,
860 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
861 cc->ready_cb = ready_cb;
862 cc->ready_cb_cls = ready_cb_cls;
865 LOG (GNUNET_ERROR_TYPE_DEBUG,
866 "Creating %s using path %s (offset: %u)\n",
870 GCPP_add_connection (path,
873 for (unsigned int i=0;i<off;i++)
874 GCP_add_connection (GCPP_get_peer_at_offset (path,
877 first_hop = GCPP_get_peer_at_offset (path,
879 cc->mq_man = GCP_request_mq (first_hop,
880 &manage_first_hop_mq,
887 * Create a connection to @a destination via @a path and
888 * notify @a cb whenever we are ready for more data. This
889 * is an inbound tunnel, so we must use the existing @a cid
891 * @param destination where to go
892 * @param path which path to take (may not be the full path)
893 * @param options options for the connection
894 * @param ct which tunnel uses this connection
895 * @param ready_cb function to call when ready to transmit
896 * @param ready_cb_cls closure for @a cb
897 * @return handle to the connection, NULL if we already have
898 * a connection that takes precedence on @a path
900 struct CadetConnection *
901 GCC_create_inbound (struct CadetPeer *destination,
902 struct CadetPeerPath *path,
903 enum GNUNET_CADET_ChannelOption options,
904 struct CadetTConnection *ct,
905 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
906 GCC_ReadyCallback ready_cb,
909 struct CadetConnection *cc;
912 off = GCPP_find_peer (path,
914 GNUNET_assert (UINT_MAX != off);
915 cc = GCPP_get_connection (path,
927 /* Two peers picked the SAME random connection identifier at the
928 same time for the same path? Must be malicious. Drop
929 connection (existing and inbound), even if it is the only
932 GCT_connection_lost (cc->ct);
933 GCC_destroy_without_tunnel (cc);
939 LOG (GNUNET_ERROR_TYPE_DEBUG,
940 "Got two connections on %s, dropping my existing %s\n",
943 GCT_connection_lost (cc->ct);
944 GCC_destroy_without_tunnel (cc);
949 LOG (GNUNET_ERROR_TYPE_DEBUG,
950 "Got two connections on %s, keeping my existing %s\n",
957 return connection_create (destination,
963 CADET_CONNECTION_CREATE_RECEIVED,
970 * Create a connection to @a destination via @a path and
971 * notify @a cb whenever we are ready for more data.
973 * @param destination where to go
974 * @param path which path to take (may not be the full path)
975 * @param off offset of @a destination on @a path
976 * @param options options for the connection
977 * @param ct tunnel that uses the connection
978 * @param ready_cb function to call when ready to transmit
979 * @param ready_cb_cls closure for @a cb
980 * @return handle to the connection
982 struct CadetConnection *
983 GCC_create (struct CadetPeer *destination,
984 struct CadetPeerPath *path,
986 enum GNUNET_CADET_ChannelOption options,
987 struct CadetTConnection *ct,
988 GCC_ReadyCallback ready_cb,
991 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
993 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
996 return connection_create (destination,
1002 CADET_CONNECTION_NEW,
1009 * Transmit message @a msg via connection @a cc. Must only be called
1010 * (once) after the connection has signalled that it is ready via the
1011 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
1012 * connection is right now ready for transmission.
1014 * @param cc connection identification
1015 * @param env envelope with message to transmit; must NOT
1016 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
1019 GCC_transmit (struct CadetConnection *cc,
1020 struct GNUNET_MQ_Envelope *env)
1022 LOG (GNUNET_ERROR_TYPE_DEBUG,
1023 "Scheduling message for transmission on %s\n",
1025 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
1026 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
1027 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
1028 cc->mqm_ready = GNUNET_NO;
1029 if (NULL != cc->task)
1031 GNUNET_SCHEDULER_cancel (cc->task);
1034 GCP_send (cc->mq_man,
1040 * Obtain the path used by this connection.
1042 * @param cc connection
1043 * @param off[out] set to the length of the path we use
1044 * @return path to @a cc
1046 struct CadetPeerPath *
1047 GCC_get_path (struct CadetConnection *cc,
1056 * Obtain unique ID for the connection.
1058 * @param cc connection.
1059 * @return unique number of the connection
1061 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1062 GCC_get_id (struct CadetConnection *cc)
1069 * Get a (static) string for a connection.
1071 * @param cc Connection.
1074 GCC_2s (const struct CadetConnection *cc)
1076 static char buf[128];
1079 return "Connection(NULL)";
1083 GNUNET_snprintf (buf,
1085 "Connection %s (%s)",
1086 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1087 GCT_2s (cc->ct->t));
1090 GNUNET_snprintf (buf,
1093 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1098 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
1102 * Log connection info.
1104 * @param cc connection
1105 * @param level Debug level to use.
1108 GCC_debug (struct CadetConnection *cc,
1109 enum GNUNET_ErrorType level)
1111 #if !defined(GNUNET_CULL_LOGGING)
1114 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1116 __FILE__, __FUNCTION__, __LINE__);
1122 "Connection (NULL)\n");
1126 "%s to %s via path %s in state %d is %s\n",
1128 GCP_2s (cc->destination),
1131 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1135 /* end of gnunet-service-cadet_connection.c */