Merge branch 'master' of git+ssh://gnunet.org/gnunet
[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: keep per-connection performance metrics (?)
31  */
32 #include "platform.h"
33 #include "gnunet-service-cadet-new.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 "gnunet_statistics_service.h"
41 #include "cadet_protocol.h"
42
43
44 #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__)
45
46
47 /**
48  * All the states a connection can be in.
49  */
50 enum CadetConnectionState
51 {
52   /**
53    * Uninitialized status, we have not yet even gotten the message queue.
54    */
55   CADET_CONNECTION_NEW,
56
57   /**
58    * Connection create message in queue, awaiting transmission by CORE.
59    */
60   CADET_CONNECTION_SENDING_CREATE,
61
62   /**
63    * Connection create message sent, waiting for ACK.
64    */
65   CADET_CONNECTION_SENT,
66
67   /**
68    * We are an inbound connection, and received a CREATE. Need to
69    * send an CREATE_ACK back.
70    */
71   CADET_CONNECTION_CREATE_RECEIVED,
72
73   /**
74    * Connection confirmed, ready to carry traffic.
75    */
76   CADET_CONNECTION_READY
77
78 };
79
80
81 /**
82  * Low-level connection to a destination.
83  */
84 struct CadetConnection
85 {
86
87   /**
88    * ID of the connection.
89    */
90   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
91
92   /**
93    * To which peer does this connection go?
94    */
95   struct CadetPeer *destination;
96
97   /**
98    * Which tunnel is using this connection?
99    */
100   struct CadetTConnection *ct;
101
102   /**
103    * Path we are using to our destination.
104    */
105   struct CadetPeerPath *path;
106
107   /**
108    * Pending message, NULL if we are ready to transmit.
109    */
110   struct GNUNET_MQ_Envelope *env;
111
112   /**
113    * Handle for calling #GCP_request_mq_cancel() once we are finished.
114    */
115   struct GCP_MessageQueueManager *mq_man;
116
117   /**
118    * Task for connection maintenance.
119    */
120   struct GNUNET_SCHEDULER_Task *task;
121
122   /**
123    * Queue entry for keepalive messages.
124    */
125   struct CadetTunnelQueueEntry *keepalive_qe;
126
127   /**
128    * Function to call once we are ready to transmit.
129    */
130   GCC_ReadyCallback ready_cb;
131
132   /**
133    * Closure for @e ready_cb.
134    */
135   void *ready_cb_cls;
136
137   /**
138    * How long do we wait before we try again with a CREATE message?
139    */
140   struct GNUNET_TIME_Relative retry_delay;
141
142   /**
143    * State of the connection.
144    */
145   enum CadetConnectionState state;
146
147   /**
148    * Offset of our @e destination in @e path.
149    */
150   unsigned int off;
151
152   /**
153    * Are we ready to transmit via @e mq_man right now?
154    */
155   int mqm_ready;
156
157 };
158
159
160 /**
161  * Destroy a connection.
162  *
163  * @param cc connection to destroy
164  */
165 void
166 GCC_destroy (struct CadetConnection *cc)
167 {
168   struct GNUNET_MQ_Envelope *env = NULL;
169
170   LOG (GNUNET_ERROR_TYPE_DEBUG,
171        "Destroying %s\n",
172        GCC_2s (cc));
173   if (CADET_CONNECTION_SENDING_CREATE != cc->state)
174   {
175     struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg;
176
177     /* Need to notify next hop that we are down. */
178     env = GNUNET_MQ_msg (destroy_msg,
179                          GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
180     destroy_msg->cid = cc->cid;
181   }
182   if (NULL != cc->mq_man)
183   {
184     GCP_request_mq_cancel (cc->mq_man,
185                            env);
186     cc->mq_man = NULL;
187   }
188   if (NULL != cc->task)
189   {
190     GNUNET_SCHEDULER_cancel (cc->task);
191     cc->task = NULL;
192   }
193   if (NULL != cc->keepalive_qe)
194   {
195     GCT_send_cancel (cc->keepalive_qe);
196     cc->keepalive_qe = NULL;
197   }
198   GCPP_del_connection (cc->path,
199                        cc->off,
200                        cc);
201   GNUNET_assert (GNUNET_YES ==
202                  GNUNET_CONTAINER_multishortmap_remove (connections,
203                                                         &GCC_get_id (cc)->connection_of_tunnel,
204                                                         cc));
205   GNUNET_free (cc);
206 }
207
208
209 /**
210  * Return the tunnel associated with this connection.
211  *
212  * @param cc connection to query
213  * @return corresponding entry in the tunnel's connection list
214  */
215 struct CadetTConnection *
216 GCC_get_ct (struct CadetConnection *cc)
217 {
218   return cc->ct;
219 }
220
221
222 /**
223  * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
224  * tunnel to prevent it from timing out.
225  *
226  * @param cls the `struct CadetConnection` to keep alive.
227  */
228 static void
229 send_keepalive (void *cls);
230
231
232 /**
233  * Keepalive was transmitted.  Remember this, and possibly
234  * schedule the next one.
235  *
236  * @param cls the `struct CadetConnection` to keep alive.
237  */
238 static void
239 keepalive_done (void *cls)
240 {
241   struct CadetConnection *cc = cls;
242
243   cc->keepalive_qe = NULL;
244   if ( (GNUNET_YES == cc->mqm_ready) &&
245        (NULL == cc->task) )
246     cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
247                                              &send_keepalive,
248                                              cc);
249 }
250
251
252 /**
253  * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the
254  * tunnel to prevent it from timing out.
255  *
256  * @param cls the `struct CadetConnection` to keep alive.
257  */
258 static void
259 send_keepalive (void *cls)
260 {
261   struct CadetConnection *cc = cls;
262   struct GNUNET_MessageHeader msg;
263
264   cc->task = NULL;
265   GNUNET_assert (NULL != cc->ct);
266   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
267   GNUNET_assert (NULL == cc->keepalive_qe);
268   LOG (GNUNET_ERROR_TYPE_INFO,
269        "Sending KEEPALIVE on behalf of %s via %s\n",
270        GCC_2s (cc),
271        GCT_2s (cc->ct->t));
272   GNUNET_STATISTICS_update (stats,
273                             "# keepalives sent",
274                             1,
275                             GNUNET_NO);
276   msg.size = htons (sizeof (msg));
277   msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
278
279   cc->keepalive_qe
280     = GCT_send (cc->ct->t,
281                 &msg,
282                 &keepalive_done,
283                 cc);
284 }
285
286
287 /**
288  * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
289  * that the end-to-end connection is up.  Process it.
290  *
291  * @param cc the connection that got the ACK.
292  */
293 void
294 GCC_handle_connection_create_ack (struct CadetConnection *cc)
295 {
296   LOG (GNUNET_ERROR_TYPE_DEBUG,
297        "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n",
298        GCC_2s (cc),
299        cc->state,
300        (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
301   if (NULL != cc->task)
302   {
303     GNUNET_SCHEDULER_cancel (cc->task);
304     cc->task = NULL;
305   }
306   cc->state = CADET_CONNECTION_READY;
307   if (GNUNET_YES == cc->mqm_ready)
308   {
309     cc->ready_cb (cc->ready_cb_cls,
310                   GNUNET_YES);
311     if ( (NULL == cc->keepalive_qe) &&
312          (GNUNET_YES == cc->mqm_ready) &&
313          (NULL == cc->task) )
314       cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
315                                                &send_keepalive,
316                                                cc);
317   }
318 }
319
320
321 /**
322  * Handle KX message.
323  *
324  * @param cc connection that received encrypted message
325  * @param msg the key exchange message
326  */
327 void
328 GCC_handle_kx (struct CadetConnection *cc,
329                const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
330 {
331   if (CADET_CONNECTION_SENT == cc->state)
332   {
333     /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine,
334        clearly something is working, so pretend we got an ACK. */
335     LOG (GNUNET_ERROR_TYPE_DEBUG,
336          "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n",
337          GCC_2s (cc));
338     GCC_handle_connection_create_ack (cc);
339   }
340   GCT_handle_kx (cc->ct,
341                  msg);
342 }
343
344
345 /**
346  * Handle encrypted message.
347  *
348  * @param cc connection that received encrypted message
349  * @param msg the encrypted message to decrypt
350  */
351 void
352 GCC_handle_encrypted (struct CadetConnection *cc,
353                       const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
354 {
355   if (CADET_CONNECTION_SENT == cc->state)
356   {
357     /* We didn't get the CREATE_ACK, but instead got payload. That's fine,
358        clearly something is working, so pretend we got an ACK. */
359     LOG (GNUNET_ERROR_TYPE_DEBUG,
360          "Faking connection ACK for %s due to ENCRYPTED payload\n",
361          GCC_2s (cc));
362     GCC_handle_connection_create_ack (cc);
363   }
364   GCT_handle_encrypted (cc->ct,
365                         msg);
366 }
367
368
369 /**
370  * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
371  * first hop.
372  *
373  * @param cls the `struct CadetConnection` to initiate
374  */
375 static void
376 send_create (void *cls)
377 {
378   struct CadetConnection *cc = cls;
379   struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
380   struct GNUNET_PeerIdentity *pids;
381   struct GNUNET_MQ_Envelope *env;
382   unsigned int path_length;
383
384   cc->task = NULL;
385   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
386   path_length = GCPP_get_length (cc->path);
387   env = GNUNET_MQ_msg_extra (create_msg,
388                              (1 + path_length) * sizeof (struct GNUNET_PeerIdentity),
389                              GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
390   create_msg->cid = cc->cid;
391   pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
392   pids[0] = my_full_id;
393   for (unsigned int i=0;i<path_length;i++)
394     pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
395                                                         i));
396   LOG (GNUNET_ERROR_TYPE_DEBUG,
397        "Sending CADET_CONNECTION_CREATE message for %s\n",
398        GCC_2s (cc));
399   cc->env = env;
400   cc->mqm_ready = GNUNET_NO;
401   cc->state = CADET_CONNECTION_SENT;
402   GCP_send (cc->mq_man,
403             env);
404 }
405
406
407 /**
408  * Send a CREATE_ACK message towards the origin.
409  *
410  * @param cls the `struct CadetConnection` to initiate
411  */
412 static void
413 send_create_ack (void *cls)
414 {
415   struct CadetConnection *cc = cls;
416   struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg;
417   struct GNUNET_MQ_Envelope *env;
418
419   cc->task = NULL;
420   GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state);
421   LOG (GNUNET_ERROR_TYPE_DEBUG,
422        "Sending CONNECTION_CREATE_ACK message for %s\n",
423        GCC_2s (cc));
424   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
425   env = GNUNET_MQ_msg (ack_msg,
426                        GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK);
427   ack_msg->cid = cc->cid;
428   cc->env = env;
429   cc->mqm_ready = GNUNET_NO;
430   cc->state = CADET_CONNECTION_READY;
431   GCP_send (cc->mq_man,
432             env);
433 }
434
435
436 /**
437  * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a
438  * connection that we already have.  Either our ACK got lost
439  * or something is fishy.  Consider retransmitting the ACK.
440  *
441  * @param cc connection that got the duplicate CREATE
442  */
443 void
444 GCC_handle_duplicate_create (struct CadetConnection *cc)
445 {
446   if (GNUNET_YES == cc->mqm_ready)
447   {
448     LOG (GNUNET_ERROR_TYPE_DEBUG,
449          "Got duplicate CREATE for %s, scheduling another ACK (%s)\n",
450          GCC_2s (cc),
451          (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
452     /* Tell tunnel that we are not ready for transmission anymore
453        (until CREATE_ACK is done) */
454     cc->ready_cb (cc->ready_cb_cls,
455                   GNUNET_NO);
456     /* Revert back to the state of having only received the 'CREATE',
457        and immediately proceed to send the CREATE_ACK. */
458     cc->state = CADET_CONNECTION_CREATE_RECEIVED;
459     if (NULL != cc->task)
460       GNUNET_SCHEDULER_cancel (cc->task);
461     cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
462                                          cc);
463   }
464   else
465   {
466     /* We are currently sending something else back, which
467        can only be an ACK or payload, either of which would
468        do. So actually no need to do anything. */
469     LOG (GNUNET_ERROR_TYPE_DEBUG,
470          "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n",
471          GCC_2s (cc));
472   }
473 }
474
475
476 /**
477  * There has been a change in the message queue existence for our
478  * peer at the first hop.  Adjust accordingly.
479  *
480  * @param cls the `struct CadetConnection`
481  * @param available #GNUNET_YES if sending is now possible,
482  *                  #GNUNET_NO if sending is no longer possible
483  *                  #GNUNET_SYSERR if sending is no longer possible
484  *                                 and the last envelope was discarded
485  */
486 static void
487 manage_first_hop_mq (void *cls,
488                      int available)
489 {
490   struct CadetConnection *cc = cls;
491
492   if (GNUNET_YES != available)
493   {
494     /* Connection is down, for now... */
495     LOG (GNUNET_ERROR_TYPE_DEBUG,
496          "Core MQ for %s went down\n",
497          GCC_2s (cc));
498     cc->mqm_ready = GNUNET_NO;
499     cc->state = CADET_CONNECTION_NEW;
500     cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
501     if (NULL != cc->task)
502     {
503       GNUNET_SCHEDULER_cancel (cc->task);
504       cc->task = NULL;
505     }
506     cc->ready_cb (cc->ready_cb_cls,
507                   GNUNET_NO);
508     return;
509   }
510
511   cc->mqm_ready = GNUNET_YES;
512   LOG (GNUNET_ERROR_TYPE_DEBUG,
513        "Core MQ for %s became available in state %d\n",
514        GCC_2s (cc),
515        cc->state);
516   switch (cc->state)
517   {
518   case CADET_CONNECTION_NEW:
519     /* Transmit immediately */
520     cc->task = GNUNET_SCHEDULER_add_now (&send_create,
521                                          cc);
522     break;
523   case CADET_CONNECTION_SENDING_CREATE:
524     /* Should not be possible to be called in this state. */
525     GNUNET_assert (0);
526     break;
527   case CADET_CONNECTION_SENT:
528     /* Retry a bit later... */
529     cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
530     cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
531                                              &send_create,
532                                              cc);
533     break;
534   case CADET_CONNECTION_CREATE_RECEIVED:
535     /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */
536     cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack,
537                                          cc);
538     break;
539   case CADET_CONNECTION_READY:
540     cc->ready_cb (cc->ready_cb_cls,
541                   GNUNET_YES);
542     if ( (NULL == cc->keepalive_qe) &&
543          (GNUNET_YES == cc->mqm_ready) &&
544          (NULL == cc->task) )
545     {
546       LOG (GNUNET_ERROR_TYPE_DEBUG,
547            "Scheduling keepalive for %s in %s\n",
548            GCC_2s (cc),
549            GNUNET_STRINGS_relative_time_to_string (keepalive_period,
550                                                    GNUNET_YES));
551       cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period,
552                                                &send_keepalive,
553                                                cc);
554     }
555     break;
556   }
557 }
558
559
560 /**
561  * Create a connection to @a destination via @a path and notify @a cb
562  * whenever we are ready for more data.  Shared logic independent of
563  * who is initiating the connection.
564  *
565  * @param destination where to go
566  * @param path which path to take (may not be the full path)
567  * @param ct which tunnel uses this connection
568  * @param init_state initial state for the connection
569  * @param ready_cb function to call when ready to transmit
570  * @param ready_cb_cls closure for @a cb
571  * @return handle to the connection
572  */
573 static struct CadetConnection *
574 connection_create (struct CadetPeer *destination,
575                    struct CadetPeerPath *path,
576                    struct CadetTConnection *ct,
577                    const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
578                    enum CadetConnectionState init_state,
579                    GCC_ReadyCallback ready_cb,
580                    void *ready_cb_cls)
581 {
582   struct CadetConnection *cc;
583   struct CadetPeer *first_hop;
584   unsigned int off;
585
586   off = GCPP_find_peer (path,
587                         destination);
588   GNUNET_assert (UINT_MAX > off);
589   cc = GNUNET_new (struct CadetConnection);
590   cc->state = init_state;
591   cc->ct = ct;
592   cc->cid = *cid;
593   GNUNET_assert (GNUNET_OK ==
594                  GNUNET_CONTAINER_multishortmap_put (connections,
595                                                      &GCC_get_id (cc)->connection_of_tunnel,
596                                                      cc,
597                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
598   cc->ready_cb = ready_cb;
599   cc->ready_cb_cls = ready_cb_cls;
600   cc->path = path;
601   cc->off = off;
602   LOG (GNUNET_ERROR_TYPE_DEBUG,
603        "Creating %s using path %s\n",
604        GCC_2s (cc),
605        GCPP_2s (path));
606   GCPP_add_connection (path,
607                        off,
608                        cc);
609   for (unsigned int i=0;i<off;i++)
610     GCP_add_connection (GCPP_get_peer_at_offset (path,
611                                                  off),
612                         cc);
613
614   first_hop = GCPP_get_peer_at_offset (path,
615                                        0);
616   cc->mq_man = GCP_request_mq (first_hop,
617                                &manage_first_hop_mq,
618                                cc);
619   return cc;
620 }
621
622
623 /**
624  * Create a connection to @a destination via @a path and
625  * notify @a cb whenever we are ready for more data.  This
626  * is an inbound tunnel, so we must use the existing @a cid
627  *
628  * @param destination where to go
629  * @param path which path to take (may not be the full path)
630  * @param ct which tunnel uses this connection
631  * @param ready_cb function to call when ready to transmit
632  * @param ready_cb_cls closure for @a cb
633  * @return handle to the connection
634  */
635 struct CadetConnection *
636 GCC_create_inbound (struct CadetPeer *destination,
637                     struct CadetPeerPath *path,
638                     struct CadetTConnection *ct,
639                     const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
640                     GCC_ReadyCallback ready_cb,
641                     void *ready_cb_cls)
642 {
643   return connection_create (destination,
644                             path,
645                             ct,
646                             cid,
647                             CADET_CONNECTION_CREATE_RECEIVED,
648                             ready_cb,
649                             ready_cb_cls);
650 }
651
652
653 /**
654  * Create a connection to @a destination via @a path and
655  * notify @a cb whenever we are ready for more data.
656  *
657  * @param destination where to go
658  * @param path which path to take (may not be the full path)
659  * @param ct tunnel that uses the connection
660  * @param ready_cb function to call when ready to transmit
661  * @param ready_cb_cls closure for @a cb
662  * @return handle to the connection
663  */
664 struct CadetConnection *
665 GCC_create (struct CadetPeer *destination,
666             struct CadetPeerPath *path,
667             struct CadetTConnection *ct,
668             GCC_ReadyCallback ready_cb,
669             void *ready_cb_cls)
670 {
671   struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
672
673   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
674                               &cid,
675                               sizeof (cid));
676   return connection_create (destination,
677                             path,
678                             ct,
679                             &cid,
680                             CADET_CONNECTION_NEW,
681                             ready_cb,
682                             ready_cb_cls);
683 }
684
685
686 /**
687  * Transmit message @a msg via connection @a cc.  Must only be called
688  * (once) after the connection has signalled that it is ready via the
689  * `ready_cb`.  Clients can also use #GCC_is_ready() to check if the
690  * connection is right now ready for transmission.
691  *
692  * @param cc connection identification
693  * @param env envelope with message to transmit; must NOT
694  *            yet have a #GNUNET_MQ_notify_sent() callback attached to it
695  */
696 void
697 GCC_transmit (struct CadetConnection *cc,
698               struct GNUNET_MQ_Envelope *env)
699 {
700   LOG (GNUNET_ERROR_TYPE_DEBUG,
701        "Scheduling message for transmission on %s\n",
702        GCC_2s (cc));
703   GNUNET_assert (GNUNET_YES == cc->mqm_ready);
704   GNUNET_assert (CADET_CONNECTION_READY == cc->state);
705   cc->mqm_ready = GNUNET_NO;
706   if (NULL != cc->task)
707   {
708     GNUNET_SCHEDULER_cancel (cc->task);
709     cc->task = NULL;
710   }
711   GCP_send (cc->mq_man,
712             env);
713 }
714
715
716 /**
717  * Obtain the path used by this connection.
718  *
719  * @param cc connection
720  * @return path to @a cc
721  */
722 struct CadetPeerPath *
723 GCC_get_path (struct CadetConnection *cc)
724 {
725   return cc->path;
726 }
727
728
729 /**
730  * Obtain unique ID for the connection.
731  *
732  * @param cc connection.
733  * @return unique number of the connection
734  */
735 const struct GNUNET_CADET_ConnectionTunnelIdentifier *
736 GCC_get_id (struct CadetConnection *cc)
737 {
738   return &cc->cid;
739 }
740
741
742 /**
743  * Get a (static) string for a connection.
744  *
745  * @param cc Connection.
746  */
747 const char *
748 GCC_2s (const struct CadetConnection *cc)
749 {
750   static char buf[128];
751
752   if (NULL == cc)
753     return "Connection(NULL)";
754
755   if (NULL != cc->ct)
756   {
757     GNUNET_snprintf (buf,
758                      sizeof (buf),
759                      "Connection %s (%s)",
760                      GNUNET_sh2s (&cc->cid.connection_of_tunnel),
761                      GCT_2s (cc->ct->t));
762     return buf;
763   }
764   GNUNET_snprintf (buf,
765                    sizeof (buf),
766                    "Connection %s",
767                    GNUNET_sh2s (&cc->cid.connection_of_tunnel));
768   return buf;
769 }
770
771
772 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
773
774
775 /**
776  * Log connection info.
777  *
778  * @param cc connection
779  * @param level Debug level to use.
780  */
781 void
782 GCC_debug (struct CadetConnection *cc,
783            enum GNUNET_ErrorType level)
784 {
785   int do_log;
786
787   do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
788                                        "cadet-con",
789                                        __FILE__, __FUNCTION__, __LINE__);
790   if (0 == do_log)
791     return;
792   if (NULL == cc)
793   {
794     LOG2 (level,
795           "Connection (NULL)\n");
796     return;
797   }
798   LOG2 (level,
799         "%s to %s via path %s in state %d is %s\n",
800         GCC_2s (cc),
801         GCP_2s (cc->destination),
802         GCPP_2s (cc->path),
803         cc->state,
804         (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy");
805 }
806
807 /* end of gnunet-service-cadet-new_connection.c */