plugin_transport_http_common.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  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 (spa->protocol);
  32. GNUNET_free (spa->host);
  33. GNUNET_free (spa->path);
  34. GNUNET_free (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
  229. SplittedHTTPAddress *saddr,
  230. uint32_t options,
  231. const char *dnsresult)
  232. {
  233. static char rbuf[1024];
  234. char *res;
  235. GNUNET_asprintf (&res, "%s.%u.%s://%s:%u%s", plugin, options, saddr->protocol,
  236. dnsresult, saddr->port, saddr->path);
  237. if (strlen (res) + 1 < 500)
  238. {
  239. GNUNET_memcpy (rbuf, res, strlen (res) + 1);
  240. GNUNET_free (res);
  241. return rbuf;
  242. }
  243. GNUNET_break (0);
  244. GNUNET_free (res);
  245. return NULL;
  246. }
  247. static void
  248. http_common_dns_reverse_lookup_cb (void *cls, const char *hostname)
  249. {
  250. struct PrettyPrinterContext *ppc = cls;
  251. if (NULL != hostname)
  252. {
  253. ppc->asc (ppc->asc_cls,
  254. http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr,
  255. ppc->options,
  256. hostname), GNUNET_OK);
  257. ppc->sucess = GNUNET_YES;
  258. }
  259. else
  260. {
  261. ppc->asc (ppc->asc_cls, NULL,
  262. (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
  263. GNUNET_CONTAINER_DLL_remove (dll_ppc_head, dll_ppc_tail, ppc);
  264. http_clean_splitted (ppc->saddr);
  265. GNUNET_free (ppc->plugin);
  266. GNUNET_free (ppc);
  267. }
  268. }
  269. static int
  270. http_common_dns_reverse_lookup (const struct sockaddr *sockaddr,
  271. socklen_t sockaddr_len,
  272. const char *type,
  273. struct SplittedHTTPAddress *saddr,
  274. uint32_t options,
  275. struct GNUNET_TIME_Relative timeout,
  276. GNUNET_TRANSPORT_AddressStringCallback asc,
  277. void *asc_cls)
  278. {
  279. struct PrettyPrinterContext *ppc;
  280. ppc = GNUNET_new (struct PrettyPrinterContext);
  281. ppc->saddr = saddr;
  282. ppc->asc = asc;
  283. ppc->asc_cls = asc_cls;
  284. ppc->plugin = GNUNET_strdup (type);
  285. ppc->options = options;
  286. ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sockaddr,
  287. sockaddr_len,
  288. GNUNET_YES,
  289. timeout,
  290. &
  291. http_common_dns_reverse_lookup_cb,
  292. ppc);
  293. if (NULL == ppc->resolver_handle)
  294. {
  295. GNUNET_free (ppc->plugin);
  296. GNUNET_free (ppc);
  297. return GNUNET_SYSERR;
  298. }
  299. GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
  300. dll_ppc_tail,
  301. ppc);
  302. return GNUNET_OK;
  303. }
  304. static void
  305. http_common_dns_ip_lookup_cb (void *cls,
  306. const struct sockaddr *addr,
  307. socklen_t addrlen)
  308. {
  309. struct PrettyPrinterContext *ppc = cls;
  310. if (NULL != addr)
  311. {
  312. ppc->asc (ppc->asc_cls,
  313. http_common_plugin_dnsresult_to_address (ppc->plugin, ppc->saddr,
  314. ppc->options,
  315. GNUNET_a2s (addr,
  316. addrlen)),
  317. GNUNET_OK);
  318. ppc->sucess = GNUNET_YES;
  319. ppc->asc (ppc->asc_cls, GNUNET_a2s (addr, addrlen), GNUNET_OK);
  320. }
  321. else
  322. {
  323. ppc->asc (ppc->asc_cls, NULL,
  324. (GNUNET_NO == ppc->sucess) ? GNUNET_SYSERR : GNUNET_OK);
  325. GNUNET_CONTAINER_DLL_remove (dll_ppc_head, dll_ppc_tail, ppc);
  326. GNUNET_free (ppc->plugin);
  327. http_clean_splitted (ppc->saddr);
  328. GNUNET_free (ppc);
  329. }
  330. }
  331. static int
  332. http_common_dns_ip_lookup (const char *name,
  333. const char *type,
  334. struct SplittedHTTPAddress *saddr,
  335. uint32_t options,
  336. struct GNUNET_TIME_Relative timeout,
  337. GNUNET_TRANSPORT_AddressStringCallback asc,
  338. void *asc_cls)
  339. {
  340. struct PrettyPrinterContext *ppc;
  341. ppc = GNUNET_new (struct PrettyPrinterContext);
  342. ppc->sucess = GNUNET_NO;
  343. ppc->saddr = saddr;
  344. ppc->asc = asc;
  345. ppc->asc_cls = asc_cls;
  346. ppc->plugin = GNUNET_strdup (type);
  347. ppc->options = options;
  348. ppc->resolver_handle = GNUNET_RESOLVER_ip_get (name,
  349. AF_UNSPEC,
  350. timeout,
  351. &http_common_dns_ip_lookup_cb,
  352. ppc);
  353. if (NULL == ppc->resolver_handle)
  354. {
  355. GNUNET_free (ppc->plugin);
  356. GNUNET_free (ppc);
  357. return GNUNET_SYSERR;
  358. }
  359. GNUNET_CONTAINER_DLL_insert (dll_ppc_head,
  360. dll_ppc_tail,
  361. ppc);
  362. return GNUNET_OK;
  363. }
  364. /**
  365. * Convert the transports address to a nice, human-readable
  366. * format.
  367. *
  368. * @param cls closure
  369. * @param type name of the transport that generated the address
  370. * @param addr one of the addresses of the host, NULL for the last address
  371. * the specific address format depends on the transport
  372. * @param addrlen length of the @a addr
  373. * @param numeric should (IP) addresses be displayed in numeric form?
  374. * @param timeout after how long should we give up?
  375. * @param asc function to call on each string
  376. * @param asc_cls closure for @a asc
  377. */
  378. void
  379. http_common_plugin_address_pretty_printer (void *cls, const char *type,
  380. const void *addr,
  381. size_t addrlen,
  382. int numeric,
  383. struct GNUNET_TIME_Relative timeout,
  384. GNUNET_TRANSPORT_AddressStringCallback
  385. asc,
  386. void *asc_cls)
  387. {
  388. const struct HttpAddress *address = addr;
  389. struct SplittedHTTPAddress *saddr;
  390. struct sockaddr *sock_addr;
  391. const char *ret;
  392. char *addr_str;
  393. int res;
  394. int have_ip;
  395. saddr = NULL;
  396. sock_addr = NULL;
  397. if ((addrlen < sizeof(struct HttpAddress)) ||
  398. (addrlen != http_common_address_get_size (address)))
  399. {
  400. GNUNET_break (0);
  401. goto handle_error;
  402. }
  403. addr_str = (char *) &address[1];
  404. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  405. {
  406. GNUNET_break (0);
  407. goto handle_error;
  408. }
  409. saddr = http_split_address (addr_str);
  410. if (NULL == saddr)
  411. {
  412. GNUNET_break (0);
  413. goto handle_error;
  414. }
  415. sock_addr = http_common_socket_from_address (addr, addrlen, &res);
  416. if (GNUNET_SYSERR == res)
  417. {
  418. /* Malformed address */
  419. GNUNET_break (0);
  420. goto handle_error;
  421. }
  422. else if (GNUNET_NO == res)
  423. {
  424. /* Could not convert to IP */
  425. have_ip = GNUNET_NO;
  426. }
  427. else if (GNUNET_YES == res)
  428. {
  429. /* Converted to IP */
  430. have_ip = GNUNET_YES;
  431. }
  432. else
  433. {
  434. /* Must not happen */
  435. GNUNET_break (0);
  436. goto handle_error;
  437. }
  438. if ((GNUNET_YES == numeric) &&
  439. (GNUNET_YES == have_ip))
  440. {
  441. /* No lookup required */
  442. ret = http_common_plugin_address_to_string (type, address, addrlen);
  443. asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
  444. asc (asc_cls, NULL, GNUNET_OK);
  445. http_clean_splitted (saddr);
  446. GNUNET_free (sock_addr);
  447. return;
  448. }
  449. if ((GNUNET_YES == numeric) &&
  450. (GNUNET_NO == have_ip))
  451. {
  452. /* Forward lookup */
  453. if (GNUNET_SYSERR ==
  454. http_common_dns_ip_lookup (saddr->host, type, saddr,
  455. address->options, timeout,
  456. asc, asc_cls))
  457. {
  458. GNUNET_break (0);
  459. goto handle_error;
  460. }
  461. /* Wait for resolver callback */
  462. GNUNET_free (sock_addr);
  463. return;
  464. }
  465. if ((GNUNET_NO == numeric) &&
  466. (GNUNET_YES == have_ip))
  467. {
  468. /* Reverse lookup */
  469. if (GNUNET_SYSERR ==
  470. http_common_dns_reverse_lookup (sock_addr,
  471. (AF_INET == sock_addr->sa_family)
  472. ? sizeof(struct sockaddr_in)
  473. : sizeof(struct sockaddr_in6),
  474. type,
  475. saddr,
  476. address->options, timeout,
  477. asc, asc_cls))
  478. {
  479. GNUNET_break (0);
  480. goto handle_error;
  481. }
  482. /* Wait for resolver callback */
  483. GNUNET_free (sock_addr);
  484. return;
  485. }
  486. if ((GNUNET_NO == numeric) &&
  487. (GNUNET_NO == have_ip))
  488. {
  489. /* No lookup required */
  490. ret = http_common_plugin_address_to_string (type, address, addrlen);
  491. asc (asc_cls, ret, (NULL == ret) ? GNUNET_SYSERR : GNUNET_OK);
  492. asc (asc_cls, NULL, GNUNET_OK);
  493. GNUNET_free (sock_addr);
  494. http_clean_splitted (saddr);
  495. return;
  496. }
  497. /* Error (argument supplied not GNUNET_YES or GNUNET_NO) */
  498. GNUNET_break (0);
  499. goto handle_error;
  500. handle_error:
  501. /* Report error */
  502. asc (asc_cls, NULL, GNUNET_SYSERR);
  503. asc (asc_cls, NULL, GNUNET_OK);
  504. GNUNET_free (sock_addr);
  505. if (NULL != saddr)
  506. http_clean_splitted (saddr);
  507. }
  508. /**
  509. * FIXME.
  510. */
  511. const char *
  512. http_common_plugin_address_to_url (void *cls,
  513. const void *addr,
  514. size_t addrlen)
  515. {
  516. static char rbuf[1024];
  517. const struct HttpAddress *address = addr;
  518. const char *addr_str;
  519. if (NULL == addr)
  520. {
  521. GNUNET_break (0);
  522. return NULL;
  523. }
  524. if (0 == addrlen)
  525. {
  526. GNUNET_break (0);
  527. return NULL;
  528. }
  529. if (addrlen != http_common_address_get_size (address))
  530. {
  531. GNUNET_break (0);
  532. return NULL;
  533. }
  534. addr_str = (char *) &address[1];
  535. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  536. return NULL;
  537. GNUNET_memcpy (rbuf,
  538. &address[1],
  539. ntohl (address->urlen));
  540. return rbuf;
  541. }
  542. /**
  543. * Function called for a quick conversion of the binary address to
  544. * a numeric address. Note that the caller must not free the
  545. * address and that the next call to this function is allowed
  546. * to override the address again.
  547. *
  548. * @param plugin the name of the plugin
  549. * @param addr binary address
  550. * @param addrlen length of the address
  551. * @return string representing the same address
  552. */
  553. const char *
  554. http_common_plugin_address_to_string (const char *plugin,
  555. const void *addr,
  556. size_t addrlen)
  557. {
  558. static char rbuf[1024];
  559. const struct HttpAddress *address = addr;
  560. const char *addr_str;
  561. char *res;
  562. GNUNET_assert (NULL != plugin);
  563. if (NULL == addr)
  564. return NULL;
  565. if (0 == addrlen)
  566. return NULL;
  567. if (addrlen != http_common_address_get_size (address))
  568. return NULL;
  569. addr_str = (char *) &address[1];
  570. if (addr_str[ntohl (address->urlen) - 1] != '\0')
  571. return NULL;
  572. GNUNET_asprintf (&res, "%s.%u.%s", plugin, ntohl (address->options),
  573. (char*)&address[1]);
  574. if (strlen (res) + 1 < 500)
  575. {
  576. GNUNET_memcpy (rbuf, res, strlen (res) + 1);
  577. GNUNET_free (res);
  578. return rbuf;
  579. }
  580. GNUNET_break (0);
  581. GNUNET_free (res);
  582. return NULL;
  583. }
  584. /**
  585. * Function called to convert a string address to
  586. * a binary address.
  587. *
  588. * @param cls closure ('struct Plugin*')
  589. * @param addr string address
  590. * @param addrlen length of the @a addr
  591. * @param buf location to store the buffer
  592. * If the function returns #GNUNET_SYSERR, its contents are undefined.
  593. * @param added length of created address
  594. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  595. */
  596. int
  597. http_common_plugin_string_to_address (void *cls,
  598. const char *addr,
  599. uint16_t addrlen,
  600. void **buf,
  601. size_t *added)
  602. {
  603. struct HttpAddress *a;
  604. char *address;
  605. char *plugin;
  606. char *optionstr;
  607. size_t urlen;
  608. uint32_t options;
  609. /* Format protocol.options.address:port */
  610. address = NULL;
  611. plugin = NULL;
  612. optionstr = NULL;
  613. if ((NULL == addr) || (addrlen == 0))
  614. {
  615. GNUNET_break (0);
  616. return GNUNET_SYSERR;
  617. }
  618. if ('\0' != addr[addrlen - 1])
  619. {
  620. GNUNET_break (0);
  621. return GNUNET_SYSERR;
  622. }
  623. if (strlen (addr) != addrlen - 1)
  624. {
  625. GNUNET_break (0);
  626. return GNUNET_SYSERR;
  627. }
  628. plugin = GNUNET_strdup (addr);
  629. optionstr = strchr (plugin, '.');
  630. if (NULL == optionstr)
  631. {
  632. GNUNET_break (0);
  633. GNUNET_free (plugin);
  634. return GNUNET_SYSERR;
  635. }
  636. optionstr[0] = '\0';
  637. optionstr++;
  638. options = atol (optionstr); /* 0 on conversion error, that's ok */
  639. address = strchr (optionstr, '.');
  640. if (NULL == address)
  641. {
  642. GNUNET_break (0);
  643. GNUNET_free (plugin);
  644. return GNUNET_SYSERR;
  645. }
  646. address[0] = '\0';
  647. address++;
  648. urlen = strlen (address) + 1;
  649. a = GNUNET_malloc (sizeof(struct HttpAddress) + urlen);
  650. a->options = htonl (options);
  651. a->urlen = htonl (urlen);
  652. GNUNET_memcpy (&a[1], address, urlen);
  653. (*buf) = a;
  654. (*added) = sizeof(struct HttpAddress) + urlen;
  655. GNUNET_free (plugin);
  656. return GNUNET_OK;
  657. }
  658. /**
  659. * Create a HTTP address from a socketaddr
  660. *
  661. * @param protocol protocol
  662. * @param addr sockaddr * address
  663. * @param addrlen length of the address
  664. * @return the HttpAddress
  665. */
  666. struct HttpAddress *
  667. http_common_address_from_socket (const char *protocol,
  668. const struct sockaddr *addr,
  669. socklen_t addrlen)
  670. {
  671. struct HttpAddress *address = NULL;
  672. char *res;
  673. size_t len;
  674. GNUNET_asprintf (&res,
  675. "%s://%s",
  676. protocol,
  677. GNUNET_a2s (addr,
  678. addrlen));
  679. len = strlen (res) + 1;
  680. address = GNUNET_malloc (sizeof(struct HttpAddress) + len);
  681. address->options = htonl (HTTP_OPTIONS_NONE);
  682. address->urlen = htonl (len);
  683. GNUNET_memcpy (&address[1], res, len);
  684. GNUNET_free (res);
  685. return address;
  686. }
  687. /**
  688. * Create a socketaddr from a HTTP address
  689. *
  690. * @param addr a `sockaddr *` address
  691. * @param addrlen length of the @a addr
  692. * @param res the result:
  693. * #GNUNET_SYSERR, invalid input,
  694. * #GNUNET_YES: could convert to ip,
  695. * #GNUNET_NO: valid input but could not convert to ip (hostname?)
  696. * @return the string
  697. */
  698. struct sockaddr *
  699. http_common_socket_from_address (const void *addr,
  700. size_t addrlen,
  701. int *res)
  702. {
  703. const struct HttpAddress *ha;
  704. struct SplittedHTTPAddress *spa;
  705. struct sockaddr_storage *s;
  706. char *to_conv;
  707. size_t urlen;
  708. (*res) = GNUNET_SYSERR;
  709. ha = (const struct HttpAddress *) addr;
  710. if (NULL == addr)
  711. {
  712. GNUNET_break (0);
  713. return NULL;
  714. }
  715. if (0 == addrlen)
  716. {
  717. GNUNET_break (0);
  718. return NULL;
  719. }
  720. if (addrlen < sizeof(struct HttpAddress))
  721. {
  722. GNUNET_break (0);
  723. return NULL;
  724. }
  725. urlen = ntohl (ha->urlen);
  726. if (sizeof(struct HttpAddress) + urlen != addrlen)
  727. {
  728. /* This is a legacy addresses */
  729. return NULL;
  730. }
  731. if (addrlen < sizeof(struct HttpAddress) + urlen)
  732. {
  733. /* This is a legacy addresses */
  734. return NULL;
  735. }
  736. if (((char *) addr)[addrlen - 1] != '\0')
  737. {
  738. GNUNET_break (0);
  739. return NULL;
  740. }
  741. spa = http_split_address ((const char *) &ha[1]);
  742. if (NULL == spa)
  743. {
  744. (*res) = GNUNET_SYSERR;
  745. return NULL;
  746. }
  747. s = GNUNET_new (struct sockaddr_storage);
  748. GNUNET_asprintf (&to_conv, "%s:%u", spa->host, spa->port);
  749. if (GNUNET_SYSERR
  750. == GNUNET_STRINGS_to_address_ip (to_conv, strlen (to_conv), s))
  751. {
  752. /* could be a hostname */
  753. GNUNET_free (s);
  754. (*res) = GNUNET_NO;
  755. s = NULL;
  756. }
  757. else if ((AF_INET != s->ss_family) && (AF_INET6 != s->ss_family))
  758. {
  759. GNUNET_free (s);
  760. (*res) = GNUNET_SYSERR;
  761. s = NULL;
  762. }
  763. else
  764. {
  765. (*res) = GNUNET_YES;
  766. }
  767. http_clean_splitted (spa);
  768. GNUNET_free (to_conv);
  769. return (struct sockaddr *) s;
  770. }
  771. /**
  772. * Get the length of an address
  773. *
  774. * @param addr address
  775. * @return the size
  776. */
  777. size_t
  778. http_common_address_get_size (const struct HttpAddress *addr)
  779. {
  780. return sizeof(struct HttpAddress) + ntohl (addr->urlen);
  781. }
  782. /**
  783. * Compare addr1 to addr2
  784. *
  785. * @param addr1 address1
  786. * @param addrlen1 address 1 length
  787. * @param addr2 address2
  788. * @param addrlen2 address 2 length
  789. * @return #GNUNET_YES if equal, #GNUNET_NO if not, #GNUNET_SYSERR on error
  790. */
  791. size_t
  792. http_common_cmp_addresses (const void *addr1,
  793. size_t addrlen1,
  794. const void *addr2,
  795. size_t addrlen2)
  796. {
  797. const char *a1 = addr1;
  798. const char *a2 = addr2;
  799. const struct HttpAddress *ha1;
  800. const struct HttpAddress *ha2;
  801. ha1 = (const struct HttpAddress *) a1;
  802. ha2 = (const struct HttpAddress *) a2;
  803. if (NULL == a1)
  804. return GNUNET_SYSERR;
  805. if (0 == addrlen1)
  806. return GNUNET_SYSERR;
  807. if (a1[addrlen1 - 1] != '\0')
  808. return GNUNET_SYSERR;
  809. if (NULL == a2)
  810. return GNUNET_SYSERR;
  811. if (0 == addrlen2)
  812. return GNUNET_SYSERR;
  813. if (a2[addrlen2 - 1] != '\0')
  814. return GNUNET_SYSERR;
  815. if (addrlen1 != addrlen2)
  816. return GNUNET_NO;
  817. if (ha1->urlen != ha2->urlen)
  818. return GNUNET_NO;
  819. if (0 == strcmp ((const char *) &ha1[1], (const char *) &ha2[1]))
  820. return GNUNET_YES;
  821. return GNUNET_NO;
  822. }
  823. /**
  824. * Function obtain the network type for an address.
  825. *
  826. * @param env the environment
  827. * @param address the address
  828. * @return the network type
  829. */
  830. enum GNUNET_NetworkType
  831. http_common_get_network_for_address (struct
  832. GNUNET_TRANSPORT_PluginEnvironment *env,
  833. const struct GNUNET_HELLO_Address *address)
  834. {
  835. struct sockaddr *sa;
  836. enum GNUNET_NetworkType net_type;
  837. size_t salen = 0;
  838. int res;
  839. net_type = GNUNET_NT_UNSPECIFIED;
  840. sa = http_common_socket_from_address (address->address,
  841. address->address_length,
  842. &res);
  843. if (GNUNET_SYSERR == res)
  844. return net_type;
  845. if (GNUNET_YES == res)
  846. {
  847. GNUNET_assert (NULL != sa);
  848. if (AF_INET == sa->sa_family)
  849. {
  850. salen = sizeof(struct sockaddr_in);
  851. }
  852. else if (AF_INET6 == sa->sa_family)
  853. {
  854. salen = sizeof(struct sockaddr_in6);
  855. }
  856. net_type = env->get_address_type (env->cls,
  857. sa,
  858. salen);
  859. GNUNET_free (sa);
  860. }
  861. return net_type;
  862. }
  863. /* end of plugin_transport_http_common.c */