uncrustify as demanded.
[oweals/gnunet.git] / src / cadet / cadet_api_list_peers.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_peers.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_PeersLister {
38   /**
39    * Monitor callback
40    */
41   GNUNET_CADET_PeersCB peers_cb;
42
43   /**
44    * Info callback closure for @c info_cb.
45    */
46   void *peers_cb_cls;
47
48   /**
49    * Message queue to talk to CADET service.
50    */
51   struct GNUNET_MQ_Handle *mq;
52
53   /**
54    * Configuration we use.
55    */
56   const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58   /**
59    * Task to reconnect.
60    */
61   struct GNUNET_SCHEDULER_Task *reconnect_task;
62
63   /**
64    * Backoff for reconnect attempts.
65    */
66   struct GNUNET_TIME_Relative backoff;
67 };
68
69
70 /**
71  * Process a local reply about info on all tunnels, pass info to the user.
72  *
73  * @param cls a `struct GNUNET_CADET_PeersLister`
74  * @param info Message itself.
75  */
76 static void
77 handle_get_peers(void *cls,
78                  const struct GNUNET_CADET_LocalInfoPeers *info)
79 {
80   struct GNUNET_CADET_PeersLister *pl = cls;
81   struct GNUNET_CADET_PeerListEntry ple;
82
83   ple.peer = info->destination;
84   ple.have_tunnel = (int)ntohs(info->tunnel);
85   ple.n_paths = (unsigned int)ntohs(info->paths);
86   ple.best_path_length = (unsigned int)ntohl(info->best_path_length);
87   pl->peers_cb(pl->peers_cb_cls,
88                &ple);
89 }
90
91
92 /**
93  * Process a end of list reply about info on all peers.
94  *
95  * @param cls a `struct GNUNET_CADET_PeersLister`
96  * @param msg Message itself.
97  */
98 static void
99 handle_get_peers_end(void *cls,
100                      const struct GNUNET_MessageHeader *msg)
101 {
102   struct GNUNET_CADET_PeersLister *pl = cls;
103
104   (void)msg;
105
106   pl->peers_cb(pl->peers_cb_cls,
107                NULL);
108   GNUNET_CADET_list_peers_cancel(pl);
109 }
110
111
112 /**
113  * Reconnect to the service and try again.
114  *
115  * @param cls a `struct GNUNET_CADET_PeersLister` operation
116  */
117 static void
118 reconnect(void *cls);
119
120
121 /**
122  * Function called on connection trouble.  Reconnects.
123  *
124  * @param cls a `struct GNUNET_CADET_PeersLister`
125  * @param error error code from MQ
126  */
127 static void
128 error_handler(void *cls,
129               enum GNUNET_MQ_Error error)
130 {
131   struct GNUNET_CADET_PeersLister *pl = cls;
132
133   GNUNET_MQ_destroy(pl->mq);
134   pl->mq = NULL;
135   pl->backoff = GNUNET_TIME_randomized_backoff(pl->backoff,
136                                                GNUNET_TIME_UNIT_MINUTES);
137   pl->reconnect_task = GNUNET_SCHEDULER_add_delayed(pl->backoff,
138                                                     &reconnect,
139                                                     pl);
140 }
141
142
143 /**
144  * Reconnect to the service and try again.
145  *
146  * @param cls a `struct GNUNET_CADET_PeersLister` operation
147  */
148 static void
149 reconnect(void *cls)
150 {
151   struct GNUNET_CADET_PeersLister *pl = cls;
152   struct GNUNET_MQ_MessageHandler handlers[] = {
153     GNUNET_MQ_hd_fixed_size(get_peers,
154                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
155                             struct GNUNET_CADET_LocalInfoPeers,
156                             pl),
157     GNUNET_MQ_hd_fixed_size(get_peers_end,
158                             GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS_END,
159                             struct GNUNET_MessageHeader,
160                             pl),
161     GNUNET_MQ_handler_end()
162   };
163   struct GNUNET_MessageHeader *msg;
164   struct GNUNET_MQ_Envelope *env;
165
166   pl->reconnect_task = NULL;
167   pl->mq = GNUNET_CLIENT_connect(pl->cfg,
168                                  "cadet",
169                                  handlers,
170                                  &error_handler,
171                                  pl);
172   if (NULL == pl->mq)
173     return;
174   env = GNUNET_MQ_msg(msg,
175                       GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS);
176   GNUNET_MQ_send(pl->mq,
177                  env);
178 }
179
180
181 /**
182  * Request information about peers known to the running cadet service.
183  * The callback will be called for every peer known to the service.
184  * Only one info request (of any kind) can be active at once.
185  *
186  * @param cfg configuration to use
187  * @param callback Function to call with the requested data.
188  * @param callback_cls Closure for @c callback.
189  * @return NULL on error
190  */
191 struct GNUNET_CADET_PeersLister *
192 GNUNET_CADET_list_peers(const struct GNUNET_CONFIGURATION_Handle *cfg,
193                         GNUNET_CADET_PeersCB callback,
194                         void *callback_cls)
195 {
196   struct GNUNET_CADET_PeersLister *pl;
197
198   if (NULL == callback)
199     {
200       GNUNET_break(0);
201       return NULL;
202     }
203   pl = GNUNET_new(struct GNUNET_CADET_PeersLister);
204   pl->peers_cb = callback;
205   pl->peers_cb_cls = callback_cls;
206   pl->cfg = cfg;
207   reconnect(pl);
208   if (NULL == pl->mq)
209     {
210       GNUNET_free(pl);
211       return NULL;
212     }
213   return pl;
214 }
215
216
217 /**
218  * Cancel a peer info request. The callback will not be called (anymore).
219  *
220  * @param pl operation handle
221  * @return Closure given to GNUNET_CADET_get_peers().
222  */
223 void *
224 GNUNET_CADET_list_peers_cancel(struct GNUNET_CADET_PeersLister *pl)
225 {
226   void *ret = pl->peers_cb_cls;
227
228   if (NULL != pl->mq)
229     GNUNET_MQ_destroy(pl->mq);
230   if (NULL != pl->reconnect_task)
231     GNUNET_SCHEDULER_cancel(pl->reconnect_task);
232   GNUNET_free(pl);
233   return ret;
234 }
235
236 /* end of cadet_api_list_peers.c */