GNUnet  0.19.4
gnunet-conversation.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013 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 "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_gnsrecord_lib.h"
32 
36 #define MAX_MESSAGE_LENGTH 1024
37 
38 #define XSTRINGIFY(x) STRINGIFY (x)
39 
40 #define STRINGIFY(x) (#x)
41 
46 {
51 
56 
61 
65  PS_ERROR
66 };
67 
68 
73 {
78 
83 
88 
93 };
94 
95 
99 struct CallList
100 {
104  struct CallList *prev;
105 
109  struct CallList *next;
110 
115 
120 
124  unsigned int caller_num;
125 };
126 
127 
132 
137 
142 static struct CallList *cl_active;
143 
147 static struct CallList *cl_head;
148 
152 static struct CallList *cl_tail;
153 
157 static char *line;
158 
163 
168 
173 
178 
183 
187 static struct GNUNET_IDENTITY_Handle *id;
188 
192 static char *ego_name;
193 
197 static struct GNUNET_IDENTITY_PublicKey peer_key;
198 
202 static char *peer_name;
203 
208 
212 static enum PhoneState phone_state;
213 
217 static enum CallState call_state;
218 
222 static unsigned int caller_num_gen;
223 
227 static char *address;
228 
232 static int verbose;
233 
234 
243 static void
246  struct GNUNET_CONVERSATION_Caller *caller,
247  const struct GNUNET_IDENTITY_PublicKey *caller_id)
248 {
249  struct CallList *cl;
250 
251  (void) cls;
252  switch (code)
253  {
255  /*
256  * FIXME: we should be playing our ringtones from contrib/sounds now!
257  *
258  ring_my_bell();
259  *
260  * see https://gstreamer.freedesktop.org/documentation/application-development/highlevel/playback-components.html on how to play a wav using the gst framework being used here
261  */fprintf (
262  stdout,
263  _ (
264  "Incoming call from `%s'. Please /accept %u or /cancel %u the call.\n"),
268  cl = GNUNET_new (struct CallList);
269  cl->caller = caller;
270  cl->caller_id = *caller_id;
271  cl->caller_num = caller_num_gen++;
273  break;
274 
276  for (cl = cl_head; NULL != cl; cl = cl->next)
277  if (caller == cl->caller)
278  break;
279  if ((NULL == cl) && (caller == cl_active->caller))
280  cl = cl_active;
281  if (NULL == cl)
282  {
283  GNUNET_break (0);
284  return;
285  }
286  fprintf (stdout,
287  _ ("Call from `%s' terminated\n"),
289  if (cl == cl_active)
290  {
291  cl_active = NULL;
293  }
294  else
295  {
297  }
298  GNUNET_free (cl);
299  break;
300  }
301 }
302 
303 
310 static void
312 {
313  struct CallList *cl = cls;
314 
315  switch (code)
316  {
318  fprintf (stdout,
319  _ ("Call from `%s' suspended by other user\n"),
321  break;
322 
324  fprintf (stdout,
325  _ ("Call from `%s' resumed by other user\n"),
327  break;
328  }
329 }
330 
331 
335 static void
337 {
338  struct GNUNET_GNSRECORD_Data rd;
339 
340  if (NULL == my_caller_id)
341  {
342  fprintf (stderr,
343  _ ("Ego `%s' no longer available, phone is now down.\n"),
344  ego_name);
346  return;
347  }
348  GNUNET_assert (NULL == phone);
350  my_caller_id,
352  NULL);
353  /* FIXME: get record and print full GNS record info later here... */
354  if (NULL == phone)
355  {
356  fprintf (stderr, "%s", _ ("Failed to setup phone (internal error)\n"));
358  }
359  else
360  {
363  address =
365  fprintf (
366  stdout,
367  _ (
368  "Phone active at `%s'. Type `/help' for a list of available commands\n"),
369  address);
371  }
372 }
373 
374 
381 static void
383 {
384  (void) cls;
385 
386  switch (code)
387  {
390  fprintf (stdout,
391  _ ("Resolved address of `%s'. Now ringing other party.\n"),
392  peer_name);
394  break;
395 
398  fprintf (stdout, _ ("Connection established to `%s'\n"), peer_name);
400  break;
401 
404  fprintf (stdout, _ ("Failed to resolve `%s'\n"), peer_name);
406  peer_name = NULL;
407  call = NULL;
408  break;
409 
411  fprintf (stdout, _ ("Call to `%s' terminated\n"), peer_name);
413  peer_name = NULL;
414  call = NULL;
415  break;
416 
419  fprintf (stdout,
420  _ ("Connection to `%s' suspended (by other user)\n"),
421  peer_name);
422  break;
423 
426  fprintf (stdout,
427  _ ("Connection to `%s' resumed (by other user)\n"),
428  peer_name);
429  break;
430 
432  fprintf (stdout, _ ("Error with the call, restarting it\n"));
434  peer_name = NULL;
435  call = NULL;
436  break;
437  }
438 }
439 
440 
446 typedef void (*ActionFunction) (const char *arguments);
447 
448 
453 {
457  const char *command;
458 
463 
467  const char *helptext;
468 };
469 
470 
476 static void
477 do_help (const char *args);
478 
479 
485 static void
486 do_quit (const char *args)
487 {
488  (void) args;
490 }
491 
492 
498 static void
499 do_unknown (const char *msg)
500 {
501  fprintf (stderr, _ ("Unknown command `%s'\n"), msg);
502 }
503 
504 
510 static void
511 do_call (const char *arg)
512 {
513  if (NULL == my_caller_id)
514  {
515  fprintf (stderr, _ ("Ego `%s' not available\n"), ego_name);
516  return;
517  }
518  if (NULL != call)
519  {
520  fprintf (stderr,
521  _ ("You are calling someone else already, hang up first!\n"));
522  return;
523  }
524  switch (phone_state)
525  {
526  case PS_LOOKUP_EGO:
527  fprintf (stderr, _ ("Ego `%s' not available\n"), ego_name);
528  return;
529 
530  case PS_LISTEN:
531  /* ok to call! */
532  break;
533 
534  case PS_ACCEPTED:
535  fprintf (
536  stderr,
537  _ (
538  "You are answering call from `%s', hang up or suspend that call first!\n"),
540  return;
541 
542  case PS_ERROR:
543  /* ok to call */
544  break;
545  }
546  if (NULL == arg)
547  {
548  fprintf (stderr, _ ("Call recipient missing.\n"));
549  do_help ("/call");
550  return;
551  }
554  GNUNET_assert (NULL == call);
556  my_caller_id,
557  arg,
558  speaker,
559  mic,
561  NULL);
562 }
563 
564 
570 static void
571 do_accept (const char *args)
572 {
573  struct CallList *cl;
574  char buf[32];
575 
576  if ((NULL != call) && (CS_SUSPENDED != call_state))
577  {
578  fprintf (stderr,
579  _ ("You are calling someone else already, hang up first!\n"));
580  return;
581  }
582  switch (phone_state)
583  {
584  case PS_LOOKUP_EGO:
585  GNUNET_break (0);
586  break;
587 
588  case PS_LISTEN:
589  /* this is the expected state */
590  break;
591 
592  case PS_ACCEPTED:
593  fprintf (
594  stderr,
595  _ (
596  "You are answering call from `%s', hang up or suspend that call first!\n"),
598  return;
599 
600  case PS_ERROR:
601  GNUNET_break (0);
602  break;
603  }
604  cl = cl_head;
605  if (NULL == cl)
606  {
607  fprintf (stderr, _ ("There is no incoming call to accept here!\n"));
608  return;
609  }
610  if ((NULL != cl->next) || (NULL != args))
611  {
612  for (cl = cl_head; NULL != cl; cl = cl->next)
613  {
614  GNUNET_snprintf (buf, sizeof(buf), "%u", cl->caller_num);
615  if (0 == strcmp (buf, args))
616  break;
617  }
618  }
619  if (NULL == cl)
620  {
621  fprintf (stderr,
622  _ ("There is no incoming call `%s' to accept right now!\n"),
623  args);
624  return;
625  }
627  cl_active = cl;
628  peer_key = cl->caller_id;
632  cl,
633  speaker,
634  mic);
635 }
636 
637 
643 static void
644 do_address (const char *args)
645 {
646  (void) args;
647  if (NULL == address)
648  {
649  fprintf (stdout, "%s", _ ("We currently do not have an address.\n"));
650  return;
651  }
652  fprintf (stdout, "%s\n", address);
653 }
654 
655 
661 static void
662 do_status (const char *args)
663 {
664  struct CallList *cl;
665 
666  (void) args;
667  switch (phone_state)
668  {
669  case PS_LOOKUP_EGO:
670  fprintf (
671  stdout,
672  _ (
673  "We are currently trying to locate the private key for the ego `%s'.\n"),
674  ego_name);
675  break;
676 
677  case PS_LISTEN:
678  fprintf (stdout,
679  _ (
680  "We are listening for incoming calls for ego `%s' on line `%s'.\n"),
681  ego_name,
682  line);
683  break;
684 
685  case PS_ACCEPTED:
686  fprintf (stdout,
687  _ ("You are having a conversation with `%s'.\n"),
689  ;
690  break;
691 
692  case PS_ERROR:
693  fprintf (
694  stdout,
695  _ (
696  "We had an internal error setting up our phone line. You can still make calls.\n"));
697  break;
698  }
699  if (NULL != call)
700  {
701  switch (call_state)
702  {
703  case CS_RESOLVING:
704  fprintf (stdout,
705  _ ("We are trying to find the network address to call `%s'.\n"),
706  peer_name);
707  break;
708 
709  case CS_RINGING:
710  fprintf (stdout,
711  _ ("We are calling `%s', their phone should be ringing.\n"),
712  peer_name);
713  break;
714 
715  case CS_CONNECTED:
716  fprintf (stdout,
717  _ ("You are having a conversation with `%s'.\n"),
718  peer_name);
719  break;
720 
721  case CS_SUSPENDED:
722  /* ok to accept incoming call right now */
723  break;
724  }
725  }
726  if ((NULL != cl_head) && ((cl_head != cl_active) || (cl_head != cl_tail)))
727  {
728  fprintf (stdout, "%s", _ ("Calls waiting:\n"));
729  for (cl = cl_head; NULL != cl; cl = cl->next)
730  {
731  if (cl == cl_active)
732  continue;
733  fprintf (stdout,
734  _ ("#%u: `%s'\n"),
735  cl->caller_num,
737  }
738  fprintf (stdout, "%s", "\n");
739  }
740 }
741 
742 
748 static void
749 do_suspend (const char *args)
750 {
751  (void) args;
752  if (NULL != call)
753  {
754  switch (call_state)
755  {
756  case CS_RESOLVING:
757  case CS_RINGING:
758  case CS_SUSPENDED:
759  fprintf (stderr,
760  "%s",
761  _ ("There is no call that could be suspended right now.\n"));
762  return;
763 
764  case CS_CONNECTED:
767  return;
768  }
769  }
770  switch (phone_state)
771  {
772  case PS_LOOKUP_EGO:
773  case PS_LISTEN:
774  case PS_ERROR:
775  fprintf (stderr,
776  "%s",
777  _ ("There is no call that could be suspended right now.\n"));
778  return;
779 
780  case PS_ACCEPTED:
781  /* expected state, do rejection logic */
782  break;
783  }
784  GNUNET_assert (NULL != cl_active);
786  cl_active = NULL;
788 }
789 
790 
796 static void
797 do_resume (const char *args)
798 {
799  struct CallList *cl;
800  char buf[32];
801 
802  if (NULL != call)
803  {
804  switch (call_state)
805  {
806  case CS_RESOLVING:
807  case CS_RINGING:
808  case CS_CONNECTED:
809  fprintf (stderr,
810  "%s",
811  _ ("There is no call that could be resumed right now.\n"));
812  return;
813 
814  case CS_SUSPENDED:
817  return;
818  }
819  }
820  switch (phone_state)
821  {
822  case PS_LOOKUP_EGO:
823  case PS_ERROR:
824  fprintf (stderr,
825  "%s",
826  _ ("There is no call that could be resumed right now.\n"));
827  return;
828 
829  case PS_LISTEN:
830  /* expected state, do resume logic */
831  break;
832 
833  case PS_ACCEPTED:
834  fprintf (stderr,
835  _ ("Already talking with `%s', cannot resume a call right now.\n"),
837  return;
838  }
839  GNUNET_assert (NULL == cl_active);
840  cl = cl_head;
841  if (NULL == cl)
842  {
843  fprintf (stderr, _ ("There is no incoming call to resume here!\n"));
844  return;
845  }
846  if ((NULL != cl->next) || (NULL != args))
847  {
848  for (cl = cl_head; NULL != cl; cl = cl->next)
849  {
850  GNUNET_snprintf (buf, sizeof(buf), "%u", cl->caller_num);
851  if (0 == strcmp (buf, args))
852  break;
853  }
854  }
855  if (NULL == cl)
856  {
857  fprintf (stderr,
858  _ ("There is no incoming call `%s' to resume right now!\n"),
859  args);
860  return;
861  }
862  cl_active = cl;
865 }
866 
867 
873 static void
874 do_reject (const char *args)
875 {
876  struct CallList *cl;
877  char buf[32];
878 
879  if (NULL != call)
880  {
882  call = NULL;
883  return;
884  }
885  switch (phone_state)
886  {
887  case PS_LOOKUP_EGO:
888  case PS_ERROR:
889  fprintf (stderr,
890  "%s",
891  _ ("There is no call that could be cancelled right now.\n"));
892  return;
893 
894  case PS_LISTEN:
895  /* look for active incoming calls to refuse */
896  cl = cl_head;
897  if (NULL == cl)
898  {
899  fprintf (stderr, _ ("There is no incoming call to refuse here!\n"));
900  return;
901  }
902  if ((NULL != cl->next) || (NULL != args))
903  {
904  for (cl = cl_head; NULL != cl; cl = cl->next)
905  {
906  GNUNET_snprintf (buf, sizeof(buf), "%u", cl->caller_num);
907  if (0 == strcmp (buf, args))
908  break;
909  }
910  }
911  if (NULL == cl)
912  {
913  fprintf (stderr,
914  _ ("There is no incoming call `%s' to refuse right now!\n"),
915  args);
916  return;
917  }
920  GNUNET_free (cl);
921  break;
922 
923  case PS_ACCEPTED:
924  /* expected state, do rejection logic */
925  GNUNET_assert (NULL != cl_active);
927  cl_active = NULL;
929  break;
930  }
931 }
932 
933 
937 static struct VoipCommand commands[] = {
938  { "/address",
939  &do_address,
940  gettext_noop (
941  "Use `/address' to find out which address this phone should have in GNS") },
942  { "/call", &do_call, gettext_noop ("Use `/call USER.gnu' to call USER") },
943  { "/accept",
944  &do_accept,
945  gettext_noop ("Use `/accept #NUM' to accept incoming call #NUM") },
946  { "/suspend",
947  &do_suspend,
948  gettext_noop ("Use `/suspend' to suspend the active call") },
949  { "/resume",
950  &do_resume,
951  gettext_noop (
952  "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming calls, no argument is needed to resume the current outgoing call.") },
953  { "/cancel",
954  &do_reject,
955  gettext_noop ("Use `/cancel' to reject or terminate a call") },
956  { "/status",
957  &do_status,
958  gettext_noop ("Use `/status' to print status information") },
959  { "/quit",
960  &do_quit,
961  gettext_noop ("Use `/quit' to terminate gnunet-conversation") },
962  { "/help",
963  &do_help,
964  gettext_noop ("Use `/help command' to get help for a specific command") },
965  { "", &do_unknown, NULL },
966  { NULL, NULL, NULL },
967 };
968 
969 
975 static void
976 do_help (const char *args)
977 {
978  unsigned int i;
979 
980  i = 0;
981  while ((NULL != args) && (0 != strlen (args)) &&
982  (commands[i].Action != &do_help))
983  {
984  if (0 == strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
985  {
986  fprintf (stdout, "%s\n", gettext (commands[i].helptext));
987  return;
988  }
989  i++;
990  }
991  i = 0;
992  fprintf (stdout, "%s", "Available commands:\n");
993  while (commands[i].Action != &do_help)
994  {
995  fprintf (stdout, "%s\n", gettext (commands[i].command));
996  i++;
997  }
998  fprintf (stdout, "%s", "\n");
999  fprintf (stdout, "%s\n", gettext (commands[i].helptext));
1000 }
1001 
1002 
1008 static void
1009 do_stop_task (void *cls)
1010 {
1011  (void) cls;
1012  if (NULL != call)
1013  {
1015  call = NULL;
1016  }
1017  if (NULL != phone)
1018  {
1020  phone = NULL;
1021  }
1022  if (NULL != handle_cmd_task)
1023  {
1025  handle_cmd_task = NULL;
1026  }
1027  if (NULL != id)
1028  {
1030  id = NULL;
1031  }
1033  speaker = NULL;
1035  mic = NULL;
1037  ego_name = NULL;
1039  peer_name = NULL;
1041 }
1042 
1043 
1050 static void
1051 handle_command_string (char *message, size_t str_len)
1052 {
1053  size_t i;
1054  const char *ptr;
1055 
1056  if (0 == str_len)
1057  return;
1058  if (message[str_len - 1] == '\n')
1059  message[str_len - 1] = '\0';
1060  if (message[str_len - 2] == '\r')
1061  message[str_len - 2] = '\0';
1062  if (0 == strlen (message))
1063  return;
1064  i = 0;
1065  while (
1066  (NULL != commands[i].command) &&
1067  (0 !=
1068  strncasecmp (commands[i].command, message, strlen (commands[i].command))))
1069  i++;
1070  ptr = &message[strlen (commands[i].command)];
1071  while (isspace ((unsigned char) *ptr))
1072  ptr++;
1073  if ('\0' == *ptr)
1074  ptr = NULL;
1075  commands[i].Action (ptr);
1076 }
1077 
1078 
1084 static void
1085 handle_command (void *cls)
1086 {
1087  char message[MAX_MESSAGE_LENGTH + 1];
1088 
1089  (void) cls;
1090  handle_cmd_task =
1092  stdin_fh,
1093  &handle_command,
1094  NULL);
1095  /* read message from command line and handle it */
1096  memset (message, 0, MAX_MESSAGE_LENGTH + 1);
1097  if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
1098  return;
1099  handle_command_string (message, strlen (message));
1100 }
1101 
1102 
1111 static void
1112 identity_cb (void *cls,
1113  struct GNUNET_IDENTITY_Ego *ego,
1114  void **ctx,
1115  const char *name)
1116 {
1117  (void) cls;
1118  (void) ctx;
1119  if (NULL == name)
1120  return;
1121  if (ego == my_caller_id)
1122  {
1123  if (verbose)
1124  fprintf (stdout, _ ("Name of our ego changed to `%s'\n"), name);
1127  return;
1128  }
1129  if (0 != strcmp (name, ego_name))
1130  return;
1131  if (NULL == ego)
1132  {
1133  if (verbose)
1134  fprintf (stdout, _ ("Our ego `%s' was deleted!\n"), ego_name);
1135  my_caller_id = NULL;
1136  return;
1137  }
1138  my_caller_id = ego;
1139  GNUNET_CONFIGURATION_set_value_string (cfg, "CONVERSATION", "LINE", line);
1140  start_phone ();
1141 }
1142 
1143 
1152 static void
1153 run (void *cls,
1154  char *const *args,
1155  const char *cfgfile,
1156  const struct GNUNET_CONFIGURATION_Handle *c)
1157 {
1158  (void) cls;
1159  (void) args;
1160  (void) cfgfile;
1164  if (NULL == ego_name)
1165  {
1166  fprintf (stderr, "%s", _ ("You must specify the NAME of an ego to use\n"));
1167  return;
1168  }
1169  id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1170  handle_cmd_task =
1172  &handle_command,
1173  NULL);
1175 }
1176 
1177 
1185 int
1186 main (int argc, char *const *argv)
1187 {
1190  'e',
1191  "ego",
1192  "NAME",
1193  gettext_noop ("sets the NAME of the ego to use for the caller ID"),
1194  &ego_name),
1196  "phone",
1197  "LINE",
1198  gettext_noop (
1199  "sets the LINE to use for the phone"),
1200  &line),
1202  int ret;
1203 
1204  int flags;
1205  flags = fcntl (0, F_GETFL, 0);
1206  flags |= O_NONBLOCK;
1207  if (0 != fcntl (0, F_SETFL, flags))
1210 
1211  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1212  return 2;
1213  ret =
1214  GNUNET_PROGRAM_run (argc,
1215  argv,
1216  "gnunet-conversation",
1217  gettext_noop (
1218  "Enables having a conversation with other GNUnet users."),
1219  options,
1220  &run,
1221  NULL);
1222  GNUNET_free_nz ((void *) argv);
1223  if (NULL != cfg)
1224  {
1226  cfg = NULL;
1227  }
1228  return (GNUNET_OK == ret) ? 0 : 1;
1229 }
1230 
1231 
1232 /* end of gnunet-conversation.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
PhoneState
Possible states of a phone.
CallState
Possible states of the phone.
#define gettext_noop(String)
Definition: gettext.h:70
#define gettext(Msgid)
Definition: gettext.h:46
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void do_suspend(const char *args)
Suspending a call.
static void do_status(const char *args)
Accepting an incoming call.
static int verbose
Be verbose.
static struct GNUNET_CONVERSATION_Call * call
Call handle (for active outgoing call).
static void do_address(const char *args)
Print address information for this phone.
static struct GNUNET_IDENTITY_Ego * my_caller_id
Our ego.
static struct CallList * cl_active
Caller handle (for active incoming call).
static void do_quit(const char *args)
Terminate the client.
static void do_call(const char *arg)
Initiating a new call.
static enum CallState call_state
Our call's current state.
void(* ActionFunction)(const char *arguments)
Function declareation for executing a action.
static struct GNUNET_IDENTITY_PublicKey peer_key
Public key of active conversation partner (if any).
static struct GNUNET_MICROPHONE_Handle * mic
Our microphone.
static void do_help(const char *args)
Action function to print help for the command shell.
static void handle_command_string(char *message, size_t str_len)
Handle user command.
static unsigned int caller_num_gen
Counts the number of incoming calls we have had so far.
static enum PhoneState phone_state
Our phone's current state.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static char * ego_name
Name of our ego.
static char * address
GNS address for this phone.
static void start_phone()
Start our phone.
static void handle_command(void *cls)
Task to handle commands from the terminal.
static char * line
Desired phone line (string to be converted to a hash).
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run by the scheduler.
static void do_stop_task(void *cls)
Task run during shutdown.
static void call_event_handler(void *cls, enum GNUNET_CONVERSATION_CallEventCode code)
Function called with an event emitted by a call.
static struct GNUNET_SPEAKER_Handle * speaker
Our speaker.
static struct GNUNET_DISK_FileHandle * stdin_fh
File handle for stdin.
static void caller_event_handler(void *cls, enum GNUNET_CONVERSATION_CallerEventCode code)
Function called with an event emitted by a caller.
@ CS_SUSPENDED
The call is currently suspended (by us).
@ CS_CONNECTED
The other party accepted our call and we are now connected.
@ CS_RESOLVING
We are looking up some other participant.
@ CS_RINGING
We are now ringing the other participant.
#define MAX_MESSAGE_LENGTH
Maximum length allowed for the command line input.
static void phone_event_handler(void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const struct GNUNET_IDENTITY_PublicKey *caller_id)
Function called with an event emitted by a phone.
static struct GNUNET_SCHEDULER_Task * handle_cmd_task
Task which handles the commands.
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
static void do_accept(const char *args)
Accepting an incoming call.
static void do_reject(const char *args)
Rejecting a call.
static char * peer_name
Name of active conversation partner (if any).
static void identity_cb(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name)
Function called by identity service with information about egos.
static struct CallList * cl_tail
Tail of calls waiting to be accepted.
int main(int argc, char *const *argv)
The main function to conversation.
static struct CallList * cl_head
Head of calls waiting to be accepted.
static struct GNUNET_CONVERSATION_Phone * phone
Phone handle.
static void do_unknown(const char *msg)
Handler for unknown command.
static void do_resume(const char *args)
Resuming a call.
static struct VoipCommand commands[]
List of supported commands.
@ PS_ERROR
Internal error.
@ PS_ACCEPTED
We accepted an incoming phone call.
@ PS_LOOKUP_EGO
We're waiting for our own idenitty.
@ PS_LISTEN
We're listening for calls.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char buf[2048]
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
API to the conversation service.
API that can be used to manipulate GNS record data.
API that can be used to store naming information on a GNUnet node;.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
void GNUNET_CONVERSATION_phone_get_record(struct GNUNET_CONVERSATION_Phone *phone, struct GNUNET_GNSRECORD_Data *rd)
Fill in a namestore record with the contact information for this phone.
struct GNUNET_CONVERSATION_Call * GNUNET_CONVERSATION_call_start(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_IDENTITY_Ego *caller_id, const char *callee, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic, GNUNET_CONVERSATION_CallEventHandler event_handler, void *event_handler_cls)
Call the phone of another user.
void GNUNET_CONVERSATION_call_suspend(struct GNUNET_CONVERSATION_Call *call)
Pause a call.
void GNUNET_CONVERSATION_caller_suspend(struct GNUNET_CONVERSATION_Caller *caller)
Pause conversation of an active call.
void GNUNET_CONVERSATION_call_resume(struct GNUNET_CONVERSATION_Call *call, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic)
Resumes a call after GNUNET_CONVERSATION_call_suspend.
void GNUNET_CONVERSATION_call_stop(struct GNUNET_CONVERSATION_Call *call)
Terminate a call.
void GNUNET_CONVERSATION_phone_destroy(struct GNUNET_CONVERSATION_Phone *phone)
Destroys a phone.
GNUNET_CONVERSATION_CallerEventCode
Information about the current status of a call.
GNUNET_CONVERSATION_PhoneEventCode
Information about active callers to a phone.
void GNUNET_CONVERSATION_caller_resume(struct GNUNET_CONVERSATION_Caller *caller, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic)
Resume suspended conversation of a phone.
void GNUNET_CONVERSATION_caller_hang_up(struct GNUNET_CONVERSATION_Caller *caller)
Hang up up a (possibly ringing) phone.
void GNUNET_CONVERSATION_caller_pick_up(struct GNUNET_CONVERSATION_Caller *caller, GNUNET_CONVERSATION_CallerEventHandler event_handler, void *event_handler_cls, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic)
Picks up a (ringing) phone.
struct GNUNET_CONVERSATION_Phone * GNUNET_CONVERSATION_phone_create(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_Ego *ego, GNUNET_CONVERSATION_PhoneEventHandler event_handler, void *event_handler_cls)
Create a new phone.
GNUNET_CONVERSATION_CallEventCode
Information about the current status of a call.
@ GNUNET_CONVERSATION_EC_CALLER_RESUME
We are the callee and the caller resumed the call.
@ GNUNET_CONVERSATION_EC_CALLER_SUSPEND
We are the callee and the caller suspended the call.
@ GNUNET_CONVERSATION_EC_PHONE_HUNG_UP
The conversation was terminated by the caller.
@ GNUNET_CONVERSATION_EC_PHONE_RING
We are the callee and the phone is ringing.
@ GNUNET_CONVERSATION_EC_CALL_SUSPENDED
We are the caller and the callee suspended the call.
@ GNUNET_CONVERSATION_EC_CALL_GNS_FAIL
We are the caller and failed to locate a phone record in GNS.
@ GNUNET_CONVERSATION_EC_CALL_PICKED_UP
We are the caller and are now ready to talk as the callee picked up.
@ GNUNET_CONVERSATION_EC_CALL_RESUMED
We are the caller and the callee suspended the call.
@ GNUNET_CONVERSATION_EC_CALL_RINGING
We are the caller and are now ringing the other party (GNS lookup succeeded).
@ GNUNET_CONVERSATION_EC_CALL_ERROR
We had an error handing the call, and are now restarting it (back to lookup).
@ GNUNET_CONVERSATION_EC_CALL_HUNG_UP
We are the caller and the callee called GNUNET_CONVERSATION_caller_hang_up.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1330
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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 * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
Definition: gnsrecord.c:155
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:531
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:757
@ GNUNET_SCHEDULER_PRIORITY_UI
Run with priority for interactive tasks.
@ GNUNET_OK
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
void GNUNET_MICROPHONE_destroy(struct GNUNET_MICROPHONE_Handle *microphone)
Destroy a microphone.
Definition: microphone.c:193
struct GNUNET_MICROPHONE_Handle * GNUNET_MICROPHONE_create_from_hardware(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a microphone that corresponds to the microphone hardware of our system.
Definition: microphone.c:170
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,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1656
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1226
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,...
Definition: scheduler.c:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_SPEAKER_Handle * GNUNET_SPEAKER_create_from_hardware(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a speaker that corresponds to the speaker hardware of our system.
Definition: speaker.c:158
void GNUNET_SPEAKER_destroy(struct GNUNET_SPEAKER_Handle *speaker)
Destroy a speaker.
Definition: speaker.c:182
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1222
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
List of incoming calls.
unsigned int caller_num
Unique number of the call.
struct GNUNET_IDENTITY_PublicKey caller_id
Public key identifying the caller.
struct CallList * next
A DLL.
struct GNUNET_CONVERSATION_Caller * caller
Handle to hang up or activate.
struct CallList * prev
A DLL.
Handle for an outgoing call.
A caller is the handle we have for an incoming call.
A phone is a device that can ring to signal an incoming call and that you can pick up to answer the c...
Handle used to access files (and pipes).
Definition of a command line option.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:97
An identity key as per LSD0001.
A microphone is a device that can capture or otherwise produce audio data.
Entry in list of pending tasks.
Definition: scheduler.c:136
A speaker is a device that can play or record audio data.
Structure which defines a command.
const char * helptext
Help text for the command.
const char * command
Command the user needs to enter.
ActionFunction Action
Function to call on command.