plugin_transport_http_common.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2002-2013 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/plugin_transport_http_common.c
  18. * @brief functionality shared between http(s)client plugins
  19. * @author Matthias Wachs
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_transport_plugin.h"
  24. #include "plugin_transport_http_common.h"
  25. #include "gnunet_resolver_service.h"
  26. static void
  27. http_clean_splitted (struct SplittedHTTPAddress *spa)
  28. {
  29. if (NULL != spa)
  30. {
  31. GNUNET_free_non_null(spa->protocol);
  32. GNUNET_free_non_null(spa->host);
  33. GNUNET_free_non_null(spa->path);
  34. GNUNET_free_non_null(spa);
  35. }
  36. }
  37. struct SplittedHTTPAddress *
  38. http_split_address (const char * addr)
  39. {
  40. struct SplittedHTTPAddress *sp;
  41. char *src = GNUNET_strdup (addr);
  42. char *protocol_start = NULL;
  43. char *host_start = NULL;
  44. char *v6_end = NULL;
  45. char *port_start = NULL;
  46. char *path_start = NULL;
  47. protocol_start = src;
  48. sp = GNUNET_new (struct SplittedHTTPAddress);
  49. /* Address string consists of protocol://host[:port]path*/
  50. host_start = strstr (src, "://");
  51. if (NULL == host_start)
  52. {
  53. GNUNET_free(src);
  54. GNUNET_free(sp);
  55. return NULL ;
  56. }
  57. host_start[0] = '\0';
  58. sp->protocol = GNUNET_strdup (protocol_start);
  59. host_start += strlen ("://");
  60. if (strlen (host_start) == 0)
  61. {
  62. GNUNET_free(src);
  63. GNUNET_free(sp->protocol);
  64. GNUNET_free(sp);
  65. return NULL ;
  66. }
  67. /* Find path start */
  68. path_start = strchr (host_start, '/');
  69. if (NULL != path_start)
  70. {
  71. sp->path = GNUNET_strdup (path_start);
  72. path_start[0] = '\0';
  73. }
  74. else
  75. sp->path = GNUNET_strdup ("");
  76. if (strlen (host_start) < 1)
  77. {
  78. GNUNET_free(src);
  79. GNUNET_free(sp->protocol);
  80. GNUNET_free(sp->path);
  81. GNUNET_free(sp);
  82. return NULL ;
  83. }
  84. if (NULL != (port_start = strrchr (host_start, ':')))
  85. {
  86. /* *We COULD have a port, but also an IPv6 address! */
  87. if (NULL != (v6_end = strchr (host_start, ']')))
  88. {
  89. if (v6_end < port_start)
  90. {
  91. /* IPv6 address + port */
  92. port_start[0] = '\0';
  93. port_start++;
  94. sp->port = atoi (port_start);
  95. if ((0 == sp->port) || (65535 < sp->port))
  96. {
  97. GNUNET_free(src);
  98. GNUNET_free(sp->protocol);
  99. GNUNET_free(sp->path);
  100. GNUNET_free(sp);
  101. return NULL ;
  102. }
  103. }
  104. else
  105. {
  106. /* IPv6 address + no port */
  107. if (0 == strcmp (sp->protocol, "https"))
  108. sp->port = HTTPS_DEFAULT_PORT;
  109. else if (0 == strcmp (sp->protocol, "http"))
  110. sp->port = HTTP_DEFAULT_PORT;
  111. }
  112. }
  113. else
  114. {
  115. /* No IPv6 address */
  116. port_start[0] = '\0';
  117. port_start++;
  118. sp->port = atoi (port_start);
  119. if ((0 == sp->port) || (65535 < sp->port))
  120. {
  121. GNUNET_free(src);
  122. GNUNET_free(sp->protocol);
  123. GNUNET_free(sp->path);
  124. GNUNET_free(sp);
  125. return NULL ;
  126. }
  127. }
  128. }
  129. else
  130. {
  131. /* No ':' as port separator, default port for protocol */
  132. if (0 == strcmp (sp->protocol, "https"))
  133. sp->port = HTTPS_DEFAULT_PORT;
  134. else if (0 == strcmp (sp->protocol, "http"))
  135. sp->port = HTTP_DEFAULT_PORT;
  136. else
  137. {
  138. GNUNET_break(0);
  139. GNUNET_free(src);
  140. GNUNET_free(sp->protocol);
  141. GNUNET_free(sp->path);
  142. GNUNET_free(sp);
  143. return NULL ;
  144. }
  145. }
  146. if (strlen (host_start) > 0)
  147. sp->host = GNUNET_strdup (host_start);
  148. else
  149. {
  150. GNUNET_break(0);
  151. GNUNET_free(src);
  152. GNUNET_free(sp->protocol);
  153. GNUNET_free(sp->path);
  154. GNUNET_free(sp);
  155. return NULL ;
  156. }
  157. GNUNET_free(src);
  158. return sp;
  159. }
  160. /**
  161. * Closure for #append_port().
  162. */
  163. struct PrettyPrinterContext
  164. {
  165. /**
  166. * DLL
  167. */
  168. struct PrettyPrinterContext *next;
  169. /**
  170. * DLL
  171. */
  172. struct PrettyPrinterContext *prev;
  173. /**
  174. * Resolver handle
  175. */
  176. struct GNUNET_RESOLVER_RequestHandle *resolver_handle;
  177. /**
  178. * Function to call with the result.
  179. */
  180. GNUNET_TRANSPORT_AddressStringCallback asc;
  181. /**
  182. * Clsoure for @e asc.
  183. */
  184. void *asc_cls;
  185. /**
  186. * Timeout task
  187. */
  188. struct GNUNET_SCHEDULER_Task * timeout_task;
  189. /**
  190. * Splitted Address
  191. */
  192. struct SplittedHTTPAddress *saddr;
  193. /**
  194. * Plugin String
  195. */
  196. char *plugin;
  197. /**
  198. * Was conversion successful
  199. */
  200. int sucess;
  201. /**
  202. * Address options
  203. */
  204. uint32_t options;
  205. };
  206. /**
  207. * Head of PPC list
  208. */
  209. static struct PrettyPrinterContext *dll_ppc_head;
  210. /**
  211. * Tail of PPC list
  212. */
  213. static struct PrettyPrinterContext *dll_ppc_tail;
  214. /**
  215. * Function called for a quick conversion of the binary address to
  216. * a numeric address. Note that the caller must not free the
  217. * address and that the next call to this function is allowed
  218. * to override the address again.
  219. *
  220. * @param plugin the name of the plugin
  221. * @param saddr the splitted http address
  222. * @param options address options
  223. * @param dnsresult dns name to include in address
  224. * @return string representing the same address or NULL on error
  225. */
  226. static const char *
  227. http_common_plugin_dnsresult_to_address (const char *plugin,
  228. const struct SplittedHTTPAddress *saddr,
  229. uint32_t options,
  230. const char *dnsresult)
  231. {
  232. static char rbuf[1024];
  233. char *res;
  234. GNUNET_asprintf (&res, "%s.%u.%s://%s:%u%s", plugin, options, saddr->protocol,
  235. dnsresult, saddr->port, saddr->path);
  236. if (strlen (res) + 1 < 500)
  237. {
  238. GNUNET_memcpy (rbuf, res, strlen (res) + 1);
  239. GNUNET_free(res);
  240. return rbuf;
  241. }
  242. GNUNET_break(0);
  243. GNUNET_free(res);
  244. return NULL ;
  245. }
  246. static void
  247. http_common_dns_reverse_lookup_cb (void *cls, const char *hostname)
  248. {
  249. struct PrettyPrinterContext *ppc = cls;
  250. if (NULL != hostname)
  251. {
  252. ppc->asc (ppc->asc_cls,
  253. http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr, ppc->options,
  254. hostname), GNUNET_OK);
  255. ppc->sucess = GNUNET_YES;
  256. }
  257. else
  258. {
  259. ppc->asc (ppc->asc_cls, NULL,
  260. (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
  261. GNUNET_CONTAINER_DLL_remove(dll_ppc_head, dll_ppc_tail, ppc);
  262. http_clean_splitted (ppc->saddr);
  263. GNUNET_free(ppc->plugin);
  264. GNUNET_free(ppc);
  265. }
  266. }
  267. static int
  268. http_common_dns_reverse_lookup (const struct sockaddr *sockaddr,
  269. socklen_t sockaddr_len,
  270. const char *type,
  271. struct SplittedHTTPAddress *saddr,
  272. uint32_t options,
  273. struct GNUNET_TIME_Relative timeout,
  274. GNUNET_TRANSPORT_AddressStringCallback asc,
  275. void *asc_cls)
  276. {
  277. struct PrettyPrinterContext *ppc;
  278. ppc = GNUNET_new (struct PrettyPrinterContext);
  279. ppc->saddr = saddr;
  280. ppc->asc = asc;
  281. ppc->asc_cls = asc_cls;
  282. ppc->plugin = GNUNET_strdup (type);
  283. ppc->options = options;
  284. ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sockaddr,
  285. sockaddr_len,
  286. GNUNET_YES,
  287. timeout,
  288. &http_common_dns_reverse_lookup_cb,
  289. ppc);
  290. if (NULL == ppc->resolver_handle)
  291. {
  292. GNUNET_free(ppc->plugin);
  293. GNUNET_free(ppc);
  294. return GNUNET_SYSERR;
  295. }
  296. GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
  297. dll_ppc_tail,
  298. ppc);
  299. return GNUNET_OK;
  300. }
  301. static void
  302. http_common_dns_ip_lookup_cb (void *cls,
  303. const struct sockaddr *addr,
  304. socklen_t addrlen)
  305. {
  306. struct PrettyPrinterContext *ppc = cls;
  307. if (NULL != addr)
  308. {
  309. ppc->asc (ppc->asc_cls,
  310. http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr, ppc->options,
  311. GNUNET_a2s (addr, addrlen)), GNUNET_OK);
  312. ppc->sucess = GNUNET_YES;
  313. ppc->asc (ppc->asc_cls, GNUNET_a2s (addr, addrlen), GNUNET_OK);
  314. }
  315. else
  316. {
  317. ppc->asc (ppc->asc_cls, NULL,
  318. (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
  319. GNUNET_CONTAINER_DLL_remove(dll_ppc_head, dll_ppc_tail, ppc);
  320. GNUNET_free(ppc->plugin);
  321. http_clean_splitted (ppc->saddr);
  322. GNUNET_free(ppc);
  323. }
  324. }
  325. static int
  326. http_common_dns_ip_lookup (const char *name,
  327. const char *type,
  328. struct SplittedHTTPAddress *saddr,
  329. uint32_t options,
  330. struct GNUNET_TIME_Relative timeout,
  331. GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls)
  332. {
  333. struct PrettyPrinterContext *ppc;
  334. ppc = GNUNET_new (struct PrettyPrinterContext);
  335. ppc->sucess = GNUNET_NO;
  336. ppc->saddr = saddr;
  337. ppc->asc = asc;
  338. ppc->asc_cls = asc_cls;
  339. ppc->plugin = GNUNET_strdup (type);
  340. ppc->options = options;
  341. ppc->resolver_handle = GNUNET_RESOLVER_ip_get (name,
  342. AF_UNSPEC,
  343. timeout,
  344. &http_common_dns_ip_lookup_cb,
  345. ppc);
  346. if (NULL == ppc->resolver_handle)
  347. {
  348. GNUNET_free(ppc->plugin);
  349. GNUNET_free(ppc);
  350. return GNUNET_SYSERR;
  351. }
  352. GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
  353. dll_ppc_tail,
  354. ppc);
  355. return GNUNET_OK;
  356. }
  357. /**
  358. * Convert the transports address to a nice, human-readable
  359. * format.
  360. *
  361. * @param cls closure
  362. * @param type name of the transport that generated the address
  363. * @param addr one of the addresses of the host, NULL for the last address
  364. * the specific address format depends on the transport
  365. * @param addrlen length of the @a addr
  366. * @param numeric should (IP) addresses be displayed in numeric form?
  367. * @param timeout after how long should we give up?
  368. * @param asc function to call on each string
  369. * @param asc_cls closure for @a asc
  370. */
  371. void
  372. http_common_plugin_address_pretty_printer (void *cls, const char *type,
  373. const void *addr,
  374. size_t addrlen,
  375. int numeric,
  376. struct GNUNET_TIME_Relative timeout,
  377. GNUNET_TRANSPORT_AddressStringCallback asc,
  378. void *asc_cls)
  379. {
  380. const struct HttpAddress *address = addr;
  381. struct SplittedHTTPAddress *saddr;
  382. struct sockaddr *sock_addr;
  383. const char *ret;
  384. char *addr_str;
  385. int res;
  386. int have_ip;
  387. saddr = NULL;
  388. sock_addr = NULL;
  389. if ( (addrlen < sizeof(struct HttpAddress)) ||
  390. (addrlen != http_common_address_get_size (address)) )
  391. {
  392. GNUNET_break(0);
  393. goto handle_error;
  394. }
  395. addr_str = (char *) &address[1];
  396. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  397. {
  398. GNUNET_break(0);
  399. goto handle_error;
  400. }
  401. saddr = http_split_address (addr_str);
  402. if (NULL == saddr)
  403. {
  404. GNUNET_break(0);
  405. goto handle_error;
  406. }
  407. sock_addr = http_common_socket_from_address (addr, addrlen, &res);
  408. if (GNUNET_SYSERR == res)
  409. {
  410. /* Malformed address */
  411. GNUNET_break (0);
  412. goto handle_error;
  413. }
  414. else if (GNUNET_NO == res)
  415. {
  416. /* Could not convert to IP */
  417. have_ip = GNUNET_NO;
  418. }
  419. else if (GNUNET_YES == res)
  420. {
  421. /* Converted to IP */
  422. have_ip = GNUNET_YES;
  423. }
  424. else
  425. {
  426. /* Must not happen */
  427. GNUNET_break (0);
  428. goto handle_error;
  429. }
  430. if ( (GNUNET_YES == numeric) &&
  431. (GNUNET_YES == have_ip) )
  432. {
  433. /* No lookup required */
  434. ret = http_common_plugin_address_to_string (type, address, addrlen);
  435. asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
  436. asc (asc_cls, NULL, GNUNET_OK);
  437. http_clean_splitted (saddr);
  438. GNUNET_free_non_null (sock_addr);
  439. return;
  440. }
  441. if ( (GNUNET_YES == numeric) &&
  442. (GNUNET_NO == have_ip) )
  443. {
  444. /* Forward lookup */
  445. if (GNUNET_SYSERR ==
  446. http_common_dns_ip_lookup (saddr->host, type, saddr,
  447. address->options, timeout,
  448. asc, asc_cls))
  449. {
  450. GNUNET_break(0);
  451. goto handle_error;
  452. }
  453. /* Wait for resolver callback */
  454. GNUNET_free_non_null (sock_addr);
  455. return;
  456. }
  457. if ( (GNUNET_NO == numeric) &&
  458. (GNUNET_YES == have_ip) )
  459. {
  460. /* Reverse lookup */
  461. if (GNUNET_SYSERR ==
  462. http_common_dns_reverse_lookup (sock_addr,
  463. (AF_INET == sock_addr->sa_family)
  464. ? sizeof(struct sockaddr_in)
  465. : sizeof(struct sockaddr_in6),
  466. type,
  467. saddr,
  468. address->options, timeout,
  469. asc, asc_cls))
  470. {
  471. GNUNET_break(0);
  472. goto handle_error;
  473. }
  474. /* Wait for resolver callback */
  475. GNUNET_free_non_null (sock_addr);
  476. return;
  477. }
  478. if ( (GNUNET_NO == numeric) &&
  479. (GNUNET_NO == have_ip) )
  480. {
  481. /* No lookup required */
  482. ret = http_common_plugin_address_to_string (type, address, addrlen);
  483. asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
  484. asc (asc_cls, NULL, GNUNET_OK);
  485. GNUNET_free_non_null (sock_addr);
  486. http_clean_splitted (saddr);
  487. return;
  488. }
  489. /* Error (argument supplied not GNUNET_YES or GNUNET_NO) */
  490. GNUNET_break (0);
  491. goto handle_error;
  492. handle_error:
  493. /* Report error */
  494. asc (asc_cls, NULL, GNUNET_SYSERR);
  495. asc (asc_cls, NULL, GNUNET_OK);
  496. GNUNET_free_non_null (sock_addr);
  497. if (NULL != saddr)
  498. http_clean_splitted (saddr);
  499. }
  500. /**
  501. * FIXME.
  502. */
  503. const char *
  504. http_common_plugin_address_to_url (void *cls,
  505. const void *addr,
  506. size_t addrlen)
  507. {
  508. static char rbuf[1024];
  509. const struct HttpAddress *address = addr;
  510. const char * addr_str;
  511. if (NULL == addr)
  512. {
  513. GNUNET_break(0);
  514. return NULL;
  515. }
  516. if (0 == addrlen)
  517. {
  518. GNUNET_break(0);
  519. return NULL;
  520. }
  521. if (addrlen != http_common_address_get_size (address))
  522. {
  523. GNUNET_break(0);
  524. return NULL;
  525. }
  526. addr_str = (char *) &address[1];
  527. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  528. return NULL;
  529. GNUNET_memcpy (rbuf,
  530. &address[1],
  531. ntohl (address->urlen));
  532. return rbuf;
  533. }
  534. /**
  535. * Function called for a quick conversion of the binary address to
  536. * a numeric address. Note that the caller must not free the
  537. * address and that the next call to this function is allowed
  538. * to override the address again.
  539. *
  540. * @param plugin the name of the plugin
  541. * @param addr binary address
  542. * @param addrlen length of the address
  543. * @return string representing the same address
  544. */
  545. const char *
  546. http_common_plugin_address_to_string (const char *plugin,
  547. const void *addr,
  548. size_t addrlen)
  549. {
  550. static char rbuf[1024];
  551. const struct HttpAddress *address = addr;
  552. const char * addr_str;
  553. char *res;
  554. GNUNET_assert(NULL != plugin);
  555. if (NULL == addr)
  556. return NULL;
  557. if (0 == addrlen)
  558. return NULL;
  559. if (addrlen != http_common_address_get_size (address))
  560. return NULL;
  561. addr_str = (char *) &address[1];
  562. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  563. return NULL;
  564. GNUNET_asprintf (&res, "%s.%u.%s", plugin, ntohl (address->options),
  565. &address[1]);
  566. if (strlen (res) + 1 < 500)
  567. {
  568. GNUNET_memcpy (rbuf, res, strlen (res) + 1);
  569. GNUNET_free(res);
  570. return rbuf;
  571. }
  572. GNUNET_break(0);
  573. GNUNET_free(res);
  574. return NULL;
  575. }
  576. /**
  577. * Function called to convert a string address to
  578. * a binary address.
  579. *
  580. * @param cls closure ('struct Plugin*')
  581. * @param addr string address
  582. * @param addrlen length of the @a addr
  583. * @param buf location to store the buffer
  584. * If the function returns #GNUNET_SYSERR, its contents are undefined.
  585. * @param added length of created address
  586. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  587. */
  588. int
  589. http_common_plugin_string_to_address (void *cls,
  590. const char *addr,
  591. uint16_t addrlen,
  592. void **buf,
  593. size_t *added)
  594. {
  595. struct HttpAddress *a;
  596. char *address;
  597. char *plugin;
  598. char *optionstr;
  599. size_t urlen;
  600. uint32_t options;
  601. /* Format protocol.options.address:port */
  602. address = NULL;
  603. plugin = NULL;
  604. optionstr = NULL;
  605. if ((NULL == addr) || (addrlen == 0))
  606. {
  607. GNUNET_break(0);
  608. return GNUNET_SYSERR;
  609. }
  610. if ('\0' != addr[addrlen - 1])
  611. {
  612. GNUNET_break(0);
  613. return GNUNET_SYSERR;
  614. }
  615. if (strlen (addr) != addrlen - 1)
  616. {
  617. GNUNET_break(0);
  618. return GNUNET_SYSERR;
  619. }
  620. plugin = GNUNET_strdup (addr);
  621. optionstr = strchr (plugin, '.');
  622. if (NULL == optionstr)
  623. {
  624. GNUNET_break(0);
  625. GNUNET_free(plugin);
  626. return GNUNET_SYSERR;
  627. }
  628. optionstr[0] = '\0';
  629. optionstr++;
  630. options = atol (optionstr); /* 0 on conversion error, that's ok */
  631. address = strchr (optionstr, '.');
  632. if (NULL == address)
  633. {
  634. GNUNET_break(0);
  635. GNUNET_free(plugin);
  636. return GNUNET_SYSERR;
  637. }
  638. address[0] = '\0';
  639. address++;
  640. urlen = strlen (address) + 1;
  641. a = GNUNET_malloc (sizeof (struct HttpAddress) + urlen);
  642. a->options = htonl (options);
  643. a->urlen = htonl (urlen);
  644. GNUNET_memcpy (&a[1], address, urlen);
  645. (*buf) = a;
  646. (*added) = sizeof(struct HttpAddress) + urlen;
  647. GNUNET_free(plugin);
  648. return GNUNET_OK;
  649. }
  650. /**
  651. * Create a HTTP address from a socketaddr
  652. *
  653. * @param protocol protocol
  654. * @param addr sockaddr * address
  655. * @param addrlen length of the address
  656. * @return the HttpAddress
  657. */
  658. struct HttpAddress *
  659. http_common_address_from_socket (const char *protocol,
  660. const struct sockaddr *addr,
  661. socklen_t addrlen)
  662. {
  663. struct HttpAddress *address = NULL;
  664. char *res;
  665. size_t len;
  666. GNUNET_asprintf (&res,
  667. "%s://%s",
  668. protocol,
  669. GNUNET_a2s (addr,
  670. addrlen));
  671. len = strlen (res) + 1;
  672. address = GNUNET_malloc (sizeof (struct HttpAddress) + len);
  673. address->options = htonl (HTTP_OPTIONS_NONE);
  674. address->urlen = htonl (len);
  675. GNUNET_memcpy (&address[1], res, len);
  676. GNUNET_free(res);
  677. return address;
  678. }
  679. /**
  680. * Create a socketaddr from a HTTP address
  681. *
  682. * @param addr a `sockaddr *` address
  683. * @param addrlen length of the @a addr
  684. * @param res the result:
  685. * #GNUNET_SYSERR, invalid input,
  686. * #GNUNET_YES: could convert to ip,
  687. * #GNUNET_NO: valid input but could not convert to ip (hostname?)
  688. * @return the string
  689. */
  690. struct sockaddr *
  691. http_common_socket_from_address (const void *addr,
  692. size_t addrlen,
  693. int *res)
  694. {
  695. const struct HttpAddress *ha;
  696. struct SplittedHTTPAddress * spa;
  697. struct sockaddr_storage *s;
  698. char * to_conv;
  699. size_t urlen;
  700. (*res) = GNUNET_SYSERR;
  701. ha = (const struct HttpAddress *) addr;
  702. if (NULL == addr)
  703. {
  704. GNUNET_break (0);
  705. return NULL;
  706. }
  707. if (0 == addrlen)
  708. {
  709. GNUNET_break (0);
  710. return NULL;
  711. }
  712. if (addrlen < sizeof(struct HttpAddress))
  713. {
  714. GNUNET_break (0);
  715. return NULL;
  716. }
  717. urlen = ntohl (ha->urlen);
  718. if (sizeof(struct HttpAddress) + urlen != addrlen)
  719. {
  720. /* This is a legacy addresses */
  721. return NULL;
  722. }
  723. if (addrlen < sizeof(struct HttpAddress) + urlen)
  724. {
  725. /* This is a legacy addresses */
  726. return NULL;
  727. }
  728. if (((char *) addr)[addrlen - 1] != '\0')
  729. {
  730. GNUNET_break (0);
  731. return NULL;
  732. }
  733. spa = http_split_address ((const char *) &ha[1]);
  734. if (NULL == spa)
  735. {
  736. (*res) = GNUNET_SYSERR;
  737. return NULL;
  738. }
  739. s = GNUNET_new (struct sockaddr_storage);
  740. GNUNET_asprintf (&to_conv, "%s:%u", spa->host, spa->port);
  741. if (GNUNET_SYSERR
  742. == GNUNET_STRINGS_to_address_ip (to_conv, strlen (to_conv), s))
  743. {
  744. /* could be a hostname */
  745. GNUNET_free(s);
  746. (*res) = GNUNET_NO;
  747. s = NULL;
  748. }
  749. else if ((AF_INET != s->ss_family) && (AF_INET6 != s->ss_family))
  750. {
  751. GNUNET_free (s);
  752. (*res) = GNUNET_SYSERR;
  753. s = NULL;
  754. }
  755. else
  756. {
  757. (*res) = GNUNET_YES;
  758. }
  759. http_clean_splitted (spa);
  760. GNUNET_free (to_conv);
  761. return (struct sockaddr *) s;
  762. }
  763. /**
  764. * Get the length of an address
  765. *
  766. * @param addr address
  767. * @return the size
  768. */
  769. size_t
  770. http_common_address_get_size (const struct HttpAddress * addr)
  771. {
  772. return sizeof(struct HttpAddress) + ntohl (addr->urlen);
  773. }
  774. /**
  775. * Compare addr1 to addr2
  776. *
  777. * @param addr1 address1
  778. * @param addrlen1 address 1 length
  779. * @param addr2 address2
  780. * @param addrlen2 address 2 length
  781. * @return #GNUNET_YES if equal, #GNUNET_NO if not, #GNUNET_SYSERR on error
  782. */
  783. size_t
  784. http_common_cmp_addresses (const void *addr1,
  785. size_t addrlen1,
  786. const void *addr2,
  787. size_t addrlen2)
  788. {
  789. const char *a1 = addr1;
  790. const char *a2 = addr2;
  791. const struct HttpAddress *ha1;
  792. const struct HttpAddress *ha2;
  793. ha1 = (const struct HttpAddress *) a1;
  794. ha2 = (const struct HttpAddress *) a2;
  795. if (NULL == a1)
  796. return GNUNET_SYSERR;
  797. if (0 == addrlen1)
  798. return GNUNET_SYSERR;
  799. if (a1[addrlen1 - 1] != '\0')
  800. return GNUNET_SYSERR;
  801. if (NULL == a2)
  802. return GNUNET_SYSERR;
  803. if (0 == addrlen2)
  804. return GNUNET_SYSERR;
  805. if (a2[addrlen2 - 1] != '\0')
  806. return GNUNET_SYSERR;
  807. if (addrlen1 != addrlen2)
  808. return GNUNET_NO;
  809. if (ha1->urlen != ha2->urlen)
  810. return GNUNET_NO;
  811. if (0 == strcmp ((const char *) &ha1[1], (const char *) &ha2[1]))
  812. return GNUNET_YES;
  813. return GNUNET_NO;
  814. }
  815. /**
  816. * Function obtain the network type for an address.
  817. *
  818. * @param env the environment
  819. * @param address the address
  820. * @return the network type
  821. */
  822. enum GNUNET_NetworkType
  823. http_common_get_network_for_address (struct GNUNET_TRANSPORT_PluginEnvironment *env,
  824. const struct GNUNET_HELLO_Address *address)
  825. {
  826. struct sockaddr *sa;
  827. enum GNUNET_NetworkType net_type;
  828. size_t salen = 0;
  829. int res;
  830. net_type = GNUNET_NT_UNSPECIFIED;
  831. sa = http_common_socket_from_address (address->address,
  832. address->address_length,
  833. &res);
  834. if (GNUNET_SYSERR == res)
  835. return net_type;
  836. if (GNUNET_YES == res)
  837. {
  838. GNUNET_assert (NULL != sa);
  839. if (AF_INET == sa->sa_family)
  840. {
  841. salen = sizeof (struct sockaddr_in);
  842. }
  843. else if (AF_INET6 == sa->sa_family)
  844. {
  845. salen = sizeof (struct sockaddr_in6);
  846. }
  847. net_type = env->get_address_type (env->cls,
  848. sa,
  849. salen);
  850. GNUNET_free (sa);
  851. }
  852. return net_type;
  853. }
  854. /* end of plugin_transport_http_common.c */