transport_api_address_to_string.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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
  160. GNUNET_CONFIGURATION_Handle *cfg,
  161. const struct GNUNET_HELLO_Address *address,
  162. int numeric,
  163. struct GNUNET_TIME_Relative timeout,
  164. GNUNET_TRANSPORT_AddressToStringCallback
  165. aluc,
  166. void *aluc_cls)
  167. {
  168. struct GNUNET_TRANSPORT_AddressToStringContext *alc
  169. = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
  170. struct GNUNET_MQ_MessageHandler handlers[] = {
  171. GNUNET_MQ_hd_var_size (reply,
  172. GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY,
  173. struct AddressToStringResultMessage,
  174. alc),
  175. GNUNET_MQ_handler_end ()
  176. };
  177. size_t alen;
  178. size_t slen;
  179. struct AddressLookupMessage *msg;
  180. struct GNUNET_MQ_Envelope *env;
  181. char *addrbuf;
  182. alen = address->address_length;
  183. slen = strlen (address->transport_name) + 1;
  184. if ((alen + slen >= GNUNET_MAX_MESSAGE_SIZE
  185. - sizeof(struct AddressLookupMessage)) ||
  186. (alen >= GNUNET_MAX_MESSAGE_SIZE) ||
  187. (slen >= GNUNET_MAX_MESSAGE_SIZE))
  188. {
  189. GNUNET_break (0);
  190. GNUNET_free (alc);
  191. return NULL;
  192. }
  193. alc->cb = aluc;
  194. alc->cb_cls = aluc_cls;
  195. alc->mq = GNUNET_CLIENT_connect (cfg,
  196. "transport",
  197. handlers,
  198. &mq_error_handler,
  199. alc);
  200. if (NULL == alc->mq)
  201. {
  202. GNUNET_break (0);
  203. GNUNET_free (alc);
  204. return NULL;
  205. }
  206. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  207. "Client tries to resolve for peer `%s' address plugin %s len %u\n",
  208. GNUNET_i2s (&address->peer),
  209. address->transport_name,
  210. (unsigned int) address->address_length);
  211. env = GNUNET_MQ_msg_extra (msg,
  212. alen + slen,
  213. GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
  214. msg->numeric_only = htons ((int16_t) numeric);
  215. msg->addrlen = htons ((uint16_t) alen);
  216. msg->timeout = GNUNET_TIME_relative_hton (timeout);
  217. addrbuf = (char *) &msg[1];
  218. GNUNET_memcpy (addrbuf,
  219. address->address,
  220. alen);
  221. GNUNET_memcpy (&addrbuf[alen],
  222. address->transport_name,
  223. slen);
  224. GNUNET_MQ_send (alc->mq,
  225. env);
  226. return alc;
  227. }
  228. /**
  229. * Cancel request for address conversion.
  230. *
  231. * @param alc the context handle
  232. */
  233. void
  234. GNUNET_TRANSPORT_address_to_string_cancel (struct
  235. GNUNET_TRANSPORT_AddressToStringContext
  236. *alc)
  237. {
  238. GNUNET_MQ_destroy (alc->mq);
  239. GNUNET_free (alc);
  240. }
  241. /* end of transport_api_address_to_string.c */