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