aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api_monitor_peers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport_api_monitor_peers.c')
-rw-r--r--src/transport/transport_api_monitor_peers.c469
1 files changed, 0 insertions, 469 deletions
diff --git a/src/transport/transport_api_monitor_peers.c b/src/transport/transport_api_monitor_peers.c
deleted file mode 100644
index 2f0f07f23..000000000
--- a/src/transport/transport_api_monitor_peers.c
+++ /dev/null
@@ -1,469 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014, 2016 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/**
22 * @file transport/transport_api_monitor_peers.c
23 * @brief montoring api for transport peer status
24 *
25 * This api provides the ability to query the transport service about
26 * the connection status of a specific or all peers.
27 *
28 * Calls back with information about peer(s) including address used, state and
29 * state timeout for peer requests.
30 */
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_arm_service.h"
34#include "gnunet_hello_lib.h"
35#include "gnunet_protocols.h"
36#include "gnunet_transport_service.h"
37#include "transport.h"
38
39/**
40 * Context for iterating validation entries.
41 */
42struct GNUNET_TRANSPORT_PeerMonitoringContext
43{
44 /**
45 * Function to call with the binary address.
46 */
47 GNUNET_TRANSPORT_PeerIterateCallback cb;
48
49 /**
50 * Closure for @e cb.
51 */
52 void *cb_cls;
53
54 /**
55 * Connection to the service.
56 */
57 struct GNUNET_MQ_Handle *mq;
58
59 /**
60 * Configuration we use.
61 */
62 const struct GNUNET_CONFIGURATION_Handle *cfg;
63
64 /**
65 * Backoff for reconnect.
66 */
67 struct GNUNET_TIME_Relative backoff;
68
69 /**
70 * Task ID for reconnect.
71 */
72 struct GNUNET_SCHEDULER_Task *reconnect_task;
73
74 /**
75 * Identity of the peer to monitor.
76 */
77 struct GNUNET_PeerIdentity peer;
78
79 /**
80 * Was this a one-shot request?
81 */
82 int one_shot;
83};
84
85
86/**
87 * Check if a state is defined as connected
88 *
89 * @param state the state value
90 * @return #GNUNET_YES or #GNUNET_NO
91 */
92int
93GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
94{
95 switch (state)
96 {
97 case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
98 case GNUNET_TRANSPORT_PS_INIT_ATS:
99 case GNUNET_TRANSPORT_PS_SYN_SENT:
100 case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
101 case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
102 return GNUNET_NO;
103
104 case GNUNET_TRANSPORT_PS_CONNECTED:
105 case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
106 case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
107 case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
108 return GNUNET_YES;
109
110 case GNUNET_TRANSPORT_PS_DISCONNECT:
111 case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
112 return GNUNET_NO;
113
114 default:
115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
116 "Unhandled state `%s'\n",
117 GNUNET_TRANSPORT_ps2s (state));
118 GNUNET_break (0);
119 break;
120 }
121 return GNUNET_SYSERR;
122}
123
124
125/**
126 * Convert peer state to human-readable string.
127 *
128 * @param state the state value
129 * @return corresponding string
130 */
131const char *
132GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
133{
134 switch (state)
135 {
136 case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
137 return "S_NOT_CONNECTED";
138
139 case GNUNET_TRANSPORT_PS_INIT_ATS:
140 return "S_INIT_ATS";
141
142 case GNUNET_TRANSPORT_PS_SYN_SENT:
143 return "S_SYN_SENT";
144
145 case GNUNET_TRANSPORT_PS_SYN_RECV_ATS:
146 return "S_SYN_RECV_ATS";
147
148 case GNUNET_TRANSPORT_PS_SYN_RECV_ACK:
149 return "S_SYN_RECV_ACK";
150
151 case GNUNET_TRANSPORT_PS_CONNECTED:
152 return "S_CONNECTED";
153
154 case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
155 return "S_RECONNECT_ATS";
156
157 case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
158 return "S_RECONNECT_SENT";
159
160 case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
161 return "S_SWITCH_SYN_SENT";
162
163 case GNUNET_TRANSPORT_PS_DISCONNECT:
164 return "S_DISCONNECT";
165
166 case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
167 return "S_DISCONNECT_FINISHED";
168
169 default:
170 GNUNET_break (0);
171 return "UNDEFINED";
172 }
173}
174
175
176/**
177 * Task run to re-establish the connection.
178 *
179 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
180 */
181static void
182do_peer_connect (void *cls);
183
184
185/**
186 * Cut the existing connection and reconnect.
187 *
188 * @param pal_ctx our context
189 */
190static void
191reconnect_peer_ctx (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
192{
193 GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
194 GNUNET_MQ_destroy (pal_ctx->mq);
195 pal_ctx->mq = NULL;
196 pal_ctx->cb (pal_ctx->cb_cls,
197 NULL,
198 NULL,
199 GNUNET_TRANSPORT_PS_NOT_CONNECTED,
200 GNUNET_TIME_UNIT_ZERO_ABS);
201 pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff);
202 pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff,
203 &do_peer_connect,
204 pal_ctx);
205}
206
207
208/**
209 * Function called with responses from the service.
210 *
211 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
212 * @param msg message from service
213 */
214static void
215handle_response_end (void *cls,
216 const struct GNUNET_MessageHeader *msg)
217{
218 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
219
220 if (pal_ctx->one_shot)
221 {
222 /* iteration finished */
223 pal_ctx->cb (pal_ctx->cb_cls,
224 NULL,
225 NULL,
226 GNUNET_TRANSPORT_PS_NOT_CONNECTED,
227 GNUNET_TIME_UNIT_ZERO_ABS);
228 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
229 return;
230 }
231 /* not quite what we expected, reconnect */
232 GNUNET_break (0);
233 reconnect_peer_ctx (pal_ctx);
234}
235
236
237/**
238 * Function called to check responses from the service.
239 *
240 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
241 * @param pir_msg message with the human-readable address
242 * @return #GNUNET_OK if @a pir_msg is well-formed
243 */
244static int
245check_response (void *cls,
246 const struct PeerIterateResponseMessage *pir_msg)
247{
248 uint16_t size = ntohs (pir_msg->header.size) - sizeof(*pir_msg);
249 size_t alen = ntohl (pir_msg->addrlen);
250 size_t tlen = ntohl (pir_msg->pluginlen);
251 const char *addr;
252 const char *transport_name;
253
254 if (size != tlen + alen)
255 {
256 GNUNET_break (0);
257 return GNUNET_SYSERR;
258 }
259 if ((0 == tlen) && (0 == alen))
260 return GNUNET_OK;
261 if (0 == tlen)
262 {
263 GNUNET_break (0); /* This must not happen: address without plugin */
264 return GNUNET_SYSERR;
265 }
266 addr = (const char *) &pir_msg[1];
267 transport_name = &addr[alen];
268 if (transport_name[tlen - 1] != '\0')
269 {
270 GNUNET_break (0);
271 return GNUNET_SYSERR;
272 }
273 return GNUNET_OK;
274}
275
276
277/**
278 * Function called with responses from the service.
279 *
280 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
281 * @param msg message with the human-readable address
282 */
283static void
284handle_response (void *cls,
285 const struct PeerIterateResponseMessage *pir_msg)
286{
287 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
288 struct GNUNET_HELLO_Address *address;
289 size_t alen = ntohl (pir_msg->addrlen);
290 size_t tlen = ntohl (pir_msg->pluginlen);
291 const char *addr;
292 const char *transport_name;
293
294 if ((0 == tlen) &&
295 (0 == alen))
296 {
297 /* No address available */
298 pal_ctx->cb (pal_ctx->cb_cls,
299 &pir_msg->peer,
300 NULL,
301 ntohl (pir_msg->state),
302 GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
303 return;
304 }
305 addr = (const char *) &pir_msg[1];
306 transport_name = &addr[alen];
307
308 /* notify client */
309 address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
310 transport_name,
311 addr,
312 alen,
313 ntohl (pir_msg->local_address_info));
314 pal_ctx->cb (pal_ctx->cb_cls,
315 &pir_msg->peer,
316 address,
317 ntohl (pir_msg->state),
318 GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
319 GNUNET_HELLO_address_free (address);
320}
321
322
323/**
324 * Generic error handler, called with the appropriate error code and
325 * the same closure specified at the creation of the message queue.
326 * Not every message queue implementation supports an error handler.
327 *
328 * @param cls closure with the `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
329 * @param error error code
330 */
331static void
332mq_error_handler (void *cls,
333 enum GNUNET_MQ_Error error)
334{
335 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
336
337 if (pal_ctx->one_shot)
338 {
339 /* Disconnect */
340 pal_ctx->cb (pal_ctx->cb_cls,
341 NULL,
342 NULL,
343 GNUNET_TRANSPORT_PS_NOT_CONNECTED,
344 GNUNET_TIME_UNIT_ZERO_ABS);
345 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
346 return;
347 }
348 reconnect_peer_ctx (pal_ctx);
349}
350
351
352/**
353 * Task run to re-establish the connection.
354 *
355 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
356 */
357static void
358do_peer_connect (void *cls)
359{
360 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
361 struct GNUNET_MQ_MessageHandler handlers[] = {
362 GNUNET_MQ_hd_var_size (response,
363 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE,
364 struct PeerIterateResponseMessage,
365 pal_ctx),
366 GNUNET_MQ_hd_fixed_size (response_end,
367 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE_END,
368 struct GNUNET_MessageHeader,
369 pal_ctx),
370 GNUNET_MQ_handler_end ()
371 };
372 struct PeerMonitorMessage *msg;
373 struct GNUNET_MQ_Envelope *env;
374
375 pal_ctx->reconnect_task = NULL;
376 pal_ctx->mq = GNUNET_CLIENT_connect (pal_ctx->cfg,
377 "transport",
378 handlers,
379 &mq_error_handler,
380 pal_ctx);
381 if (NULL == pal_ctx->mq)
382 return;
383 env = GNUNET_MQ_msg (msg,
384 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST);
385 msg->one_shot = htonl (pal_ctx->one_shot);
386 msg->peer = pal_ctx->peer;
387 GNUNET_MQ_send (pal_ctx->mq,
388 env);
389}
390
391
392/**
393 * Return information about a specific peer or all peers currently known to
394 * transport service once or in monitoring mode. To obtain information about
395 * a specific peer, a peer identity can be passed. To obtain information about
396 * all peers currently known to transport service, NULL can be passed as peer
397 * identity.
398 *
399 * For each peer, the callback is called with information about the address used
400 * to communicate with this peer, the state this peer is currently in and the
401 * the current timeout for this state.
402 *
403 * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one
404 * more time with 'NULL'. After this, the operation must no longer be
405 * explicitly canceled.
406 *
407 * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
408 * the peer_callback!
409 *
410 * @param cfg configuration to use
411 * @param peer a specific peer identity to obtain information for,
412 * NULL for all peers
413 * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
414 * #GNUNET_NO to monitor peers continuously
415 * @param peer_callback function to call with the results
416 * @param peer_callback_cls closure for @a peer_address_callback
417 */
418struct GNUNET_TRANSPORT_PeerMonitoringContext *
419GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
420 const struct GNUNET_PeerIdentity *peer,
421 int one_shot,
422 GNUNET_TRANSPORT_PeerIterateCallback
423 peer_callback,
424 void *peer_callback_cls)
425{
426 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx
427 = GNUNET_new (struct GNUNET_TRANSPORT_PeerMonitoringContext);
428
429 pal_ctx->cb = peer_callback;
430 pal_ctx->cb_cls = peer_callback_cls;
431 pal_ctx->cfg = cfg;
432 if (NULL != peer)
433 pal_ctx->peer = *peer;
434 pal_ctx->one_shot = one_shot;
435 do_peer_connect (pal_ctx);
436 if (NULL == pal_ctx->mq)
437 {
438 GNUNET_free (pal_ctx);
439 return NULL;
440 }
441 return pal_ctx;
442}
443
444
445/**
446 * Cancel request to monitor peers
447 *
448 * @param pic handle for the request to cancel
449 */
450void
451GNUNET_TRANSPORT_monitor_peers_cancel (struct
452 GNUNET_TRANSPORT_PeerMonitoringContext *
453 pic)
454{
455 if (NULL != pic->mq)
456 {
457 GNUNET_MQ_destroy (pic->mq);
458 pic->mq = NULL;
459 }
460 if (NULL != pic->reconnect_task)
461 {
462 GNUNET_SCHEDULER_cancel (pic->reconnect_task);
463 pic->reconnect_task = NULL;
464 }
465 GNUNET_free (pic);
466}
467
468
469/* end of transport_api_monitor_peers.c */