transport_api_monitor_validation.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file transport/transport_api_monitor_validation.c
  19. * @brief montoring api for validation status
  20. *
  21. * This api provides the ability to query the transport service about
  22. * the status of address validation.
  23. */
  24. #include "platform.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_arm_service.h"
  27. #include "gnunet_hello_lib.h"
  28. #include "gnunet_protocols.h"
  29. #include "gnunet_transport_service.h"
  30. #include "transport.h"
  31. /**
  32. * Context for the address lookup.
  33. */
  34. struct GNUNET_TRANSPORT_ValidationMonitoringContext
  35. {
  36. /**
  37. * Function to call with the binary address.
  38. */
  39. GNUNET_TRANSPORT_ValidationIterateCallback cb;
  40. /**
  41. * Closure for @e cb.
  42. */
  43. void *cb_cls;
  44. /**
  45. * Connection to the service.
  46. */
  47. struct GNUNET_CLIENT_Connection *client;
  48. /**
  49. * Configuration we use.
  50. */
  51. const struct GNUNET_CONFIGURATION_Handle *cfg;
  52. /**
  53. * When should this operation time out?
  54. */
  55. struct GNUNET_TIME_Absolute timeout;
  56. /**
  57. * Backoff for reconnect.
  58. */
  59. struct GNUNET_TIME_Relative backoff;
  60. /**
  61. * Task ID for reconnect.
  62. */
  63. GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
  64. /**
  65. * Identity of the peer to monitor.
  66. */
  67. struct GNUNET_PeerIdentity peer;
  68. /**
  69. * Was this a one-shot request?
  70. */
  71. int one_shot;
  72. };
  73. /**
  74. * Convert validation state to human-readable string.
  75. *
  76. * @param state the state value
  77. * @return corresponding string
  78. */
  79. const char *
  80. GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
  81. {
  82. switch (state)
  83. {
  84. case GNUNET_TRANSPORT_VS_NONE:
  85. return "NONE";
  86. case GNUNET_TRANSPORT_VS_NEW:
  87. return "NEW";
  88. case GNUNET_TRANSPORT_VS_REMOVE:
  89. return "REMOVE";
  90. case GNUNET_TRANSPORT_VS_TIMEOUT:
  91. return "TIMEOUT";
  92. case GNUNET_TRANSPORT_VS_UPDATE:
  93. return "UPDATE";
  94. default:
  95. GNUNET_break (0);
  96. return "UNDEFINED";
  97. }
  98. }
  99. /**
  100. * Function called with responses from the service.
  101. *
  102. * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
  103. * @param msg NULL on timeout or error, otherwise presumably a
  104. * message with the human-readable address
  105. */
  106. static void
  107. val_response_processor (void *cls,
  108. const struct GNUNET_MessageHeader *msg);
  109. /**
  110. * Send our subscription request to the service.
  111. *
  112. * @param val_ctx our context
  113. */
  114. static void
  115. send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
  116. {
  117. struct ValidationMonitorMessage msg;
  118. msg.header.size = htons (sizeof (struct ValidationMonitorMessage));
  119. msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
  120. msg.one_shot = htonl (val_ctx->one_shot);
  121. msg.peer = val_ctx->peer;
  122. GNUNET_assert (GNUNET_OK ==
  123. GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
  124. &msg.header,
  125. GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
  126. GNUNET_YES,
  127. &val_response_processor,
  128. val_ctx));
  129. }
  130. /**
  131. * Task run to re-establish the connection.
  132. *
  133. * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
  134. * @param tc scheduler context, unused
  135. */
  136. static void
  137. do_val_connect (void *cls,
  138. const struct GNUNET_SCHEDULER_TaskContext *tc)
  139. {
  140. struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
  141. val_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
  142. val_ctx->client = GNUNET_CLIENT_connect ("transport", val_ctx->cfg);
  143. GNUNET_assert (NULL != val_ctx->client);
  144. send_val_mon_request (val_ctx);
  145. }
  146. /**
  147. * Cut the existing connection and reconnect.
  148. *
  149. * @param val_ctx our context
  150. */
  151. static void
  152. reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
  153. {
  154. GNUNET_assert (GNUNET_NO == val_ctx->one_shot);
  155. GNUNET_CLIENT_disconnect (val_ctx->client);
  156. val_ctx->client = NULL;
  157. /* notify clients about (re)connect */
  158. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  159. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  160. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
  161. val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff);
  162. val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff,
  163. &do_val_connect,
  164. val_ctx);
  165. }
  166. /**
  167. * Function called with responses from the service.
  168. *
  169. * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
  170. * @param msg NULL on timeout or error, otherwise presumably a
  171. * message with the human-readable address
  172. */
  173. static void
  174. val_response_processor (void *cls,
  175. const struct GNUNET_MessageHeader *msg)
  176. {
  177. struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
  178. struct ValidationIterateResponseMessage *vr_msg;
  179. struct GNUNET_HELLO_Address *address;
  180. const char *addr;
  181. const char *transport_name;
  182. size_t size;
  183. size_t tlen;
  184. size_t alen;
  185. if (NULL == msg)
  186. {
  187. if (val_ctx->one_shot)
  188. {
  189. /* Disconnect */
  190. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  191. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  192. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
  193. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  194. }
  195. else
  196. {
  197. reconnect_val_ctx (val_ctx);
  198. }
  199. return;
  200. }
  201. size = ntohs (msg->size);
  202. GNUNET_break (ntohs (msg->type) ==
  203. GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
  204. if (size == sizeof (struct GNUNET_MessageHeader))
  205. {
  206. /* Done! */
  207. if (val_ctx->one_shot)
  208. {
  209. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  210. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  211. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
  212. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  213. }
  214. else
  215. {
  216. reconnect_val_ctx (val_ctx);
  217. }
  218. return;
  219. }
  220. if ((size < sizeof (struct ValidationIterateResponseMessage)) ||
  221. (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE))
  222. {
  223. GNUNET_break (0);
  224. if (val_ctx->one_shot)
  225. {
  226. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  227. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  228. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
  229. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  230. }
  231. else
  232. {
  233. reconnect_val_ctx (val_ctx);
  234. }
  235. return;
  236. }
  237. vr_msg = (struct ValidationIterateResponseMessage *) msg;
  238. tlen = ntohl (vr_msg->pluginlen);
  239. alen = ntohl (vr_msg->addrlen);
  240. if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen)
  241. {
  242. GNUNET_break (0);
  243. if (val_ctx->one_shot)
  244. {
  245. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  246. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  247. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
  248. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  249. }
  250. else
  251. {
  252. reconnect_val_ctx (val_ctx);
  253. }
  254. return;
  255. }
  256. if ( (0 == tlen) && (0 == alen) )
  257. {
  258. GNUNET_break (0);
  259. if (val_ctx->one_shot)
  260. {
  261. val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
  262. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
  263. GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
  264. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  265. }
  266. else
  267. {
  268. reconnect_val_ctx (val_ctx);
  269. }
  270. return;
  271. }
  272. else
  273. {
  274. if (0 == tlen)
  275. {
  276. GNUNET_break (0); /* This must not happen: address without plugin */
  277. return;
  278. }
  279. addr = (const char *) &vr_msg[1];
  280. transport_name = &addr[alen];
  281. if (transport_name[tlen - 1] != '\0')
  282. {
  283. /* Corrupt plugin name */
  284. GNUNET_break (0);
  285. if (val_ctx->one_shot)
  286. {
  287. val_ctx->cb (val_ctx->cb_cls,
  288. NULL, NULL,
  289. GNUNET_TIME_UNIT_ZERO_ABS,
  290. GNUNET_TIME_UNIT_ZERO_ABS,
  291. GNUNET_TIME_UNIT_ZERO_ABS,
  292. GNUNET_TRANSPORT_VS_NONE);
  293. GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
  294. }
  295. else
  296. {
  297. reconnect_val_ctx (val_ctx);
  298. }
  299. return;
  300. }
  301. /* notify client */
  302. address = GNUNET_HELLO_address_allocate (&vr_msg->peer,
  303. transport_name,
  304. addr, alen,
  305. ntohl (vr_msg->local_address_info));
  306. val_ctx->cb (val_ctx->cb_cls,
  307. &vr_msg->peer,
  308. address,
  309. GNUNET_TIME_absolute_ntoh (vr_msg->last_validation),
  310. GNUNET_TIME_absolute_ntoh (vr_msg->valid_until),
  311. GNUNET_TIME_absolute_ntoh (vr_msg->next_validation),
  312. ntohl(vr_msg->state));
  313. GNUNET_HELLO_address_free (address);
  314. }
  315. /* expect more replies */
  316. GNUNET_CLIENT_receive (val_ctx->client,
  317. &val_response_processor,
  318. val_ctx,
  319. GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
  320. }
  321. /**
  322. * Return information about pending address validation operations for a specific
  323. * or all peers
  324. *
  325. * @param cfg configuration to use
  326. * @param peer a specific peer identity to obtain validation entries for,
  327. * NULL for all peers
  328. * @param one_shot #GNUNET_YES to return all entries and then end (with NULL+NULL),
  329. * #GNUNET_NO to monitor validation entries continuously
  330. * @param timeout how long is the lookup allowed to take at most
  331. * @param validation_callback function to call with the results
  332. * @param validation_callback_cls closure for peer_address_callback
  333. */
  334. struct GNUNET_TRANSPORT_ValidationMonitoringContext *
  335. GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg,
  336. const struct GNUNET_PeerIdentity *peer,
  337. int one_shot,
  338. struct GNUNET_TIME_Relative timeout,
  339. GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
  340. void *validation_callback_cls)
  341. {
  342. struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
  343. struct GNUNET_CLIENT_Connection *client;
  344. client = GNUNET_CLIENT_connect ("transport", cfg);
  345. if (NULL == client)
  346. return NULL;
  347. if (GNUNET_YES != one_shot)
  348. timeout = GNUNET_TIME_UNIT_FOREVER_REL;
  349. val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
  350. val_ctx->cb = validation_callback;
  351. val_ctx->cb_cls = validation_callback_cls;
  352. val_ctx->cfg = cfg;
  353. val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
  354. if (NULL != peer)
  355. val_ctx->peer = *peer;
  356. val_ctx->one_shot = one_shot;
  357. val_ctx->client = client;
  358. send_val_mon_request (val_ctx);
  359. return val_ctx;
  360. }
  361. /**
  362. * Return information about all current pending validation operations
  363. *
  364. * @param vic handle for the request to cancel
  365. */
  366. void
  367. GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
  368. {
  369. if (NULL != vic->client)
  370. {
  371. GNUNET_CLIENT_disconnect (vic->client);
  372. vic->client = NULL;
  373. }
  374. if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
  375. {
  376. GNUNET_SCHEDULER_cancel (vic->reconnect_task);
  377. vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
  378. }
  379. GNUNET_free (vic);
  380. }
  381. /* end of transport_api_monitor_validation.c */