aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-conversation.c
diff options
context:
space:
mode:
authorAndreas Fuchs <fuchandr@in.tum.de>2013-10-01 11:34:38 +0000
committerAndreas Fuchs <fuchandr@in.tum.de>2013-10-01 11:34:38 +0000
commit70c7532c4d0c684afc4158984f9a37ae7cf05ba3 (patch)
tree693ef5a8b848db69c6e4b79c2d6f2a583f99db0c /src/conversation/gnunet-conversation.c
parent408c3426ad378e8eef910ca6fea1144110346b0b (diff)
downloadgnunet-70c7532c4d0c684afc4158984f9a37ae7cf05ba3.tar.gz
gnunet-70c7532c4d0c684afc4158984f9a37ae7cf05ba3.zip
Initial conversation (experimental) commit
Diffstat (limited to 'src/conversation/gnunet-conversation.c')
-rw-r--r--src/conversation/gnunet-conversation.c419
1 files changed, 419 insertions, 0 deletions
diff --git a/src/conversation/gnunet-conversation.c b/src/conversation/gnunet-conversation.c
new file mode 100644
index 000000000..9570737f4
--- /dev/null
+++ b/src/conversation/gnunet-conversation.c
@@ -0,0 +1,419 @@
1/*
2 This file is part of GNUnet.
3 (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, InGNUNET_SERVERc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file conversation/gnunet-conversation.c
23 * @brief conversation implementation
24 * @author Simon Dieterle
25 * @author Andreas Fuchs
26 */
27#include <gnunet/platform.h>
28#include <gnunet/gnunet_constants.h>
29#include <gnunet/gnunet_util_lib.h>
30#include "gnunet_conversation_service.h"
31#include <fcntl.h>
32
33#define MAX_MESSAGE_LENGTH (32 * 1024)
34
35/**
36* CONVERSATION handle
37*/
38struct GNUNET_CONVERSATION_Handle *conversation = NULL;
39
40/**
41* Task which handles the commands
42*/
43static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
44
45/**
46* Function declareation for executing a action
47*/
48typedef int (*ActionFunction) (const char *argumetns, const void *xtra);
49
50/**
51* Structure which defines a command
52*/
53struct VoipCommand
54{
55 const char *command;
56 ActionFunction Action;
57 const char *helptext;
58};
59
60/******************************************************************************/
61/*********************** DECLARATIONS *************************/
62/******************************************************************************/
63
64static int do_help (const char *args, const void *xtra);
65
66/******************************************************************************/
67/*********************** Functions *************************/
68/******************************************************************************/
69
70
71/**
72 * Method called whenever a call is incoming
73 *
74 * @param cls closure
75 * @param handle to the conversation session
76 * @param caller peer that calls you
77 */
78void
79call_handler (void *cls, struct GNUNET_CONVERSATION_Handle *handle,
80 const struct GNUNET_PeerIdentity *caller)
81{
82 FPRINTF (stdout, _("Incoming call from peer: %s\n"),
83 GNUNET_i2s_full (caller));
84}
85
86/**
87 * Method called whenever a call is rejected
88 *
89 * @param cls closure
90 * @param handle to the conversation session
91 * @param peer peer that rejected your call
92 */
93void
94reject_handler (void *cls, struct GNUNET_CONVERSATION_Handle *handle, int reason,
95 const struct GNUNET_PeerIdentity *peer)
96{
97 FPRINTF (stdout, _("Peer %s rejected your call. Reason: %d\n"),
98 GNUNET_i2s_full (peer), reason);
99}
100
101/**
102 * Method called whenever a notification is there
103 *
104 * @param cls closure
105 * @param handle to the conversation session
106 * @param type the type of the notification
107 * @param peer peer that the notification is about
108 */
109void
110notification_handler (void *cls, struct GNUNET_CONVERSATION_Handle *handle, int type,
111 const struct GNUNET_PeerIdentity *peer)
112{
113 switch (type)
114 {
115 case NotificationType_SERVICE_BLOCKED:
116 FPRINTF (stdout, _("The service is already in use. Try again later."));
117
118 break;
119
120 case NotificationType_NO_PEER:
121 FPRINTF (stdout, _("The Peer you were calling is no correct peer.\n"));
122
123 break;
124
125 case NotificationType_NO_ANSWER:
126 FPRINTF (stdout, _("Peer %s did not answer your call.\n"),
127 GNUNET_i2s_full (peer));
128
129 break;
130
131 case NotificationType_AVAILABLE_AGAIN:
132 FPRINTF (stdout, _("Peer %s is now available.\n"),
133 GNUNET_i2s_full (peer));
134
135 break;
136
137 case NotificationType_CALL_ACCEPTED:
138 FPRINTF (stdout, _("Peer %s has accepted your call.\n"),
139 GNUNET_i2s_full (peer));
140
141 break;
142
143 case NotificationType_CALL_TERMINATED:
144 FPRINTF (stdout, _("Peer %s has terminated the call.\n"),
145 GNUNET_i2s_full (peer));
146 break;
147 }
148
149}
150
151/**
152 * Method called whenever a notification for missed calls is there
153 *
154 * @param cls closure
155 * @param handle to the conversation session
156 * @param missed_calls a list of missed calls
157 */
158void
159missed_call_handler (void *cls, struct GNUNET_CONVERSATION_Handle *handle,
160 struct GNUNET_CONVERSATION_MissedCallNotification *missed_calls)
161{
162 FPRINTF (stdout, _("You have missed calls.\n"));
163}
164
165/**
166* Terminating the client
167*/
168static int
169do_quit (const char *args, const void *xtra)
170{
171 return GNUNET_SYSERR;
172}
173
174/**
175*
176*/
177static int
178do_unknown (const char *msg, const void *xtra)
179{
180 FPRINTF (stderr, _("Unknown command `%s'\n"), msg);
181 return GNUNET_OK;
182}
183
184/**
185* Initiating a new call
186*/
187static int
188do_call (const char *arg, const void *xtra)
189{
190 char *callee = GNUNET_strdup (arg);
191 FPRINTF (stdout, _("Initiating call to: %s\n"), callee);
192 GNUNET_CONVERSATION_call (conversation, callee, GNUNET_YES);
193
194 return GNUNET_OK;
195}
196
197/**
198* Initiating a new call
199*/
200static int
201do_call_peer (const char *arg, const void *xtra)
202{
203 char *callee = GNUNET_strdup (arg);
204 FPRINTF (stdout, _("Initiating call to: %s\n"), callee);
205 GNUNET_CONVERSATION_call (conversation, callee, GNUNET_NO);
206
207 return GNUNET_OK;
208}
209
210/**
211* Accepting an incoming call
212*/
213static int
214do_accept (const char *args, const void *xtra)
215{
216 FPRINTF (stdout, _("Accepting the call\n"));
217 GNUNET_CONVERSATION_accept (conversation);
218
219 return GNUNET_OK;
220}
221
222/**
223* Rejecting a call
224*/
225static int
226do_reject (const char *args, const void *xtra)
227{
228 FPRINTF (stdout, _("Rejecting the call\n"));
229 GNUNET_CONVERSATION_reject (conversation);
230
231 return GNUNET_OK;
232}
233
234/**
235* Terminating a call
236*/
237static int
238do_hang_up (const char *args, const void *xtra)
239{
240 FPRINTF (stdout, _("Terminating the call\n"));
241 GNUNET_CONVERSATION_hangup (conversation);
242
243 return GNUNET_OK;
244}
245
246/**
247 * List of supported commands.
248 */
249static struct VoipCommand commands[] = {
250 {"/call ", &do_call, gettext_noop ("Use `/call gads_record'")},
251 {"/callpeer ", &do_call_peer,
252 gettext_noop ("Use `/call private_key' to call a person")},
253 {"/accept", &do_accept,
254 gettext_noop ("Use `/accept' to accept an incoming call")},
255 {"/terminate", &do_hang_up,
256 gettext_noop ("Use `/terminate' to end a call")},
257 {"/reject", &do_reject,
258 gettext_noop ("Use `/rejet' to reject an incoming call")},
259 {"/quit", &do_quit, gettext_noop ("Use `/quit' to terminate gnunet-conversation")},
260 {"/help", &do_help,
261 gettext_noop ("Use `/help command' to get help for a specific command")},
262 {"/", &do_unknown, NULL},
263 {"", &do_unknown, NULL},
264 {NULL, NULL, NULL},
265};
266
267/**
268*
269*/
270static int
271do_help (const char *args, const void *xtra)
272{
273 int i;
274
275 i = 0;
276 while ((NULL != args) && (0 != strlen (args)) &&
277 (commands[i].Action != &do_help))
278 {
279 if (0 ==
280 strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
281 {
282 FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
283 return GNUNET_OK;
284 }
285 i++;
286 }
287 i = 0;
288 FPRINTF (stdout, "%s", "Available commands:");
289 while (commands[i].Action != &do_help)
290 {
291 FPRINTF (stdout, " %s", gettext (commands[i].command));
292 i++;
293 }
294 FPRINTF (stdout, "%s", "\n");
295 FPRINTF (stdout, "%s\n", gettext (commands[i].helptext));
296 return GNUNET_OK;
297}
298
299/**
300*
301*/
302static void
303do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
304{
305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running shutdown task\n");
306 GNUNET_CONVERSATION_disconnect (conversation);
307
308 if (handle_cmd_task != GNUNET_SCHEDULER_NO_TASK)
309 {
310 GNUNET_SCHEDULER_cancel (handle_cmd_task);
311 handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
312 }
313
314 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running shutdown task finished\n");
315}
316
317/**
318*
319*/
320void
321handle_command (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
322{
323 char message[MAX_MESSAGE_LENGTH + 1];
324 int i;
325
326 /* read message from command line and handle it */
327 memset (message, 0, MAX_MESSAGE_LENGTH + 1);
328 if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
329 goto next;
330 if (strlen (message) == 0)
331 goto next;
332 if (message[strlen (message) - 1] == '\n')
333 message[strlen (message) - 1] = '\0';
334 if (strlen (message) == 0)
335 goto next;
336 i = 0;
337 while ((NULL != commands[i].command) &&
338 (0 !=
339 strncasecmp (commands[i].command, message,
340 strlen (commands[i].command))))
341 i++;
342 if (GNUNET_OK !=
343 commands[i].Action (&message[strlen (commands[i].command)], NULL))
344 goto out;
345
346next:
347 handle_cmd_task =
348 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_multiply
349 (GNUNET_TIME_UNIT_MILLISECONDS,
350 100),
351 GNUNET_SCHEDULER_PRIORITY_UI,
352 &handle_command, NULL);
353 return;
354
355out:
356 handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
357 GNUNET_SCHEDULER_shutdown ();
358}
359
360/**
361 * Main function that will be run by the scheduler.
362 *
363 * @param cls closure
364 * @param args remaining command-line arguments
365 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
366 * @param c configuration
367 */
368static void
369run (void *cls, char *const *args, const char *cfgfile,
370 const struct GNUNET_CONFIGURATION_Handle *c)
371{
372 if (NULL ==
373 (conversation =
374 GNUNET_CONVERSATION_connect (c, NULL, &call_handler, &reject_handler,
375 &notification_handler, &missed_call_handler)))
376 {
377 FPRINTF (stderr, "%s", _("Could not access CONVERSATION service. Exiting.\n"));
378 return;
379 }
380
381 handle_cmd_task =
382 GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
383 &handle_command, NULL);
384 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
385 NULL);
386}
387
388/** * The main function to conversation.
389 *
390 * @param argc number of arguments from the command line
391 * @param argv command line arguments
392 * @return 0 ok, 1 on error
393 */
394int
395main (int argc, char *const *argv)
396{
397 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
398 GNUNET_GETOPT_OPTION_END
399 };
400
401 int flags;
402 int ret;
403
404 flags = fcntl (0, F_GETFL, 0);
405 flags |= O_NONBLOCK;
406 fcntl (0, F_SETFL, flags);
407
408 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
409 return 2;
410
411 ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-conversation",
412 gettext_noop ("Print information about conversation."),
413 options, &run, NULL);
414 GNUNET_free ((void *) argv);
415
416 return ret;
417}
418
419/* end of gnunet-conversation.c */