diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-05 12:52:48 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-05 12:52:48 +0000 |
commit | 660c1d610b9ae61814d501b73c4bb745201e023d (patch) | |
tree | 97c2f49a82a873f291e0ca1fbd6680944094571f /src/conversation | |
parent | 096f081ac0f1ae884e97bad0574b2df5b10adefa (diff) | |
download | gnunet-660c1d610b9ae61814d501b73c4bb745201e023d.tar.gz gnunet-660c1d610b9ae61814d501b73c4bb745201e023d.zip |
-cleaning up command-line tool
Diffstat (limited to 'src/conversation')
-rw-r--r-- | src/conversation/gnunet-conversation-new.c | 334 |
1 files changed, 291 insertions, 43 deletions
diff --git a/src/conversation/gnunet-conversation-new.c b/src/conversation/gnunet-conversation-new.c index 57315ac0d..4be8f11aa 100644 --- a/src/conversation/gnunet-conversation-new.c +++ b/src/conversation/gnunet-conversation-new.c | |||
@@ -27,9 +27,61 @@ | |||
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_constants.h" | 28 | #include "gnunet_constants.h" |
29 | #include "gnunet_conversation_service.h" | 29 | #include "gnunet_conversation_service.h" |
30 | #include <fcntl.h> | ||
31 | 30 | ||
32 | #define MAX_MESSAGE_LENGTH (32 * 1024) | 31 | |
32 | /** | ||
33 | * Maximum length allowed for the command line input. | ||
34 | */ | ||
35 | #define MAX_MESSAGE_LENGTH 1024 | ||
36 | |||
37 | |||
38 | /** | ||
39 | * Possible states of the program. | ||
40 | */ | ||
41 | enum ConversationState | ||
42 | { | ||
43 | /** | ||
44 | * We're waiting for our own idenitty. | ||
45 | */ | ||
46 | CS_LOOKUP_EGO, | ||
47 | |||
48 | /** | ||
49 | * We're listening for calls | ||
50 | */ | ||
51 | CS_LISTEN, | ||
52 | |||
53 | /** | ||
54 | * Our phone is ringing. | ||
55 | */ | ||
56 | CS_RING, | ||
57 | |||
58 | /** | ||
59 | * We accepted an incoming phone call. | ||
60 | */ | ||
61 | CS_ACCEPTED, | ||
62 | |||
63 | /** | ||
64 | * We are looking up some other participant. | ||
65 | */ | ||
66 | CS_RESOLVING, | ||
67 | |||
68 | /** | ||
69 | * We are now ringing the other participant. | ||
70 | */ | ||
71 | CS_RINGING, | ||
72 | |||
73 | /** | ||
74 | * The other party accepted our call and we are now connected. | ||
75 | */ | ||
76 | CS_CONNECTED, | ||
77 | |||
78 | /** | ||
79 | * Internal error | ||
80 | */ | ||
81 | CS_ERROR | ||
82 | |||
83 | }; | ||
84 | |||
33 | 85 | ||
34 | /** | 86 | /** |
35 | * Phone handle | 87 | * Phone handle |
@@ -82,10 +134,25 @@ static struct GNUNET_IDENTITY_Handle *id; | |||
82 | static char *ego_name; | 134 | static char *ego_name; |
83 | 135 | ||
84 | /** | 136 | /** |
137 | * Name of conversation partner (if any). | ||
138 | */ | ||
139 | static char *peer_name; | ||
140 | |||
141 | /** | ||
85 | * File handle for stdin. | 142 | * File handle for stdin. |
86 | */ | 143 | */ |
87 | static struct GNUNET_DISK_FileHandle *stdin_fh; | 144 | static struct GNUNET_DISK_FileHandle *stdin_fh; |
88 | 145 | ||
146 | /** | ||
147 | * Our current state. | ||
148 | */ | ||
149 | static enum ConversationState state; | ||
150 | |||
151 | /** | ||
152 | * Be verbose. | ||
153 | */ | ||
154 | static int verbose; | ||
155 | |||
89 | 156 | ||
90 | /** | 157 | /** |
91 | * Function called with an event emitted by a phone. | 158 | * Function called with an event emitted by a phone. |
@@ -105,9 +172,13 @@ phone_event_handler (void *cls, | |||
105 | switch (code) | 172 | switch (code) |
106 | { | 173 | { |
107 | case GNUNET_CONVERSATION_EC_RING: | 174 | case GNUNET_CONVERSATION_EC_RING: |
175 | GNUNET_break (CS_LISTEN == state); | ||
176 | GNUNET_free_non_null (peer_name); | ||
177 | peer_name = GNUNET_strdup (va_arg (va, const char *)); | ||
108 | FPRINTF (stdout, | 178 | FPRINTF (stdout, |
109 | _("Incoming call from `%s'. Enter /accept to take it.\n"), | 179 | _("Incoming call from `%s'.\nPlease /accept or /cancel the call.\n"), |
110 | va_arg (va, const char *)); | 180 | peer_name); |
181 | state = CS_RING; | ||
111 | break; | 182 | break; |
112 | case GNUNET_CONVERSATION_EC_RINGING: | 183 | case GNUNET_CONVERSATION_EC_RINGING: |
113 | GNUNET_break (0); | 184 | GNUNET_break (0); |
@@ -122,9 +193,12 @@ phone_event_handler (void *cls, | |||
122 | GNUNET_break (0); | 193 | GNUNET_break (0); |
123 | break; | 194 | break; |
124 | case GNUNET_CONVERSATION_EC_TERMINATED: | 195 | case GNUNET_CONVERSATION_EC_TERMINATED: |
196 | GNUNET_break ( (CS_RING == state) || | ||
197 | (CS_ACCEPTED == state) ); | ||
125 | FPRINTF (stdout, | 198 | FPRINTF (stdout, |
126 | _("Call terminated: %s\n"), | 199 | _("Call terminated: %s\n"), |
127 | va_arg (va, const char *)); | 200 | va_arg (va, const char *)); |
201 | state = CS_LISTEN; | ||
128 | break; | 202 | break; |
129 | } | 203 | } |
130 | va_end (va); | 204 | va_end (va); |
@@ -132,6 +206,42 @@ phone_event_handler (void *cls, | |||
132 | 206 | ||
133 | 207 | ||
134 | /** | 208 | /** |
209 | * Start our phone. | ||
210 | */ | ||
211 | static void | ||
212 | start_phone () | ||
213 | { | ||
214 | if (NULL == caller_id) | ||
215 | { | ||
216 | FPRINTF (stderr, | ||
217 | _("Ego `%s' no longer available, phone is now down.\n"), | ||
218 | ego_name); | ||
219 | state = CS_LOOKUP_EGO; | ||
220 | return; | ||
221 | } | ||
222 | phone = GNUNET_CONVERSATION_phone_create (cfg, | ||
223 | caller_id, | ||
224 | &phone_event_handler, NULL); | ||
225 | /* FIXME: get record and print full GNS record info later here... */ | ||
226 | if (NULL == phone) | ||
227 | { | ||
228 | FPRINTF (stderr, | ||
229 | "%s", | ||
230 | _("Failed to setup phone (internal error)\n")); | ||
231 | state = CS_ERROR; | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | if (verbose) | ||
236 | FPRINTF (stdout, | ||
237 | _("Phone active on line %u\n"), | ||
238 | (unsigned int) line); | ||
239 | state = CS_LISTEN; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | |||
244 | /** | ||
135 | * Function called with an event emitted by a phone. | 245 | * Function called with an event emitted by a phone. |
136 | * | 246 | * |
137 | * @param cls closure | 247 | * @param cls closure |
@@ -152,41 +262,47 @@ call_event_handler (void *cls, | |||
152 | GNUNET_break (0); | 262 | GNUNET_break (0); |
153 | break; | 263 | break; |
154 | case GNUNET_CONVERSATION_EC_RINGING: | 264 | case GNUNET_CONVERSATION_EC_RINGING: |
155 | FPRINTF (stdout, | 265 | GNUNET_break (CS_RESOLVING == state); |
156 | "%s", | 266 | if (verbose) |
157 | _("Ringing other party\n")); | 267 | FPRINTF (stdout, |
268 | "%s", | ||
269 | _("Resolved address. Now ringing other party.\n")); | ||
270 | state = CS_RINGING; | ||
158 | break; | 271 | break; |
159 | case GNUNET_CONVERSATION_EC_READY: | 272 | case GNUNET_CONVERSATION_EC_READY: |
273 | GNUNET_break (CS_RINGING == state); | ||
160 | FPRINTF (stdout, | 274 | FPRINTF (stdout, |
161 | _("Connection established: %s\n"), | 275 | _("Connection established: %s\n"), |
162 | va_arg (va, const char *)); | 276 | va_arg (va, const char *)); |
277 | state = CS_CONNECTED; | ||
163 | break; | 278 | break; |
164 | case GNUNET_CONVERSATION_EC_GNS_FAIL: | 279 | case GNUNET_CONVERSATION_EC_GNS_FAIL: |
280 | GNUNET_break (CS_RESOLVING == state); | ||
165 | FPRINTF (stdout, | 281 | FPRINTF (stdout, |
166 | "%s", | 282 | "%s", |
167 | _("Failed to resolve name\n")); | 283 | _("Failed to resolve name\n")); |
284 | GNUNET_CONVERSATION_call_stop (call, NULL); | ||
285 | call = NULL; | ||
286 | start_phone (); | ||
168 | break; | 287 | break; |
169 | case GNUNET_CONVERSATION_EC_BUSY: | 288 | case GNUNET_CONVERSATION_EC_BUSY: |
289 | GNUNET_break (CS_RINGING == state); | ||
170 | FPRINTF (stdout, | 290 | FPRINTF (stdout, |
171 | "%s", | 291 | "%s", |
172 | _("Line busy\n")); | 292 | _("Line busy\n")); |
293 | GNUNET_CONVERSATION_call_stop (call, NULL); | ||
294 | call = NULL; | ||
295 | start_phone (); | ||
173 | break; | 296 | break; |
174 | case GNUNET_CONVERSATION_EC_TERMINATED: | 297 | case GNUNET_CONVERSATION_EC_TERMINATED: |
298 | GNUNET_break ( (CS_RINGING == state) || | ||
299 | (CS_CONNECTED == state) ); | ||
175 | FPRINTF (stdout, | 300 | FPRINTF (stdout, |
176 | _("Call terminated: %s\n"), | 301 | _("Call terminated: %s\n"), |
177 | va_arg (va, const char *)); | 302 | va_arg (va, const char *)); |
178 | GNUNET_CONVERSATION_call_stop (call, NULL); | 303 | GNUNET_CONVERSATION_call_stop (call, NULL); |
179 | call = NULL; | 304 | call = NULL; |
180 | if (NULL == caller_id) | 305 | start_phone (); |
181 | { | ||
182 | FPRINTF (stderr, | ||
183 | _("Ego `%s' no longer available, phone is now down.\n"), | ||
184 | ego_name); | ||
185 | return; | ||
186 | } | ||
187 | phone = GNUNET_CONVERSATION_phone_create (cfg, | ||
188 | caller_id, | ||
189 | &phone_event_handler, NULL); | ||
190 | break; | 306 | break; |
191 | } | 307 | } |
192 | va_end (va); | 308 | va_end (va); |
@@ -266,8 +382,6 @@ do_unknown (const char *msg) | |||
266 | static void | 382 | static void |
267 | do_call (const char *arg) | 383 | do_call (const char *arg) |
268 | { | 384 | { |
269 | if (NULL != call) | ||
270 | return; | ||
271 | if (NULL == caller_id) | 385 | if (NULL == caller_id) |
272 | { | 386 | { |
273 | FPRINTF (stderr, | 387 | FPRINTF (stderr, |
@@ -275,18 +389,62 @@ do_call (const char *arg) | |||
275 | ego_name); | 389 | ego_name); |
276 | return; | 390 | return; |
277 | } | 391 | } |
278 | /* FIXME: also check that we do NOT have a running conversation or ring */ | 392 | switch (state) |
393 | { | ||
394 | case CS_LOOKUP_EGO: | ||
395 | FPRINTF (stderr, | ||
396 | _("Ego `%s' not available\n"), | ||
397 | ego_name); | ||
398 | return; | ||
399 | case CS_LISTEN: | ||
400 | /* ok to call! */ | ||
401 | break; | ||
402 | case CS_RING: | ||
403 | FPRINTF (stdout, | ||
404 | _("Hanging up on incoming phone call from `%s' to call `%s'.\n"), | ||
405 | peer_name, | ||
406 | arg); | ||
407 | GNUNET_CONVERSATION_phone_hang_up (phone, NULL); | ||
408 | break; | ||
409 | case CS_ACCEPTED: | ||
410 | FPRINTF (stderr, | ||
411 | _("You are already in a conversation with `%s', refusing to call `%s'.\n"), | ||
412 | peer_name, | ||
413 | arg); | ||
414 | return; | ||
415 | case CS_RESOLVING: | ||
416 | case CS_RINGING: | ||
417 | FPRINTF (stderr, | ||
418 | _("Aborting call to `%s'\n"), | ||
419 | peer_name); | ||
420 | GNUNET_CONVERSATION_call_stop (call, NULL); | ||
421 | call = NULL; | ||
422 | break; | ||
423 | case CS_CONNECTED: | ||
424 | FPRINTF (stderr, | ||
425 | _("You are already in a conversation with `%s', refusing to call `%s'.\n"), | ||
426 | peer_name, | ||
427 | arg); | ||
428 | return; | ||
429 | case CS_ERROR: | ||
430 | /* ok to call */ | ||
431 | break; | ||
432 | } | ||
433 | GNUNET_assert (NULL == call); | ||
279 | if (NULL != phone) | 434 | if (NULL != phone) |
280 | { | 435 | { |
281 | GNUNET_CONVERSATION_phone_destroy (phone); | 436 | GNUNET_CONVERSATION_phone_destroy (phone); |
282 | phone = NULL; | 437 | phone = NULL; |
283 | } | 438 | } |
439 | GNUNET_free_non_null (peer_name); | ||
440 | peer_name = GNUNET_strdup (arg); | ||
284 | call = GNUNET_CONVERSATION_call_start (cfg, | 441 | call = GNUNET_CONVERSATION_call_start (cfg, |
285 | caller_id, | 442 | caller_id, |
286 | arg, | 443 | arg, |
287 | speaker, | 444 | speaker, |
288 | mic, | 445 | mic, |
289 | &call_event_handler, NULL); | 446 | &call_event_handler, NULL); |
447 | state = CS_RESOLVING; | ||
290 | } | 448 | } |
291 | 449 | ||
292 | 450 | ||
@@ -298,13 +456,90 @@ do_call (const char *arg) | |||
298 | static void | 456 | static void |
299 | do_accept (const char *args) | 457 | do_accept (const char *args) |
300 | { | 458 | { |
301 | if (NULL == phone) | 459 | switch (state) |
460 | { | ||
461 | case CS_LOOKUP_EGO: | ||
462 | case CS_LISTEN: | ||
463 | case CS_ERROR: | ||
464 | FPRINTF (stderr, | ||
465 | _("There is no incoming call to be accepted!\n")); | ||
466 | return; | ||
467 | case CS_RING: | ||
468 | /* this is the expected state */ | ||
469 | break; | ||
470 | case CS_ACCEPTED: | ||
471 | FPRINTF (stderr, | ||
472 | _("You are already in a conversation with `%s'.\n"), | ||
473 | peer_name); | ||
474 | return; | ||
475 | case CS_RESOLVING: | ||
476 | case CS_RINGING: | ||
477 | FPRINTF (stderr, | ||
478 | _("You are trying to call `%s', cannot accept incoming calls right now.\n"), | ||
479 | peer_name); | ||
302 | return; | 480 | return; |
303 | /* FIXME: also check that we don't have a running conversation */ | 481 | case CS_CONNECTED: |
482 | FPRINTF (stderr, | ||
483 | _("You are already in a conversation with `%s'.\n"), | ||
484 | peer_name); | ||
485 | return; | ||
486 | } | ||
487 | GNUNET_assert (NULL != phone); | ||
304 | GNUNET_CONVERSATION_phone_pick_up (phone, | 488 | GNUNET_CONVERSATION_phone_pick_up (phone, |
305 | args, | 489 | args, |
306 | speaker, | 490 | speaker, |
307 | mic); | 491 | mic); |
492 | state = CS_ACCEPTED; | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Accepting an incoming call | ||
498 | * | ||
499 | * @param args arguments given to the command | ||
500 | */ | ||
501 | static void | ||
502 | do_status (const char *args) | ||
503 | { | ||
504 | switch (state) | ||
505 | { | ||
506 | case CS_LOOKUP_EGO: | ||
507 | FPRINTF (stdout, | ||
508 | _("We are currently trying to locate the private key for the ego `%s'.\n"), | ||
509 | ego_name); | ||
510 | break; | ||
511 | case CS_LISTEN: | ||
512 | FPRINTF (stdout, | ||
513 | _("We are listening for incoming calls for ego `%s' on line %u.\n"), | ||
514 | ego_name, | ||
515 | line); | ||
516 | break; | ||
517 | case CS_RING: | ||
518 | FPRINTF (stdout, | ||
519 | _("The phone is rining. `%s' is trying to call us.\n"), | ||
520 | peer_name); | ||
521 | break; | ||
522 | case CS_ACCEPTED: | ||
523 | case CS_CONNECTED: | ||
524 | FPRINTF (stdout, | ||
525 | _("You are having a conversation with `%s'.\n"), | ||
526 | peer_name); | ||
527 | break; | ||
528 | case CS_RESOLVING: | ||
529 | FPRINTF (stdout, | ||
530 | _("We are trying to find the network address to call `%s'.\n"), | ||
531 | peer_name); | ||
532 | break; | ||
533 | case CS_RINGING: | ||
534 | FPRINTF (stdout, | ||
535 | _("We are calling `%s', his phone should be ringing.\n"), | ||
536 | peer_name); | ||
537 | break; | ||
538 | case CS_ERROR: | ||
539 | FPRINTF (stdout, | ||
540 | _("We had an internal error setting up our phone line. You can still make calls.\n")); | ||
541 | break; | ||
542 | } | ||
308 | } | 543 | } |
309 | 544 | ||
310 | 545 | ||
@@ -316,19 +551,35 @@ do_accept (const char *args) | |||
316 | static void | 551 | static void |
317 | do_reject (const char *args) | 552 | do_reject (const char *args) |
318 | { | 553 | { |
319 | /* FIXME: also check that we do have a running conversation or ring */ | 554 | switch (state) |
555 | { | ||
556 | case CS_LOOKUP_EGO: | ||
557 | case CS_LISTEN: | ||
558 | case CS_ERROR: | ||
559 | FPRINTF (stderr, | ||
560 | "%s", | ||
561 | _("There is no call that could be cancelled right now.\n")); | ||
562 | return; | ||
563 | case CS_RING: | ||
564 | case CS_ACCEPTED: | ||
565 | case CS_RESOLVING: | ||
566 | case CS_RINGING: | ||
567 | case CS_CONNECTED: | ||
568 | /* expected state, do rejection logic */ | ||
569 | break; | ||
570 | } | ||
320 | if (NULL == call) | 571 | if (NULL == call) |
321 | { | 572 | { |
573 | GNUNET_assert (NULL != phone); | ||
322 | GNUNET_CONVERSATION_phone_hang_up (phone, | 574 | GNUNET_CONVERSATION_phone_hang_up (phone, |
323 | args); | 575 | args); |
576 | state = CS_LISTEN; | ||
324 | } | 577 | } |
325 | else | 578 | else |
326 | { | 579 | { |
327 | GNUNET_CONVERSATION_call_stop (call, args); | 580 | GNUNET_CONVERSATION_call_stop (call, args); |
328 | call = NULL; | 581 | call = NULL; |
329 | phone = GNUNET_CONVERSATION_phone_create (cfg, | 582 | start_phone (); |
330 | caller_id, | ||
331 | &phone_event_handler, NULL); | ||
332 | } | 583 | } |
333 | } | 584 | } |
334 | 585 | ||
@@ -343,6 +594,8 @@ static struct VoipCommand commands[] = { | |||
343 | gettext_noop ("Use `/accept MESSAGE' to accept an incoming call")}, | 594 | gettext_noop ("Use `/accept MESSAGE' to accept an incoming call")}, |
344 | {"/cancel", &do_reject, | 595 | {"/cancel", &do_reject, |
345 | gettext_noop ("Use `/cancel MESSAGE' to reject or terminate a call")}, | 596 | gettext_noop ("Use `/cancel MESSAGE' to reject or terminate a call")}, |
597 | {"/status", &do_status, | ||
598 | gettext_noop ("Use `/status to print status information")}, | ||
346 | {"/quit", &do_quit, | 599 | {"/quit", &do_quit, |
347 | gettext_noop ("Use `/quit' to terminate gnunet-conversation")}, | 600 | gettext_noop ("Use `/quit' to terminate gnunet-conversation")}, |
348 | {"/help", &do_help, | 601 | {"/help", &do_help, |
@@ -436,6 +689,8 @@ do_stop_task (void *cls, | |||
436 | ego_name = NULL; | 689 | ego_name = NULL; |
437 | GNUNET_CONFIGURATION_destroy (cfg); | 690 | GNUNET_CONFIGURATION_destroy (cfg); |
438 | cfg = NULL; | 691 | cfg = NULL; |
692 | GNUNET_free_non_null (peer_name); | ||
693 | state = CS_ERROR; | ||
439 | } | 694 | } |
440 | 695 | ||
441 | 696 | ||
@@ -451,7 +706,7 @@ handle_command (void *cls, | |||
451 | { | 706 | { |
452 | char message[MAX_MESSAGE_LENGTH + 1]; | 707 | char message[MAX_MESSAGE_LENGTH + 1]; |
453 | const char *ptr; | 708 | const char *ptr; |
454 | int i; | 709 | size_t i; |
455 | 710 | ||
456 | handle_cmd_task = | 711 | handle_cmd_task = |
457 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | 712 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
@@ -497,9 +752,10 @@ identity_cb (void *cls, | |||
497 | return; | 752 | return; |
498 | if (ego == caller_id) | 753 | if (ego == caller_id) |
499 | { | 754 | { |
500 | FPRINTF (stdout, | 755 | if (verbose) |
501 | _("Name of our ego changed to `%s'\n"), | 756 | FPRINTF (stdout, |
502 | name); | 757 | _("Name of our ego changed to `%s'\n"), |
758 | name); | ||
503 | GNUNET_free (ego_name); | 759 | GNUNET_free (ego_name); |
504 | ego_name = GNUNET_strdup (name); | 760 | ego_name = GNUNET_strdup (name); |
505 | return; | 761 | return; |
@@ -509,6 +765,10 @@ identity_cb (void *cls, | |||
509 | return; | 765 | return; |
510 | if (NULL == ego) | 766 | if (NULL == ego) |
511 | { | 767 | { |
768 | if (verbose) | ||
769 | FPRINTF (stdout, | ||
770 | _("Our ego `%s' was deleted!\n"), | ||
771 | ego_name); | ||
512 | caller_id = NULL; | 772 | caller_id = NULL; |
513 | return; | 773 | return; |
514 | } | 774 | } |
@@ -517,19 +777,7 @@ identity_cb (void *cls, | |||
517 | "CONVERSATION", | 777 | "CONVERSATION", |
518 | "LINE", | 778 | "LINE", |
519 | line); | 779 | line); |
520 | phone = GNUNET_CONVERSATION_phone_create (cfg, | 780 | start_phone (); |
521 | caller_id, | ||
522 | &phone_event_handler, NULL); | ||
523 | /* FIXME: get record and print full GNS record info later here... */ | ||
524 | if (NULL == phone) | ||
525 | { | ||
526 | fprintf (stderr, | ||
527 | _("Failed to setup phone (internal error)\n")); | ||
528 | } | ||
529 | else | ||
530 | fprintf (stdout, | ||
531 | _("Phone active on line %u\n"), | ||
532 | (unsigned int) line); | ||
533 | } | 781 | } |
534 | 782 | ||
535 | 783 | ||