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