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  if (flags & GNUNET_MESSENGER_FLAG_SENT)
84  printf (">");
85  else
86  printf ("<");
87 
88  printf (" '%s' says: \"%s\"\n", sender_name, message->body.text.text);
89  break;
90  }
91  default:
92  {
93  printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
94  break;
95  }
96  }
97 }
98 
100 
106 static void
107 shutdown_hook (void *cls)
108 {
109  struct GNUNET_MESSENGER_Room *room = cls;
110 
111  if (read_task)
112  GNUNET_SCHEDULER_cancel (read_task);
113 
114  if (room)
116 
117  if (messenger)
118  GNUNET_MESSENGER_disconnect (messenger);
119 }
120 
121 static void
122 listen_stdio (void *cls);
123 
124 #define MAX_BUFFER_SIZE 60000
125 
126 static int
128  const struct GNUNET_MESSENGER_Contact *contact)
129 {
130  struct GNUNET_MESSENGER_Message *message = cls;
131 
133  GNUNET_MESSENGER_send_message (room, message, contact);
134 
135  return GNUNET_YES;
136 }
137 
139 
145 static void
146 read_stdio (void *cls)
147 {
148  read_task = NULL;
149 
150  char buffer[MAX_BUFFER_SIZE];
151  ssize_t length;
152 
153  length = read (0, buffer, MAX_BUFFER_SIZE);
154 
155  if ((length <= 0) || (length >= MAX_BUFFER_SIZE))
156  {
158  return;
159  }
160 
161  if (buffer[length - 1] == '\n')
162  buffer[length - 1] = '\0';
163  else
164  buffer[length] = '\0';
165 
166  struct GNUNET_MESSENGER_Room *room = cls;
167 
168  struct GNUNET_MESSENGER_Message message;
170  message.body.text.text = buffer;
171 
172  if (GNUNET_YES == private_mode)
174  else
175  GNUNET_MESSENGER_send_message (room, &message, NULL);
176 
177  read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
178 }
179 
185 static void
186 listen_stdio (void *cls)
187 {
188  read_task = NULL;
189 
191 
193 
196  NULL, &read_stdio, cls);
197 
199 }
200 
206 static void
207 idle (void *cls)
208 {
209  struct GNUNET_MESSENGER_Room *room = cls;
210 
211  printf ("* You joined the room.\n");
212 
213  read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room);
214 }
215 
216 char *door_id;
217 char *ego_name;
218 char *room_key;
219 
221 
228 static void
230 {
231  struct GNUNET_HashCode key;
232  memset (&key, 0, sizeof(key));
233 
234  if (room_key)
235  GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
236 
237  struct GNUNET_PeerIdentity door_peer;
238  struct GNUNET_PeerIdentity *door = NULL;
239 
240  if ((door_id) &&
242  door = &door_peer;
243 
244  const char *name = GNUNET_MESSENGER_get_name (handle);
245 
246  if (!name)
247  name = "anonymous";
248 
249  printf ("* Welcome to the messenger, '%s'!\n", name);
250 
251  struct GNUNET_MESSENGER_Room *room;
252 
253  if (door)
254  {
255  printf ("* You try to entry a room...\n");
256 
257  room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
258  }
259  else
260  {
261  printf ("* You try to open a room...\n");
262 
263  room = GNUNET_MESSENGER_open_room (messenger, &key);
264  }
265 
266  GNUNET_SCHEDULER_cancel (shutdown_task);
267 
268  shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room);
269 
270  if (!room)
272  else
273  {
274  struct GNUNET_MESSENGER_Message message;
276  message.body.name.name = GNUNET_strdup(name);
277 
278  GNUNET_MESSENGER_send_message (room, &message, NULL);
279  GNUNET_free(message.body.name.name);
280 
282  room);
283  }
284 }
285 
294 static void
295 run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
296 {
297  messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL);
298 
299  shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
300 }
301 
309 int
310 main (int argc, char **argv)
311 {
312  const char *description = "Open and connect to rooms using the MESSENGER to chat.";
313 
314  struct GNUNET_GETOPT_CommandLineOption options[] =
315  {
316  GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
317  GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
318  GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
319  GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
321  };
322 
323  return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
324  NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
325 }
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.
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 Compatible flags can be OR&#39;ed togethe...
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:100
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:357
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