GNUnet  0.11.x
gnunet-messenger.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2020--2021 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
26 #include <stdio.h>
27 
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
31 
33 
44 void
45 on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
46  const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
48 {
49  const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
50 
51  if (!sender_name)
52  sender_name = "anonymous";
53 
54  printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
55 
57  printf ("*");
58 
59  switch (message->header.kind)
60  {
62  {
63  printf ("* '%s' joined the room!\n", sender_name);
64  break;
65  }
67  {
68  printf ("* '%s' gets renamed to '%s'\n", sender_name, message->body.name.name);
69  break;
70  }
72  {
73  printf ("* '%s' leaves the room!\n", sender_name);
74  break;
75  }
77  {
78  printf ("* '%s' opened the room on: %s\n", sender_name, GNUNET_i2s_full (&(message->body.peer.peer)));
79  break;
80  }
82  {
83  printf ("* '%s' says: \"%s\"\n", sender_name, message->body.text.text);
84  break;
85  }
86  default:
87  {
88  printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
89  break;
90  }
91  }
92 }
93 
95 
101 static void
102 shutdown_hook (void *cls)
103 {
104  struct GNUNET_MESSENGER_Room *room = cls;
105 
106  if (read_task)
107  GNUNET_SCHEDULER_cancel (read_task);
108 
109  if (room)
111 
112  if (messenger)
113  GNUNET_MESSENGER_disconnect (messenger);
114 }
115 
116 static void
117 listen_stdio (void *cls);
118 
119 #define MAX_BUFFER_SIZE 60000
120 
121 static int
123  const struct GNUNET_MESSENGER_Contact *contact)
124 {
125  struct GNUNET_MESSENGER_Message *message = cls;
126 
128  GNUNET_MESSENGER_send_message (room, message, contact);
129 
130  return GNUNET_YES;
131 }
132 
134 
140 static void
141 read_stdio (void *cls)
142 {
143  read_task = NULL;
144 
145  char buffer[MAX_BUFFER_SIZE];
146  ssize_t length;
147 
148  length = read (0, buffer, MAX_BUFFER_SIZE);
149 
150  if ((length <= 0) || (length >= MAX_BUFFER_SIZE))
151  {
153  return;
154  }
155 
156  if (buffer[length - 1] == '\n')
157  buffer[length - 1] = '\0';
158  else
159  buffer[length] = '\0';
160 
161  struct GNUNET_MESSENGER_Room *room = cls;
162 
163  struct GNUNET_MESSENGER_Message message;
165  message.body.text.text = buffer;
166 
167  if (GNUNET_YES == private_mode)
169  else
170  GNUNET_MESSENGER_send_message (room, &message, NULL);
171 
172  read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
173 }
174 
180 static void
181 listen_stdio (void *cls)
182 {
183  read_task = NULL;
184 
186 
188 
191  NULL, &read_stdio, cls);
192 
194 }
195 
201 static void
202 idle (void *cls)
203 {
204  struct GNUNET_MESSENGER_Room *room = cls;
205 
206  printf ("* You joined the room.\n");
207 
208  read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room);
209 }
210 
211 char *door_id;
212 char *ego_name;
213 char *room_key;
214 
216 
223 static void
225 {
226  struct GNUNET_HashCode key;
227  memset (&key, 0, sizeof(key));
228 
229  if (room_key)
230  GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
231 
232  struct GNUNET_PeerIdentity *door = NULL;
233 
234  if (door_id)
235  {
236  door = GNUNET_new(struct GNUNET_PeerIdentity);
237 
239  {
240  GNUNET_free(door);
241  door = NULL;
242  }
243  }
244 
245  const char *name = GNUNET_MESSENGER_get_name (handle);
246 
247  if (!name)
248  name = "anonymous";
249 
250  printf ("* Welcome to the messenger, '%s'!\n", name);
251 
252  struct GNUNET_MESSENGER_Room *room;
253 
254  if (door)
255  {
256  printf ("* You try to entry a room...\n");
257 
258  room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
259  }
260  else
261  {
262  printf ("* You try to open a room...\n");
263 
264  room = GNUNET_MESSENGER_open_room (messenger, &key);
265  }
266 
267  GNUNET_SCHEDULER_cancel (shutdown_task);
268 
269  shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room);
270 
271  if (!room)
273  else
274  {
275  struct GNUNET_MESSENGER_Message message;
277  message.body.name.name = GNUNET_strdup(name);
278 
279  GNUNET_MESSENGER_send_message (room, &message, NULL);
280  GNUNET_free(message.body.name.name);
281 
283  room);
284  }
285 }
286 
295 static void
296 run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
297 {
298  messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL);
299 
300  shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
301 }
302 
310 int
311 main (int argc, char **argv)
312 {
313  const char *description = "Open and connect to rooms using the MESSENGER to chat.";
314 
315  struct GNUNET_GETOPT_CommandLineOption options[] =
316  {
317  GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
318  GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
319  GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
320  GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
322  };
323 
324  return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
325  NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
326 }
struct GNUNET_PeerIdentity peer
The peer identity of the sender opening a room.
struct GNUNET_MESSENGER_MessageHeader header
Header.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
struct GNUNET_ShortHashCode sender_id
The senders id inside of the room the message was sent in.
struct GNUNET_MESSENGER_Room * GNUNET_MESSENGER_open_room(struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
Open a room to send and receive messages.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:363
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
void GNUNET_MESSENGER_close_room(struct GNUNET_MESSENGER_Room *room)
Close a room which was entered, opened or both in various order and variety.
void GNUNET_MESSENGER_send_message(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_MESSENGER_Contact *contact)
Send a message into a room.
void on_message(void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, enum GNUNET_MESSENGER_MessageFlags flags)
Function called whenever a message is received or sent.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1199
struct GNUNET_MESSENGER_Room * GNUNET_MESSENGER_enter_room(struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
Enter a room to send and receive messages through a door opened using GNUNET_MESSENGER_open_room.
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1134
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
const char * GNUNET_MESSENGER_contact_get_name(const struct GNUNET_MESSENGER_Contact *contact)
Get the name used by the contact.
#define MAX_BUFFER_SIZE
struct GNUNET_MESSENGER_MessageText text
static void idle(void *cls)
Initial task to startup application.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
static void listen_stdio(void *cls)
Wait for input on STDIO and send it out over the ch.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
struct GNUNET_SCHEDULER_Task * shutdown_task
static int iterate_send_private_message(void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact)
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
char * text
The containing text.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main function that will be run by the scheduler.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
char * door_id
GNUNET_MESSENGER_MessageFlags
Enum for the different supported flags used by message handling.
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1263
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1247
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_zero_(void)
Return relative time of 0ms.
Definition: time.c:135
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:341
struct GNUNET_MESSENGER_MessageBody body
Body.
collection of IO descriptors
const char * GNUNET_MESSENGER_name_of_kind(enum GNUNET_MESSENGER_MessageKind kind)
Get the name of a message kind.
Definition: messenger_api.c:35
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1841
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void read_stdio(void *cls)
Task run in stdio mode, after some data is available at stdin.
A 512-bit hashcode.
Run when otherwise idle.
struct GNUNET_MESSENGER_MessageName name
struct GNUNET_MESSENGER_MessagePeer peer
int main(int argc, char **argv)
The main function to obtain messenger information.
char * ego_name
static void shutdown_hook(void *cls)
Task to shut down this application.
struct GNUNET_MESSENGER_Handle * messenger
The identity of the host (wraps the signing key of the peer).
struct GNUNET_MESSENGER_Handle * GNUNET_MESSENGER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_MESSENGER_IdentityCallback identity_callback, void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls)
Set up a handle for the messenger related functions and connects to all necessary services...
int GNUNET_MESSENGER_iterate_members(struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback, void *cls)
Iterates through all members of a given room and calls a selected callback for each of them with a pr...
configuration data
Definition: configuration.c:84
const char * name
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
void GNUNET_MESSENGER_disconnect(struct GNUNET_MESSENGER_Handle *handle)
Disconnect all of the messengers used services and clears up its used memory.
Entry in list of pending tasks.
Definition: scheduler.c:134
const char * GNUNET_MESSENGER_get_name(const struct GNUNET_MESSENGER_Handle *handle)
Get the name (if specified, otherwise NULL) used by the messenger.
const struct GNUNET_IDENTITY_PublicKey * GNUNET_MESSENGER_contact_get_key(const struct GNUNET_MESSENGER_Contact *contact)
Get the public key used by the contact or NULL if the anonymous key was used.
char * name
The new name which replaces the current senders name.
struct GNUNET_SCHEDULER_Task * read_task
Run with the default priority (normal P2P operations).
char * room_key
int private_mode
static void on_identity(void *cls, struct GNUNET_MESSENGER_Handle *handle)
Function called when an identity is retrieved.
#define GNUNET_free(ptr)
Wrapper around free.
enum GNUNET_MESSENGER_MessageKind kind
The kind of the message.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
#define gettext_noop(String)
Definition: gettext.h:69
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972