gnunet-daemon-hostlist.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2007, 2008, 2009, 2014 GNUnet e.V.
  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., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. /**
  18. * @file hostlist/gnunet-daemon-hostlist.c
  19. * @brief code for bootstrapping via hostlist servers
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet-daemon-hostlist_client.h"
  24. #include "gnunet_core_service.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_protocols.h"
  27. #include "gnunet_statistics_service.h"
  28. #if HAVE_MHD
  29. #include "gnunet-daemon-hostlist_server.h"
  30. /**
  31. * Set if we are allowed to advertise our hostlist to others.
  32. */
  33. static int advertising;
  34. /**
  35. * Set if the user wants us to run a hostlist server.
  36. */
  37. static int provide_hostlist;
  38. /**
  39. * Handle to hostlist server's connect handler
  40. */
  41. static GNUNET_CORE_ConnectEventHandler server_ch;
  42. #endif
  43. /**
  44. * Set if we are allowed to learn about peers by accessing
  45. * hostlist servers.
  46. */
  47. static int bootstrapping;
  48. /**
  49. * Set if the user allows us to learn about new hostlists
  50. * from the network.
  51. */
  52. static int learning;
  53. /**
  54. * Statistics handle.
  55. */
  56. static struct GNUNET_STATISTICS_Handle *stats;
  57. /**
  58. * Handle to the core service (NULL until we've connected to it).
  59. */
  60. static struct GNUNET_CORE_Handle *core;
  61. /**
  62. * Handle to the hostlist client's advertisement handler
  63. */
  64. static GNUNET_HOSTLIST_UriHandler client_adv_handler;
  65. /**
  66. * Handle to hostlist client's connect handler
  67. */
  68. static GNUNET_CORE_ConnectEventHandler client_ch;
  69. /**
  70. * Handle to hostlist client's disconnect handler
  71. */
  72. static GNUNET_CORE_DisconnectEventHandler client_dh;
  73. GNUNET_NETWORK_STRUCT_BEGIN
  74. /**
  75. * A HOSTLIST_ADV message is used to exchange information about
  76. * hostlist advertisements. This struct is always
  77. * followed by the actual url under which the hostlist can be obtained:
  78. *
  79. * 1) transport-name (0-terminated)
  80. * 2) address-length (uint32_t, network byte order; possibly
  81. * unaligned!)
  82. * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly
  83. * unaligned!)
  84. * 4) address (address-length bytes; possibly unaligned!)
  85. */
  86. struct GNUNET_HOSTLIST_ADV_Message
  87. {
  88. /**
  89. * Type will be GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT.
  90. */
  91. struct GNUNET_MessageHeader header;
  92. /**
  93. * Always zero (for alignment).
  94. */
  95. uint32_t reserved GNUNET_PACKED;
  96. };
  97. GNUNET_NETWORK_STRUCT_END
  98. /**
  99. * Our own peer identity.
  100. */
  101. static struct GNUNET_PeerIdentity me;
  102. /**
  103. * Callback invoked once our connection to CORE service is up.
  104. *
  105. * @param cls NULL
  106. * @param my_identity our peer's identity
  107. */
  108. static void
  109. core_init (void *cls,
  110. const struct GNUNET_PeerIdentity *my_identity)
  111. {
  112. me = *my_identity;
  113. }
  114. /**
  115. * Core handler for p2p hostlist advertisements
  116. *
  117. * @param cls closure
  118. * @param message advertisement message we got
  119. * @return #GNUNET_OK if message is well-formed
  120. */
  121. static int
  122. check_advertisement (void *cls,
  123. const struct GNUNET_MessageHeader *message)
  124. {
  125. size_t size;
  126. size_t uri_size;
  127. const char *uri;
  128. size = ntohs (message->size);
  129. if (size <= sizeof (struct GNUNET_MessageHeader))
  130. {
  131. GNUNET_break_op (0);
  132. return GNUNET_SYSERR;
  133. }
  134. uri = (const char *) &message[1];
  135. uri_size = size - sizeof (struct GNUNET_MessageHeader);
  136. if (uri[uri_size - 1] != '\0')
  137. {
  138. GNUNET_break_op (0);
  139. return GNUNET_SYSERR;
  140. }
  141. return GNUNET_OK;
  142. }
  143. /**
  144. * Core handler for p2p hostlist advertisements
  145. *
  146. * @param cls closure
  147. * @param message advertisement message we got
  148. * @return #GNUNET_OK on success
  149. */
  150. static void
  151. handle_advertisement (void *cls,
  152. const struct GNUNET_MessageHeader *message)
  153. {
  154. const char *uri = (const char *) &message[1];
  155. GNUNET_assert (NULL != client_adv_handler);
  156. (void) (*client_adv_handler) (uri);
  157. }
  158. /**
  159. * Method called whenever a given peer connects. Wrapper to call both
  160. * client's and server's functions
  161. *
  162. * @param cls closure
  163. * @param peer peer identity this notification is about
  164. * @param mq queue for sending messages to @a peer
  165. * @return peer
  166. */
  167. static void *
  168. connect_handler (void *cls,
  169. const struct GNUNET_PeerIdentity *peer,
  170. struct GNUNET_MQ_Handle *mq)
  171. {
  172. if (0 == memcmp (&me,
  173. peer,
  174. sizeof (struct GNUNET_PeerIdentity)))
  175. return NULL;
  176. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  177. "A new peer connected, notifying client and server\n");
  178. if (NULL != client_ch)
  179. GNUNET_assert (NULL ==
  180. (*client_ch) (cls,
  181. peer,
  182. mq));
  183. #if HAVE_MHD
  184. if (NULL != server_ch)
  185. GNUNET_assert (NULL ==
  186. (*server_ch) (cls,
  187. peer,
  188. mq));
  189. #endif
  190. return (void *) peer;
  191. }
  192. /**
  193. * Method called whenever a given peer disconnects. Wrapper to call
  194. * both client's and server's functions
  195. *
  196. * @param cls closure
  197. * @param peer peer identity this notification is about
  198. */
  199. static void
  200. disconnect_handler (void *cls,
  201. const struct GNUNET_PeerIdentity *peer,
  202. void *internal_cls)
  203. {
  204. if (0 == memcmp (&me,
  205. peer,
  206. sizeof (struct GNUNET_PeerIdentity)))
  207. return;
  208. /* call hostlist client disconnect handler */
  209. if (NULL != client_dh)
  210. (*client_dh) (cls,
  211. peer,
  212. NULL);
  213. }
  214. /**
  215. * Last task run during shutdown. Disconnects us from
  216. * the other services.
  217. *
  218. * @param cls NULL
  219. */
  220. static void
  221. cleaning_task (void *cls)
  222. {
  223. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  224. "Hostlist daemon is shutting down\n");
  225. if (NULL != core)
  226. {
  227. GNUNET_CORE_disconnect (core);
  228. core = NULL;
  229. }
  230. if (bootstrapping)
  231. {
  232. GNUNET_HOSTLIST_client_stop ();
  233. }
  234. #if HAVE_MHD
  235. if (provide_hostlist)
  236. {
  237. GNUNET_HOSTLIST_server_stop ();
  238. }
  239. #endif
  240. if (NULL != stats)
  241. {
  242. GNUNET_STATISTICS_destroy (stats,
  243. GNUNET_NO);
  244. stats = NULL;
  245. }
  246. }
  247. /**
  248. * Main function that will be run.
  249. *
  250. * @param cls closure
  251. * @param args remaining command-line arguments
  252. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  253. * @param cfg configuration
  254. */
  255. static void
  256. run (void *cls,
  257. char *const *args,
  258. const char *cfgfile,
  259. const struct GNUNET_CONFIGURATION_Handle *cfg)
  260. {
  261. struct GNUNET_MQ_MessageHandler learn_handlers[] = {
  262. GNUNET_MQ_hd_var_size (advertisement,
  263. GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT,
  264. struct GNUNET_MessageHeader,
  265. NULL),
  266. GNUNET_MQ_handler_end ()
  267. };
  268. struct GNUNET_MQ_MessageHandler no_learn_handlers[] = {
  269. GNUNET_MQ_handler_end ()
  270. };
  271. if ((! bootstrapping) && (! learning)
  272. #if HAVE_MHD
  273. && (! provide_hostlist)
  274. #endif
  275. )
  276. {
  277. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  278. _("None of the functions for the hostlist daemon were enabled. I have no reason to run!\n"));
  279. return;
  280. }
  281. stats = GNUNET_STATISTICS_create ("hostlist", cfg);
  282. if (NULL == stats)
  283. {
  284. GNUNET_break (0);
  285. return;
  286. }
  287. if (bootstrapping)
  288. GNUNET_HOSTLIST_client_start (cfg,
  289. stats,
  290. &client_ch,
  291. &client_dh,
  292. &client_adv_handler,
  293. learning);
  294. core =
  295. GNUNET_CORE_connect (cfg,
  296. NULL,
  297. &core_init,
  298. &connect_handler,
  299. &disconnect_handler,
  300. learning ? learn_handlers : no_learn_handlers);
  301. #if HAVE_MHD
  302. if (provide_hostlist)
  303. GNUNET_HOSTLIST_server_start (cfg,
  304. stats,
  305. core,
  306. &server_ch,
  307. advertising);
  308. #endif
  309. GNUNET_SCHEDULER_add_shutdown (&cleaning_task,
  310. NULL);
  311. if (NULL == core)
  312. {
  313. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  314. _("Failed to connect to `%s' service.\n"), "core");
  315. GNUNET_SCHEDULER_shutdown ();
  316. return;
  317. }
  318. }
  319. /**
  320. * The main function for the hostlist daemon.
  321. *
  322. * @param argc number of arguments from the command line
  323. * @param argv command line arguments
  324. * @return 0 ok, 1 on error
  325. */
  326. int
  327. main (int argc, char *const *argv)
  328. {
  329. struct GNUNET_GETOPT_CommandLineOption options[] = {
  330. #if HAVE_MHD
  331. GNUNET_GETOPT_option_flag ('a',
  332. "advertise",
  333. gettext_noop ("advertise our hostlist to other peers"),
  334. &advertising),
  335. #endif
  336. GNUNET_GETOPT_option_flag ('b',
  337. "bootstrap",
  338. gettext_noop ("bootstrap using hostlists (it is highly recommended that you always use this option)"),
  339. &bootstrapping),
  340. GNUNET_GETOPT_option_flag ('e',
  341. "enable-learning",
  342. gettext_noop ("enable learning about hostlist servers from other peers"),
  343. &learning),
  344. #if HAVE_MHD
  345. GNUNET_GETOPT_option_flag ('p',
  346. "provide-hostlist",
  347. gettext_noop ("provide a hostlist server"),
  348. &provide_hostlist),
  349. #endif
  350. GNUNET_GETOPT_OPTION_END
  351. };
  352. int ret;
  353. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  354. return 2;
  355. GNUNET_log_setup ("hostlist", "WARNING", NULL);
  356. ret =
  357. (GNUNET_OK ==
  358. GNUNET_PROGRAM_run (argc, argv,
  359. "hostlist",
  360. _("GNUnet hostlist server and client"),
  361. options,
  362. &run, NULL)) ? 0 : 1;
  363. GNUNET_free ((void*) argv);
  364. return ret;
  365. }
  366. /* end of gnunet-daemon-hostlist.c */