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