aboutsummaryrefslogtreecommitdiff
path: root/src/service/cadet/gnunet-service-cadet_connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/cadet/gnunet-service-cadet_connection.c')
-rw-r--r--src/service/cadet/gnunet-service-cadet_connection.c1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/src/service/cadet/gnunet-service-cadet_connection.c b/src/service/cadet/gnunet-service-cadet_connection.c
new file mode 100644
index 000000000..f01c1388e
--- /dev/null
+++ b/src/service/cadet/gnunet-service-cadet_connection.c
@@ -0,0 +1,1079 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
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
27 */
28#include "platform.h"
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"
37
38
39#define LOG(level, ...) GNUNET_log_from (level, "cadet-con", __VA_ARGS__)
40
41
42/**
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!
45 */
46#define INITIAL_CONNECTION_CREATE_RETRY_DELAY \
47 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200)
48
49
50/**
51 * All the states a connection can be in.
52 */
53enum CadetConnectionState
54{
55 /**
56 * Uninitialized status, we have not yet even gotten the message queue.
57 */
58 CADET_CONNECTION_NEW,
59
60 /**
61 * Connection create message in queue, awaiting transmission by CORE.
62 */
63 CADET_CONNECTION_SENDING_CREATE,
64
65 /**
66 * Connection create message sent, waiting for ACK.
67 */
68 CADET_CONNECTION_SENT,
69
70 /**
71 * We are an inbound connection, and received a CREATE. Need to
72 * send an CREATE_ACK back.
73 */
74 CADET_CONNECTION_CREATE_RECEIVED,
75
76 /**
77 * Connection confirmed, ready to carry traffic.
78 */
79 CADET_CONNECTION_READY
80};
81
82/**
83 * Low-level connection to a destination.
84 */
85struct CadetConnection
86{
87 /**
88 * ID of the connection.
89 */
90 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
91
92 /**
93 * To which peer does this connection go?
94 */
95 struct CadetPeer *destination;
96
97 /**
98 * Which tunnel is using this connection?
99 */
100 struct CadetTConnection *ct;
101
102 /**
103 * Path we are using to our destination.
104 */
105 struct CadetPeerPath *path;
106
107 /**
108 * Pending message, NULL if we are ready to transmit.
109 */
110 struct GNUNET_MQ_Envelope *env;
111
112 /**
113 * Handle for calling #GCP_request_mq_cancel() once we are finished.
114 */
115 struct GCP_MessageQueueManager *mq_man;
116
117 /**
118 * Task for connection maintenance.
119 */
120 struct GNUNET_SCHEDULER_Task *task;
121
122 /**
123 * Queue entry for keepalive messages.
124 */
125 struct CadetTunnelQueueEntry *keepalive_qe;
126
127 /**
128 * Function to call once we are ready to transmit.
129 */
130 GCC_ReadyCallback ready_cb;
131
132 /**
133 * Closure for @e ready_cb.
134 */
135 void *ready_cb_cls;
136
137 /**
138 * How long do we wait before we try again with a CREATE message?
139 */
140 struct GNUNET_TIME_Relative retry_delay;
141
142 /**
143 * Earliest time for re-trying CREATE
144 */
145 struct GNUNET_TIME_Absolute create_at;
146
147 /**
148 * Earliest time for re-trying CREATE_ACK
149 */
150 struct GNUNET_TIME_Absolute create_ack_at;
151
152 /**
153 * Performance metrics for this connection.
154 */
155 struct CadetConnectionMetrics metrics;
156
157 /**
158 * State of the connection.
159 */
160 enum CadetConnectionState state;
161
162 /**
163 * How many latency observations did we make for this connection?
164 */
165 unsigned int latency_datapoints;
166
167 /**
168 * Offset of our @e destination in @e path.
169 */
170 unsigned int off;
171
172 /**
173 * Are we ready to transmit via @e mq_man right now?
174 */
175 int mqm_ready;
176};
177
178
179/**
180 * Lookup a connection by its identifier.
181 *
182 * @param cid identifier to resolve
183 * @return NULL if connection was not found
184 */
185struct CadetConnection *
186GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
187{
188 return GNUNET_CONTAINER_multishortmap_get (connections,
189 &cid->connection_of_tunnel);
190}
191
192
193/**
194 * Update the connection state. Also triggers the necessary
195 * MQM notifications.
196 *
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
200 */
201static void
202update_state (struct CadetConnection *cc,
203 enum CadetConnectionState new_state,
204 int new_mqm_ready)
205{
206 int old_ready;
207 int new_ready;
208
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",
211 GCT_2s (cc->ct->t),
212 cc->state,
213 new_state,
214 cc->mqm_ready,
215 new_mqm_ready);
216
217 if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
218 return; /* no change, nothing to do */
219 old_ready =
220 ((CADET_CONNECTION_READY == cc->state) && (GNUNET_YES == cc->mqm_ready));
221 new_ready =
222 ((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
223 cc->state = new_state;
224 cc->mqm_ready = new_mqm_ready;
225
226 LOG (GNUNET_ERROR_TYPE_DEBUG,
227 "Updating connection state for %s having old_ready %d and new_rady %d\n",
228 GCT_2s (cc->ct->t),
229 old_ready,
230 new_ready);
231
232 if (old_ready != new_ready)
233 cc->ready_cb (cc->ready_cb_cls, new_ready);
234}
235
236
237/**
238 * Destroy a connection, part of the internal implementation. Called
239 * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel().
240 *
241 * @param cc connection to destroy
242 */
243static void
244GCC_destroy (struct CadetConnection *cc)
245{
246 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying %s\n", GCC_2s (cc));
247 if (NULL != cc->mq_man)
248 {
249 GCP_request_mq_cancel (cc->mq_man, NULL);
250 cc->mq_man = NULL;
251 }
252 if (NULL != cc->task)
253 {
254 GNUNET_SCHEDULER_cancel (cc->task);
255 cc->task = NULL;
256 }
257 if (NULL != cc->keepalive_qe)
258 {
259 GCT_send_cancel (cc->keepalive_qe);
260 cc->keepalive_qe = NULL;
261 }
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);
265 GNUNET_assert (
266 GNUNET_YES ==
267 GNUNET_CONTAINER_multishortmap_remove (connections,
268 &GCC_get_id (cc)
269 ->connection_of_tunnel,
270 cc));
271 GNUNET_free (cc);
272}
273
274
275/**
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
279 * exists).
280 *
281 * @param cc connection to destroy
282 */
283void
284GCC_destroy_without_core (struct CadetConnection *cc)
285{
286 if (NULL != cc->ct)
287 {
288 GCT_connection_lost (cc->ct);
289 cc->ct = NULL;
290 }
291 GCC_destroy (cc);
292}
293
294
295/**
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.
299 *
300 * @param cc connection to destroy
301 */
302void
303GCC_destroy_without_tunnel (struct CadetConnection *cc)
304{
305 cc->ct = NULL;
306 if ((CADET_CONNECTION_SENDING_CREATE != cc->state) && (NULL != cc->mq_man))
307 {
308 struct GNUNET_MQ_Envelope *env;
309 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
310
311 /* Need to notify next hop that we are down. */
312 env =
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);
316 cc->mq_man = NULL;
317 }
318 GCC_destroy (cc);
319}
320
321
322/**
323 * Return the tunnel associated with this connection.
324 *
325 * @param cc connection to query
326 * @return corresponding entry in the tunnel's connection list
327 */
328struct CadetTConnection *
329GCC_get_ct (struct CadetConnection *cc)
330{
331 return cc->ct;
332}
333
334
335/**
336 * Obtain performance @a metrics from @a cc.
337 *
338 * @param cc connection to query
339 * @return the metrics
340 */
341const struct CadetConnectionMetrics *
342GCC_get_metrics (struct CadetConnection *cc)
343{
344 return &cc->metrics;
345}
346
347
348/**
349 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
350 * tunnel to prevent it from timing out.
351 *
352 * @param cls the `struct CadetConnection` to keep alive.
353 */
354static void
355send_keepalive (void *cls);
356
357
358/**
359 * Keepalive was transmitted. Remember this, and possibly
360 * schedule the next one.
361 *
362 * @param cls the `struct CadetConnection` to keep alive.
363 * @param cid identifier of the connection within the tunnel, NULL
364 * if transmission failed
365 */
366static void
367keepalive_done (void *cls,
368 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
369{
370 struct CadetConnection *cc = cls;
371
372 cc->keepalive_qe = NULL;
373 if ((GNUNET_YES == cc->mqm_ready) && (NULL == cc->task))
374 cc->task =
375 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
376}
377
378
379/**
380 * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
381 * tunnel to prevent it from timing out.
382 *
383 * @param cls the `struct CadetConnection` to keep alive.
384 */
385static void
386send_keepalive (void *cls)
387{
388 struct CadetConnection *cc = cls;
389 struct GNUNET_MessageHeader msg;
390
391 cc->task = NULL;
392 if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t))
393 {
394 /* Tunnel not yet ready, wait with keepalives... */
395 cc->task =
396 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
397 return;
398 }
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",
404 GCC_2s (cc),
405 GCT_2s (cc->ct->t));
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);
409
410 cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc, NULL);
411}
412
413
414/**
415 * We sent a message for which we expect to receive an ACK via
416 * the connection identified by @a cti.
417 *
418 * @param cid connection identifier where we expect an ACK
419 */
420void
421GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
422{
423 struct CadetConnection *cc;
424
425 cc = GCC_lookup (cid);
426 if (NULL == cc)
427 return; /* whopise, connection already down? */
428 cc->metrics.num_acked_transmissions++;
429}
430
431
432/**
433 * We observed an ACK for a message that was originally sent via
434 * the connection identified by @a cid.
435 *
436 * @param cid 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).
439 */
440void
441GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
442{
443 struct CadetConnection *cc;
444
445 cc = GCC_lookup (cid);
446 if (NULL == cc)
447 return; /* whopise, connection already down? */
448 cc->metrics.num_successes++;
449}
450
451
452void
453GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
454 struct GNUNET_TIME_Relative latency)
455{
456 struct CadetConnection *cc;
457 double weight;
458 double result;
459
460 cc = GCC_lookup (cid);
461 if (NULL == cc)
462 return; /* whopise, connection already down? */
463 GNUNET_STATISTICS_update (stats, "# latencies observed", 1, GNUNET_NO);
464 cc->latency_datapoints++;
465 if (cc->latency_datapoints >= 7)
466 weight = 7.0;
467 else
468 weight = cc->latency_datapoints;
469 /* Compute weighted average, giving at MOST weight 7 to the
470 existing values, or less if that value is based on fewer than 7
471 measurements. */
472 result = (weight * cc->metrics.aged_latency.rel_value_us)
473 + 1.0 * latency.rel_value_us;
474 result /= (weight + 1.0);
475 cc->metrics.aged_latency.rel_value_us = (uint64_t) result;
476}
477
478
479void
480GCC_handle_connection_create_ack (struct CadetConnection *cc)
481{
482 LOG (GNUNET_ERROR_TYPE_DEBUG,
483 "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
484 GCC_2s (cc),
485 cc->state,
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)
490 {
491 GNUNET_SCHEDULER_cancel (cc->task);
492 cc->task = NULL;
493 }
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) &&
497 (NULL == cc->task))
498 cc->task =
499 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
500}
501
502
503/**
504 * Handle KX message.
505 *
506 * @param cc connection that received encrypted message
507 * @param msg the key exchange message
508 */
509void
510GCC_handle_kx (struct CadetConnection *cc,
511 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
512{
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),
517 cc->state);
518 if (CADET_CONNECTION_SENT == cc->state)
519 {
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",
524 GCC_2s (cc));
525 GCC_handle_connection_create_ack (cc);
526 }
527 GCT_handle_kx (cc->ct, msg);
528}
529
530
531/**
532 * Handle KX_AUTH message.
533 *
534 * @param cc connection that received encrypted message
535 * @param msg the key exchange message
536 */
537void
538GCC_handle_kx_auth (struct CadetConnection *cc,
539 const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg)
540{
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),
545 cc->state);
546 if (CADET_CONNECTION_SENT == cc->state)
547 {
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",
552 GCC_2s (cc));
553 GCC_handle_connection_create_ack (cc);
554 }
555 GCT_handle_kx_auth (cc->ct, msg);
556}
557
558
559/**
560 * Handle encrypted message.
561 *
562 * @param cc connection that received encrypted message
563 * @param msg the encrypted message to decrypt
564 */
565void
566GCC_handle_encrypted (struct CadetConnection *cc,
567 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
568{
569 if (CADET_CONNECTION_SENT == cc->state)
570 {
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",
575 GCC_2s (cc));
576 GCC_handle_connection_create_ack (cc);
577 }
578 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
579 GCT_handle_encrypted (cc->ct, msg);
580}
581
582
583/**
584 * Set the signature for a monotime value on a GNUNET_CADET_ConnectionCreateMessage.
585 *
586 * @param msg The GNUNET_CADET_ConnectionCreateMessage.
587 */
588void
589set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
590{
591
592 struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
593 GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
594 .purpose.size = htonl (sizeof(cp)),
595 .monotonic_time = msg->monotime};
596
597 GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
598 &msg->monotime_sig);
599
600}
601
602
603/**
604 * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
605 * first hop.
606 *
607 * @param cls the `struct CadetConnection` to initiate
608 */
609static void
610send_create (void *cls)
611{
612 struct CadetConnection *cc = cls;
613 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
614 struct GNUNET_PeerIdentity *pids;
615 struct GNUNET_MQ_Envelope *env;
616 struct CadetTunnel *t;
617
618 cc->task = NULL;
619 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
620 env =
621 GNUNET_MQ_msg_extra (create_msg,
622 (2 + cc->off) * sizeof(struct GNUNET_PeerIdentity),
623 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
624 // 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.
625 create_msg->options = 2;
626 create_msg->cid = cc->cid;
627
628 // check for tunnel state and set signed monotime (xrs,t3ss)
629 t = GCP_get_tunnel (cc->destination, GNUNET_YES);
630 if ((NULL != t) && (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
631 (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
632 {
633 create_msg->has_monotime = GNUNET_YES;
634 create_msg->monotime = GNUNET_TIME_absolute_hton (
635 GNUNET_TIME_absolute_get_monotonic (cfg));
636 set_monotime_sig (create_msg);
637 }
638
639 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
640 pids[0] = my_full_id;
641 for (unsigned int i = 0; i <= cc->off; i++)
642 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, i));
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n",
645 GCC_2s (cc),
646 cc->off + 2);
647 cc->env = env;
648 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
649 cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
650 update_state (cc, CADET_CONNECTION_SENT, GNUNET_NO);
651 GCP_send (cc->mq_man, env);
652}
653
654
655/**
656 * Send a CREATE_ACK message towards the origin.
657 *
658 * @param cls the `struct CadetConnection` to initiate
659 */
660static void
661send_create_ack (void *cls)
662{
663 struct CadetConnection *cc = cls;
664 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
665 struct GNUNET_MQ_Envelope *env;
666
667 cc->task = NULL;
668 LOG (GNUNET_ERROR_TYPE_DEBUG,
669 "Sending CONNECTION_CREATE_ACK message for %s\n",
670 GCC_2s (cc));
671 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
672 env =
673 GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
674 ack_msg->cid = cc->cid;
675 cc->env = env;
676 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
677 cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay);
678 if (CADET_CONNECTION_CREATE_RECEIVED == cc->state)
679 update_state (cc, CADET_CONNECTION_READY, GNUNET_NO);
680 if (CADET_CONNECTION_READY == cc->state)
681 cc->task =
682 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
683 GCP_send (cc->mq_man, env);
684}
685
686
687/**
688 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
689 * connection that we already have. Either our ACK got lost
690 * or something is fishy. Consider retransmitting the ACK.
691 *
692 * @param cc connection that got the duplicate CREATE
693 */
694void
695GCC_handle_duplicate_create (struct CadetConnection *cc)
696{
697 if (GNUNET_YES == cc->mqm_ready)
698 {
699 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
701 GCC_2s (cc),
702 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
703 /* Revert back to the state of having only received the 'CREATE',
704 and immediately proceed to send the CREATE_ACK. */
705 update_state (cc, CADET_CONNECTION_CREATE_RECEIVED, cc->mqm_ready);
706 if (NULL != cc->task)
707 GNUNET_SCHEDULER_cancel (cc->task);
708 cc->task =
709 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
710 }
711 else
712 {
713 /* We are currently sending something else back, which
714 can only be an ACK or payload, either of which would
715 do. So actually no need to do anything. */
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
718 GCC_2s (cc));
719 }
720}
721
722
723/**
724 * There has been a change in the message queue existence for our
725 * peer at the first hop. Adjust accordingly.
726 *
727 * @param cls the `struct CadetConnection`
728 * @param available #GNUNET_YES if sending is now possible,
729 * #GNUNET_NO if sending is no longer possible
730 * #GNUNET_SYSERR if sending is no longer possible
731 * and the last envelope was discarded
732 */
733static void
734manage_first_hop_mq (void *cls, int available)
735{
736 struct CadetConnection *cc = cls;
737
738 if (GNUNET_YES != available)
739 {
740 /* Connection is down, for now... */
741 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core MQ for %s went down\n", GCC_2s (cc));
742 update_state (cc, CADET_CONNECTION_NEW, GNUNET_NO);
743 cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY;
744 if (NULL != cc->task)
745 {
746 GNUNET_SCHEDULER_cancel (cc->task);
747 cc->task = NULL;
748 }
749 return;
750 }
751
752 update_state (cc, cc->state, GNUNET_YES);
753 LOG (GNUNET_ERROR_TYPE_DEBUG,
754 "Core MQ for %s became available in state %d\n",
755 GCC_2s (cc),
756 cc->state);
757 switch (cc->state)
758 {
759 case CADET_CONNECTION_NEW:
760 /* Transmit immediately */
761 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
762 break;
763
764 case CADET_CONNECTION_SENDING_CREATE:
765 /* Should not be possible to be called in this state. */
766 GNUNET_assert (0);
767 break;
768
769 case CADET_CONNECTION_SENT:
770 /* Retry a bit later... */
771 cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, &send_create, cc);
772 break;
773
774 case CADET_CONNECTION_CREATE_RECEIVED:
775 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
776 cc->metrics.age = GNUNET_TIME_absolute_get ();
777 cc->task =
778 GNUNET_SCHEDULER_add_at (cc->create_ack_at, &send_create_ack, cc);
779 break;
780
781 case CADET_CONNECTION_READY:
782 if ((NULL == cc->keepalive_qe) && (GNUNET_YES == cc->mqm_ready) &&
783 (NULL == cc->task))
784 {
785 LOG (GNUNET_ERROR_TYPE_DEBUG,
786 "Scheduling keepalive for %s in %s\n",
787 GCC_2s (cc),
788 GNUNET_STRINGS_relative_time_to_string (keepalive_period,
789 GNUNET_YES));
790 cc->task =
791 GNUNET_SCHEDULER_add_delayed (keepalive_period, &send_keepalive, cc);
792 }
793 break;
794 }
795}
796
797
798/**
799 * Create a connection to @a destination via @a path and notify @a cb
800 * whenever we are ready for more data. Shared logic independent of
801 * who is initiating the connection.
802 *
803 * @param destination where to go
804 * @param path which path to take (may not be the full path)
805 * @param off offset of @a destination on @a path
806 * @param ct which tunnel uses this connection
807 * @param init_state initial state for the connection
808 * @param ready_cb function to call when ready to transmit
809 * @param ready_cb_cls closure for @a cb
810 * @return handle to the connection
811 */
812static struct CadetConnection *
813connection_create (struct CadetPeer *destination,
814 struct CadetPeerPath *path,
815 unsigned int off,
816 struct CadetTConnection *ct,
817 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
818 enum CadetConnectionState init_state,
819 GCC_ReadyCallback ready_cb,
820 void *ready_cb_cls)
821{
822 struct CadetConnection *cc;
823 struct CadetPeer *first_hop;
824
825 cc = GNUNET_new (struct CadetConnection);
826 cc->state = init_state;
827 cc->ct = ct;
828 cc->destination = destination; /* xrs,t3ss,lurchi*/
829 cc->cid = *cid;
830 cc->retry_delay =
831 GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
832 GNUNET_assert (GNUNET_OK ==
833 GNUNET_CONTAINER_multishortmap_put (
834 connections,
835 &GCC_get_id (cc)->connection_of_tunnel,
836 cc,
837 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
838 cc->ready_cb = ready_cb;
839 cc->ready_cb_cls = ready_cb_cls;
840 cc->path = path;
841 cc->off = off;
842 LOG (GNUNET_ERROR_TYPE_DEBUG,
843 "Creating %s using path %s (offset: %u)\n",
844 GCC_2s (cc),
845 GCPP_2s (path),
846 off);
847 GCPP_add_connection (path, off, cc);
848 for (unsigned int i = 0; i < off; i++)
849 GCP_add_connection (GCPP_get_peer_at_offset (path, i), cc);
850 first_hop = GCPP_get_peer_at_offset (path, 0);
851 cc->mq_man = GCP_request_mq (first_hop, &manage_first_hop_mq, cc);
852 return cc;
853}
854
855
856/**
857 * Create a connection to @a destination via @a path and
858 * notify @a cb whenever we are ready for more data. This
859 * is an inbound tunnel, so we must use the existing @a cid
860 *
861 * @param destination where to go
862 * @param path which path to take (may not be the full path)
863 * @param ct which tunnel uses this connection
864 * @param ready_cb function to call when ready to transmit
865 * @param ready_cb_cls closure for @a cb
866 * @return handle to the connection, NULL if we already have
867 * a connection that takes precedence on @a path
868 */
869struct CadetConnection *
870GCC_create_inbound (struct CadetPeer *destination,
871 struct CadetPeerPath *path,
872 struct CadetTConnection *ct,
873 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
874 GCC_ReadyCallback ready_cb,
875 void *ready_cb_cls)
876{
877 struct CadetConnection *cc;
878 unsigned int off;
879
880 off = GCPP_find_peer (path, destination);
881 GNUNET_assert (UINT_MAX != off);
882 cc = GCPP_get_connection (path, destination, off);
883 if (NULL != cc)
884 {
885 int cmp;
886
887 cmp = GNUNET_memcmp (cid, &cc->cid);
888 if (0 == cmp)
889 {
890 /* Two peers picked the SAME random connection identifier at the
891 same time for the same path? Must be malicious. Drop
892 connection (existing and inbound), even if it is the only
893 one. */
894 GNUNET_break_op (0);
895 GCT_connection_lost (cc->ct);
896 GCC_destroy_without_tunnel (cc);
897 return NULL;
898 }
899 if (0 < cmp)
900 {
901 /* drop existing */
902 LOG (GNUNET_ERROR_TYPE_DEBUG,
903 "Got two connections on %s, dropping my existing %s\n",
904 GCPP_2s (path),
905 GCC_2s (cc));
906 GCT_connection_lost (cc->ct);
907 GCC_destroy_without_tunnel (cc);
908 }
909 else
910 {
911 /* keep existing */
912 LOG (GNUNET_ERROR_TYPE_DEBUG,
913 "Got two connections on %s, keeping my existing %s\n",
914 GCPP_2s (path),
915 GCC_2s (cc));
916 return NULL;
917 }
918 }
919
920 return connection_create (destination,
921 path,
922 off,
923 ct,
924 cid,
925 CADET_CONNECTION_CREATE_RECEIVED,
926 ready_cb,
927 ready_cb_cls);
928}
929
930
931struct CadetConnection *
932GCC_create (struct CadetPeer *destination,
933 struct CadetPeerPath *path,
934 unsigned int off,
935 struct CadetTConnection *ct,
936 GCC_ReadyCallback ready_cb,
937 void *ready_cb_cls)
938{
939 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
940
941 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof(cid));
942 return connection_create (destination,
943 path,
944 off,
945 ct,
946 &cid,
947 CADET_CONNECTION_NEW,
948 ready_cb,
949 ready_cb_cls);
950}
951
952
953/**
954 * Transmit message @a msg via connection @a cc. Must only be called
955 * (once) after the connection has signalled that it is ready via the
956 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
957 * connection is right now ready for transmission.
958 *
959 * @param cc connection identification
960 * @param env envelope with message to transmit; must NOT
961 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
962 */
963void
964GCC_transmit (struct CadetConnection *cc, struct GNUNET_MQ_Envelope *env)
965{
966 LOG (GNUNET_ERROR_TYPE_DEBUG,
967 "Scheduling message for transmission on %s\n",
968 GCC_2s (cc));
969 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
970 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
971 cc->metrics.last_use = GNUNET_TIME_absolute_get ();
972 cc->mqm_ready = GNUNET_NO;
973 if (NULL != cc->task)
974 {
975 GNUNET_SCHEDULER_cancel (cc->task);
976 cc->task = NULL;
977 }
978 GCP_send (cc->mq_man, env);
979}
980
981
982/**
983 * Obtain the path used by this connection.
984 *
985 * @param cc connection
986 * @param[out] off set to the length of the path we use
987 * @return path to @a cc
988 */
989struct CadetPeerPath *
990GCC_get_path (struct CadetConnection *cc, unsigned int *off)
991{
992 *off = cc->off;
993 return cc->path;
994}
995
996
997/**
998 * Obtain unique ID for the connection.
999 *
1000 * @param cc connection.
1001 * @return unique number of the connection
1002 */
1003const struct GNUNET_CADET_ConnectionTunnelIdentifier *
1004GCC_get_id (struct CadetConnection *cc)
1005{
1006 return &cc->cid;
1007}
1008
1009
1010/**
1011 * Get a (static) string for a connection.
1012 *
1013 * @param cc Connection.
1014 */
1015const char *
1016GCC_2s (const struct CadetConnection *cc)
1017{
1018 static char buf[128];
1019
1020 if (NULL == cc)
1021 return "Connection(NULL)";
1022
1023 if (NULL != cc->ct)
1024 {
1025 GNUNET_snprintf (buf,
1026 sizeof(buf),
1027 "Connection %s (%s)",
1028 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
1029 GCT_2s (cc->ct->t));
1030 return buf;
1031 }
1032 GNUNET_snprintf (buf,
1033 sizeof(buf),
1034 "Connection %s",
1035 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
1036 return buf;
1037}
1038
1039
1040#define LOG2(level, ...) \
1041 GNUNET_log_from_nocheck (level, "cadet-con", __VA_ARGS__)
1042
1043
1044/**
1045 * Log connection info.
1046 *
1047 * @param cc connection
1048 * @param level Debug level to use.
1049 */
1050void
1051GCC_debug (struct CadetConnection *cc, enum GNUNET_ErrorType level)
1052{
1053#if ! defined(GNUNET_CULL_LOGGING)
1054 int do_log;
1055
1056 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1057 "cadet-con",
1058 __FILE__,
1059 __FUNCTION__,
1060 __LINE__);
1061 if (0 == do_log)
1062 return;
1063 if (NULL == cc)
1064 {
1065 LOG2 (level, "Connection (NULL)\n");
1066 return;
1067 }
1068 LOG2 (level,
1069 "%s to %s via path %s in state %d is %s\n",
1070 GCC_2s (cc),
1071 GCP_2s (cc->destination),
1072 GCPP_2s (cc->path),
1073 cc->state,
1074 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
1075#endif
1076}
1077
1078
1079/* end of gnunet-service-cadet_connection.c */