gnunet-service-testbed-logger.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2008--2013 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 testbed/gnunet-service-testbed-logger.c
  19. * @brief service for collecting messages and writing to a file
  20. * @author Sree Harsha Totakura
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. /**
  25. * Generic logging shorthand
  26. */
  27. #define LOG(type, ...) \
  28. GNUNET_log (type, __VA_ARGS__)
  29. /**
  30. * Debug logging shorthand
  31. */
  32. #define LOG_DEBUG(...) \
  33. LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
  34. /**
  35. * The message queue for sending messages to clients
  36. */
  37. struct MessageQueue
  38. {
  39. /**
  40. * The message to be sent
  41. */
  42. struct GNUNET_MessageHeader *msg;
  43. /**
  44. * The client to send the message to
  45. */
  46. struct GNUNET_SERVER_Client *client;
  47. /**
  48. * next pointer for DLL
  49. */
  50. struct MessageQueue *next;
  51. /**
  52. * prev pointer for DLL
  53. */
  54. struct MessageQueue *prev;
  55. };
  56. /**
  57. * The message queue head
  58. */
  59. static struct MessageQueue *mq_head;
  60. /**
  61. * The message queue tail
  62. */
  63. static struct MessageQueue *mq_tail;
  64. /**
  65. * Handle for buffered writing.
  66. */
  67. struct GNUNET_BIO_WriteHandle *bio;
  68. /**
  69. * The shutdown task handle
  70. */
  71. static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
  72. /**
  73. * The number of connections we have
  74. */
  75. static unsigned int nconn;
  76. /**
  77. * Are we shutting down?
  78. */
  79. static int in_shutdown;
  80. /**
  81. * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
  82. *
  83. * @param cls NULL
  84. * @param client identification of the client
  85. * @param msg the actual message
  86. */
  87. static void
  88. handle_log_msg (void *cls, struct GNUNET_SERVER_Client *client,
  89. const struct GNUNET_MessageHeader *msg)
  90. {
  91. uint16_t ms;
  92. ms = ntohs (msg->size);
  93. ms -= sizeof (struct GNUNET_MessageHeader);
  94. GNUNET_BIO_write (bio, &msg[1], ms);
  95. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  96. }
  97. /**
  98. * Task to clean up and shutdown nicely
  99. *
  100. * @param cls NULL
  101. * @param tc the TaskContext from scheduler
  102. */
  103. static void
  104. shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  105. {
  106. struct MessageQueue *mq_entry;
  107. shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
  108. in_shutdown = GNUNET_YES;
  109. if (0 != nconn)
  110. {
  111. /* Delay shutdown if there are active connections */
  112. shutdown_task_id = GNUNET_SCHEDULER_add_delayed
  113. (GNUNET_TIME_UNIT_FOREVER_REL,
  114. &shutdown_task, NULL);
  115. return;
  116. }
  117. while (NULL != (mq_entry = mq_head))
  118. {
  119. GNUNET_free (mq_entry->msg);
  120. GNUNET_SERVER_client_drop (mq_entry->client);
  121. GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
  122. GNUNET_free (mq_entry);
  123. }
  124. GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio));
  125. }
  126. /**
  127. * Functions with this signature are called whenever a client
  128. * is disconnected on the network level.
  129. *
  130. * @param cls closure
  131. * @param client identification of the client; NULL
  132. * for the last call when the server is destroyed
  133. */
  134. static void
  135. client_disconnected (void *cls, struct GNUNET_SERVER_Client *client)
  136. {
  137. if (NULL == client)
  138. {
  139. GNUNET_break (0 == nconn);
  140. return;
  141. }
  142. nconn--;
  143. if (GNUNET_YES != in_shutdown)
  144. return;
  145. GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id);
  146. GNUNET_SCHEDULER_cancel (shutdown_task_id);
  147. shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
  148. }
  149. /**
  150. * Functions with this signature are called whenever a client
  151. * is connected on the network level.
  152. *
  153. * @param cls closure
  154. * @param client identification of the client
  155. */
  156. static void
  157. client_connected (void *cls, struct GNUNET_SERVER_Client *client)
  158. {
  159. if (NULL == client)
  160. {
  161. GNUNET_break (0 == nconn);
  162. return;
  163. }
  164. GNUNET_SERVER_client_persist_ (client);
  165. nconn++;
  166. }
  167. /**
  168. * Testbed setup
  169. *
  170. * @param cls closure
  171. * @param server the initialized server
  172. * @param cfg configuration to use
  173. */
  174. static void
  175. logger_run (void *cls, struct GNUNET_SERVER_Handle *server,
  176. const struct GNUNET_CONFIGURATION_Handle *cfg)
  177. {
  178. static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
  179. {&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0},
  180. {NULL, NULL, 0, 0}
  181. };
  182. char *dir;
  183. char *fn;
  184. char *hname;
  185. size_t hname_len;
  186. pid_t pid;
  187. if (GNUNET_OK !=
  188. GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR",
  189. &dir))
  190. {
  191. LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied. Exiting\n");
  192. GNUNET_SCHEDULER_shutdown ();
  193. return;
  194. }
  195. pid = getpid ();
  196. hname_len = GNUNET_OS_get_hostname_max_length ();
  197. hname = GNUNET_malloc (hname_len);
  198. if (0 != gethostname (hname, hname_len))
  199. {
  200. LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname. Exiting\n");
  201. GNUNET_free (hname);
  202. GNUNET_free (dir);
  203. GNUNET_SCHEDULER_shutdown ();
  204. return;
  205. }
  206. (void) GNUNET_asprintf (&fn, "%s/%.*s_%jd.dat", dir, hname_len, hname,
  207. (intmax_t) pid);
  208. GNUNET_free (hname);
  209. GNUNET_free (dir);
  210. if (NULL == (bio = GNUNET_BIO_write_open (fn)))
  211. {
  212. GNUNET_free (fn);
  213. GNUNET_SCHEDULER_shutdown ();
  214. return;
  215. }
  216. GNUNET_free (fn);
  217. GNUNET_SERVER_add_handlers (server, message_handlers);
  218. GNUNET_SERVER_connect_notify (server, &client_connected, NULL);
  219. GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL);
  220. shutdown_task_id =
  221. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  222. &shutdown_task, NULL);
  223. LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
  224. }
  225. /**
  226. * The starting point of execution
  227. */
  228. int
  229. main (int argc, char *const *argv)
  230. {
  231. //sleep (15); /* Debugging */
  232. return (GNUNET_OK ==
  233. GNUNET_SERVICE_run (argc, argv, "testbed-logger",
  234. GNUNET_SERVICE_OPTION_NONE,
  235. &logger_run, NULL)) ? 0 : 1;
  236. }
  237. /* end of gnunet-service-testbed.c */