gnunet-messenger.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2020 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. * @author Tobias Frisch
  18. * @file src/messenger/gnunet-messenger.c
  19. * @brief Print information about messenger groups.
  20. */
  21. #include <stdio.h>
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_messenger_service.h"
  25. struct GNUNET_MESSENGER_Handle *messenger;
  26. /**
  27. * Function called whenever a message is received or sent.
  28. *
  29. * @param cls Closure
  30. * @param room Room
  31. * @param message Message
  32. * @param hash Hash of message
  33. */
  34. void
  35. on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
  36. const struct GNUNET_HashCode *hash)
  37. {
  38. struct GNUNET_MESSENGER_Contact *sender = GNUNET_MESSENGER_get_member (room, &(message->header.sender_id));
  39. const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
  40. if (!sender_name)
  41. sender_name = "anonymous";
  42. switch (message->header.kind)
  43. {
  44. case GNUNET_MESSENGER_KIND_JOIN:
  45. {
  46. printf ("* '%s' joined the room! [ %u %u %u %u ]\n", sender_name, message->body.join.key.ecdsa_key.q_y[0],
  47. message->body.join.key.ecdsa_key.q_y[1], message->body.join.key.ecdsa_key.q_y[2],
  48. message->body.join.key.ecdsa_key.q_y[3]);
  49. break;
  50. }
  51. case GNUNET_MESSENGER_KIND_LEAVE:
  52. {
  53. printf ("* '%s' leaves the room!\n", sender_name);
  54. break;
  55. }
  56. case GNUNET_MESSENGER_KIND_PEER:
  57. {
  58. printf ("* '%s' opened the room on: %s\n", sender_name, GNUNET_i2s_full (&(message->body.peer.peer)));
  59. break;
  60. }
  61. case GNUNET_MESSENGER_KIND_TEXT:
  62. {
  63. printf ("* '%s' says: \"%s\"\n", sender_name, message->body.text.text);
  64. break;
  65. }
  66. default:
  67. {
  68. break;
  69. }
  70. }
  71. }
  72. struct GNUNET_SCHEDULER_Task *read_task;
  73. /**
  74. * Task to shut down this application.
  75. *
  76. * @param cls Closure
  77. */
  78. static void
  79. shutdown_hook (void *cls)
  80. {
  81. struct GNUNET_MESSENGER_Room *room = cls;
  82. if (read_task)
  83. GNUNET_SCHEDULER_cancel (read_task);
  84. if (room)
  85. GNUNET_MESSENGER_close_room (room);
  86. if (messenger)
  87. GNUNET_MESSENGER_disconnect (messenger);
  88. }
  89. static void
  90. listen_stdio (void *cls);
  91. #define MAX_BUFFER_SIZE 60000
  92. /**
  93. * Task run in stdio mode, after some data is available at stdin.
  94. *
  95. * @param cls Closure
  96. */
  97. static void
  98. read_stdio (void *cls)
  99. {
  100. read_task = NULL;
  101. char buffer[MAX_BUFFER_SIZE];
  102. ssize_t length;
  103. length = read (0, buffer, MAX_BUFFER_SIZE);
  104. if ((length <= 0) || (length >= MAX_BUFFER_SIZE))
  105. {
  106. GNUNET_SCHEDULER_shutdown ();
  107. return;
  108. }
  109. if (buffer[length - 1] == '\n')
  110. buffer[length - 1] = '\0';
  111. else
  112. buffer[length] = '\0';
  113. struct GNUNET_MESSENGER_Room *room = cls;
  114. struct GNUNET_MESSENGER_Message message;
  115. message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
  116. message.body.text.text = buffer;
  117. GNUNET_MESSENGER_send_message (room, &message);
  118. read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
  119. }
  120. /**
  121. * Wait for input on STDIO and send it out over the #ch.
  122. *
  123. * @param cls Closure
  124. */
  125. static void
  126. listen_stdio (void *cls)
  127. {
  128. read_task = NULL;
  129. struct GNUNET_NETWORK_FDSet *rs = GNUNET_NETWORK_fdset_create ();
  130. GNUNET_NETWORK_fdset_set_native (rs, 0);
  131. read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
  132. GNUNET_TIME_UNIT_FOREVER_REL,
  133. rs,
  134. NULL,
  135. &read_stdio, cls);
  136. GNUNET_NETWORK_fdset_destroy (rs);
  137. }
  138. /**
  139. * Initial task to startup application.
  140. *
  141. * @param cls Closure
  142. */
  143. static void
  144. idle (void *cls)
  145. {
  146. struct GNUNET_MESSENGER_Room *room = cls;
  147. printf ("* You joined the room.\n");
  148. read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room);
  149. }
  150. char *door_id;
  151. char *ego_name;
  152. char *room_key;
  153. struct GNUNET_SCHEDULER_Task *shutdown_task;
  154. /**
  155. * Function called when an identity is retrieved.
  156. *
  157. * @param cls Closure
  158. * @param handle Handle of messenger service
  159. */
  160. static void
  161. on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
  162. {
  163. struct GNUNET_HashCode key;
  164. memset (&key, 0, sizeof(key));
  165. if (room_key)
  166. GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
  167. struct GNUNET_PeerIdentity *door = NULL;
  168. if (door_id)
  169. {
  170. door = GNUNET_new(struct GNUNET_PeerIdentity);
  171. if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door->public_key)))
  172. {
  173. GNUNET_free(door);
  174. door = NULL;
  175. }
  176. }
  177. const char *name = GNUNET_MESSENGER_get_name (handle);
  178. if (!name)
  179. name = "anonymous";
  180. printf ("* Welcome to the messenger, '%s'!\n", name);
  181. struct GNUNET_MESSENGER_Room *room;
  182. if (door)
  183. {
  184. printf ("* You try to entry a room...\n");
  185. room = GNUNET_MESSENGER_entry_room (messenger, door, &key);
  186. }
  187. else
  188. {
  189. printf ("* You try to open a room...\n");
  190. room = GNUNET_MESSENGER_open_room (messenger, &key);
  191. }
  192. GNUNET_SCHEDULER_cancel (shutdown_task);
  193. shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room);
  194. if (!room)
  195. GNUNET_SCHEDULER_shutdown ();
  196. else
  197. GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
  198. room);
  199. }
  200. /**
  201. * Main function that will be run by the scheduler.
  202. *
  203. * @param cls closure
  204. * @param args remaining command-line arguments
  205. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  206. * @param cfg configuration
  207. */
  208. static void
  209. run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
  210. {
  211. messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL);
  212. shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
  213. }
  214. /**
  215. * The main function to obtain messenger information.
  216. *
  217. * @param argc number of arguments from the command line
  218. * @param argv command line arguments
  219. * @return 0 ok, 1 on error
  220. */
  221. int
  222. main (int argc, char **argv)
  223. {
  224. const char *description = "Open and connect to rooms using the MESSENGER to chat.";
  225. struct GNUNET_GETOPT_CommandLineOption options[] = {
  226. GNUNET_GETOPT_option_string ('d',
  227. "door",
  228. "PEERIDENTITY",
  229. "peer identity to entry into the room",
  230. &door_id),
  231. GNUNET_GETOPT_option_string ('e',
  232. "ego",
  233. "IDENTITY",
  234. "identity to use for messaging",
  235. &ego_name),
  236. GNUNET_GETOPT_option_string ('r',
  237. "room",
  238. "ROOMKEY",
  239. "key of the room to connect to",
  240. &room_key),
  241. GNUNET_GETOPT_OPTION_END };
  242. return (GNUNET_OK == GNUNET_PROGRAM_run (argc,
  243. argv,
  244. "gnunet-messenger\0",
  245. gettext_noop(description),
  246. options,
  247. &run,
  248. NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
  249. }