transport_api_address_to_string.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009-2014, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file transport/transport_api_address_to_string.c
  18. * @author Christian Grothoff
  19. * @brief enable clients to convert addresses to human readable strings
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_arm_service.h"
  24. #include "gnunet_hello_lib.h"
  25. #include "gnunet_protocols.h"
  26. #include "gnunet_transport_service.h"
  27. #include "transport.h"
  28. /**
  29. * Context for the address lookup.
  30. */
  31. struct GNUNET_TRANSPORT_AddressToStringContext
  32. {
  33. /**
  34. * Function to call with the human-readable address.
  35. */
  36. GNUNET_TRANSPORT_AddressToStringCallback cb;
  37. /**
  38. * Closure for @e cb.
  39. */
  40. void *cb_cls;
  41. /**
  42. * Connection to the service.
  43. */
  44. struct GNUNET_MQ_Handle *mq;
  45. };
  46. /**
  47. * Function called with responses from the service.
  48. *
  49. * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
  50. * @param msg message with the human-readable address
  51. * @return #GNUNET_OK if message is well-formed
  52. */
  53. static int
  54. check_reply (void *cls,
  55. const struct AddressToStringResultMessage *atsm)
  56. {
  57. uint16_t size = ntohs (atsm->header.size) - sizeof (*atsm);
  58. const char *address;
  59. int result;
  60. uint32_t addr_len;
  61. result = (int) ntohl (atsm->res);
  62. addr_len = ntohl (atsm->addr_len);
  63. if (GNUNET_SYSERR == result)
  64. return GNUNET_OK;
  65. if (0 == size)
  66. {
  67. if (GNUNET_OK != result)
  68. {
  69. GNUNET_break (0);
  70. return GNUNET_SYSERR;
  71. }
  72. return GNUNET_OK;
  73. }
  74. address = (const char *) &atsm[1];
  75. if ( (addr_len > size) ||
  76. (address[addr_len -1] != '\0') )
  77. {
  78. /* invalid reply */
  79. GNUNET_break (0);
  80. return GNUNET_SYSERR;
  81. }
  82. return GNUNET_OK;
  83. }
  84. /**
  85. * Function called with responses from the service.
  86. *
  87. * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
  88. * @param msg message with the human-readable address
  89. */
  90. static void
  91. handle_reply (void *cls,
  92. const struct AddressToStringResultMessage *atsm)
  93. {
  94. struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
  95. uint16_t size = ntohs (atsm->header.size) - sizeof (*atsm);
  96. const char *address;
  97. int result;
  98. result = (int) ntohl (atsm->res);
  99. if (GNUNET_SYSERR == result)
  100. {
  101. /* expect more replies; as this is not the last
  102. call, we must pass the empty string for the address */
  103. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  104. "Address resolution failed\n");
  105. alucb->cb (alucb->cb_cls,
  106. "",
  107. GNUNET_NO);
  108. return;
  109. }
  110. if (0 == size)
  111. {
  112. /* we are done (successfully, without communication errors) */
  113. alucb->cb (alucb->cb_cls,
  114. NULL,
  115. GNUNET_OK);
  116. GNUNET_TRANSPORT_address_to_string_cancel (alucb);
  117. return;
  118. }
  119. address = (const char *) &atsm[1];
  120. /* return normal reply to caller, also expect more replies */
  121. alucb->cb (alucb->cb_cls,
  122. address,
  123. GNUNET_OK);
  124. }
  125. /**
  126. * Generic error handler, called with the appropriate
  127. * error code and the same closure specified at the creation of
  128. * the message queue.
  129. * Not every message queue implementation supports an error handler.
  130. *
  131. * @param cls the `struct GNUNET_TRANSPORT_AddressToStringContext *`
  132. * @param error error code
  133. */
  134. static void
  135. mq_error_handler (void *cls,
  136. enum GNUNET_MQ_Error error)
  137. {
  138. struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
  139. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  140. "Disconnected from transport, address resolution failed\n");
  141. alucb->cb (alucb->cb_cls,
  142. NULL,
  143. GNUNET_SYSERR);
  144. GNUNET_TRANSPORT_address_to_string_cancel (alucb);
  145. }
  146. /**
  147. * Convert a binary address into a human readable address.
  148. *
  149. * @param cfg configuration to use
  150. * @param address address to convert (binary format)
  151. * @param numeric should (IP) addresses be displayed in numeric form
  152. * (otherwise do reverse DNS lookup)
  153. * @param timeout how long is the lookup allowed to take at most
  154. * @param aluc function to call with the results
  155. * @param aluc_cls closure for @a aluc
  156. * @return handle to cancel the operation, NULL on error
  157. */
  158. struct GNUNET_TRANSPORT_AddressToStringContext *
  159. GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
  160. const struct GNUNET_HELLO_Address *address,
  161. int numeric,
  162. struct GNUNET_TIME_Relative timeout,
  163. GNUNET_TRANSPORT_AddressToStringCallback aluc,
  164. void *aluc_cls)
  165. {
  166. struct GNUNET_TRANSPORT_AddressToStringContext *alc
  167. = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
  168. struct GNUNET_MQ_MessageHandler handlers[] = {
  169. GNUNET_MQ_hd_var_size (reply,
  170. GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY,
  171. struct AddressToStringResultMessage,
  172. alc),
  173. GNUNET_MQ_handler_end ()
  174. };
  175. size_t alen;
  176. size_t slen;
  177. struct AddressLookupMessage *msg;
  178. struct GNUNET_MQ_Envelope *env;
  179. char *addrbuf;
  180. alen = address->address_length;
  181. slen = strlen (address->transport_name) + 1;
  182. if ( (alen + slen >= GNUNET_MAX_MESSAGE_SIZE
  183. - sizeof (struct AddressLookupMessage)) ||
  184. (alen >= GNUNET_MAX_MESSAGE_SIZE) ||
  185. (slen >= GNUNET_MAX_MESSAGE_SIZE) )
  186. {
  187. GNUNET_break (0);
  188. GNUNET_free (alc);
  189. return NULL;
  190. }
  191. alc->cb = aluc;
  192. alc->cb_cls = aluc_cls;
  193. alc->mq = GNUNET_CLIENT_connect (cfg,
  194. "transport",
  195. handlers,
  196. &mq_error_handler,
  197. alc);
  198. if (NULL == alc->mq)
  199. {
  200. GNUNET_break (0);
  201. GNUNET_free (alc);
  202. return NULL;
  203. }
  204. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  205. "Client tries to resolve for peer `%s' address plugin %s len %u\n",
  206. GNUNET_i2s (&address->peer),
  207. address->transport_name,
  208. (unsigned int) address->address_length);
  209. env = GNUNET_MQ_msg_extra (msg,
  210. alen + slen,
  211. GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
  212. msg->numeric_only = htons ((int16_t) numeric);
  213. msg->addrlen = htons ((uint16_t) alen);
  214. msg->timeout = GNUNET_TIME_relative_hton (timeout);
  215. addrbuf = (char *) &msg[1];
  216. GNUNET_memcpy (addrbuf,
  217. address->address,
  218. alen);
  219. GNUNET_memcpy (&addrbuf[alen],
  220. address->transport_name,
  221. slen);
  222. GNUNET_MQ_send (alc->mq,
  223. env);
  224. return alc;
  225. }
  226. /**
  227. * Cancel request for address conversion.
  228. *
  229. * @param alc the context handle
  230. */
  231. void
  232. GNUNET_TRANSPORT_address_to_string_cancel (struct GNUNET_TRANSPORT_AddressToStringContext *alc)
  233. {
  234. GNUNET_MQ_destroy (alc->mq);
  235. GNUNET_free (alc);
  236. }
  237. /* end of transport_api_address_to_string.c */