3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
23 * @file cadet/gnunet-service-cadet-new_connection.c
24 * @brief management of CORE-level end-to-end connections; establishes
25 * end-to-end routes and transmits messages along the route
26 * @author Bartlomiej Polot
27 * @author Christian Grothoff
30 * - Optimization: keepalive messages / timeout (timeout to be done @ peer level!)
31 * - Optimization: keep performance metrics (?)
34 #include "gnunet-service-cadet-new_channel.h"
35 #include "gnunet-service-cadet-new_connection.h"
36 #include "gnunet-service-cadet-new_paths.h"
37 #include "gnunet-service-cadet-new_peer.h"
38 #include "gnunet-service-cadet-new_tunnels.h"
39 #include "gnunet_cadet_service.h"
40 #include "cadet_protocol.h"
43 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
47 * All the states a connection can be in.
49 enum CadetConnectionState
52 * Uninitialized status, we have not yet even gotten the message queue.
57 * Connection create message in queue, awaiting transmission by CORE.
59 CADET_CONNECTION_SENDING_CREATE,
62 * Connection create message sent, waiting for ACK.
64 CADET_CONNECTION_SENT,
67 * We are an inbound connection, and received a CREATE. Need to
68 * send an CREATE_ACK back.
70 CADET_CONNECTION_CREATE_RECEIVED,
73 * Connection confirmed, ready to carry traffic.
75 CADET_CONNECTION_READY
81 * Low-level connection to a destination.
83 struct CadetConnection
87 * ID of the connection.
89 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
92 * To which peer does this connection go?
94 struct CadetPeer *destination;
97 * Which tunnel is using this connection?
99 struct CadetTConnection *ct;
102 * Path we are using to our destination.
104 struct CadetPeerPath *path;
107 * Pending message, NULL if we are ready to transmit.
109 struct GNUNET_MQ_Envelope *env;
112 * Handle for calling #GCP_request_mq_cancel() once we are finished.
114 struct GCP_MessageQueueManager *mq_man;
117 * Task for connection maintenance.
119 struct GNUNET_SCHEDULER_Task *task;
122 * Function to call once we are ready to transmit.
124 GCC_ReadyCallback ready_cb;
127 * Closure for @e ready_cb.
132 * How long do we wait before we try again with a CREATE message?
134 struct GNUNET_TIME_Relative retry_delay;
137 * State of the connection.
139 enum CadetConnectionState state;
142 * Offset of our @e destination in @e path.
147 * Are we ready to transmit via @e mq_man right now?
155 * Destroy a connection.
157 * @param cc connection to destroy
160 GCC_destroy (struct CadetConnection *cc)
162 struct GNUNET_MQ_Envelope *env = NULL;
164 LOG (GNUNET_ERROR_TYPE_DEBUG,
167 if (CADET_CONNECTION_SENDING_CREATE != cc->state)
169 struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
171 /* Need to notify next hop that we are down. */
172 env = GNUNET_MQ_msg (destroy_msg,
173 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
174 destroy_msg->cid = cc->cid;
176 GCP_request_mq_cancel (cc->mq_man,
179 if (NULL != cc->task)
181 GNUNET_SCHEDULER_cancel (cc->task);
184 GCPP_del_connection (cc->path,
187 GNUNET_assert (GNUNET_YES ==
188 GNUNET_CONTAINER_multishortmap_remove (connections,
189 &GCC_get_id (cc)->connection_of_tunnel,
196 * Return the tunnel associated with this connection.
198 * @param cc connection to query
199 * @return corresponding entry in the tunnel's connection list
201 struct CadetTConnection *
202 GCC_get_ct (struct CadetConnection *cc)
209 * A connection ACK was received for this connection, implying
210 * that the end-to-end connection is up. Process it.
212 * @param cc the connection that got the ACK.
215 GCC_handle_connection_create_ack (struct CadetConnection *cc)
217 LOG (GNUNET_ERROR_TYPE_DEBUG,
218 "Received CREATE_ACK for %s in state %d (%s)\n",
221 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
222 if (NULL != cc->task)
224 GNUNET_SCHEDULER_cancel (cc->task);
228 cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
232 cc->state = CADET_CONNECTION_READY;
233 if (GNUNET_YES == cc->mqm_ready)
234 cc->ready_cb (cc->ready_cb_cls,
242 * @param cc connection that received encrypted message
243 * @param msg the key exchange message
246 GCC_handle_kx (struct CadetConnection *cc,
247 const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
249 if (CADET_CONNECTION_SENT == cc->state)
251 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
252 clearly something is working, so pretend we got an ACK. */
253 LOG (GNUNET_ERROR_TYPE_DEBUG,
254 "Faking connection ACK for %s due to KX\n",
256 GCC_handle_connection_create_ack (cc);
258 GCT_handle_kx (cc->ct,
264 * Handle encrypted message.
266 * @param cc connection that received encrypted message
267 * @param msg the encrypted message to decrypt
270 GCC_handle_encrypted (struct CadetConnection *cc,
271 const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
273 if (CADET_CONNECTION_SENT == cc->state)
275 /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
276 clearly something is working, so pretend we got an ACK. */
277 LOG (GNUNET_ERROR_TYPE_DEBUG,
278 "Faking connection ACK for %s due to ENCRYPTED payload\n",
280 GCC_handle_connection_create_ack (cc);
282 GCT_handle_encrypted (cc->ct,
288 * Send a CREATE message to the first hop.
290 * @param cls the `struct CadetConnection` to initiate
293 send_create (void *cls)
295 struct CadetConnection *cc = cls;
296 struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
297 struct GNUNET_PeerIdentity *pids;
298 struct GNUNET_MQ_Envelope *env;
299 unsigned int path_length;
302 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
303 path_length = GCPP_get_length (cc->path);
304 env = GNUNET_MQ_msg_extra (create_msg,
305 (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
306 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
307 create_msg->cid = cc->cid;
308 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
309 pids[0] = my_full_id;
310 for (unsigned int i=0;i<path_length;i++)
311 pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "Sending CONNECTION_CREATE message for %s\n",
317 cc->mqm_ready = GNUNET_NO;
318 cc->state = CADET_CONNECTION_SENT;
319 GCP_send (cc->mq_man,
325 * Send a CREATE_ACK message towards the origin.
327 * @param cls the `struct CadetConnection` to initiate
330 send_create_ack (void *cls)
332 struct CadetConnection *cc = cls;
333 struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
334 struct GNUNET_MQ_Envelope *env;
337 GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
338 LOG (GNUNET_ERROR_TYPE_DEBUG,
339 "Sending CONNECTION_CREATE_ACK message for %s\n",
341 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
342 env = GNUNET_MQ_msg (ack_msg,
343 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
344 ack_msg->cid = cc->cid;
346 cc->mqm_ready = GNUNET_NO;
347 cc->state = CADET_CONNECTION_READY;
348 GCP_send (cc->mq_man,
354 * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
355 * connection that we already have. Either our ACK got lost
356 * or something is fishy. Consider retransmitting the ACK.
358 * @param cc connection that got the duplicate CREATE
361 GCC_handle_duplicate_create (struct CadetConnection *cc)
363 if (GNUNET_YES == cc->mqm_ready)
365 LOG (GNUNET_ERROR_TYPE_DEBUG,
366 "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
368 (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
369 /* Tell tunnel that we are not ready for transmission anymore
370 (until CREATE_ACK is done) */
371 cc->ready_cb (cc->ready_cb_cls,
373 /* Revert back to the state of having only received the 'CREATE',
374 and immediately proceed to send the CREATE_ACK. */
375 cc->state = CADET_CONNECTION_CREATE_RECEIVED;
376 if (NULL != cc->task)
377 GNUNET_SCHEDULER_cancel (cc->task);
378 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
383 /* We are currently sending something else back, which
384 can only be an ACK or payload, either of which would
385 do. So actually no need to do anything. */
386 LOG (GNUNET_ERROR_TYPE_DEBUG,
387 "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
394 * There has been a change in the message queue existence for our
395 * peer at the first hop. Adjust accordingly.
397 * @param cls the `struct CadetConnection`
398 * @param available #GNUNET_YES if sending is now possible,
399 * #GNUNET_NO if sending is no longer possible
400 * #GNUNET_SYSERR if sending is no longer possible
401 * and the last envelope was discarded
404 manage_first_hop_mq (void *cls,
407 struct CadetConnection *cc = cls;
409 if (GNUNET_YES != available)
411 /* Connection is down, for now... */
412 LOG (GNUNET_ERROR_TYPE_DEBUG,
413 "Core MQ for %s went down\n",
415 cc->mqm_ready = GNUNET_NO;
416 cc->state = CADET_CONNECTION_NEW;
417 cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
418 if (NULL != cc->task)
420 GNUNET_SCHEDULER_cancel (cc->task);
423 cc->ready_cb (cc->ready_cb_cls,
428 cc->mqm_ready = GNUNET_YES;
429 LOG (GNUNET_ERROR_TYPE_DEBUG,
430 "Core MQ for %s became available in state %d\n",
435 case CADET_CONNECTION_NEW:
436 /* Transmit immediately */
437 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
440 case CADET_CONNECTION_SENDING_CREATE:
441 /* Should not be possible to be called in this state. */
444 case CADET_CONNECTION_SENT:
445 /* Retry a bit later... */
446 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
447 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
451 case CADET_CONNECTION_CREATE_RECEIVED:
452 /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
453 cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
456 case CADET_CONNECTION_READY:
457 cc->ready_cb (cc->ready_cb_cls,
465 * Create a connection to @a destination via @a path and notify @a cb
466 * whenever we are ready for more data. Shared logic independent of
467 * who is initiating the connection.
469 * @param destination where to go
470 * @param path which path to take (may not be the full path)
471 * @param ct which tunnel uses this connection
472 * @param init_state initial state for the connection
473 * @param ready_cb function to call when ready to transmit
474 * @param ready_cb_cls closure for @a cb
475 * @return handle to the connection
477 static struct CadetConnection *
478 connection_create (struct CadetPeer *destination,
479 struct CadetPeerPath *path,
480 struct CadetTConnection *ct,
481 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
482 enum CadetConnectionState init_state,
483 GCC_ReadyCallback ready_cb,
486 struct CadetConnection *cc;
487 struct CadetPeer *first_hop;
490 off = GCPP_find_peer (path,
492 GNUNET_assert (UINT_MAX > off);
493 cc = GNUNET_new (struct CadetConnection);
494 cc->state = init_state;
497 GNUNET_assert (GNUNET_OK ==
498 GNUNET_CONTAINER_multishortmap_put (connections,
499 &GCC_get_id (cc)->connection_of_tunnel,
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
502 cc->ready_cb = ready_cb;
503 cc->ready_cb_cls = ready_cb_cls;
506 LOG (GNUNET_ERROR_TYPE_DEBUG,
507 "Creating %s using path %s\n",
510 GCPP_add_connection (path,
513 for (unsigned int i=0;i<off;i++)
514 GCP_add_connection (GCPP_get_peer_at_offset (path,
518 first_hop = GCPP_get_peer_at_offset (path,
520 cc->mq_man = GCP_request_mq (first_hop,
521 &manage_first_hop_mq,
528 * Create a connection to @a destination via @a path and
529 * notify @a cb whenever we are ready for more data. This
530 * is an inbound tunnel, so we must use the existing @a cid
532 * @param destination where to go
533 * @param path which path to take (may not be the full path)
534 * @param ct which tunnel uses this connection
535 * @param ready_cb function to call when ready to transmit
536 * @param ready_cb_cls closure for @a cb
537 * @return handle to the connection
539 struct CadetConnection *
540 GCC_create_inbound (struct CadetPeer *destination,
541 struct CadetPeerPath *path,
542 struct CadetTConnection *ct,
543 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
544 GCC_ReadyCallback ready_cb,
547 return connection_create (destination,
551 CADET_CONNECTION_CREATE_RECEIVED,
558 * Create a connection to @a destination via @a path and
559 * notify @a cb whenever we are ready for more data.
561 * @param destination where to go
562 * @param path which path to take (may not be the full path)
563 * @param ct tunnel that uses the connection
564 * @param ready_cb function to call when ready to transmit
565 * @param ready_cb_cls closure for @a cb
566 * @return handle to the connection
568 struct CadetConnection *
569 GCC_create (struct CadetPeer *destination,
570 struct CadetPeerPath *path,
571 struct CadetTConnection *ct,
572 GCC_ReadyCallback ready_cb,
575 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
577 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
580 return connection_create (destination,
584 CADET_CONNECTION_NEW,
591 * Transmit message @a msg via connection @a cc. Must only be called
592 * (once) after the connection has signalled that it is ready via the
593 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
594 * connection is right now ready for transmission.
596 * @param cc connection identification
597 * @param env envelope with message to transmit; must NOT
598 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
601 GCC_transmit (struct CadetConnection *cc,
602 struct GNUNET_MQ_Envelope *env)
604 LOG (GNUNET_ERROR_TYPE_DEBUG,
605 "Scheduling message for transmission on %s\n",
607 GNUNET_assert (GNUNET_YES == cc->mqm_ready);
608 GNUNET_assert (CADET_CONNECTION_READY == cc->state);
609 cc->mqm_ready = GNUNET_NO;
610 GCP_send (cc->mq_man,
616 * Obtain the path used by this connection.
618 * @param cc connection
619 * @return path to @a cc
621 struct CadetPeerPath *
622 GCC_get_path (struct CadetConnection *cc)
629 * Obtain unique ID for the connection.
631 * @param cc connection.
632 * @return unique number of the connection
634 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
635 GCC_get_id (struct CadetConnection *cc)
642 * Get a (static) string for a connection.
644 * @param cc Connection.
647 GCC_2s (const struct CadetConnection *cc)
649 static char buf[128];
652 return "Connection(NULL)";
656 GNUNET_snprintf (buf,
658 "Connection %s (%s)",
659 GNUNET_sh2s (&cc->cid.connection_of_tunnel),
663 GNUNET_snprintf (buf,
666 GNUNET_sh2s (&cc->cid.connection_of_tunnel));
671 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
675 * Log connection info.
677 * @param cc connection
678 * @param level Debug level to use.
681 GCC_debug (struct CadetConnection *cc,
682 enum GNUNET_ErrorType level)
686 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
688 __FILE__, __FUNCTION__, __LINE__);
694 "Connection (NULL)\n");
698 "%s to %s via path %s in state %d is %s\n",
700 GCP_2s (cc->destination),
703 (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
706 /* end of gnunet-service-cadet-new_connection.c */