another special case for loopback
[oweals/gnunet.git] / src / cadet / gnunet-service-cadet-new_connection.c
1
2 /*
3      This file is part of GNUnet.
4      Copyright (C) 2001-2017 GNUnet e.V.
5
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.
10
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.
15
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.
20 */
21
22 /**
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
28  *
29  * TODO:
30  * - Optimization: keepalive messages / timeout (timeout to be done @ peer level!)
31  * - Optimization: keep performance metrics (?)
32  */
33 #include "platform.h"
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"
41
42
43 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
44
45
46 /**
47  * All the states a connection can be in.
48  */
49 enum CadetConnectionState
50 {
51   /**
52    * Uninitialized status, we have not yet even gotten the message queue.
53    */
54   CADET_CONNECTION_NEW,
55
56   /**
57    * Connection create message in queue, awaiting transmission by CORE.
58    */
59   CADET_CONNECTION_SENDING_CREATE,
60
61   /**
62    * Connection create message sent, waiting for ACK.
63    */
64   CADET_CONNECTION_SENT,
65
66   /**
67    * We are an inbound connection, and received a CREATE. Need to
68    * send an CREATE_ACK back.
69    */
70   CADET_CONNECTION_CREATE_RECEIVED,
71
72   /**
73    * Connection confirmed, ready to carry traffic.
74    */
75   CADET_CONNECTION_READY
76
77 };
78
79
80 /**
81  * Low-level connection to a destination.
82  */
83 struct CadetConnection
84 {
85
86   /**
87    * ID of the connection.
88    */
89   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
90
91   /**
92    * To which peer does this connection go?
93    */
94   struct CadetPeer *destination;
95
96   /**
97    * Which tunnel is using this connection?
98    */
99   struct CadetTConnection *ct;
100
101   /**
102    * Path we are using to our destination.
103    */
104   struct CadetPeerPath *path;
105
106   /**
107    * Pending message, NULL if we are ready to transmit.
108    */
109   struct GNUNET_MQ_Envelope *env;
110
111   /**
112    * Handle for calling #GCP_request_mq_cancel() once we are finished.
113    */
114   struct GCP_MessageQueueManager *mq_man;
115
116   /**
117    * Task for connection maintenance.
118    */
119   struct GNUNET_SCHEDULER_Task *task;
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    * State of the connection.
138    */
139   enum CadetConnectionState state;
140
141   /**
142    * Offset of our @e destination in @e path.
143    */
144   unsigned int off;
145
146   /**
147    * Are we ready to transmit via @e mq_man right now?
148    */
149   int mqm_ready;
150
151 };
152
153
154 /**
155  * Destroy a connection.
156  *
157  * @param cc connection to destroy
158  */
159 void
160 GCC_destroy (struct CadetConnection *cc)
161 {
162   struct GNUNET_MQ_Envelope *env = NULL;
163
164   LOG (GNUNET_ERROR_TYPE_DEBUG,
165        "Destroying %s\n",
166        GCC_2s (cc));
167   if (CADET_CONNECTION_SENDING_CREATE != cc->state)
168   {
169     struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
170
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;
175   }
176   GCP_request_mq_cancel (cc->mq_man,
177                          env);
178   cc->mq_man = NULL;
179   if (NULL != cc->task)
180   {
181     GNUNET_SCHEDULER_cancel (cc->task);
182     cc->task = NULL;
183   }
184   GCPP_del_connection (cc->path,
185                        cc->off,
186                        cc);
187   GNUNET_assert (GNUNET_YES ==
188                  GNUNET_CONTAINER_multishortmap_remove (connections,
189                                                         &GCC_get_id (cc)->connection_of_tunnel,
190                                                         cc));
191   GNUNET_free (cc);
192 }
193
194
195 /**
196  * Return the tunnel associated with this connection.
197  *
198  * @param cc connection to query
199  * @return corresponding entry in the tunnel's connection list
200  */
201 struct CadetTConnection *
202 GCC_get_ct (struct CadetConnection *cc)
203 {
204   return cc->ct;
205 }
206
207
208 /**
209  * A connection ACK was received for this connection, implying
210  * that the end-to-end connection is up.  Process it.
211  *
212  * @param cc the connection that got the ACK.
213  */
214 void
215 GCC_handle_connection_create_ack (struct CadetConnection *cc)
216 {
217   LOG (GNUNET_ERROR_TYPE_DEBUG,
218        "Received CREATE_ACK for %s in state %d (%s)\n",
219        GCC_2s (cc),
220        cc->state,
221        (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
222   if (NULL != cc->task)
223   {
224     GNUNET_SCHEDULER_cancel (cc->task);
225     cc->task = NULL;
226   }
227 #if FIXME_KEEPALIVE
228   cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
229                                            &send_keepalive,
230                                            cc);
231 #endif
232   cc->state = CADET_CONNECTION_READY;
233   if (GNUNET_YES == cc->mqm_ready)
234     cc->ready_cb (cc->ready_cb_cls,
235                   GNUNET_YES);
236 }
237
238
239 /**
240  * Handle KX message.
241  *
242  * @param cc connection that received encrypted message
243  * @param msg the key exchange message
244  */
245 void
246 GCC_handle_kx (struct CadetConnection *cc,
247                const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
248 {
249   if (CADET_CONNECTION_SENT == cc->state)
250   {
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",
255          GCC_2s (cc));
256     GCC_handle_connection_create_ack (cc);
257   }
258   GCT_handle_kx (cc->ct,
259                  msg);
260 }
261
262
263 /**
264  * Handle encrypted message.
265  *
266  * @param cc connection that received encrypted message
267  * @param msg the encrypted message to decrypt
268  */
269 void
270 GCC_handle_encrypted (struct CadetConnection *cc,
271                       const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
272 {
273   if (CADET_CONNECTION_SENT == cc->state)
274   {
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",
279          GCC_2s (cc));
280     GCC_handle_connection_create_ack (cc);
281   }
282   GCT_handle_encrypted (cc->ct,
283                         msg);
284 }
285
286
287 /**
288  * Send a CREATE message to the first hop.
289  *
290  * @param cls the `struct CadetConnection` to initiate
291  */
292 static void
293 send_create (void *cls)
294 {
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;
300
301   cc->task = NULL;
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,
312                                                         i));
313   LOG (GNUNET_ERROR_TYPE_DEBUG,
314        "Sending CONNECTION_CREATE message for %s\n",
315        GCC_2s (cc));
316   cc->env = env;
317   cc->mqm_ready = GNUNET_NO;
318   cc->state = CADET_CONNECTION_SENT;
319   GCP_send (cc->mq_man,
320             env);
321 }
322
323
324 /**
325  * Send a CREATE_ACK message towards the origin.
326  *
327  * @param cls the `struct CadetConnection` to initiate
328  */
329 static void
330 send_create_ack (void *cls)
331 {
332   struct CadetConnection *cc = cls;
333   struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
334   struct GNUNET_MQ_Envelope *env;
335
336   cc->task = NULL;
337   GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
338   LOG (GNUNET_ERROR_TYPE_DEBUG,
339        "Sending CONNECTION_CREATE_ACK message for %s\n",
340        GCC_2s (cc));
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;
345   cc->env = env;
346   cc->mqm_ready = GNUNET_NO;
347   cc->state = CADET_CONNECTION_READY;
348   GCP_send (cc->mq_man,
349             env);
350 }
351
352
353 /**
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.
357  *
358  * @param cc connection that got the duplicate CREATE
359  */
360 void
361 GCC_handle_duplicate_create (struct CadetConnection *cc)
362 {
363   if (GNUNET_YES == cc->mqm_ready)
364   {
365     LOG (GNUNET_ERROR_TYPE_DEBUG,
366          "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
367          GCC_2s (cc),
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,
372                   GNUNET_NO);
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,
379                                          cc);
380   }
381   else
382   {
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",
388          GCC_2s (cc));
389   }
390 }
391
392
393 /**
394  * There has been a change in the message queue existence for our
395  * peer at the first hop.  Adjust accordingly.
396  *
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
402  */
403 static void
404 manage_first_hop_mq (void *cls,
405                      int available)
406 {
407   struct CadetConnection *cc = cls;
408
409   if (GNUNET_YES != available)
410   {
411     /* Connection is down, for now... */
412     LOG (GNUNET_ERROR_TYPE_DEBUG,
413          "Core MQ for %s went down\n",
414          GCC_2s (cc));
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)
419     {
420       GNUNET_SCHEDULER_cancel (cc->task);
421       cc->task = NULL;
422     }
423     cc->ready_cb (cc->ready_cb_cls,
424                   GNUNET_NO);
425     return;
426   }
427
428   cc->mqm_ready = GNUNET_YES;
429   LOG (GNUNET_ERROR_TYPE_DEBUG,
430        "Core MQ for %s became available in state %d\n",
431        GCC_2s (cc),
432        cc->state);
433   switch (cc->state)
434   {
435   case CADET_CONNECTION_NEW:
436     /* Transmit immediately */
437     cc->task = GNUNET_SCHEDULER_add_now (&send_create,
438                                          cc);
439     break;
440   case CADET_CONNECTION_SENDING_CREATE:
441     /* Should not be possible to be called in this state. */
442     GNUNET_assert (0);
443     break;
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,
448                                              &send_create,
449                                              cc);
450     break;
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,
454                                          cc);
455     break;
456   case CADET_CONNECTION_READY:
457     cc->ready_cb (cc->ready_cb_cls,
458                   GNUNET_YES);
459     break;
460   }
461 }
462
463
464 /**
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.
468  *
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
476  */
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,
484                    void *ready_cb_cls)
485 {
486   struct CadetConnection *cc;
487   struct CadetPeer *first_hop;
488   unsigned int off;
489
490   off = GCPP_find_peer (path,
491                         destination);
492   GNUNET_assert (UINT_MAX > off);
493   cc = GNUNET_new (struct CadetConnection);
494   cc->state = init_state;
495   cc->ct = ct;
496   cc->cid = *cid;
497   GNUNET_assert (GNUNET_OK ==
498                  GNUNET_CONTAINER_multishortmap_put (connections,
499                                                      &GCC_get_id (cc)->connection_of_tunnel,
500                                                      cc,
501                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
502   cc->ready_cb = ready_cb;
503   cc->ready_cb_cls = ready_cb_cls;
504   cc->path = path;
505   cc->off = off;
506   LOG (GNUNET_ERROR_TYPE_DEBUG,
507        "Creating %s using path %s\n",
508        GCC_2s (cc),
509        GCPP_2s (path));
510   GCPP_add_connection (path,
511                        off,
512                        cc);
513   for (unsigned int i=0;i<off;i++)
514     GCP_add_connection (GCPP_get_peer_at_offset (path,
515                                                  off),
516                         cc);
517
518   first_hop = GCPP_get_peer_at_offset (path,
519                                        0);
520   cc->mq_man = GCP_request_mq (first_hop,
521                                &manage_first_hop_mq,
522                                cc);
523   return cc;
524 }
525
526
527 /**
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
531  *
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
538  */
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,
545                     void *ready_cb_cls)
546 {
547   return connection_create (destination,
548                             path,
549                             ct,
550                             cid,
551                             CADET_CONNECTION_CREATE_RECEIVED,
552                             ready_cb,
553                             ready_cb_cls);
554 }
555
556
557 /**
558  * Create a connection to @a destination via @a path and
559  * notify @a cb whenever we are ready for more data.
560  *
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
567  */
568 struct CadetConnection *
569 GCC_create (struct CadetPeer *destination,
570             struct CadetPeerPath *path,
571             struct CadetTConnection *ct,
572             GCC_ReadyCallback ready_cb,
573             void *ready_cb_cls)
574 {
575   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
576
577   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
578                               &cid,
579                               sizeof (cid));
580   return connection_create (destination,
581                             path,
582                             ct,
583                             &cid,
584                             CADET_CONNECTION_NEW,
585                             ready_cb,
586                             ready_cb_cls);
587 }
588
589
590 /**
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.
595  *
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
599  */
600 void
601 GCC_transmit (struct CadetConnection *cc,
602               struct GNUNET_MQ_Envelope *env)
603 {
604   LOG (GNUNET_ERROR_TYPE_DEBUG,
605        "Scheduling message for transmission on %s\n",
606        GCC_2s (cc));
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,
611             env);
612 }
613
614
615 /**
616  * Obtain the path used by this connection.
617  *
618  * @param cc connection
619  * @return path to @a cc
620  */
621 struct CadetPeerPath *
622 GCC_get_path (struct CadetConnection *cc)
623 {
624   return cc->path;
625 }
626
627
628 /**
629  * Obtain unique ID for the connection.
630  *
631  * @param cc connection.
632  * @return unique number of the connection
633  */
634 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
635 GCC_get_id (struct CadetConnection *cc)
636 {
637   return &cc->cid;
638 }
639
640
641 /**
642  * Get a (static) string for a connection.
643  *
644  * @param cc Connection.
645  */
646 const char *
647 GCC_2s (const struct CadetConnection *cc)
648 {
649   static char buf[128];
650
651   if (NULL == cc)
652     return "Connection(NULL)";
653
654   if (NULL != cc->ct)
655   {
656     GNUNET_snprintf (buf,
657                      sizeof (buf),
658                      "Connection %s (%s)",
659                      GNUNET_sh2s (&cc->cid.connection_of_tunnel),
660                      GCT_2s (cc->ct->t));
661     return buf;
662   }
663   GNUNET_snprintf (buf,
664                    sizeof (buf),
665                    "Connection %s",
666                    GNUNET_sh2s (&cc->cid.connection_of_tunnel));
667   return buf;
668 }
669
670
671 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
672
673
674 /**
675  * Log connection info.
676  *
677  * @param cc connection
678  * @param level Debug level to use.
679  */
680 void
681 GCC_debug (struct CadetConnection *cc,
682            enum GNUNET_ErrorType level)
683 {
684   int do_log;
685
686   do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
687                                        "cadet-con",
688                                        __FILE__, __FUNCTION__, __LINE__);
689   if (0 == do_log)
690     return;
691   if (NULL == cc)
692   {
693     LOG2 (level,
694           "Connection (NULL)\n");
695     return;
696   }
697   LOG2 (level,
698         "%s to %s via path %s in state %d is %s\n",
699         GCC_2s (cc),
700         GCP_2s (cc->destination),
701         GCPP_2s (cc->path),
702         cc->state,
703         (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
704 }
705
706 /* end of gnunet-service-cadet-new_connection.c */