Merge branch 'master' of gnunet.org:gnunet
[oweals/gnunet.git] / src / cadet / cadet_api_list_tunnels.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011, 2017, 2019 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  * Process a local reply about info on all tunnels, pass info to the user.
75  *
76  * @param cls a `struct GNUNET_CADET_ListTunnels *`
77  * @param info Message itself.
78  */
79 static void
80 handle_get_tunnels (void *cls,
81                     const struct GNUNET_CADET_LocalInfoTunnel *info)
82 {
83   struct GNUNET_CADET_ListTunnels *lt = cls;
84   struct GNUNET_CADET_TunnelDetails td;
85   
86   td.peer = info->destination;
87   td.channels = ntohl (info->channels);
88   td.connections = ntohl (info->connections);
89   td.estate = ntohs (info->estate);
90   td.cstate = ntohs (info->cstate);
91   lt->tunnels_cb (lt->tunnels_cb_cls,
92                   &td);
93 }
94
95
96 /**
97  * Process a local reply about info on all tunnels, pass info to the user.
98  *
99  * @param cls a `struct GNUNET_CADET_ListTunnels *`
100  * @param message Message itself.
101  */
102 static void
103 handle_get_tunnels_end (void *cls,
104                         const struct GNUNET_MessageHeader *msg)
105 {
106   struct GNUNET_CADET_ListTunnels *lt = cls;
107   (void) msg;
108   
109   lt->tunnels_cb (lt->tunnels_cb_cls,
110                   NULL);
111   GNUNET_CADET_list_tunnels_cancel (lt);
112 }
113
114
115 /**
116  * Reconnect to the service and try again.
117  *
118  * @param cls a `struct GNUNET_CADET_ListTunnels` operation
119  */
120 static void
121 reconnect (void *cls);
122
123
124 /**
125  * Function called on connection trouble.  Reconnects.
126  *
127  * @param cls a `struct GNUNET_CADET_ListTunnels`
128  * @param error error code from MQ
129  */
130 static void
131 error_handler (void *cls,
132                enum GNUNET_MQ_Error error)
133 {
134   struct GNUNET_CADET_ListTunnels *lt = cls;
135
136   GNUNET_MQ_destroy (lt->mq);
137   lt->mq = NULL;
138   lt->backoff = GNUNET_TIME_randomized_backoff (lt->backoff,
139                                                 GNUNET_TIME_UNIT_MINUTES);
140   lt->reconnect_task = GNUNET_SCHEDULER_add_delayed (lt->backoff,
141                                                      &reconnect,
142                                                      lt);
143 }
144
145
146 /**
147  * Reconnect to the service and try again.
148  *
149  * @param cls a `struct GNUNET_CADET_ListTunnels` operation
150  */
151 static void
152 reconnect (void *cls)
153 {
154   struct GNUNET_CADET_ListTunnels *lt = cls;
155   struct GNUNET_MQ_MessageHandler handlers[] = {
156     GNUNET_MQ_hd_fixed_size (get_tunnels,
157                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
158                              struct GNUNET_CADET_LocalInfoTunnel,
159                              lt),
160     GNUNET_MQ_hd_fixed_size (get_tunnels_end,
161                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END,
162                              struct GNUNET_MessageHeader,
163                              lt),
164     GNUNET_MQ_handler_end ()
165   };
166   struct GNUNET_MessageHeader *msg;
167   struct GNUNET_MQ_Envelope *env;
168
169   lt->reconnect_task = NULL;
170   lt->mq = GNUNET_CLIENT_connect (lt->cfg,
171                                   "cadet",
172                                   handlers,
173                                   &error_handler,
174                                   lt);  
175   if (NULL == lt->mq)
176     return;
177   env = GNUNET_MQ_msg (msg,
178                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS);
179   GNUNET_MQ_send (lt->mq,
180                   env);
181 }
182
183
184 /**
185  * Request information about tunnels of the running cadet peer.
186  * The callback will be called for every tunnel of the service.
187  * Only one info request (of any kind) can be active at once.
188  *
189  * @param cfg configuration to use
190  * @param callback Function to call with the requested data.
191  * @param callback_cls Closure for @c callback.
192  * @return NULL on error
193  */
194 struct GNUNET_CADET_ListTunnels *
195 GNUNET_CADET_list_tunnels (const struct GNUNET_CONFIGURATION_Handle *cfg,
196                            GNUNET_CADET_TunnelsCB callback,
197                            void *callback_cls)
198 {
199   struct GNUNET_CADET_ListTunnels *lt;
200
201   if (NULL == callback)
202   {
203     GNUNET_break (0);
204     return NULL;
205   }
206   lt = GNUNET_new (struct GNUNET_CADET_ListTunnels);
207   lt->tunnels_cb = callback;
208   lt->tunnels_cb_cls = callback_cls;
209   lt->cfg = cfg;
210   reconnect (lt);
211   if (NULL == lt->mq)
212   {
213     GNUNET_free (lt);
214     return NULL;
215   }
216   return lt;
217 }
218
219
220 /**
221  * Cancel a monitor request. The monitor callback will not be called.
222  *
223  * @param lt operation handle
224  * @return Closure given to GNUNET_CADET_list_tunnels().
225  */
226 void *
227 GNUNET_CADET_list_tunnels_cancel (struct GNUNET_CADET_ListTunnels *lt)
228 {
229   void *ret = lt->tunnels_cb_cls;
230
231   if (NULL != lt->mq)
232     GNUNET_MQ_destroy (lt->mq);
233   if (NULL != lt->reconnect_task)
234     GNUNET_SCHEDULER_cancel (lt->reconnect_task);
235   GNUNET_free (lt);
236   return ret;
237 }
238
239
240 /* end of cadet_api_list_tunnels.c */