diff options
author | Andreas Fuchs <fuchandr@in.tum.de> | 2013-10-01 11:34:38 +0000 |
---|---|---|
committer | Andreas Fuchs <fuchandr@in.tum.de> | 2013-10-01 11:34:38 +0000 |
commit | 70c7532c4d0c684afc4158984f9a37ae7cf05ba3 (patch) | |
tree | 693ef5a8b848db69c6e4b79c2d6f2a583f99db0c /src/conversation/gnunet-conversation.c | |
parent | 408c3426ad378e8eef910ca6fea1144110346b0b (diff) | |
download | gnunet-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.c | 419 |
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 | */ | ||
38 | struct GNUNET_CONVERSATION_Handle *conversation = NULL; | ||
39 | |||
40 | /** | ||
41 | * Task which handles the commands | ||
42 | */ | ||
43 | static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task; | ||
44 | |||
45 | /** | ||
46 | * Function declareation for executing a action | ||
47 | */ | ||
48 | typedef int (*ActionFunction) (const char *argumetns, const void *xtra); | ||
49 | |||
50 | /** | ||
51 | * Structure which defines a command | ||
52 | */ | ||
53 | struct VoipCommand | ||
54 | { | ||
55 | const char *command; | ||
56 | ActionFunction Action; | ||
57 | const char *helptext; | ||
58 | }; | ||
59 | |||
60 | /******************************************************************************/ | ||
61 | /*********************** DECLARATIONS *************************/ | ||
62 | /******************************************************************************/ | ||
63 | |||
64 | static 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 | */ | ||
78 | void | ||
79 | call_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 | */ | ||
93 | void | ||
94 | reject_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 | */ | ||
109 | void | ||
110 | notification_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 | */ | ||
158 | void | ||
159 | missed_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 | */ | ||
168 | static int | ||
169 | do_quit (const char *args, const void *xtra) | ||
170 | { | ||
171 | return GNUNET_SYSERR; | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * | ||
176 | */ | ||
177 | static int | ||
178 | do_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 | */ | ||
187 | static int | ||
188 | do_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 | */ | ||
200 | static int | ||
201 | do_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 | */ | ||
213 | static int | ||
214 | do_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 | */ | ||
225 | static int | ||
226 | do_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 | */ | ||
237 | static int | ||
238 | do_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 | */ | ||
249 | static 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 | */ | ||
270 | static int | ||
271 | do_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 | */ | ||
302 | static void | ||
303 | do_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 | */ | ||
320 | void | ||
321 | handle_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 | |||
346 | next: | ||
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 | |||
355 | out: | ||
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 | */ | ||
368 | static void | ||
369 | run (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 | ¬ification_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 | */ | ||
394 | int | ||
395 | main (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 */ | ||