GNUnet  0.10.x
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 
45 enum PhoneState {
50 
55 
60 
65 };
66 
67 
71 enum CallState {
76 
81 
86 
91 };
92 
93 
97 struct CallList {
101  struct CallList *prev;
102 
106  struct CallList *next;
107 
112 
117 
121  unsigned int caller_num;
122 };
123 
124 
129 
134 
139 static struct CallList *cl_active;
140 
144 static struct CallList *cl_head;
145 
149 static struct CallList *cl_tail;
150 
154 static char *line;
155 
160 
165 
170 
175 
180 
184 static struct GNUNET_IDENTITY_Handle *id;
185 
189 static char *ego_name;
190 
195 
199 static char *peer_name;
200 
205 
210 
214 static enum CallState call_state;
215 
219 static unsigned int caller_num_gen;
220 
224 static char *address;
225 
229 static int verbose;
230 
231 
240 static void
245 {
246  struct CallList *cl;
247 
248  (void)cls;
249  switch (code)
250  {
252  /*
253  * FIXME: we should be playing our ringtones from contrib/sounds now!
254  *
255  ring_my_bell();
256  *
257  * 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
258  */
259  fprintf(
260  stdout,
261  _(
262  "Incoming call from `%s'. Please /accept %u or /cancel %u the call.\n"),
266  cl = GNUNET_new(struct CallList);
267  cl->caller = caller;
268  cl->caller_id = *caller_id;
269  cl->caller_num = caller_num_gen++;
270  GNUNET_CONTAINER_DLL_insert(cl_head, cl_tail, cl);
271  break;
272 
274  for (cl = cl_head; NULL != cl; cl = cl->next)
275  if (caller == cl->caller)
276  break;
277  if ((NULL == cl) && (caller == cl_active->caller))
278  cl = cl_active;
279  if (NULL == cl)
280  {
281  GNUNET_break(0);
282  return;
283  }
284  fprintf(stdout,
285  _("Call from `%s' terminated\n"),
287  if (cl == cl_active)
288  {
289  cl_active = NULL;
291  }
292  else
293  {
294  GNUNET_CONTAINER_DLL_remove(cl_head, cl_tail, cl);
295  }
296  GNUNET_free(cl);
297  break;
298  }
299 }
300 
301 
308 static void
310 {
311  struct CallList *cl = cls;
312 
313  switch (code)
314  {
316  fprintf(stdout,
317  _("Call from `%s' suspended by other user\n"),
319  break;
320 
322  fprintf(stdout,
323  _("Call from `%s' resumed by other user\n"),
325  break;
326  }
327 }
328 
329 
333 static void
335 {
336  struct GNUNET_GNSRECORD_Data rd;
337 
338  if (NULL == my_caller_id)
339  {
340  fprintf(stderr,
341  _("Ego `%s' no longer available, phone is now down.\n"),
342  ego_name);
344  return;
345  }
346  GNUNET_assert(NULL == phone);
348  my_caller_id,
350  NULL);
351  /* FIXME: get record and print full GNS record info later here... */
352  if (NULL == phone)
353  {
354  fprintf(stderr, "%s", _("Failed to setup phone (internal error)\n"));
356  }
357  else
358  {
361  address =
363  fprintf(
364  stdout,
365  _(
366  "Phone active at `%s'. Type `/help' for a list of available commands\n"),
367  address);
369  }
370 }
371 
372 
379 static void
381 {
382  (void)cls;
383 
384  switch (code)
385  {
388  fprintf(stdout,
389  _("Resolved address of `%s'. Now ringing other party.\n"),
390  peer_name);
392  break;
393 
396  fprintf(stdout, _("Connection established to `%s'\n"), peer_name);
398  break;
399 
402  fprintf(stdout, _("Failed to resolve `%s'\n"), peer_name);
404  peer_name = NULL;
405  call = NULL;
406  break;
407 
409  fprintf(stdout, _("Call to `%s' terminated\n"), peer_name);
411  peer_name = NULL;
412  call = NULL;
413  break;
414 
417  fprintf(stdout,
418  _("Connection to `%s' suspended (by other user)\n"),
419  peer_name);
420  break;
421 
424  fprintf(stdout,
425  _("Connection to `%s' resumed (by other user)\n"),
426  peer_name);
427  break;
428 
430  fprintf(stdout, _("Error with the call, restarting it\n"));
432  peer_name = NULL;
433  call = NULL;
434  break;
435  }
436 }
437 
438 
444 typedef void (*ActionFunction) (const char *arguments);
445 
446 
450 struct VoipCommand {
454  const char *command;
455 
460 
464  const char *helptext;
465 };
466 
467 
473 static void
474 do_help(const char *args);
475 
476 
482 static void
483 do_quit(const char *args)
484 {
485  (void)args;
487 }
488 
489 
495 static void
496 do_unknown(const char *msg)
497 {
498  fprintf(stderr, _("Unknown command `%s'\n"), msg);
499 }
500 
501 
507 static void
508 do_call(const char *arg)
509 {
510  if (NULL == my_caller_id)
511  {
512  fprintf(stderr, _("Ego `%s' not available\n"), ego_name);
513  return;
514  }
515  if (NULL != call)
516  {
517  fprintf(stderr,
518  _("You are calling someone else already, hang up first!\n"));
519  return;
520  }
521  switch (phone_state)
522  {
523  case PS_LOOKUP_EGO:
524  fprintf(stderr, _("Ego `%s' not available\n"), ego_name);
525  return;
526 
527  case PS_LISTEN:
528  /* ok to call! */
529  break;
530 
531  case PS_ACCEPTED:
532  fprintf(
533  stderr,
534  _(
535  "You are answering call from `%s', hang up or suspend that call first!\n"),
537  return;
538 
539  case PS_ERROR:
540  /* ok to call */
541  break;
542  }
543  if (NULL == arg)
544  {
545  fprintf(stderr, _("Call recipient missing.\n"));
546  do_help("/call");
547  return;
548  }
549  peer_name = GNUNET_strdup(arg);
551  GNUNET_assert(NULL == call);
553  my_caller_id,
554  arg,
555  speaker,
556  mic,
558  NULL);
559 }
560 
561 
567 static void
568 do_accept(const char *args)
569 {
570  struct CallList *cl;
571  char buf[32];
572 
573  if ((NULL != call) && (CS_SUSPENDED != call_state))
574  {
575  fprintf(stderr,
576  _("You are calling someone else already, hang up first!\n"));
577  return;
578  }
579  switch (phone_state)
580  {
581  case PS_LOOKUP_EGO:
582  GNUNET_break(0);
583  break;
584 
585  case PS_LISTEN:
586  /* this is the expected state */
587  break;
588 
589  case PS_ACCEPTED:
590  fprintf(
591  stderr,
592  _(
593  "You are answering call from `%s', hang up or suspend that call first!\n"),
595  return;
596 
597  case PS_ERROR:
598  GNUNET_break(0);
599  break;
600  }
601  cl = cl_head;
602  if (NULL == cl)
603  {
604  fprintf(stderr, _("There is no incoming call to accept here!\n"));
605  return;
606  }
607  if ((NULL != cl->next) || (NULL != args))
608  {
609  for (cl = cl_head; NULL != cl; cl = cl->next)
610  {
611  GNUNET_snprintf(buf, sizeof(buf), "%u", cl->caller_num);
612  if (0 == strcmp(buf, args))
613  break;
614  }
615  }
616  if (NULL == cl)
617  {
618  fprintf(stderr,
619  _("There is no incoming call `%s' to accept right now!\n"),
620  args);
621  return;
622  }
623  GNUNET_CONTAINER_DLL_remove(cl_head, cl_tail, cl);
624  cl_active = cl;
625  peer_key = cl->caller_id;
629  cl,
630  speaker,
631  mic);
632 }
633 
634 
640 static void
641 do_address(const char *args)
642 {
643  (void)args;
644  if (NULL == address)
645  {
646  fprintf(stdout, "%s", _("We currently do not have an address.\n"));
647  return;
648  }
649  fprintf(stdout, "%s\n", address);
650 }
651 
652 
658 static void
659 do_status(const char *args)
660 {
661  struct CallList *cl;
662 
663  (void)args;
664  switch (phone_state)
665  {
666  case PS_LOOKUP_EGO:
667  fprintf(
668  stdout,
669  _(
670  "We are currently trying to locate the private key for the ego `%s'.\n"),
671  ego_name);
672  break;
673 
674  case PS_LISTEN:
675  fprintf(stdout,
676  _(
677  "We are listening for incoming calls for ego `%s' on line `%s'.\n"),
678  ego_name,
679  line);
680  break;
681 
682  case PS_ACCEPTED:
683  fprintf(stdout,
684  _("You are having a conversation with `%s'.\n"),
686  ;
687  break;
688 
689  case PS_ERROR:
690  fprintf(
691  stdout,
692  _(
693  "We had an internal error setting up our phone line. You can still make calls.\n"));
694  break;
695  }
696  if (NULL != call)
697  {
698  switch (call_state)
699  {
700  case CS_RESOLVING:
701  fprintf(stdout,
702  _("We are trying to find the network address to call `%s'.\n"),
703  peer_name);
704  break;
705 
706  case CS_RINGING:
707  fprintf(stdout,
708  _("We are calling `%s', their phone should be ringing.\n"),
709  peer_name);
710  break;
711 
712  case CS_CONNECTED:
713  fprintf(stdout,
714  _("You are having a conversation with `%s'.\n"),
715  peer_name);
716  break;
717 
718  case CS_SUSPENDED:
719  /* ok to accept incoming call right now */
720  break;
721  }
722  }
723  if ((NULL != cl_head) && ((cl_head != cl_active) || (cl_head != cl_tail)))
724  {
725  fprintf(stdout, "%s", _("Calls waiting:\n"));
726  for (cl = cl_head; NULL != cl; cl = cl->next)
727  {
728  if (cl == cl_active)
729  continue;
730  fprintf(stdout,
731  _("#%u: `%s'\n"),
732  cl->caller_num,
734  }
735  fprintf(stdout, "%s", "\n");
736  }
737 }
738 
739 
745 static void
746 do_suspend(const char *args)
747 {
748  (void)args;
749  if (NULL != call)
750  {
751  switch (call_state)
752  {
753  case CS_RESOLVING:
754  case CS_RINGING:
755  case CS_SUSPENDED:
756  fprintf(stderr,
757  "%s",
758  _("There is no call that could be suspended right now.\n"));
759  return;
760 
761  case CS_CONNECTED:
764  return;
765  }
766  }
767  switch (phone_state)
768  {
769  case PS_LOOKUP_EGO:
770  case PS_LISTEN:
771  case PS_ERROR:
772  fprintf(stderr,
773  "%s",
774  _("There is no call that could be suspended right now.\n"));
775  return;
776 
777  case PS_ACCEPTED:
778  /* expected state, do rejection logic */
779  break;
780  }
781  GNUNET_assert(NULL != cl_active);
783  cl_active = NULL;
785 }
786 
787 
793 static void
794 do_resume(const char *args)
795 {
796  struct CallList *cl;
797  char buf[32];
798 
799  if (NULL != call)
800  {
801  switch (call_state)
802  {
803  case CS_RESOLVING:
804  case CS_RINGING:
805  case CS_CONNECTED:
806  fprintf(stderr,
807  "%s",
808  _("There is no call that could be resumed right now.\n"));
809  return;
810 
811  case CS_SUSPENDED:
813  GNUNET_CONVERSATION_call_resume(call, speaker, mic);
814  return;
815  }
816  }
817  switch (phone_state)
818  {
819  case PS_LOOKUP_EGO:
820  case PS_ERROR:
821  fprintf(stderr,
822  "%s",
823  _("There is no call that could be resumed right now.\n"));
824  return;
825 
826  case PS_LISTEN:
827  /* expected state, do resume logic */
828  break;
829 
830  case PS_ACCEPTED:
831  fprintf(stderr,
832  _("Already talking with `%s', cannot resume a call right now.\n"),
834  return;
835  }
836  GNUNET_assert(NULL == cl_active);
837  cl = cl_head;
838  if (NULL == cl)
839  {
840  fprintf(stderr, _("There is no incoming call to resume here!\n"));
841  return;
842  }
843  if ((NULL != cl->next) || (NULL != args))
844  {
845  for (cl = cl_head; NULL != cl; cl = cl->next)
846  {
847  GNUNET_snprintf(buf, sizeof(buf), "%u", cl->caller_num);
848  if (0 == strcmp(buf, args))
849  break;
850  }
851  }
852  if (NULL == cl)
853  {
854  fprintf(stderr,
855  _("There is no incoming call `%s' to resume right now!\n"),
856  args);
857  return;
858  }
859  cl_active = cl;
860  GNUNET_CONVERSATION_caller_resume(cl_active->caller, speaker, mic);
862 }
863 
864 
870 static void
871 do_reject(const char *args)
872 {
873  struct CallList *cl;
874  char buf[32];
875 
876  if (NULL != call)
877  {
879  call = NULL;
880  return;
881  }
882  switch (phone_state)
883  {
884  case PS_LOOKUP_EGO:
885  case PS_ERROR:
886  fprintf(stderr,
887  "%s",
888  _("There is no call that could be cancelled right now.\n"));
889  return;
890 
891  case PS_LISTEN:
892  /* look for active incoming calls to refuse */
893  cl = cl_head;
894  if (NULL == cl)
895  {
896  fprintf(stderr, _("There is no incoming call to refuse here!\n"));
897  return;
898  }
899  if ((NULL != cl->next) || (NULL != args))
900  {
901  for (cl = cl_head; NULL != cl; cl = cl->next)
902  {
903  GNUNET_snprintf(buf, sizeof(buf), "%u", cl->caller_num);
904  if (0 == strcmp(buf, args))
905  break;
906  }
907  }
908  if (NULL == cl)
909  {
910  fprintf(stderr,
911  _("There is no incoming call `%s' to refuse right now!\n"),
912  args);
913  return;
914  }
916  GNUNET_CONTAINER_DLL_remove(cl_head, cl_tail, cl);
917  GNUNET_free(cl);
918  break;
919 
920  case PS_ACCEPTED:
921  /* expected state, do rejection logic */
922  GNUNET_assert(NULL != cl_active);
924  cl_active = NULL;
926  break;
927  }
928 }
929 
930 
934 static struct VoipCommand commands[] = {
935  { "/address",
936  &do_address,
937  gettext_noop(
938  "Use `/address' to find out which address this phone should have in GNS") },
939  { "/call", &do_call, gettext_noop("Use `/call USER.gnu' to call USER") },
940  { "/accept",
941  &do_accept,
942  gettext_noop("Use `/accept #NUM' to accept incoming call #NUM") },
943  { "/suspend",
944  &do_suspend,
945  gettext_noop("Use `/suspend' to suspend the active call") },
946  { "/resume",
947  &do_resume,
948  gettext_noop(
949  "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming calls, no argument is needed to resume the current outgoing call.") },
950  { "/cancel",
951  &do_reject,
952  gettext_noop("Use `/cancel' to reject or terminate a call") },
953  { "/status",
954  &do_status,
955  gettext_noop("Use `/status' to print status information") },
956  { "/quit",
957  &do_quit,
958  gettext_noop("Use `/quit' to terminate gnunet-conversation") },
959  { "/help",
960  &do_help,
961  gettext_noop("Use `/help command' to get help for a specific command") },
962  { "", &do_unknown, NULL },
963  { NULL, NULL, NULL },
964 };
965 
966 
972 static void
973 do_help(const char *args)
974 {
975  unsigned int i;
976 
977  i = 0;
978  while ((NULL != args) && (0 != strlen(args)) &&
979  (commands[i].Action != &do_help))
980  {
981  if (0 == strncasecmp(&args[1], &commands[i].command[1], strlen(args) - 1))
982  {
983  fprintf(stdout, "%s\n", gettext(commands[i].helptext));
984  return;
985  }
986  i++;
987  }
988  i = 0;
989  fprintf(stdout, "%s", "Available commands:\n");
990  while (commands[i].Action != &do_help)
991  {
992  fprintf(stdout, "%s\n", gettext(commands[i].command));
993  i++;
994  }
995  fprintf(stdout, "%s", "\n");
996  fprintf(stdout, "%s\n", gettext(commands[i].helptext));
997 }
998 
999 
1005 static void
1006 do_stop_task(void *cls)
1007 {
1008  (void)cls;
1009  if (NULL != call)
1010  {
1012  call = NULL;
1013  }
1014  if (NULL != phone)
1015  {
1017  phone = NULL;
1018  }
1019  if (NULL != handle_cmd_task)
1020  {
1021  GNUNET_SCHEDULER_cancel(handle_cmd_task);
1022  handle_cmd_task = NULL;
1023  }
1024  if (NULL != id)
1025  {
1027  id = NULL;
1028  }
1029  GNUNET_SPEAKER_destroy(speaker);
1030  speaker = NULL;
1032  mic = NULL;
1034  ego_name = NULL;
1036  peer_name = NULL;
1038 }
1039 
1040 
1047 static void
1048 handle_command_string(char *message, size_t str_len)
1049 {
1050  size_t i;
1051  const char *ptr;
1052 
1053  if (0 == str_len)
1054  return;
1055  if (message[str_len - 1] == '\n')
1056  message[str_len - 1] = '\0';
1057  if (message[str_len - 2] == '\r')
1058  message[str_len - 2] = '\0';
1059  if (0 == strlen(message))
1060  return;
1061  i = 0;
1062  while (
1063  (NULL != commands[i].command) &&
1064  (0 !=
1065  strncasecmp(commands[i].command, message, strlen(commands[i].command))))
1066  i++;
1067  ptr = &message[strlen(commands[i].command)];
1068  while (isspace((unsigned char)*ptr))
1069  ptr++;
1070  if ('\0' == *ptr)
1071  ptr = NULL;
1072  commands[i].Action(ptr);
1073 }
1074 
1075 
1081 static void
1082 handle_command(void *cls)
1083 {
1084  char message[MAX_MESSAGE_LENGTH + 1];
1085 
1086  (void)cls;
1087  handle_cmd_task =
1089  stdin_fh,
1090  &handle_command,
1091  NULL);
1092  /* read message from command line and handle it */
1093  memset(message, 0, MAX_MESSAGE_LENGTH + 1);
1094  if (NULL == fgets(message, MAX_MESSAGE_LENGTH, stdin))
1095  return;
1096  handle_command_string(message, strlen(message));
1097 }
1098 
1099 
1108 static void
1109 identity_cb(void *cls,
1110  struct GNUNET_IDENTITY_Ego *ego,
1111  void **ctx,
1112  const char *name)
1113 {
1114  (void)cls;
1115  (void)ctx;
1116  if (NULL == name)
1117  return;
1118  if (ego == my_caller_id)
1119  {
1120  if (verbose)
1121  fprintf(stdout, _("Name of our ego changed to `%s'\n"), name);
1123  ego_name = GNUNET_strdup(name);
1124  return;
1125  }
1126  if (0 != strcmp(name, ego_name))
1127  return;
1128  if (NULL == ego)
1129  {
1130  if (verbose)
1131  fprintf(stdout, _("Our ego `%s' was deleted!\n"), ego_name);
1132  my_caller_id = NULL;
1133  return;
1134  }
1135  my_caller_id = ego;
1136  GNUNET_CONFIGURATION_set_value_string(cfg, "CONVERSATION", "LINE", line);
1137  start_phone();
1138 }
1139 
1140 
1149 static void
1150 run(void *cls,
1151  char *const *args,
1152  const char *cfgfile,
1153  const struct GNUNET_CONFIGURATION_Handle *c)
1154 {
1155  (void)cls;
1156  (void)args;
1157  (void)cfgfile;
1158  cfg = GNUNET_CONFIGURATION_dup(c);
1159  speaker = GNUNET_SPEAKER_create_from_hardware(cfg);
1161  if (NULL == ego_name)
1162  {
1163  fprintf(stderr, "%s", _("You must specify the NAME of an ego to use\n"));
1164  return;
1165  }
1166  id = GNUNET_IDENTITY_connect(cfg, &identity_cb, NULL);
1167  handle_cmd_task =
1169  &handle_command,
1170  NULL);
1172 }
1173 
1174 
1182 int
1183 main(int argc, char *const *argv)
1184 {
1185  struct GNUNET_GETOPT_CommandLineOption options[] =
1187  'e',
1188  "ego",
1189  "NAME",
1190  gettext_noop("sets the NAME of the ego to use for the caller ID"),
1191  &ego_name),
1193  "phone",
1194  "LINE",
1195  gettext_noop(
1196  "sets the LINE to use for the phone"),
1197  &line),
1199  int ret;
1200 
1201  int flags;
1202  flags = fcntl(0, F_GETFL, 0);
1203  flags |= O_NONBLOCK;
1204  if (0 != fcntl(0, F_SETFL, flags))
1206  stdin_fh = GNUNET_DISK_get_handle_from_int_fd(0);
1207 
1208  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
1209  return 2;
1210  ret =
1211  GNUNET_PROGRAM_run(argc,
1212  argv,
1213  "gnunet-conversation",
1214  gettext_noop(
1215  "Enables having a conversation with other GNUnet users."),
1216  options,
1217  &run,
1218  NULL);
1219  GNUNET_free((void *)argv);
1220  if (NULL != cfg)
1221  {
1223  cfg = NULL;
1224  }
1225  return (GNUNET_OK == ret) ? 0 : 1;
1226 }
1227 
1228 /* end of gnunet-conversation.c */
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:525
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct CallList * cl_tail
Tail of calls waiting to be accepted.
static struct GNUNET_CONVERSATION_Phone * phone
Phone handle.
Internal error.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void handle_command(void *cls)
Task to handle commands from the terminal.
const char * helptext
Help text for the command.
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_call(const char *arg)
Initiating a new call.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void do_suspend(const char *args)
Suspending a call.
static struct GNUNET_SCHEDULER_Task * handle_cmd_task
Task which handles the commands.
We&#39;re waiting for our own idenitty.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
List of incoming calls.
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:1284
unsigned int caller_num
Unique number of the call.
#define gettext(Msgid)
Definition: gettext.h:45
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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
static enum CallState call_state
Our call&#39;s current state.
static char * ego_name
Name of our ego.
We are the caller and the callee suspended the call.
void GNUNET_CONVERSATION_caller_hang_up(struct GNUNET_CONVERSATION_Caller *caller)
Hang up up a (possibly ringing) phone.
static enum PhoneState phone_state
Our phone&#39;s current state.
We are the callee and the caller resumed the call.
Structure which defines a command.
static struct CallList * cl_head
Head of calls waiting to be accepted.
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_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:1615
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static void do_resume(const char *args)
Resuming a call.
size_t data_size
Number of bytes in data.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static char * peer_name
Name of active conversation partner (if any).
static void handle_command_string(char *message, size_t str_len)
Handle user command.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct CallList * next
A DLL.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
static struct GNUNET_MICROPHONE_Handle * mic
Our microphone.
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.
We are the caller and are now ready to talk as the callee picked up.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
A phone is a device that can ring to signal an incoming call and that you can pick up to answer the c...
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Handle for an ego.
Definition: identity.h:237
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:1191
const void * data
Binary value stored in the DNS record.
static char * line
Desired phone line (string to be converted to a hash).
We accepted an incoming phone call.
static struct GNUNET_IDENTITY_Ego * my_caller_id
Our ego.
Handle for the service.
Definition: identity_api.c:94
static void caller_event_handler(void *cls, enum GNUNET_CONVERSATION_CallerEventCode code)
Function called with an event emitted by a caller.
static void do_reject(const char *args)
Rejecting a call.
Run with priority for interactive tasks.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void do_status(const char *args)
Accepting an incoming call.
static struct VoipCommand commands[]
List of supported commands.
static struct GNUNET_SPEAKER_Handle * speaker
Our speaker.
int main(int argc, char *const *argv)
The main function to conversation.
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_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char buf[2048]
void GNUNET_CONVERSATION_phone_destroy(struct GNUNET_CONVERSATION_Phone *phone)
Destroys a phone.
We are the caller and are now ringing the other party (GNS lookup succeeded).
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.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:835
We are the caller and the callee called GNUNET_CONVERSATION_caller_hang_up.
static void phone_event_handler(void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const struct GNUNET_CRYPTO_EcdsaPublicKey *caller_id)
Function called with an event emitted by a 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.
static void do_accept(const char *args)
Accepting an incoming call.
A caller is the handle we have for an incoming call.
static struct GNUNET_DISK_FileHandle * stdin_fh
File handle for stdin.
static void start_phone()
Start our phone.
The conversation was terminated by the caller.
ActionFunction Action
Function to call on command.
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.
We are the caller and failed to locate a phone record in GNS.
const char * name
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.
CallState
Possible states of the phone.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
GNUNET_CONVERSATION_CallerEventCode
Information about the current status of a call.
static struct GNUNET_CRYPTO_EcdsaPublicKey peer_key
Public key of active conversation partner (if any).
void GNUNET_SPEAKER_destroy(struct GNUNET_SPEAKER_Handle *speaker)
Destroy a speaker.
Definition: speaker.c:181
The other party accepted our call and we are now connected.
static void do_stop_task(void *cls)
Task run during shutdown.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup(const struct GNUNET_CONFIGURATION_Handle *cfg)
Duplicate an existing configuration object.
#define MAX_MESSAGE_LENGTH
Maximum length allowed for the command line input.
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.
We are the callee and the caller suspended the call.
static struct GNUNET_CONVERSATION_Call * call
Call handle (for active outgoing call).
static int verbose
Be verbose.
We&#39;re listening for calls.
void GNUNET_MICROPHONE_destroy(struct GNUNET_MICROPHONE_Handle *microphone)
Destroy a microphone.
Definition: microphone.c:192
void GNUNET_CONVERSATION_caller_suspend(struct GNUNET_CONVERSATION_Caller *caller)
Pause conversation of an active call.
uint32_t record_type
Type of the GNS/DNS record.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1369
configuration data
Definition: configuration.c:83
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.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
We are now ringing the other participant.
We are the callee and the phone is ringing.
Entry in list of pending tasks.
Definition: scheduler.c:131
static void call_event_handler(void *cls, enum GNUNET_CONVERSATION_CallEventCode code)
Function called with an event emitted by a call.
static void do_address(const char *args)
Print address information for this phone.
static void do_unknown(const char *msg)
Handler for unknown command.
void GNUNET_CONVERSATION_call_stop(struct GNUNET_CONVERSATION_Call *call)
Terminate a call.
int 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:367
We are the caller and the callee suspended the call.
void(* ActionFunction)(const char *arguments)
Function declareation for executing a action.
static struct CallList * cl_active
Caller handle (for active incoming call).
Handle for an outgoing call.
struct GNUNET_CONVERSATION_Caller * caller
Handle to hang up or activate.
The call is currently suspended (by us).
PhoneState
Possible states of a phone.
GNUNET_CONVERSATION_CallEventCode
Information about the current status of a call.
static unsigned int caller_num_gen
Counts the number of incoming calls we have had so far.
A microphone is a device that can capture or otherwise produce audio data.
We had an error handing the call, and are now restarting it (back to lookup).
struct CallList * prev
A DLL.
We are looking up some other participant.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;value&#39; of a record to a string.
Definition: gnsrecord.c:142
static char * address
GNS address for this phone.
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
A speaker is a device that can play or record audio data.
Handle used to access files (and pipes).
void GNUNET_CONVERSATION_call_suspend(struct GNUNET_CONVERSATION_Call *call)
Pause a call.
static void do_help(const char *args)
Action function to print help for the command shell.
const char * command
Command the user needs to enter.
static void do_quit(const char *args)
Terminate the client.
struct GNUNET_CRYPTO_EcdsaPublicKey caller_id
Public key identifying the caller.
GNUNET_CONVERSATION_PhoneEventCode
Information about active callers to a phone.
#define GNUNET_free(ptr)
Wrapper around free.
#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:956