transport validation monitoring API (not yet complete) + CLI
[oweals/gnunet.git] / src / transport / transport_api_monitoring.c
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_monitoring.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  */
43 struct 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  */
95 struct 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  * Check if a state is defined as connected
145  *
146  * @param state the state value
147  * @return GNUNET_YES or GNUNET_NO
148  */
149 int
150 GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
151 {
152   switch (state)
153   {
154   case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
155   case GNUNET_TRANSPORT_PS_INIT_ATS:
156   case GNUNET_TRANSPORT_PS_INIT_BLACKLIST:
157   case GNUNET_TRANSPORT_PS_CONNECT_SENT:
158   case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST_INBOUND:
159   case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS:
160   case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST:
161   case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK:
162     return GNUNET_NO;
163   case GNUNET_TRANSPORT_PS_CONNECTED:
164   case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
165   case GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST:
166   case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
167   case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST:
168   case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT:
169     return GNUNET_YES;
170   case GNUNET_TRANSPORT_PS_DISCONNECT:
171   case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
172     return GNUNET_NO;
173   default:
174     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
175                 "Unhandled state `%s' \n",
176                 GNUNET_TRANSPORT_ps2s (state));
177     GNUNET_break (0);
178     break;
179   }
180   return GNUNET_SYSERR;
181 }
182
183 /**
184  * Convert peer state to human-readable string.
185  *
186  * @param state the state value
187  * @return corresponding string
188  */
189 const char *
190 GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
191 {
192   switch (state)
193   {
194   case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
195     return "S_NOT_CONNECTED";
196   case GNUNET_TRANSPORT_PS_INIT_ATS:
197     return "S_INIT_ATS";
198   case GNUNET_TRANSPORT_PS_INIT_BLACKLIST:
199     return "S_INIT_BLACKLIST";
200   case GNUNET_TRANSPORT_PS_CONNECT_SENT:
201     return "S_CONNECT_SENT";
202   case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST_INBOUND:
203     return "S_CONNECT_RECV_BLACKLIST_INBOUND";
204   case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS:
205     return "S_CONNECT_RECV_ATS";
206   case GNUNET_TRANSPORT_PS_CONNECT_RECV_BLACKLIST:
207     return "S_CONNECT_RECV_BLACKLIST";
208   case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK:
209     return "S_CONNECT_RECV_ACK";
210   case GNUNET_TRANSPORT_PS_CONNECTED:
211     return "S_CONNECTED";
212   case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
213     return "S_RECONNECT_ATS";
214   case GNUNET_TRANSPORT_PS_RECONNECT_BLACKLIST:
215     return "S_RECONNECT_BLACKLIST";
216   case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
217     return "S_RECONNECT_SENT";
218   case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_BLACKLIST:
219     return "S_CONNECTED_SWITCHING_BLACKLIST";
220   case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT:
221     return "S_CONNECTED_SWITCHING_CONNECT_SENT";
222   case GNUNET_TRANSPORT_PS_DISCONNECT:
223     return "S_DISCONNECT";
224   case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
225     return "S_DISCONNECT_FINISHED";
226   default:
227     GNUNET_break (0);
228     return "UNDEFINED";
229   }
230 }
231
232 /**
233  * Convert validation state to human-readable string.
234  *
235  * @param state the state value
236  * @return corresponding string
237  */
238 const char *
239 GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
240 {
241   switch (state)
242   {
243   case GNUNET_TRANSPORT_VS_NEW:
244     return "NEW";
245   case GNUNET_TRANSPORT_VS_REMOVE:
246     return "REMOVE";
247   case GNUNET_TRANSPORT_VS_TIMEOUT:
248     return "TIMEOUT";
249   case GNUNET_TRANSPORT_VS_UPDATE:
250     return "UPDATE";
251   default:
252     GNUNET_break (0);
253     return "UNDEFINED";
254   }
255 }
256
257
258 /**
259  * Function called with responses from the service.
260  *
261  * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
262  * @param msg NULL on timeout or error, otherwise presumably a
263  *        message with the human-readable address
264  */
265 static void
266 peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
267
268
269 /**
270  * Function called with responses from the service.
271  *
272  * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
273  * @param msg NULL on timeout or error, otherwise presumably a
274  *        message with the human-readable address
275  */
276 static void
277 val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
278
279 /**
280  * Send our subscription request to the service.
281  *
282  * @param pal_ctx our context
283  */
284 static void
285 send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
286 {
287   struct PeerMonitorMessage msg;
288
289   msg.header.size = htons (sizeof (struct PeerMonitorMessage));
290   msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST);
291   msg.one_shot = htonl (pal_ctx->one_shot);
292   msg.peer = pal_ctx->peer;
293   GNUNET_assert (GNUNET_OK ==
294                  GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
295                     &msg.header,
296                     GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
297                     GNUNET_YES,
298                     &peer_response_processor,
299                     pal_ctx));
300 }
301
302 /**
303  * Send our subscription request to the service.
304  *
305  * @param pal_ctx our context
306  */
307 static void
308 send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
309 {
310   struct ValidationMonitorMessage msg;
311
312   msg.header.size = htons (sizeof (struct PeerMonitorMessage));
313   msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
314   msg.one_shot = htonl (val_ctx->one_shot);
315   msg.peer = val_ctx->peer;
316   GNUNET_assert (GNUNET_OK ==
317                  GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
318                     &msg.header,
319                     GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
320                     GNUNET_YES,
321                     &val_response_processor,
322                     val_ctx));
323 }
324
325
326 /**
327  * Task run to re-establish the connection.
328  *
329  * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
330  * @param tc scheduler context, unused
331  */
332 static void
333 do_connect (void *cls,
334             const struct GNUNET_SCHEDULER_TaskContext *tc)
335 {
336   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
337
338   pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
339   pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
340   GNUNET_assert (NULL != pal_ctx->client);
341   send_peer_mon_request (pal_ctx);
342 }
343
344
345 /**
346  * Cut the existing connection and reconnect.
347  *
348  * @param pal_ctx our context
349  */
350 static void
351 reconnect (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
352 {
353   GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
354   GNUNET_CLIENT_disconnect (pal_ctx->client);
355   pal_ctx->client = NULL;
356   pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff);
357   pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff,
358                                                           &do_connect,
359                                                           pal_ctx);
360 }
361
362 /**
363  * Function called with responses from the service.
364  *
365  * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
366  * @param msg NULL on timeout or error, otherwise presumably a
367  *        message with the human-readable address
368  */
369 static void
370 val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
371 {
372   struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
373   GNUNET_break (0);
374   if (msg == NULL)
375   {
376     GNUNET_break (0);
377     if (val_ctx->one_shot)
378     {
379       /* Disconnect */
380       val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
381           GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
382           GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
383       GNUNET_TRANSPORT_monitor_peers_cancel (val_ctx);
384     }
385     else
386     {
387       reconnect (val_ctx);
388     }
389     return;
390   }
391
392   /* expect more replies */
393   GNUNET_CLIENT_receive (val_ctx->client, &val_response_processor,
394       val_ctx, GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
395
396   return;
397
398   struct ValidationIterateResponseMessage *vir_msg;
399   struct GNUNET_HELLO_Address *address;
400   const char *addr;
401   const char *transport_name;
402   uint16_t size;
403   size_t alen;
404   size_t tlen;
405 #if 0
406
407   size = ntohs (msg->size);
408   GNUNET_break (ntohs (msg->type) ==
409       GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
410   if (size == sizeof (struct GNUNET_MessageHeader))
411   {
412     /* Done! */
413     if (pal_ctx->one_shot)
414     {
415       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
416           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
417       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
418     }
419     else
420     {
421       reconnect (pal_ctx);
422     }
423     return;
424   }
425
426   if ((size < sizeof (struct PeerIterateResponseMessage)) ||
427       (ntohs (msg->type) !=
428           GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
429   {
430     GNUNET_break (0);
431     if (pal_ctx->one_shot)
432     {
433       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
434           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
435       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
436     }
437     else
438     {
439       reconnect (pal_ctx);
440     }
441     return;
442   }
443
444   pir_msg = (struct PeerIterateResponseMessage *) msg;
445   tlen = ntohl (pir_msg->pluginlen);
446   alen = ntohl (pir_msg->addrlen);
447
448   if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
449   {
450     GNUNET_break (0);
451     if (pal_ctx->one_shot)
452     {
453       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
454           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
455       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
456     }
457     else
458     {
459       reconnect (pal_ctx);
460     }
461     return;
462   }
463
464   if ( (0 == tlen) && (0 == alen) )
465   {
466     /* No address available */
467     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
468         ntohl(pir_msg->state),
469         GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
470   }
471   else
472   {
473     if (0 == tlen)
474     {
475       GNUNET_break (0); /* This must not happen: address without plugin */
476       return;
477     }
478     addr = (const char *) &pir_msg[1];
479     transport_name = &addr[alen];
480
481     if (transport_name[tlen - 1] != '\0')
482     {
483       /* Corrupt plugin name */
484       GNUNET_break (0);
485       if (pal_ctx->one_shot)
486       {
487         pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
488             GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
489         GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
490       }
491       else
492       {
493         reconnect (pal_ctx);
494       }
495       return;
496     }
497
498     /* notify client */
499     address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
500         transport_name, addr, alen, ntohl(pir_msg->local_address_info));
501     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
502         ntohl(pir_msg->state),
503         GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
504     GNUNET_HELLO_address_free (address);
505   }
506 #endif
507
508 }
509
510
511 /**
512  * Function called with responses from the service.
513  *
514  * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
515  * @param msg NULL on timeout or error, otherwise presumably a
516  *        message with the human-readable address
517  */
518 static void
519 peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
520 {
521   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
522   struct PeerIterateResponseMessage *pir_msg;
523   struct GNUNET_HELLO_Address *address;
524   const char *addr;
525   const char *transport_name;
526   uint16_t size;
527   size_t alen;
528   size_t tlen;
529   GNUNET_break (0);
530   if (msg == NULL)
531   {
532     if (pal_ctx->one_shot)
533     {
534       /* Disconnect */
535       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
536           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
537       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
538     }
539     else
540     {
541       reconnect (pal_ctx);
542     }
543     return;
544   }
545   size = ntohs (msg->size);
546   GNUNET_break (ntohs (msg->type) ==
547       GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
548   if (size == sizeof (struct GNUNET_MessageHeader))
549   {
550     /* Done! */
551     if (pal_ctx->one_shot)
552     {
553       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
554           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
555       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
556     }
557     else
558     {
559       reconnect (pal_ctx);
560     }
561     return;
562   }
563
564   if ((size < sizeof (struct PeerIterateResponseMessage)) ||
565       (ntohs (msg->type) !=
566           GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
567   {
568     GNUNET_break (0);
569     if (pal_ctx->one_shot)
570     {
571       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
572           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
573       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
574     }
575     else
576     {
577       reconnect (pal_ctx);
578     }
579     return;
580   }
581
582   pir_msg = (struct PeerIterateResponseMessage *) msg;
583   tlen = ntohl (pir_msg->pluginlen);
584   alen = ntohl (pir_msg->addrlen);
585
586   if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
587   {
588     GNUNET_break (0);
589     if (pal_ctx->one_shot)
590     {
591       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
592           GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
593       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
594     }
595     else
596     {
597       reconnect (pal_ctx);
598     }
599     return;
600   }
601
602   if ( (0 == tlen) && (0 == alen) )
603   {
604     /* No address available */
605     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
606         ntohl(pir_msg->state),
607         GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
608   }
609   else
610   {
611     if (0 == tlen)
612     {
613       GNUNET_break (0); /* This must not happen: address without plugin */
614       return;
615     }
616     addr = (const char *) &pir_msg[1];
617     transport_name = &addr[alen];
618
619     if (transport_name[tlen - 1] != '\0')
620     {
621       /* Corrupt plugin name */
622       GNUNET_break (0);
623       if (pal_ctx->one_shot)
624       {
625         pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
626             GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
627         GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
628       }
629       else
630       {
631         reconnect (pal_ctx);
632       }
633       return;
634     }
635
636     /* notify client */
637     address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
638         transport_name, addr, alen, ntohl(pir_msg->local_address_info));
639     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
640         ntohl(pir_msg->state),
641         GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
642     GNUNET_HELLO_address_free (address);
643
644   }
645
646   /* expect more replies */
647   GNUNET_CLIENT_receive (pal_ctx->client, &peer_response_processor,
648                          pal_ctx,
649                          GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout));
650 }
651
652
653 /**
654  * Return information about a specific peer or all peers currently known to
655  * transport service once or in monitoring mode. To obtain information about
656  * a specific peer, a peer identity can be passed. To obtain information about
657  * all peers currently known to transport service, NULL can be passed as peer
658  * identity.
659  *
660  * For each peer, the callback is called with information about the address used
661  * to communicate with this peer, the state this peer is currently in and the
662  * the current timeout for this state.
663  *
664  * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one
665  * more time with 'NULL'. After this, the operation must no longer be
666  * explicitly canceled.
667  *
668  * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
669  * the peer_callback!
670  *
671  * @param cfg configuration to use
672  * @param peer a specific peer identity to obtain information for,
673  *      NULL for all peers
674  * @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL),
675  *                 GNUNET_NO to monitor peers continuously
676  * @param timeout how long is the lookup allowed to take at most
677  * @param peer_callback function to call with the results
678  * @param peer_callback_cls closure for peer_address_callback
679  */
680 struct GNUNET_TRANSPORT_PeerMonitoringContext *
681 GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
682     const struct GNUNET_PeerIdentity *peer,
683     int one_shot,
684     struct GNUNET_TIME_Relative timeout,
685     GNUNET_TRANSPORT_PeerIterateCallback peer_callback,
686     void *peer_callback_cls)
687 {
688   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx;
689   struct GNUNET_CLIENT_Connection *client;
690
691   client = GNUNET_CLIENT_connect ("transport", cfg);
692   if (client == NULL)
693     return NULL;
694   if (GNUNET_YES != one_shot)
695     timeout = GNUNET_TIME_UNIT_FOREVER_REL;
696   pal_ctx = GNUNET_new (struct GNUNET_TRANSPORT_PeerMonitoringContext);
697   pal_ctx->cb = peer_callback;
698   pal_ctx->cb_cls = peer_callback_cls;
699   pal_ctx->cfg = cfg;
700   pal_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
701   if (NULL != peer)
702     pal_ctx->peer = *peer;
703   pal_ctx->one_shot = one_shot;
704   pal_ctx->client = client;
705   send_peer_mon_request (pal_ctx);
706
707   return pal_ctx;
708 }
709
710
711 /**
712  * Cancel request to monitor peers
713  *
714  * @param pic handle for the request to cancel
715  */
716 void
717 GNUNET_TRANSPORT_monitor_peers_cancel (struct GNUNET_TRANSPORT_PeerMonitoringContext *pic)
718 {
719   if (NULL != pic->client)
720   {
721     GNUNET_CLIENT_disconnect (pic->client);
722     pic->client = NULL;
723   }
724   if (GNUNET_SCHEDULER_NO_TASK != pic->reconnect_task)
725   {
726     GNUNET_SCHEDULER_cancel (pic->reconnect_task);
727     pic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
728   }
729   GNUNET_free (pic);
730 }
731
732
733 /**
734  * Return information about pending address validation operations for a specific
735  * or all peers
736  *
737  * @param cfg configuration to use
738  * @param peer a specific peer identity to obtain validation entries for,
739  *      NULL for all peers
740  * @param one_shot GNUNET_YES to return all entries and then end (with NULL+NULL),
741  *                 GNUNET_NO to monitor validation entries continuously
742  * @param timeout how long is the lookup allowed to take at most
743  * @param validation_callback function to call with the results
744  * @param validation_callback_cls closure for peer_address_callback
745  */
746 struct GNUNET_TRANSPORT_ValidationMonitoringContext *
747 GNUNET_TRANSPORT_monitor_validation_entries (const struct
748                                 GNUNET_CONFIGURATION_Handle *cfg,
749                                 const struct GNUNET_PeerIdentity *peer,
750                                 int one_shot,
751                                 struct GNUNET_TIME_Relative timeout,
752                                 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
753                                 void *validation_callback_cls)
754 {
755   struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
756   struct GNUNET_CLIENT_Connection *client;
757
758   client = GNUNET_CLIENT_connect ("transport", cfg);
759   if (client == NULL)
760     return NULL;
761   if (GNUNET_YES != one_shot)
762     timeout = GNUNET_TIME_UNIT_FOREVER_REL;
763   val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
764   val_ctx->cb = validation_callback;
765   val_ctx->cb_cls = validation_callback_cls;
766   val_ctx->cfg = cfg;
767   val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
768   if (NULL != peer)
769     val_ctx->peer = *peer;
770   val_ctx->one_shot = one_shot;
771   val_ctx->client = client;
772   send_val_mon_request (val_ctx);
773
774   return val_ctx;
775 }
776
777
778 /**
779  * Return information about all current pending validation operations
780  *
781  * @param vic handle for the request to cancel
782  */
783 void
784 GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
785 {
786   if (NULL != vic->client)
787   {
788     GNUNET_CLIENT_disconnect (vic->client);
789     vic->client = NULL;
790   }
791   if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
792   {
793     GNUNET_SCHEDULER_cancel (vic->reconnect_task);
794     vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
795   }
796   GNUNET_free (vic);
797 }
798
799
800 /* end of transport_api_monitoring.c */