hostlist-server.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2008, 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 hostlist/hostlist-server.c
  19. * @author Christian Grothoff, Matthias Wachs
  20. * @brief application to provide an integrated hostlist HTTP server
  21. */
  22. #include "platform.h"
  23. #include <microhttpd.h>
  24. #include "hostlist-server.h"
  25. #include "gnunet_hello_lib.h"
  26. #include "gnunet_peerinfo_service.h"
  27. #include "gnunet-daemon-hostlist.h"
  28. #include "gnunet_resolver_service.h"
  29. #define DEBUG_HOSTLIST_SERVER GNUNET_NO
  30. /**
  31. * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
  32. */
  33. static struct MHD_Daemon *daemon_handle_v6;
  34. /**
  35. * Handle to the HTTP server as provided by libmicrohttpd for IPv4.
  36. */
  37. static struct MHD_Daemon *daemon_handle_v4;
  38. /**
  39. * Our configuration.
  40. */
  41. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  42. /**
  43. * For keeping statistics.
  44. */
  45. static struct GNUNET_STATISTICS_Handle *stats;
  46. /**
  47. * Handle to the core service (NULL until we've connected to it).
  48. */
  49. static struct GNUNET_CORE_Handle *core;
  50. /**
  51. * Handle to the peerinfo notify service (NULL until we've connected to it).
  52. */
  53. static struct GNUNET_PEERINFO_NotifyContext *notify;
  54. /**
  55. * Our primary task for IPv4.
  56. */
  57. static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v4;
  58. /**
  59. * Our primary task for IPv6.
  60. */
  61. static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
  62. /**
  63. * Our canonical response.
  64. */
  65. static struct MHD_Response *response;
  66. /**
  67. * NULL if we are not currenlty iterating over peer information.
  68. */
  69. static struct GNUNET_PEERINFO_IteratorContext *pitr;
  70. /**
  71. * Handle for accessing peerinfo service.
  72. */
  73. static struct GNUNET_PEERINFO_Handle *peerinfo;
  74. /**
  75. * Context for host processor.
  76. */
  77. struct HostSet
  78. {
  79. unsigned int size;
  80. char *data;
  81. };
  82. /**
  83. * Set if we are allowed to advertise our hostlist to others.
  84. */
  85. static int advertising;
  86. /**
  87. * Buffer for the hostlist address
  88. */
  89. static char *hostlist_uri;
  90. /**
  91. * Function that assembles our response.
  92. */
  93. static void
  94. finish_response (struct HostSet *results)
  95. {
  96. if (response != NULL)
  97. MHD_destroy_response (response);
  98. #if DEBUG_HOSTLIST_SERVER
  99. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  100. "Creating hostlist response with %u bytes\n",
  101. (unsigned int) results->size);
  102. #endif
  103. response =
  104. MHD_create_response_from_data (results->size, results->data, MHD_YES,
  105. MHD_NO);
  106. if ((daemon_handle_v4 == NULL) && (daemon_handle_v6 == NULL))
  107. {
  108. MHD_destroy_response (response);
  109. response = NULL;
  110. }
  111. GNUNET_STATISTICS_set (stats, gettext_noop ("bytes in hostlist"),
  112. results->size, GNUNET_YES);
  113. GNUNET_free (results);
  114. }
  115. /**
  116. * Set 'cls' to GNUNET_YES (we have an address!).
  117. *
  118. * @param cls closure, an 'int*'
  119. * @param tname name of the transport (ignored)
  120. * @param expiration expiration time (call is ignored if this is in the past)
  121. * @param addr the address (ignored)
  122. * @param addrlen length of the address (ignored)
  123. * @return GNUNET_SYSERR to stop iterating (unless expiration has occured)
  124. */
  125. static int
  126. check_has_addr (void *cls, const char *tname,
  127. struct GNUNET_TIME_Absolute expiration, const void *addr,
  128. uint16_t addrlen)
  129. {
  130. int *arg = cls;
  131. if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0)
  132. {
  133. GNUNET_STATISTICS_update (stats,
  134. gettext_noop ("expired addresses encountered"), 1,
  135. GNUNET_YES);
  136. return GNUNET_YES; /* ignore this address */
  137. }
  138. *arg = GNUNET_YES;
  139. return GNUNET_SYSERR;
  140. }
  141. /**
  142. * Callback that processes each of the known HELLOs for the
  143. * hostlist response construction.
  144. */
  145. static void
  146. host_processor (void *cls, const struct GNUNET_PeerIdentity *peer,
  147. const struct GNUNET_HELLO_Message *hello, const char *err_msg)
  148. {
  149. struct HostSet *results = cls;
  150. size_t old;
  151. size_t s;
  152. int has_addr;
  153. if (err_msg != NULL)
  154. {
  155. GNUNET_assert (NULL == peer);
  156. pitr = NULL;
  157. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  158. _("Error in communication with PEERINFO service: %s\n"),
  159. err_msg);
  160. return;
  161. }
  162. if (peer == NULL)
  163. {
  164. pitr = NULL;
  165. finish_response (results);
  166. return;
  167. }
  168. if (hello == NULL)
  169. return;
  170. has_addr = GNUNET_NO;
  171. GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_has_addr, &has_addr);
  172. if (GNUNET_NO == has_addr)
  173. {
  174. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  175. "HELLO for peer `%4s' has no address, not suitable for hostlist!\n",
  176. GNUNET_i2s (peer));
  177. GNUNET_STATISTICS_update (stats,
  178. gettext_noop
  179. ("HELLOs without addresses encountered (ignored)"),
  180. 1, GNUNET_NO);
  181. return;
  182. }
  183. old = results->size;
  184. s = GNUNET_HELLO_size (hello);
  185. #if DEBUG_HOSTLIST_SERVER
  186. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  187. "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
  188. (unsigned int) s, "HELLO", GNUNET_i2s (peer));
  189. #endif
  190. if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
  191. (old + s >= MAX_BYTES_PER_HOSTLISTS))
  192. {
  193. GNUNET_STATISTICS_update (stats,
  194. gettext_noop
  195. ("bytes not included in hostlist (size limit)"),
  196. s, GNUNET_NO);
  197. return; /* too large, skip! */
  198. }
  199. #if DEBUG_HOSTLIST_SERVER
  200. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  201. "Adding peer `%s' to hostlist (%u bytes)\n", GNUNET_i2s (peer),
  202. (unsigned int) s);
  203. #endif
  204. GNUNET_array_grow (results->data, results->size, old + s);
  205. memcpy (&results->data[old], hello, s);
  206. }
  207. /**
  208. * Hostlist access policy (very permissive, allows everything).
  209. */
  210. static int
  211. accept_policy_callback (void *cls, const struct sockaddr *addr,
  212. socklen_t addrlen)
  213. {
  214. if (NULL == response)
  215. {
  216. #if DEBUG_HOSTLIST_SERVER
  217. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  218. "Received request for hostlist, but I am not yet ready; rejecting!\n");
  219. #endif
  220. return MHD_NO;
  221. }
  222. return MHD_YES; /* accept all */
  223. }
  224. /**
  225. * Main request handler.
  226. */
  227. static int
  228. access_handler_callback (void *cls, struct MHD_Connection *connection,
  229. const char *url, const char *method,
  230. const char *version, const char *upload_data,
  231. size_t * upload_data_size, void **con_cls)
  232. {
  233. static int dummy;
  234. if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
  235. {
  236. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  237. _("Refusing `%s' request to hostlist server\n"), method);
  238. GNUNET_STATISTICS_update (stats,
  239. gettext_noop
  240. ("hostlist requests refused (not HTTP GET)"), 1,
  241. GNUNET_YES);
  242. return MHD_NO;
  243. }
  244. if (NULL == *con_cls)
  245. {
  246. (*con_cls) = &dummy;
  247. #if DEBUG_HOSTLIST_SERVER
  248. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Sending 100 CONTINUE reply\n"));
  249. #endif
  250. return MHD_YES; /* send 100 continue */
  251. }
  252. if (*upload_data_size != 0)
  253. {
  254. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  255. _("Refusing `%s' request with %llu bytes of upload data\n"),
  256. method, (unsigned long long) *upload_data_size);
  257. GNUNET_STATISTICS_update (stats,
  258. gettext_noop
  259. ("hostlist requests refused (upload data)"), 1,
  260. GNUNET_YES);
  261. return MHD_NO; /* do not support upload data */
  262. }
  263. if (response == NULL)
  264. {
  265. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  266. _
  267. ("Could not handle hostlist request since I do not have a response yet\n"));
  268. GNUNET_STATISTICS_update (stats,
  269. gettext_noop
  270. ("hostlist requests refused (not ready)"), 1,
  271. GNUNET_YES);
  272. return MHD_NO; /* internal error, no response yet */
  273. }
  274. GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received request for our hostlist\n"));
  275. GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests processed"),
  276. 1, GNUNET_YES);
  277. return MHD_queue_response (connection, MHD_HTTP_OK, response);
  278. }
  279. /**
  280. * Handler called by core when core is ready to transmit message
  281. * @param cls closure
  282. * @param size size of buffer to copy message to
  283. * @param buf buffer to copy message to
  284. */
  285. static size_t
  286. adv_transmit_ready (void *cls, size_t size, void *buf)
  287. {
  288. static uint64_t hostlist_adv_count;
  289. size_t transmission_size;
  290. size_t uri_size; /* Including \0 termination! */
  291. struct GNUNET_MessageHeader header;
  292. char *cbuf;
  293. if (buf == NULL)
  294. {
  295. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  296. "Transmission failed, buffer invalid!\n");
  297. return 0;
  298. }
  299. uri_size = strlen (hostlist_uri) + 1;
  300. transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
  301. header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
  302. header.size = htons (transmission_size);
  303. GNUNET_assert (size >= transmission_size);
  304. memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
  305. cbuf = buf;
  306. memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size);
  307. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  308. "Sent advertisement message: Copied %u bytes into buffer!\n",
  309. (unsigned int) transmission_size);
  310. hostlist_adv_count++;
  311. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n",
  312. hostlist_adv_count);
  313. GNUNET_STATISTICS_update (stats,
  314. gettext_noop ("# hostlist advertisements send"), 1,
  315. GNUNET_NO);
  316. return transmission_size;
  317. }
  318. /**
  319. * Method called whenever a given peer connects.
  320. *
  321. * @param cls closure
  322. * @param peer peer identity this notification is about
  323. * @param atsi performance data
  324. */
  325. static void
  326. connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer,
  327. const struct GNUNET_TRANSPORT_ATS_Information *atsi)
  328. {
  329. size_t size;
  330. if (!advertising)
  331. return;
  332. if (hostlist_uri == NULL)
  333. return;
  334. size = strlen (hostlist_uri) + 1;
  335. if (size + sizeof (struct GNUNET_MessageHeader) >=
  336. GNUNET_SERVER_MAX_MESSAGE_SIZE)
  337. {
  338. GNUNET_break (0);
  339. return;
  340. }
  341. size += sizeof (struct GNUNET_MessageHeader);
  342. if (NULL == core)
  343. {
  344. GNUNET_break (0);
  345. return;
  346. }
  347. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  348. "Asked core to transmit advertisement message with a size of %u bytes to peer `%s'\n",
  349. size, GNUNET_i2s (peer));
  350. if (NULL ==
  351. GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 0,
  352. GNUNET_ADV_TIMEOUT, peer, size,
  353. &adv_transmit_ready, NULL))
  354. {
  355. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  356. _("Advertisement message could not be queued by core\n"));
  357. }
  358. }
  359. /**
  360. * Method called whenever a given peer disconnects.
  361. *
  362. * @param cls closure
  363. * @param peer peer identity this notification is about
  364. */
  365. static void
  366. disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
  367. {
  368. /* nothing to do */
  369. }
  370. /**
  371. * PEERINFO calls this function to let us know about a possible peer
  372. * that we might want to connect to.
  373. *
  374. * @param cls closure (not used)
  375. * @param peer potential peer to connect to
  376. * @param hello HELLO for this peer (or NULL)
  377. * @param err_msg NULL if successful, otherwise contains error message
  378. */
  379. static void
  380. process_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
  381. const struct GNUNET_HELLO_Message *hello, const char *err_msg)
  382. {
  383. struct HostSet *results;
  384. #if DEBUG_HOSTLIST_SERVER
  385. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  386. "Peerinfo is notifying us to rebuild our hostlist\n");
  387. #endif
  388. if (err_msg != NULL)
  389. {
  390. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  391. _("Error in communication with PEERINFO service\n"));
  392. /* return; */
  393. }
  394. results = GNUNET_malloc (sizeof (struct HostSet));
  395. GNUNET_assert (peerinfo != NULL);
  396. pitr =
  397. GNUNET_PEERINFO_iterate (peerinfo, NULL, GNUNET_TIME_UNIT_MINUTES,
  398. &host_processor, results);
  399. }
  400. /**
  401. * Function that queries MHD's select sets and
  402. * starts the task waiting for them.
  403. */
  404. static GNUNET_SCHEDULER_TaskIdentifier
  405. prepare_daemon (struct MHD_Daemon *daemon_handle);
  406. /**
  407. * Call MHD to process pending requests and then go back
  408. * and schedule the next run.
  409. */
  410. static void
  411. run_daemon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  412. {
  413. struct MHD_Daemon *daemon_handle = cls;
  414. if (daemon_handle == daemon_handle_v4)
  415. hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
  416. else
  417. hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
  418. if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  419. return;
  420. GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
  421. if (daemon_handle == daemon_handle_v4)
  422. hostlist_task_v4 = prepare_daemon (daemon_handle);
  423. else
  424. hostlist_task_v6 = prepare_daemon (daemon_handle);
  425. }
  426. /**
  427. * Function that queries MHD's select sets and
  428. * starts the task waiting for them.
  429. */
  430. static GNUNET_SCHEDULER_TaskIdentifier
  431. prepare_daemon (struct MHD_Daemon *daemon_handle)
  432. {
  433. GNUNET_SCHEDULER_TaskIdentifier ret;
  434. fd_set rs;
  435. fd_set ws;
  436. fd_set es;
  437. struct GNUNET_NETWORK_FDSet *wrs;
  438. struct GNUNET_NETWORK_FDSet *wws;
  439. struct GNUNET_NETWORK_FDSet *wes;
  440. int max;
  441. unsigned long long timeout;
  442. int haveto;
  443. struct GNUNET_TIME_Relative tv;
  444. FD_ZERO (&rs);
  445. FD_ZERO (&ws);
  446. FD_ZERO (&es);
  447. wrs = GNUNET_NETWORK_fdset_create ();
  448. wes = GNUNET_NETWORK_fdset_create ();
  449. wws = GNUNET_NETWORK_fdset_create ();
  450. max = -1;
  451. GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
  452. haveto = MHD_get_timeout (daemon_handle, &timeout);
  453. if (haveto == MHD_YES)
  454. tv.rel_value = (uint64_t) timeout;
  455. else
  456. tv = GNUNET_TIME_UNIT_FOREVER_REL;
  457. GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
  458. GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
  459. GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
  460. ret =
  461. GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
  462. GNUNET_SCHEDULER_NO_TASK, tv, wrs, wws,
  463. &run_daemon, daemon_handle);
  464. GNUNET_NETWORK_fdset_destroy (wrs);
  465. GNUNET_NETWORK_fdset_destroy (wws);
  466. GNUNET_NETWORK_fdset_destroy (wes);
  467. return ret;
  468. }
  469. /**
  470. * Start server offering our hostlist.
  471. *
  472. * @return GNUNET_OK on success
  473. */
  474. int
  475. GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
  476. struct GNUNET_STATISTICS_Handle *st,
  477. struct GNUNET_CORE_Handle *co,
  478. GNUNET_CORE_ConnectEventHandler *server_ch,
  479. GNUNET_CORE_DisconnectEventHandler *server_dh,
  480. int advertise)
  481. {
  482. unsigned long long port;
  483. char *hostname;
  484. size_t size;
  485. advertising = advertise;
  486. if (!advertising)
  487. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  488. "Advertising not enabled on this hostlist server\n");
  489. else
  490. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  491. "Advertising enabled on this hostlist server\n");
  492. cfg = c;
  493. stats = st;
  494. peerinfo = GNUNET_PEERINFO_connect (cfg);
  495. if (peerinfo == NULL)
  496. {
  497. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  498. _("Could not access PEERINFO service. Exiting.\n"));
  499. return GNUNET_SYSERR;
  500. }
  501. if (GNUNET_OK !=
  502. GNUNET_CONFIGURATION_get_value_number (cfg, "HOSTLIST", "HTTPPORT",
  503. &port))
  504. return GNUNET_SYSERR;
  505. if ((port == 0) || (port > UINT16_MAX))
  506. {
  507. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  508. _("Invalid port number %llu. Exiting.\n"), port);
  509. return GNUNET_SYSERR;
  510. }
  511. if (GNUNET_SYSERR ==
  512. GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
  513. "EXTERNAL_DNS_NAME", &hostname))
  514. hostname = GNUNET_RESOLVER_local_fqdn_get ();
  515. GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Hostlist service starts on %s:%llu\n"),
  516. hostname, port);
  517. if (NULL != hostname)
  518. {
  519. size = strlen (hostname);
  520. if (size + 15 > MAX_URL_LEN)
  521. {
  522. GNUNET_break (0);
  523. }
  524. else
  525. {
  526. GNUNET_asprintf (&hostlist_uri, "http://%s:%u/", hostname,
  527. (unsigned int) port);
  528. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  529. _("Address to obtain hostlist: `%s'\n"), hostlist_uri);
  530. }
  531. GNUNET_free (hostname);
  532. }
  533. daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6
  534. #if DEBUG_HOSTLIST_SERVER
  535. | MHD_USE_DEBUG
  536. #endif
  537. , (unsigned short) port,
  538. &accept_policy_callback, NULL,
  539. &access_handler_callback, NULL,
  540. MHD_OPTION_CONNECTION_LIMIT,
  541. (unsigned int) 16,
  542. MHD_OPTION_PER_IP_CONNECTION_LIMIT,
  543. (unsigned int) 1,
  544. MHD_OPTION_CONNECTION_TIMEOUT,
  545. (unsigned int) 16,
  546. MHD_OPTION_CONNECTION_MEMORY_LIMIT,
  547. (size_t) (16 * 1024), MHD_OPTION_END);
  548. daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG
  549. #if DEBUG_HOSTLIST_SERVER
  550. | MHD_USE_DEBUG
  551. #endif
  552. , (unsigned short) port,
  553. &accept_policy_callback, NULL,
  554. &access_handler_callback, NULL,
  555. MHD_OPTION_CONNECTION_LIMIT,
  556. (unsigned int) 16,
  557. MHD_OPTION_PER_IP_CONNECTION_LIMIT,
  558. (unsigned int) 1,
  559. MHD_OPTION_CONNECTION_TIMEOUT,
  560. (unsigned int) 16,
  561. MHD_OPTION_CONNECTION_MEMORY_LIMIT,
  562. (size_t) (16 * 1024), MHD_OPTION_END);
  563. if ((daemon_handle_v6 == NULL) && (daemon_handle_v4 == NULL))
  564. {
  565. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  566. _("Could not start hostlist HTTP server on port %u\n"),
  567. (unsigned short) port);
  568. return GNUNET_SYSERR;
  569. }
  570. core = co;
  571. *server_ch = &connect_handler;
  572. *server_dh = &disconnect_handler;
  573. if (daemon_handle_v4 != NULL)
  574. hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
  575. if (daemon_handle_v6 != NULL)
  576. hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
  577. notify = GNUNET_PEERINFO_notify (cfg, process_notify, NULL);
  578. return GNUNET_OK;
  579. }
  580. /**
  581. * Stop server offering our hostlist.
  582. */
  583. void
  584. GNUNET_HOSTLIST_server_stop ()
  585. {
  586. #if DEBUG_HOSTLIST_SERVER
  587. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
  588. #endif
  589. if (NULL != notify)
  590. {
  591. GNUNET_PEERINFO_notify_cancel (notify);
  592. notify = NULL;
  593. }
  594. if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
  595. {
  596. GNUNET_SCHEDULER_cancel (hostlist_task_v6);
  597. hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
  598. }
  599. if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
  600. {
  601. GNUNET_SCHEDULER_cancel (hostlist_task_v4);
  602. hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
  603. }
  604. if (pitr != NULL)
  605. {
  606. GNUNET_PEERINFO_iterate_cancel (pitr);
  607. pitr = NULL;
  608. }
  609. if (NULL != daemon_handle_v4)
  610. {
  611. MHD_stop_daemon (daemon_handle_v4);
  612. daemon_handle_v4 = NULL;
  613. }
  614. if (NULL != daemon_handle_v6)
  615. {
  616. MHD_stop_daemon (daemon_handle_v6);
  617. daemon_handle_v6 = NULL;
  618. }
  619. if (response != NULL)
  620. {
  621. MHD_destroy_response (response);
  622. response = NULL;
  623. }
  624. if (peerinfo != NULL)
  625. {
  626. GNUNET_PEERINFO_disconnect (peerinfo);
  627. peerinfo = NULL;
  628. }
  629. cfg = NULL;
  630. stats = NULL;
  631. core = NULL;
  632. }
  633. /* end of hostlist-server.c */