more work on #5385
[oweals/gnunet.git] / src / cadet / cadet_api_list_tunnels.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011, 2017 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 /**
21  * @file cadet/cadet_api_list_tunnels.c
22  * @brief cadet api: client implementation of cadet service
23  * @author Bartlomiej Polot
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_cadet_service.h"
30 #include "cadet.h"
31 #include "cadet_protocol.h"
32
33
34 /**
35  * Operation handle.
36  */
37 struct GNUNET_CADET_ListTunnels
38 {
39
40   /**
41    * Monitor callback
42    */
43   GNUNET_CADET_TunnelsCB tunnels_cb;
44
45   /**
46    * Info callback closure for @c tunnels_cb.
47    */
48   void *tunnels_cb_cls;
49   
50   /**
51    * Message queue to talk to CADET service.
52    */
53   struct GNUNET_MQ_Handle *mq;
54
55   /**
56    * Configuration we use.
57    */
58   const struct GNUNET_CONFIGURATION_Handle *cfg;
59
60   /**
61    * Task to reconnect.
62    */
63   struct GNUNET_SCHEDULER_Task *reconnect_task;
64
65   /**
66    * Backoff for reconnect attempts.
67    */
68   struct GNUNET_TIME_Relative backoff;
69
70 };
71
72
73 /**
74  * Send message of @a type to CADET service of @a h
75  *
76  * @param h handle to CADET service
77  * @param type message type of trivial information request to send
78  */
79 static void
80 send_info_request (struct GNUNET_CADET_Handle *h,
81                    uint16_t type)
82 {
83   struct GNUNET_MessageHeader *msg;
84   struct GNUNET_MQ_Envelope *env;
85
86   env = GNUNET_MQ_msg (msg,
87                        type);
88   GNUNET_MQ_send (h->mq,
89                   env);
90 }
91
92
93 /**
94  * Check that message received from CADET service is well-formed.
95  *
96  * @param cls the `struct GNUNET_CADET_Handle`
97  * @param message the message we got
98  * @return #GNUNET_OK if the message is well-formed,
99  *         #GNUNET_SYSERR otherwise
100  */
101 static int
102 check_get_tunnels (void *cls,
103                    const struct GNUNET_MessageHeader *message)
104 {
105   size_t esize;
106
107   (void) cls;
108   esize = ntohs (message->size);
109   if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == esize)
110     return GNUNET_OK;
111   if (sizeof (struct GNUNET_MessageHeader) == esize)
112     return GNUNET_OK;
113   return GNUNET_SYSERR;
114 }
115
116
117 /**
118  * Process a local reply about info on all tunnels, pass info to the user.
119  *
120  * @param cls Closure (Cadet handle).
121  * @param message Message itself.
122  */
123 static void
124 handle_get_tunnels (void *cls,
125                     const struct GNUNET_MessageHeader *msg)
126 {
127   struct GNUNET_CADET_Handle *h = cls;
128   const struct GNUNET_CADET_LocalInfoTunnel *info =
129     (const struct GNUNET_CADET_LocalInfoTunnel *) msg;
130
131   if (NULL == h->info_cb.tunnels_cb)
132     return;
133   if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == ntohs (msg->size))
134     h->info_cb.tunnels_cb (h->info_cls,
135                            &info->destination,
136                            ntohl (info->channels),
137                            ntohl (info->connections),
138                            ntohs (info->estate),
139                            ntohs (info->cstate));
140   else
141     h->info_cb.tunnels_cb (h->info_cls,
142                            NULL,
143                            0,
144                            0,
145                            0,
146                            0);
147 }
148
149
150 static void
151 reconnect (void *cls)
152 {
153   struct GNUNET_CADET_ListTunnels *lt = cls;
154   struct GNUNET_MQ_MessageHandler *handlers[] = {
155     GNUNET_MQ_hd_var_size (get_tunnels,
156                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
157                            struct GNUNET_MessageHeader,
158                            h),
159     GNUNET_MQ_handler_end ()
160   }
161   struct GNUNET_MessageHeader *msg;
162   struct GNUNET_MQ_Envelope *env;
163
164   cm->mq = GNUNET_CLIENT_connect (cm->cfg,
165                                   "cadet",
166                                   handlers,
167                                   &error_handler,
168                                   cm);
169                                  
170   env = GNUNET_MQ_msg (msg,
171                        type);
172   GNUNET_MQ_send (cm->mq,
173                   env);
174 }
175
176
177 /**
178  * Request information about tunnels of the running cadet peer.
179  * The callback will be called for every tunnel of the service.
180  * Only one info request (of any kind) can be active at once.
181  *
182  * WARNING: unstable API, likely to change in the future!
183  *
184  * @param h Handle to the cadet peer.
185  * @param callback Function to call with the requested data.
186  * @param callback_cls Closure for @c callback.
187  * @return #GNUNET_OK / #GNUNET_SYSERR
188  */
189 struct GNUNET_CADET_ListTunnels *
190 GNUNET_CADET_list_tunnels (const struct GNUNET_CONFIGURATION_Handle *cfg,
191                            GNUNET_CADET_TunnelsCB callback,
192                            void *callback_cls)
193 {
194
195   if (NULL != h->info_cb.tunnels_cb)
196   {
197     GNUNET_break (0);
198     return GNUNET_SYSERR;
199   }
200   send_info_request (h,
201                      GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
202   h->info_cb.tunnels_cb = callback;
203   h->info_cls = callback_cls;
204   return GNUNET_OK;
205 }
206
207
208 /**
209  * Cancel a monitor request. The monitor callback will not be called.
210  *
211  * @param h Cadet handle.
212  * @return Closure given to GNUNET_CADET_list_tunnels().
213  */
214 void *
215 GNUNET_CADET_list_tunnels_cancel (struct GNUNET_CADET_ListTunnels *lt)
216 {
217   void *cls = h->info_cls;
218
219   h->info_cb.tunnels_cb = NULL;
220   h->info_cls = NULL;
221   return cls;
222 }
223
224