aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api_monitoring.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport_api_monitoring.c')
-rw-r--r--src/transport/transport_api_monitoring.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/src/transport/transport_api_monitoring.c b/src/transport/transport_api_monitoring.c
new file mode 100644
index 000000000..d7bc56e09
--- /dev/null
+++ b/src/transport/transport_api_monitoring.c
@@ -0,0 +1,460 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file transport/transport_api_montoring.c
23 * @brief montoring api for transport peer status and validation entries
24 *
25 * This api provides the ability to query the transport service about
26 * the status of a specific or all peers as well as address validation entries.
27 *
28 * Calls back with information about peer(s) including address used, state and
29 * state timeout for peer requests and address, address lifetime and next revalidation
30 * for validation entries.
31 */
32#include "platform.h"
33#include "gnunet_util_lib.h"
34#include "gnunet_arm_service.h"
35#include "gnunet_hello_lib.h"
36#include "gnunet_protocols.h"
37#include "gnunet_transport_service.h"
38#include "transport.h"
39
40/**
41 * Context for iterating validation entries.
42 */
43struct GNUNET_TRANSPORT_PeerMonitoringContext
44{
45 /**
46 * Function to call with the binary address.
47 */
48 GNUNET_TRANSPORT_PeerIterateCallback cb;
49
50 /**
51 * Closure for cb.
52 */
53 void *cb_cls;
54
55 /**
56 * Connection to the service.
57 */
58 struct GNUNET_CLIENT_Connection *client;
59
60 /**
61 * Configuration we use.
62 */
63 const struct GNUNET_CONFIGURATION_Handle *cfg;
64
65 /**
66 * When should this operation time out?
67 */
68 struct GNUNET_TIME_Absolute timeout;
69
70 /**
71 * Backoff for reconnect.
72 */
73 struct GNUNET_TIME_Relative backoff;
74
75 /**
76 * Task ID for reconnect.
77 */
78 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
79
80 /**
81 * Identity of the peer to monitor.
82 */
83 struct GNUNET_PeerIdentity peer;
84
85 /**
86 * Was this a one-shot request?
87 */
88 int one_shot;
89};
90
91
92/**
93 * Context for the address lookup.
94 */
95struct GNUNET_TRANSPORT_ValidationMonitoringContext
96{
97 /**
98 * Function to call with the binary address.
99 */
100 GNUNET_TRANSPORT_ValidationIterateCallback cb;
101
102 /**
103 * Closure for cb.
104 */
105 void *cb_cls;
106
107 /**
108 * Connection to the service.
109 */
110 struct GNUNET_CLIENT_Connection *client;
111
112 /**
113 * Configuration we use.
114 */
115 const struct GNUNET_CONFIGURATION_Handle *cfg;
116
117 /**
118 * When should this operation time out?
119 */
120 struct GNUNET_TIME_Absolute timeout;
121
122 /**
123 * Backoff for reconnect.
124 */
125 struct GNUNET_TIME_Relative backoff;
126
127 /**
128 * Task ID for reconnect.
129 */
130 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
131
132 /**
133 * Identity of the peer to monitor.
134 */
135 struct GNUNET_PeerIdentity peer;
136
137 /**
138 * Was this a one-shot request?
139 */
140 int one_shot;
141};
142
143
144
145/**
146 * Function called with responses from the service.
147 *
148 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
149 * @param msg NULL on timeout or error, otherwise presumably a
150 * message with the human-readable address
151 */
152static void
153peer_address_response_processor (void *cls,
154 const struct GNUNET_MessageHeader *msg);
155
156
157/**
158 * Send our subscription request to the service.
159 *
160 * @param pal_ctx our context
161 */
162static void
163send_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
164{
165 struct PeerIterateMessage msg;
166
167 msg.header.size = htons (sizeof (struct PeerIterateMessage));
168 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE);
169 msg.one_shot = htonl (pal_ctx->one_shot);
170 msg.timeout = GNUNET_TIME_absolute_hton (pal_ctx->timeout);
171 msg.peer = pal_ctx->peer;
172 GNUNET_assert (GNUNET_OK ==
173 GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
174 &msg.header,
175 GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
176 GNUNET_YES,
177 &peer_address_response_processor,
178 pal_ctx));
179}
180
181/**
182 * Task run to re-establish the connection.
183 *
184 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
185 * @param tc scheduler context, unused
186 */
187static void
188do_connect (void *cls,
189 const struct GNUNET_SCHEDULER_TaskContext *tc)
190{
191 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
192
193 pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
194 pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
195 GNUNET_assert (NULL != pal_ctx->client);
196 send_request (pal_ctx);
197}
198
199
200/**
201 * Cut the existing connection and reconnect.
202 *
203 * @param pal_ctx our context
204 */
205static void
206reconnect (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
207{
208 GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
209 GNUNET_CLIENT_disconnect (pal_ctx->client);
210 pal_ctx->client = NULL;
211 pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff);
212 pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff,
213 &do_connect,
214 pal_ctx);
215}
216
217
218/**
219 * Function called with responses from the service.
220 *
221 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
222 * @param msg NULL on timeout or error, otherwise presumably a
223 * message with the human-readable address
224 */
225static void
226peer_address_response_processor (void *cls,
227 const struct GNUNET_MessageHeader *msg)
228{
229 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
230 struct PeerIterateResponseMessage *air_msg;
231 struct GNUNET_HELLO_Address *address;
232 const char *addr;
233 const char *transport_name;
234 uint16_t size;
235 size_t alen;
236 size_t tlen;
237
238 if (msg == NULL)
239 {
240 if (pal_ctx->one_shot)
241 {
242 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
243 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
244 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
245 }
246 else
247 {
248 reconnect (pal_ctx);
249 }
250 return;
251 }
252 size = ntohs (msg->size);
253 GNUNET_break (ntohs (msg->type) ==
254 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE);
255 if (size == sizeof (struct GNUNET_MessageHeader))
256 {
257 /* done! */
258 if (pal_ctx->one_shot)
259 {
260 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
261 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
262 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
263 }
264 else
265 {
266 reconnect (pal_ctx);
267 }
268 return;
269 }
270
271 if ((size < sizeof (struct PeerIterateResponseMessage)) ||
272 (ntohs (msg->type) !=
273 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE))
274 {
275 GNUNET_break (0);
276 if (pal_ctx->one_shot)
277 {
278 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
279 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
280 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
281 }
282 else
283 {
284 reconnect (pal_ctx);
285 }
286 return;
287 }
288
289 air_msg = (struct PeerIterateResponseMessage *) msg;
290 tlen = ntohl (air_msg->pluginlen);
291 alen = ntohl (air_msg->addrlen);
292
293 if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
294 {
295 GNUNET_break (0);
296 if (pal_ctx->one_shot)
297 {
298 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
299 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
300 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
301 }
302 else
303 {
304 reconnect (pal_ctx);
305 }
306 return;
307 }
308
309 if (alen == 0 && tlen == 0)
310 {
311 pal_ctx->cb (pal_ctx->cb_cls, &air_msg->peer, NULL,
312 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
313 }
314 else
315 {
316 addr = (const char *) &air_msg[1];
317 transport_name = &addr[alen];
318
319 if (transport_name[tlen - 1] != '\0')
320 {
321 GNUNET_break (0);
322 if (pal_ctx->one_shot)
323 {
324 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
325 S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
326 GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
327 }
328 else
329 {
330 reconnect (pal_ctx);
331 }
332 return;
333 }
334
335 /* notify client */
336 address = GNUNET_HELLO_address_allocate (&air_msg->peer,
337 transport_name, addr, alen);
338 pal_ctx->cb (pal_ctx->cb_cls, &air_msg->peer, address,
339 ntohl(air_msg->state),
340 GNUNET_TIME_absolute_ntoh (air_msg->state_timeout));
341 GNUNET_HELLO_address_free (address);
342 }
343
344 /* expect more replies */
345 GNUNET_CLIENT_receive (pal_ctx->client, &peer_address_response_processor,
346 pal_ctx,
347 GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout));
348}
349
350
351/**
352 * Return all the known addresses for a specific peer or all peers.
353 * Returns continuously all address if one_shot is set to GNUNET_NO
354 *
355 * CHANGE: Returns the address(es) that we are currently using for this
356 * peer. Upon completion, the 'AddressLookUpCallback' is called one more
357 * time with 'NULL' for the address and the peer. After this, the operation must no
358 * longer be explicitly canceled.
359 *
360 * @param cfg configuration to use
361 * @param peer peer identity to look up the addresses of, CHANGE: allow NULL for all (connected) peers
362 * @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL),
363 * GNUNET_NO to monitor the set of addresses used (continuously, must be explicitly canceled)
364 * @param timeout how long is the lookup allowed to take at most (irrelevant if one_shot is set to GNUNET_NO)
365 * @param peer_address_callback function to call with the results
366 * @param peer_address_callback_cls closure for peer_address_callback
367 */
368struct GNUNET_TRANSPORT_PeerMonitoringContext *
369GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
370 const struct GNUNET_PeerIdentity *peer,
371 int one_shot,
372 struct GNUNET_TIME_Relative timeout,
373 GNUNET_TRANSPORT_PeerIterateCallback peer_address_callback,
374 void *peer_address_callback_cls)
375{
376 struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx;
377 struct GNUNET_CLIENT_Connection *client;
378
379 client = GNUNET_CLIENT_connect ("transport", cfg);
380 if (client == NULL)
381 return NULL;
382 if (GNUNET_YES != one_shot)
383 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
384 pal_ctx = GNUNET_new (struct GNUNET_TRANSPORT_PeerMonitoringContext);
385 pal_ctx->cb = peer_address_callback;
386 pal_ctx->cb_cls = peer_address_callback_cls;
387 pal_ctx->cfg = cfg;
388 pal_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
389 if (NULL != peer)
390 pal_ctx->peer = *peer;
391 pal_ctx->one_shot = one_shot;
392 pal_ctx->client = client;
393 send_request (pal_ctx);
394
395 return pal_ctx;
396}
397
398
399/**
400 * Cancel request for address conversion.
401 *
402 * @param alc handle for the request to cancel
403 */
404void
405GNUNET_TRANSPORT_monitor_peers_cancel (
406 struct GNUNET_TRANSPORT_PeerMonitoringContext *alc)
407{
408 if (NULL != alc->client)
409 {
410 GNUNET_CLIENT_disconnect (alc->client);
411 alc->client = NULL;
412 }
413 if (GNUNET_SCHEDULER_NO_TASK != alc->reconnect_task)
414 {
415 GNUNET_SCHEDULER_cancel (alc->reconnect_task);
416 alc->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
417 }
418 GNUNET_free (alc);
419}
420
421
422/**
423 * Return information about a peer's or all current pending validation operations
424 *
425 * @param cfg configuration to use
426 * @param peer a specific peer identity to obtain validation entries for,
427 * NULL for all peers
428 * @param one_shot GNUNET_YES to return all entries and then end (with NULL+NULL),
429 * GNUNET_NO to monitor validation entries continuously
430 * @param timeout how long is the lookup allowed to take at most
431 * @param peer_address_callback function to call with the results
432 * @param peer_address_callback_cls closure for peer_address_callback
433 */
434struct GNUNET_TRANSPORT_ValidationMonitoringContext *
435GNUNET_TRANSPORT_monitor_validation_entries (const struct
436 GNUNET_CONFIGURATION_Handle *cfg,
437 const struct GNUNET_PeerIdentity *peer,
438 int one_shot,
439 struct GNUNET_TIME_Relative timeout,
440 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
441 void *validation_callback_cls)
442{
443 /* Not implemented */
444 return NULL;
445}
446
447
448/**
449 * Return information about all current pending validation operations
450 *
451 * @param vic handle for the request to cancel
452 */
453void
454GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
455{
456 /* Not implemented */
457}
458
459
460/* end of transport_api_montoring.c */