aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-06-22 20:08:16 +0000
committerChristian Grothoff <christian@grothoff.org>2014-06-22 20:08:16 +0000
commiteeaa12c3dbd18925c1177cfc66f52711b612fd9e (patch)
tree012f822b6d20f324f68ea29d9fe2237a0716935e /src/transport
parent194669680385bd40ce7c84b11021b21b6ed6d295 (diff)
downloadgnunet-eeaa12c3dbd18925c1177cfc66f52711b612fd9e.tar.gz
gnunet-eeaa12c3dbd18925c1177cfc66f52711b612fd9e.zip
-split up transport_api_monitoring into monitor_peers and monitor_validation
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/Makefile.am15
-rw-r--r--src/transport/transport_api_monitor_peers.c (renamed from src/transport/transport_api_monitoring.c)399
-rw-r--r--src/transport/transport_api_monitor_validation.c424
3 files changed, 438 insertions, 400 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 5f35125dc..5a4a443a7 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -33,13 +33,13 @@ if HAVE_LIBGNURL
33 HTTP_REL_TEST = test_transport_api_reliability_http 33 HTTP_REL_TEST = test_transport_api_reliability_http
34 HTTP_QUOTA_TEST = test_quota_compliance_http \ 34 HTTP_QUOTA_TEST = test_quota_compliance_http \
35 test_quota_compliance_http_asymmetric 35 test_quota_compliance_http_asymmetric
36 HTTP_SWITCH = test_transport_address_switch_http 36 HTTP_SWITCH = test_transport_address_switch_http
37 HTTPS_API_TEST = test_transport_api_https 37 HTTPS_API_TEST = test_transport_api_https
38 HTTPS_API_TIMEOUT_TEST = test_transport_api_timeout_https 38 HTTPS_API_TIMEOUT_TEST = test_transport_api_timeout_https
39 HTTPS_REL_TEST = test_transport_api_reliability_https 39 HTTPS_REL_TEST = test_transport_api_reliability_https
40 HTTPS_QUOTA_TEST = test_quota_compliance_https \ 40 HTTPS_QUOTA_TEST = test_quota_compliance_https \
41 test_quota_compliance_https_asymmetric 41 test_quota_compliance_https_asymmetric
42 HTTPS_SWITCH = test_transport_address_switch_https 42 HTTPS_SWITCH = test_transport_address_switch_https
43endif 43endif
44endif 44endif
45 45
@@ -137,7 +137,8 @@ libgnunettransport_la_SOURCES = \
137 transport_api.c transport.h \ 137 transport_api.c transport.h \
138 transport_api_blacklist.c \ 138 transport_api_blacklist.c \
139 transport_api_address_to_string.c \ 139 transport_api_address_to_string.c \
140 transport_api_monitoring.c 140 transport_api_monitor_peers.c \
141 transport_api_monitor_validation.c
141libgnunettransport_la_LIBADD = \ 142libgnunettransport_la_LIBADD = \
142 $(top_builddir)/src/hello/libgnunethello.la \ 143 $(top_builddir)/src/hello/libgnunethello.la \
143 $(top_builddir)/src/util/libgnunetutil.la \ 144 $(top_builddir)/src/util/libgnunetutil.la \
@@ -1032,7 +1033,7 @@ test_transport_address_switch_tcp_LDADD = \
1032 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 1033 $(top_builddir)/src/statistics/libgnunetstatistics.la \
1033 $(top_builddir)/src/util/libgnunetutil.la \ 1034 $(top_builddir)/src/util/libgnunetutil.la \
1034 $(top_builddir)/src/transport/libgnunettransporttesting.la 1035 $(top_builddir)/src/transport/libgnunettransporttesting.la
1035 1036
1036 test_transport_address_switch_udp_SOURCES = \ 1037 test_transport_address_switch_udp_SOURCES = \
1037 test_transport_address_switch.c 1038 test_transport_address_switch.c
1038test_transport_address_switch_udp_LDADD = \ 1039test_transport_address_switch_udp_LDADD = \
@@ -1041,8 +1042,8 @@ test_transport_address_switch_udp_LDADD = \
1041 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 1042 $(top_builddir)/src/statistics/libgnunetstatistics.la \
1042 $(top_builddir)/src/util/libgnunetutil.la \ 1043 $(top_builddir)/src/util/libgnunetutil.la \
1043 $(top_builddir)/src/transport/libgnunettransporttesting.la 1044 $(top_builddir)/src/transport/libgnunettransporttesting.la
1044 1045
1045 1046
1046 test_transport_address_switch_http_SOURCES = \ 1047 test_transport_address_switch_http_SOURCES = \
1047 test_transport_address_switch.c 1048 test_transport_address_switch.c
1048test_transport_address_switch_http_LDADD = \ 1049test_transport_address_switch_http_LDADD = \
@@ -1051,7 +1052,7 @@ test_transport_address_switch_http_LDADD = \
1051 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 1052 $(top_builddir)/src/statistics/libgnunetstatistics.la \
1052 $(top_builddir)/src/util/libgnunetutil.la \ 1053 $(top_builddir)/src/util/libgnunetutil.la \
1053 $(top_builddir)/src/transport/libgnunettransporttesting.la 1054 $(top_builddir)/src/transport/libgnunettransporttesting.la
1054 1055
1055 test_transport_address_switch_https_SOURCES = \ 1056 test_transport_address_switch_https_SOURCES = \
1056 test_transport_address_switch.c 1057 test_transport_address_switch.c
1057test_transport_address_switch_https_LDADD = \ 1058test_transport_address_switch_https_LDADD = \
diff --git a/src/transport/transport_api_monitoring.c b/src/transport/transport_api_monitor_peers.c
index adea00278..e04819711 100644
--- a/src/transport/transport_api_monitoring.c
+++ b/src/transport/transport_api_monitor_peers.c
@@ -19,15 +19,14 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file transport/transport_api_monitoring.c 22 * @file transport/transport_api_monitor_peers.c
23 * @brief montoring api for transport peer status and validation entries 23 * @brief montoring api for transport peer status
24 * 24 *
25 * This api provides the ability to query the transport service about 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. 26 * the connection status of a specific or all peers.
27 * 27 *
28 * Calls back with information about peer(s) including address used, state and 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 29 * state timeout for peer requests.
30 * for validation entries.
31 */ 30 */
32#include "platform.h" 31#include "platform.h"
33#include "gnunet_util_lib.h" 32#include "gnunet_util_lib.h"
@@ -90,58 +89,6 @@ struct GNUNET_TRANSPORT_PeerMonitoringContext
90 89
91 90
92/** 91/**
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 @e 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 * Check if a state is defined as connected 92 * Check if a state is defined as connected
146 * 93 *
147 * @param state the state value 94 * @param state the state value
@@ -218,37 +165,9 @@ GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
218 165
219 166
220/** 167/**
221 * Convert validation state to human-readable string.
222 *
223 * @param state the state value
224 * @return corresponding string
225 */
226const char *
227GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
228{
229 switch (state)
230 {
231 case GNUNET_TRANSPORT_VS_NONE:
232 return "NONE";
233 case GNUNET_TRANSPORT_VS_NEW:
234 return "NEW";
235 case GNUNET_TRANSPORT_VS_REMOVE:
236 return "REMOVE";
237 case GNUNET_TRANSPORT_VS_TIMEOUT:
238 return "TIMEOUT";
239 case GNUNET_TRANSPORT_VS_UPDATE:
240 return "UPDATE";
241 default:
242 GNUNET_break (0);
243 return "UNDEFINED";
244 }
245}
246
247
248/**
249 * Function called with responses from the service. 168 * Function called with responses from the service.
250 * 169 *
251 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*' 170 * @param cls our `struct GNUNET_TRANSPORT_PeerAddressLookupContext *`
252 * @param msg NULL on timeout or error, otherwise presumably a 171 * @param msg NULL on timeout or error, otherwise presumably a
253 * message with the human-readable address 172 * message with the human-readable address
254 */ 173 */
@@ -258,18 +177,6 @@ peer_response_processor (void *cls,
258 177
259 178
260/** 179/**
261 * Function called with responses from the service.
262 *
263 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
264 * @param msg NULL on timeout or error, otherwise presumably a
265 * message with the human-readable address
266 */
267static void
268val_response_processor (void *cls,
269 const struct GNUNET_MessageHeader *msg);
270
271
272/**
273 * Send our subscription request to the service. 180 * Send our subscription request to the service.
274 * 181 *
275 * @param pal_ctx our context 182 * @param pal_ctx our context
@@ -294,29 +201,6 @@ send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
294 201
295 202
296/** 203/**
297 * Send our subscription request to the service.
298 *
299 * @param val_ctx our context
300 */
301static void
302send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
303{
304 struct ValidationMonitorMessage msg;
305
306 msg.header.size = htons (sizeof (struct ValidationMonitorMessage));
307 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
308 msg.one_shot = htonl (val_ctx->one_shot);
309 msg.peer = val_ctx->peer;
310 GNUNET_assert (GNUNET_OK ==
311 GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
312 &msg.header,
313 GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
314 GNUNET_YES,
315 &val_response_processor,
316 val_ctx));
317}
318
319/**
320 * Task run to re-establish the connection. 204 * Task run to re-establish the connection.
321 * 205 *
322 * @param cls our `struct GNUNET_TRANSPORT_PeerAddressLookupContext *` 206 * @param cls our `struct GNUNET_TRANSPORT_PeerAddressLookupContext *`
@@ -357,211 +241,6 @@ reconnect_peer_ctx (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
357 241
358 242
359/** 243/**
360 * Task run to re-establish the connection.
361 *
362 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
363 * @param tc scheduler context, unused
364 */
365static void
366do_val_connect (void *cls,
367 const struct GNUNET_SCHEDULER_TaskContext *tc)
368{
369 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
370
371 val_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
372 val_ctx->client = GNUNET_CLIENT_connect ("transport", val_ctx->cfg);
373 GNUNET_assert (NULL != val_ctx->client);
374 send_val_mon_request (val_ctx);
375}
376
377
378/**
379 * Cut the existing connection and reconnect.
380 *
381 * @param val_ctx our context
382 */
383static void
384reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
385{
386 GNUNET_assert (GNUNET_NO == val_ctx->one_shot);
387 GNUNET_CLIENT_disconnect (val_ctx->client);
388 val_ctx->client = NULL;
389 /* notify clients about (re)connect */
390 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
391 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
392 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
393 val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff);
394 val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff,
395 &do_val_connect,
396 val_ctx);
397}
398
399
400/**
401 * Function called with responses from the service.
402 *
403 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
404 * @param msg NULL on timeout or error, otherwise presumably a
405 * message with the human-readable address
406 */
407static void
408val_response_processor (void *cls,
409 const struct GNUNET_MessageHeader *msg)
410{
411 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
412 struct ValidationIterateResponseMessage *vr_msg;
413 struct GNUNET_HELLO_Address *address;
414 const char *addr;
415 const char *transport_name;
416 size_t size;
417 size_t tlen;
418 size_t alen;
419
420 if (NULL == msg)
421 {
422 if (val_ctx->one_shot)
423 {
424 /* Disconnect */
425 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
426 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
427 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
428 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
429 }
430 else
431 {
432 reconnect_val_ctx (val_ctx);
433 }
434 return;
435 }
436 size = ntohs (msg->size);
437 GNUNET_break (ntohs (msg->type) ==
438 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
439
440 if (size == sizeof (struct GNUNET_MessageHeader))
441 {
442 /* Done! */
443 if (val_ctx->one_shot)
444 {
445 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
446 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
447 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
448 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
449 }
450 else
451 {
452 reconnect_val_ctx (val_ctx);
453 }
454 return;
455 }
456
457 if ((size < sizeof (struct ValidationIterateResponseMessage)) ||
458 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE))
459 {
460 GNUNET_break (0);
461 if (val_ctx->one_shot)
462 {
463 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
464 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
465 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
466 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
467 }
468 else
469 {
470 reconnect_val_ctx (val_ctx);
471 }
472 return;
473 }
474
475 vr_msg = (struct ValidationIterateResponseMessage *) msg;
476 tlen = ntohl (vr_msg->pluginlen);
477 alen = ntohl (vr_msg->addrlen);
478
479 if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen)
480 {
481 GNUNET_break (0);
482 if (val_ctx->one_shot)
483 {
484 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
485 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
486 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
487 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
488 }
489 else
490 {
491 reconnect_val_ctx (val_ctx);
492 }
493 return;
494 }
495 if ( (0 == tlen) && (0 == alen) )
496 {
497 GNUNET_break (0);
498 if (val_ctx->one_shot)
499 {
500 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
501 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
502 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
503 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
504 }
505 else
506 {
507 reconnect_val_ctx (val_ctx);
508 }
509 return;
510 }
511 else
512 {
513 if (0 == tlen)
514 {
515 GNUNET_break (0); /* This must not happen: address without plugin */
516 return;
517 }
518 addr = (const char *) &vr_msg[1];
519 transport_name = &addr[alen];
520
521 if (transport_name[tlen - 1] != '\0')
522 {
523 /* Corrupt plugin name */
524 GNUNET_break (0);
525 if (val_ctx->one_shot)
526 {
527 val_ctx->cb (val_ctx->cb_cls,
528 NULL, NULL,
529 GNUNET_TIME_UNIT_ZERO_ABS,
530 GNUNET_TIME_UNIT_ZERO_ABS,
531 GNUNET_TIME_UNIT_ZERO_ABS,
532 GNUNET_TRANSPORT_VS_NONE);
533 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
534 }
535 else
536 {
537 reconnect_val_ctx (val_ctx);
538 }
539 return;
540 }
541
542 /* notify client */
543 address = GNUNET_HELLO_address_allocate (&vr_msg->peer,
544 transport_name,
545 addr, alen,
546 ntohl (vr_msg->local_address_info));
547 val_ctx->cb (val_ctx->cb_cls,
548 &vr_msg->peer,
549 address,
550 GNUNET_TIME_absolute_ntoh (vr_msg->last_validation),
551 GNUNET_TIME_absolute_ntoh (vr_msg->valid_until),
552 GNUNET_TIME_absolute_ntoh (vr_msg->next_validation),
553 ntohl(vr_msg->state));
554 GNUNET_HELLO_address_free (address);
555 }
556 /* expect more replies */
557 GNUNET_CLIENT_receive (val_ctx->client,
558 &val_response_processor,
559 val_ctx,
560 GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
561}
562
563
564/**
565 * Function called with responses from the service. 244 * Function called with responses from the service.
566 * 245 *
567 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *` 246 * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
@@ -785,70 +464,4 @@ GNUNET_TRANSPORT_monitor_peers_cancel (struct GNUNET_TRANSPORT_PeerMonitoringCon
785} 464}
786 465
787 466
788/** 467/* end of transport_api_monitor_peers.c */
789 * Return information about pending address validation operations for a specific
790 * or all peers
791 *
792 * @param cfg configuration to use
793 * @param peer a specific peer identity to obtain validation entries for,
794 * NULL for all peers
795 * @param one_shot #GNUNET_YES to return all entries and then end (with NULL+NULL),
796 * #GNUNET_NO to monitor validation entries continuously
797 * @param timeout how long is the lookup allowed to take at most
798 * @param validation_callback function to call with the results
799 * @param validation_callback_cls closure for peer_address_callback
800 */
801struct GNUNET_TRANSPORT_ValidationMonitoringContext *
802GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg,
803 const struct GNUNET_PeerIdentity *peer,
804 int one_shot,
805 struct GNUNET_TIME_Relative timeout,
806 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
807 void *validation_callback_cls)
808{
809 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
810 struct GNUNET_CLIENT_Connection *client;
811
812 client = GNUNET_CLIENT_connect ("transport", cfg);
813 if (client == NULL)
814 return NULL;
815 if (GNUNET_YES != one_shot)
816 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
817 val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
818 val_ctx->cb = validation_callback;
819 val_ctx->cb_cls = validation_callback_cls;
820 val_ctx->cfg = cfg;
821 val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
822 if (NULL != peer)
823 val_ctx->peer = *peer;
824 val_ctx->one_shot = one_shot;
825 val_ctx->client = client;
826 send_val_mon_request (val_ctx);
827
828 return val_ctx;
829}
830
831
832/**
833 * Return information about all current pending validation operations
834 *
835 * @param vic handle for the request to cancel
836 */
837void
838GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
839{
840 if (NULL != vic->client)
841 {
842 GNUNET_CLIENT_disconnect (vic->client);
843 vic->client = NULL;
844 }
845 if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
846 {
847 GNUNET_SCHEDULER_cancel (vic->reconnect_task);
848 vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
849 }
850 GNUNET_free (vic);
851}
852
853
854/* end of transport_api_monitoring.c */
diff --git a/src/transport/transport_api_monitor_validation.c b/src/transport/transport_api_monitor_validation.c
new file mode 100644
index 000000000..621a6b00e
--- /dev/null
+++ b/src/transport/transport_api_monitor_validation.c
@@ -0,0 +1,424 @@
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_monitor_validation.c
23 * @brief montoring api for validation status
24 *
25 * This api provides the ability to query the transport service about
26 * the status of address validation.
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_arm_service.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_protocols.h"
33#include "gnunet_transport_service.h"
34#include "transport.h"
35
36
37/**
38 * Context for the address lookup.
39 */
40struct GNUNET_TRANSPORT_ValidationMonitoringContext
41{
42 /**
43 * Function to call with the binary address.
44 */
45 GNUNET_TRANSPORT_ValidationIterateCallback cb;
46
47 /**
48 * Closure for @e cb.
49 */
50 void *cb_cls;
51
52 /**
53 * Connection to the service.
54 */
55 struct GNUNET_CLIENT_Connection *client;
56
57 /**
58 * Configuration we use.
59 */
60 const struct GNUNET_CONFIGURATION_Handle *cfg;
61
62 /**
63 * When should this operation time out?
64 */
65 struct GNUNET_TIME_Absolute timeout;
66
67 /**
68 * Backoff for reconnect.
69 */
70 struct GNUNET_TIME_Relative backoff;
71
72 /**
73 * Task ID for reconnect.
74 */
75 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
76
77 /**
78 * Identity of the peer to monitor.
79 */
80 struct GNUNET_PeerIdentity peer;
81
82 /**
83 * Was this a one-shot request?
84 */
85 int one_shot;
86};
87
88
89/**
90 * Convert validation state to human-readable string.
91 *
92 * @param state the state value
93 * @return corresponding string
94 */
95const char *
96GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
97{
98 switch (state)
99 {
100 case GNUNET_TRANSPORT_VS_NONE:
101 return "NONE";
102 case GNUNET_TRANSPORT_VS_NEW:
103 return "NEW";
104 case GNUNET_TRANSPORT_VS_REMOVE:
105 return "REMOVE";
106 case GNUNET_TRANSPORT_VS_TIMEOUT:
107 return "TIMEOUT";
108 case GNUNET_TRANSPORT_VS_UPDATE:
109 return "UPDATE";
110 default:
111 GNUNET_break (0);
112 return "UNDEFINED";
113 }
114}
115
116
117/**
118 * Function called with responses from the service.
119 *
120 * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
121 * @param msg NULL on timeout or error, otherwise presumably a
122 * message with the human-readable address
123 */
124static void
125val_response_processor (void *cls,
126 const struct GNUNET_MessageHeader *msg);
127
128
129/**
130 * Send our subscription request to the service.
131 *
132 * @param val_ctx our context
133 */
134static void
135send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
136{
137 struct ValidationMonitorMessage msg;
138
139 msg.header.size = htons (sizeof (struct ValidationMonitorMessage));
140 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
141 msg.one_shot = htonl (val_ctx->one_shot);
142 msg.peer = val_ctx->peer;
143 GNUNET_assert (GNUNET_OK ==
144 GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
145 &msg.header,
146 GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
147 GNUNET_YES,
148 &val_response_processor,
149 val_ctx));
150}
151
152
153/**
154 * Task run to re-establish the connection.
155 *
156 * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
157 * @param tc scheduler context, unused
158 */
159static void
160do_val_connect (void *cls,
161 const struct GNUNET_SCHEDULER_TaskContext *tc)
162{
163 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
164
165 val_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
166 val_ctx->client = GNUNET_CLIENT_connect ("transport", val_ctx->cfg);
167 GNUNET_assert (NULL != val_ctx->client);
168 send_val_mon_request (val_ctx);
169}
170
171
172/**
173 * Cut the existing connection and reconnect.
174 *
175 * @param val_ctx our context
176 */
177static void
178reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
179{
180 GNUNET_assert (GNUNET_NO == val_ctx->one_shot);
181 GNUNET_CLIENT_disconnect (val_ctx->client);
182 val_ctx->client = NULL;
183 /* notify clients about (re)connect */
184 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
185 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
186 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
187 val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff);
188 val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff,
189 &do_val_connect,
190 val_ctx);
191}
192
193
194/**
195 * Function called with responses from the service.
196 *
197 * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
198 * @param msg NULL on timeout or error, otherwise presumably a
199 * message with the human-readable address
200 */
201static void
202val_response_processor (void *cls,
203 const struct GNUNET_MessageHeader *msg)
204{
205 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
206 struct ValidationIterateResponseMessage *vr_msg;
207 struct GNUNET_HELLO_Address *address;
208 const char *addr;
209 const char *transport_name;
210 size_t size;
211 size_t tlen;
212 size_t alen;
213
214 if (NULL == msg)
215 {
216 if (val_ctx->one_shot)
217 {
218 /* Disconnect */
219 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
220 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
221 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
222 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
223 }
224 else
225 {
226 reconnect_val_ctx (val_ctx);
227 }
228 return;
229 }
230 size = ntohs (msg->size);
231 GNUNET_break (ntohs (msg->type) ==
232 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
233
234 if (size == sizeof (struct GNUNET_MessageHeader))
235 {
236 /* Done! */
237 if (val_ctx->one_shot)
238 {
239 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
240 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
241 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
242 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
243 }
244 else
245 {
246 reconnect_val_ctx (val_ctx);
247 }
248 return;
249 }
250
251 if ((size < sizeof (struct ValidationIterateResponseMessage)) ||
252 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE))
253 {
254 GNUNET_break (0);
255 if (val_ctx->one_shot)
256 {
257 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
258 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
259 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
260 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
261 }
262 else
263 {
264 reconnect_val_ctx (val_ctx);
265 }
266 return;
267 }
268
269 vr_msg = (struct ValidationIterateResponseMessage *) msg;
270 tlen = ntohl (vr_msg->pluginlen);
271 alen = ntohl (vr_msg->addrlen);
272
273 if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen)
274 {
275 GNUNET_break (0);
276 if (val_ctx->one_shot)
277 {
278 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
279 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
280 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
281 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
282 }
283 else
284 {
285 reconnect_val_ctx (val_ctx);
286 }
287 return;
288 }
289 if ( (0 == tlen) && (0 == alen) )
290 {
291 GNUNET_break (0);
292 if (val_ctx->one_shot)
293 {
294 val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
295 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
296 GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
297 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
298 }
299 else
300 {
301 reconnect_val_ctx (val_ctx);
302 }
303 return;
304 }
305 else
306 {
307 if (0 == tlen)
308 {
309 GNUNET_break (0); /* This must not happen: address without plugin */
310 return;
311 }
312 addr = (const char *) &vr_msg[1];
313 transport_name = &addr[alen];
314
315 if (transport_name[tlen - 1] != '\0')
316 {
317 /* Corrupt plugin name */
318 GNUNET_break (0);
319 if (val_ctx->one_shot)
320 {
321 val_ctx->cb (val_ctx->cb_cls,
322 NULL, NULL,
323 GNUNET_TIME_UNIT_ZERO_ABS,
324 GNUNET_TIME_UNIT_ZERO_ABS,
325 GNUNET_TIME_UNIT_ZERO_ABS,
326 GNUNET_TRANSPORT_VS_NONE);
327 GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
328 }
329 else
330 {
331 reconnect_val_ctx (val_ctx);
332 }
333 return;
334 }
335
336 /* notify client */
337 address = GNUNET_HELLO_address_allocate (&vr_msg->peer,
338 transport_name,
339 addr, alen,
340 ntohl (vr_msg->local_address_info));
341 val_ctx->cb (val_ctx->cb_cls,
342 &vr_msg->peer,
343 address,
344 GNUNET_TIME_absolute_ntoh (vr_msg->last_validation),
345 GNUNET_TIME_absolute_ntoh (vr_msg->valid_until),
346 GNUNET_TIME_absolute_ntoh (vr_msg->next_validation),
347 ntohl(vr_msg->state));
348 GNUNET_HELLO_address_free (address);
349 }
350 /* expect more replies */
351 GNUNET_CLIENT_receive (val_ctx->client,
352 &val_response_processor,
353 val_ctx,
354 GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
355}
356
357
358/**
359 * Return information about pending address validation operations for a specific
360 * or all peers
361 *
362 * @param cfg configuration to use
363 * @param peer a specific peer identity to obtain validation entries for,
364 * NULL for all peers
365 * @param one_shot #GNUNET_YES to return all entries and then end (with NULL+NULL),
366 * #GNUNET_NO to monitor validation entries continuously
367 * @param timeout how long is the lookup allowed to take at most
368 * @param validation_callback function to call with the results
369 * @param validation_callback_cls closure for peer_address_callback
370 */
371struct GNUNET_TRANSPORT_ValidationMonitoringContext *
372GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg,
373 const struct GNUNET_PeerIdentity *peer,
374 int one_shot,
375 struct GNUNET_TIME_Relative timeout,
376 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
377 void *validation_callback_cls)
378{
379 struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
380 struct GNUNET_CLIENT_Connection *client;
381
382 client = GNUNET_CLIENT_connect ("transport", cfg);
383 if (NULL == client)
384 return NULL;
385 if (GNUNET_YES != one_shot)
386 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
387 val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
388 val_ctx->cb = validation_callback;
389 val_ctx->cb_cls = validation_callback_cls;
390 val_ctx->cfg = cfg;
391 val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
392 if (NULL != peer)
393 val_ctx->peer = *peer;
394 val_ctx->one_shot = one_shot;
395 val_ctx->client = client;
396 send_val_mon_request (val_ctx);
397
398 return val_ctx;
399}
400
401
402/**
403 * Return information about all current pending validation operations
404 *
405 * @param vic handle for the request to cancel
406 */
407void
408GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
409{
410 if (NULL != vic->client)
411 {
412 GNUNET_CLIENT_disconnect (vic->client);
413 vic->client = NULL;
414 }
415 if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
416 {
417 GNUNET_SCHEDULER_cancel (vic->reconnect_task);
418 vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
419 }
420 GNUNET_free (vic);
421}
422
423
424/* end of transport_api_monitor_validation.c */