more work on channel/tunnel logic
[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 /**
44  * All the states a connection can be in.
45  */
46 enum 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  */
80 struct 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    * Function to call once we are ready to transmit.
120    */
121   GCC_ReadyCallback ready_cb;
122
123   /**
124    * Closure for @e ready_cb.
125    */
126   void *ready_cb_cls;
127
128   /**
129    * How long do we wait before we try again with a CREATE message?
130    */
131   struct GNUNET_TIME_Relative retry_delay;
132
133   /**
134    * State of the connection.
135    */
136   enum CadetConnectionState state;
137
138   /**
139    * Offset of our @e destination in @e path.
140    */
141   unsigned int off;
142
143   /**
144    * Are we ready to transmit via @e mq_man right now?
145    */
146   int mqm_ready;
147
148 };
149
150
151 /**
152  * Destroy a connection.
153  *
154  * @param cc connection to destroy
155  */
156 void
157 GCC_destroy (struct CadetConnection *cc)
158 {
159   struct GNUNET_MQ_Envelope *env = NULL;
160
161   if (CADET_CONNECTION_SENDING_CREATE != cc->state)
162   {
163     struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
164
165     /* Need to notify next hop that we are down. */
166     env = GNUNET_MQ_msg (destroy_msg,
167                          GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
168     destroy_msg->cid = cc->cid;
169   }
170   GCP_request_mq_cancel (cc->mq_man,
171                          env);
172   cc->mq_man = NULL;
173   GCPP_del_connection (cc->path,
174                        cc->off,
175                        cc);
176   GNUNET_assert (GNUNET_YES ==
177                  GNUNET_CONTAINER_multishortmap_remove (connections,
178                                                         &GCC_get_id (cc)->connection_of_tunnel,
179                                                         cc));
180   GNUNET_free (cc);
181 }
182
183
184 /**
185  * Return the tunnel associated with this connection.
186  *
187  * @param cc connection to query
188  * @return corresponding entry in the tunnel's connection list
189  */
190 struct CadetTConnection *
191 GCC_get_ct (struct CadetConnection *cc)
192 {
193   return cc->ct;
194 }
195
196
197 /**
198  * A connection ACK was received for this connection, implying
199  * that the end-to-end connection is up.  Process it.
200  *
201  * @param cc the connection that got the ACK.
202  */
203 void
204 GCC_handle_connection_ack (struct CadetConnection *cc)
205 {
206   if (NULL != cc->task)
207   {
208     GNUNET_SCHEDULER_cancel (cc->task);
209     cc->task = NULL;
210   }
211 #if FIXME_KEEPALIVE
212   cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
213                                            &send_keepalive,
214                                            cc);
215 #endif
216   cc->state = CADET_CONNECTION_READY;
217   if (GNUNET_YES == cc->mqm_ready)
218     cc->ready_cb (cc->ready_cb_cls,
219                   GNUNET_YES);
220 }
221
222
223 /**
224  * Handle KX message.
225  *
226  * @param cc connection that received encrypted message
227  * @param msg the key exchange message
228  */
229 void
230 GCC_handle_kx (struct CadetConnection *cc,
231                const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
232 {
233   if (CADET_CONNECTION_SENT == cc->state)
234   {
235     /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
236        clearly something is working, so pretend we got an ACK. */
237     GCC_handle_connection_ack (cc);
238   }
239   GCT_handle_kx (cc->ct,
240                  msg);
241 }
242
243
244 /**
245  * Handle encrypted message.
246  *
247  * @param cc connection that received encrypted message
248  * @param msg the encrypted message to decrypt
249  */
250 void
251 GCC_handle_encrypted (struct CadetConnection *cc,
252                       const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
253 {
254   if (CADET_CONNECTION_SENT == cc->state)
255   {
256     /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
257        clearly something is working, so pretend we got an ACK. */
258     GCC_handle_connection_ack (cc);
259   }
260   GCT_handle_encrypted (cc->ct,
261                         msg);
262 }
263
264
265 /**
266  * Send a CREATE message to the first hop.
267  *
268  * @param cls the `struct CadetConnection` to initiate
269  */
270 static void
271 send_create (void *cls)
272 {
273   struct CadetConnection *cc = cls;
274   struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
275   struct GNUNET_PeerIdentity *pids;
276   struct GNUNET_MQ_Envelope *env;
277   unsigned int path_length;
278
279   cc->task = NULL;
280   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
281   path_length = GCPP_get_length (cc->path);
282   env = GNUNET_MQ_msg_extra (create_msg,
283                              path_length * sizeof (struct GNUNET_PeerIdentity),
284                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
285   create_msg->cid = cc->cid;
286   pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
287   for (unsigned int i=0;i<path_length;i++)
288     pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
289                                                     i));
290   cc->env = env;
291   cc->mqm_ready = GNUNET_NO;
292   cc->state = CADET_CONNECTION_SENT;
293   GCP_send (cc->mq_man,
294             env);
295 }
296
297
298 /**
299  * Send a CREATE_ACK message towards the origin.
300  *
301  * @param cls the `struct CadetConnection` to initiate
302  */
303 static void
304 send_create_ack (void *cls)
305 {
306   struct CadetConnection *cc = cls;
307   struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
308   struct GNUNET_PeerIdentity *pids;
309   struct GNUNET_MQ_Envelope *env;
310   unsigned int path_length;
311
312   cc->task = NULL;
313   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
314   path_length = GCPP_get_length (cc->path);
315   env = GNUNET_MQ_msg_extra (create_msg,
316                              path_length * sizeof (struct GNUNET_PeerIdentity),
317                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
318   create_msg->cid = cc->cid;
319   pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
320   for (unsigned int i=0;i<path_length;i++)
321     pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
322                                                     i));
323   cc->env = env;
324   cc->mqm_ready = GNUNET_NO;
325   cc->state = CADET_CONNECTION_READY;
326   GCP_send (cc->mq_man,
327             env);
328 }
329
330
331 /**
332  * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
333  * connection that we already have.  Either our ACK got lost
334  * or something is fishy.  Consider retransmitting the ACK.
335  *
336  * @param cc connection that got the duplicate CREATE
337  */
338 void
339 GCC_handle_duplicate_create (struct CadetConnection *cc)
340 {
341   if (GNUNET_YES == cc->mqm_ready)
342   {
343     /* Tell tunnel that we are not ready for transmission anymore
344        (until CREATE_ACK is done) */
345     cc->ready_cb (cc->ready_cb_cls,
346                   GNUNET_NO);
347
348     /* Revert back to the state of having only received the 'CREATE',
349        and immediately proceed to send the CREATE_ACK. */
350     cc->state = CADET_CONNECTION_CREATE_RECEIVED;
351     cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
352                                          cc);
353   }
354   else
355   {
356     /* We are currently sending something else back, which
357        can only be an ACK or payload, either of which would
358        do. So actually no need to do anything. */
359   }
360 }
361
362
363 /**
364  * There has been a change in the message queue existence for our
365  * peer at the first hop.  Adjust accordingly.
366  *
367  * @param cls the `struct CadetConnection`
368  * @param available #GNUNET_YES if sending is now possible,
369  *                  #GNUNET_NO if sending is no longer possible
370  *                  #GNUNET_SYSERR if sending is no longer possible
371  *                                 and the last envelope was discarded
372  */
373 static void
374 manage_first_hop_mq (void *cls,
375                      int available)
376 {
377   struct CadetConnection *cc = cls;
378
379   if (GNUNET_YES != available)
380   {
381     /* Connection is down, for now... */
382     cc->mqm_ready = GNUNET_NO;
383     cc->state = CADET_CONNECTION_NEW;
384     cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
385     if (NULL != cc->task)
386     {
387       GNUNET_SCHEDULER_cancel (cc->task);
388       cc->task = NULL;
389     }
390     cc->ready_cb (cc->ready_cb_cls,
391                   GNUNET_NO);
392     return;
393   }
394
395   cc->mqm_ready = GNUNET_YES;
396   switch (cc->state)
397   {
398   case CADET_CONNECTION_NEW:
399     /* Transmit immediately */
400     cc->task = GNUNET_SCHEDULER_add_now (&send_create,
401                                          cc);
402     break;
403   case CADET_CONNECTION_SENDING_CREATE:
404     /* Should not be possible to be called in this state. */
405     GNUNET_assert (0);
406     break;
407   case CADET_CONNECTION_SENT:
408     /* Retry a bit later... */
409     cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
410     cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
411                                              &send_create,
412                                              cc);
413     break;
414   case CADET_CONNECTION_CREATE_RECEIVED:
415     /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
416     cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
417                                          cc);
418     break;
419   case CADET_CONNECTION_READY:
420     cc->ready_cb (cc->ready_cb_cls,
421                   GNUNET_YES);
422     break;
423   }
424 }
425
426
427 /**
428  * Create a connection to @a destination via @a path and notify @a cb
429  * whenever we are ready for more data.  Shared logic independent of
430  * who is initiating the connection.
431  *
432  * @param destination where to go
433  * @param path which path to take (may not be the full path)
434  * @param ct which tunnel uses this connection
435  * @param init_state initial state for the connection
436  * @param ready_cb function to call when ready to transmit
437  * @param ready_cb_cls closure for @a cb
438  * @return handle to the connection
439  */
440 static struct CadetConnection *
441 connection_create (struct CadetPeer *destination,
442                    struct CadetPeerPath *path,
443                    struct CadetTConnection *ct,
444                    const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
445                    enum CadetConnectionState init_state,
446                    GCC_ReadyCallback ready_cb,
447                    void *ready_cb_cls)
448 {
449   struct CadetConnection *cc;
450   struct CadetPeer *first_hop;
451   unsigned int off;
452
453   off = GCPP_find_peer (path,
454                         destination);
455   GNUNET_assert (UINT_MAX > off);
456   cc = GNUNET_new (struct CadetConnection);
457   cc->state = init_state;
458   cc->ct = ct;
459   cc->cid = *cid;
460   GNUNET_assert (GNUNET_OK ==
461                  GNUNET_CONTAINER_multishortmap_put (connections,
462                                                      &GCC_get_id (cc)->connection_of_tunnel,
463                                                      cc,
464                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
465   cc->ready_cb = ready_cb;
466   cc->ready_cb_cls = ready_cb_cls;
467   cc->path = path;
468   cc->off = off;
469   GCPP_add_connection (path,
470                        off,
471                        cc);
472   for (unsigned int i=0;i<off;i++)
473     GCP_add_connection (GCPP_get_peer_at_offset (path,
474                                                  off),
475                         cc);
476
477   first_hop = GCPP_get_peer_at_offset (path,
478                                        0);
479   cc->mq_man = GCP_request_mq (first_hop,
480                                &manage_first_hop_mq,
481                                cc);
482   return cc;
483 }
484
485
486 /**
487  * Create a connection to @a destination via @a path and
488  * notify @a cb whenever we are ready for more data.  This
489  * is an inbound tunnel, so we must use the existing @a cid
490  *
491  * @param destination where to go
492  * @param path which path to take (may not be the full path)
493  * @param ct which tunnel uses this connection
494  * @param ready_cb function to call when ready to transmit
495  * @param ready_cb_cls closure for @a cb
496  * @return handle to the connection
497  */
498 struct CadetConnection *
499 GCC_create_inbound (struct CadetPeer *destination,
500                     struct CadetPeerPath *path,
501                     struct CadetTConnection *ct,
502                     const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
503                     GCC_ReadyCallback ready_cb,
504                     void *ready_cb_cls)
505 {
506   return connection_create (destination,
507                             path,
508                             ct,
509                             cid,
510                             CADET_CONNECTION_CREATE_RECEIVED,
511                             ready_cb,
512                             ready_cb_cls);
513 }
514
515
516 /**
517  * Create a connection to @a destination via @a path and
518  * notify @a cb whenever we are ready for more data.
519  *
520  * @param destination where to go
521  * @param path which path to take (may not be the full path)
522  * @param ct tunnel that uses the connection
523  * @param ready_cb function to call when ready to transmit
524  * @param ready_cb_cls closure for @a cb
525  * @return handle to the connection
526  */
527 struct CadetConnection *
528 GCC_create (struct CadetPeer *destination,
529             struct CadetPeerPath *path,
530             struct CadetTConnection *ct,
531             GCC_ReadyCallback ready_cb,
532             void *ready_cb_cls)
533 {
534   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
535
536   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
537                               &cid,
538                               sizeof (cid));
539   return connection_create (destination,
540                             path,
541                             ct,
542                             &cid,
543                             CADET_CONNECTION_NEW,
544                             ready_cb,
545                             ready_cb_cls);
546 }
547
548
549 /**
550  * Transmit message @a msg via connection @a cc.  Must only be called
551  * (once) after the connection has signalled that it is ready via the
552  * `ready_cb`.  Clients can also use #GCC_is_ready() to check if the
553  * connection is right now ready for transmission.
554  *
555  * @param cc connection identification
556  * @param env envelope with message to transmit; must NOT
557  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
558  */
559 void
560 GCC_transmit (struct CadetConnection *cc,
561               struct GNUNET_MQ_Envelope *env)
562 {
563   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
564   GNUNET_assert (CADET_CONNECTION_READY == cc->state);
565   cc->mqm_ready = GNUNET_NO;
566   GCP_send (cc->mq_man,
567             env);
568 }
569
570
571 /**
572  * Obtain the path used by this connection.
573  *
574  * @param cc connection
575  * @return path to @a cc
576  */
577 struct CadetPeerPath *
578 GCC_get_path (struct CadetConnection *cc)
579 {
580   return cc->path;
581 }
582
583
584 /**
585  * Obtain unique ID for the connection.
586  *
587  * @param cc connection.
588  * @return unique number of the connection
589  */
590 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
591 GCC_get_id (struct CadetConnection *cc)
592 {
593   return &cc->cid;
594 }
595
596
597 /**
598  * Get a (static) string for a connection.
599  *
600  * @param cc Connection.
601  */
602 const char *
603 GCC_2s (const struct CadetConnection *cc)
604 {
605   static char buf[128];
606
607   if (NULL == cc)
608     return "Connection(NULL)";
609
610   if (NULL != cc->ct)
611   {
612     GNUNET_snprintf (buf,
613                      sizeof (buf),
614                      "Connection(%s(Tunnel(%s)))",
615                      GNUNET_sh2s (&cc->cid.connection_of_tunnel),
616                      GCT_2s (cc->ct->t));
617     return buf;
618   }
619   GNUNET_snprintf (buf,
620                    sizeof (buf),
621                    "Connection(%s(Tunnel(NULL)))",
622                    GNUNET_sh2s (&cc->cid.connection_of_tunnel));
623   return buf;
624 }
625
626
627 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
628
629
630 /**
631  * Log connection info.
632  *
633  * @param cc connection
634  * @param level Debug level to use.
635  */
636 void
637 GCC_debug (struct CadetConnection *cc,
638            enum GNUNET_ErrorType level)
639 {
640   int do_log;
641   char *s;
642
643   do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
644                                        "cadet-con",
645                                        __FILE__, __FUNCTION__, __LINE__);
646   if (0 == do_log)
647     return;
648   if (NULL == cc)
649   {
650     LOG2 (level,
651           "Connection (NULL)\n");
652     return;
653   }
654   s = GCPP_2s (cc->path);
655   LOG2 (level,
656         "Connection %s to %s via path %s in state %d is %s\n",
657         GCC_2s (cc),
658         GCP_2s (cc->destination),
659         s,
660         cc->state,
661         (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
662   GNUNET_free (s);
663 }
664
665 /* end of gnunet-service-cadet-new_connection.c */