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 #ifdef WINDOWS
33 #include "../util/gnunet-helper-w32-console.h"
34 #endif
35 
39 #define MAX_MESSAGE_LENGTH 1024
40 
41 #define XSTRINGIFY(x) STRINGIFY(x)
42 
43 #define STRINGIFY(x) (#x)
44 
45 #ifdef WINDOWS
46 
49 struct GNUNET_HELPER_Handle *stdin_hlp;
50 #endif
51 
56 {
61 
66 
71 
76 };
77 
78 
83 {
88 
93 
98 
103 
104 };
105 
106 
110 struct CallList
111 {
112 
116  struct CallList *prev;
117 
121  struct CallList *next;
122 
127 
132 
136  unsigned int caller_num;
137 
138 };
139 
140 
141 
146 
151 
156 static struct CallList *cl_active;
157 
161 static struct CallList *cl_head;
162 
166 static struct CallList *cl_tail;
167 
171 static char *line;
172 
177 
182 
187 
192 
197 
201 static struct GNUNET_IDENTITY_Handle *id;
202 
206 static char *ego_name;
207 
212 
216 static char *peer_name;
217 
222 
227 
231 static enum CallState call_state;
232 
236 static unsigned int caller_num_gen;
237 
241 static char *address;
242 
246 static int verbose;
247 
248 
257 static void
262 {
263  struct CallList *cl;
264 
265  (void) cls;
266  switch (code)
267  {
269  /*
270  * FIXME: we should be playing our ringtones from contrib/sounds now!
271  *
272  ring_my_bell();
273  *
274  * 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
275  */
276  FPRINTF (stdout,
277  _("Incoming call from `%s'. Please /accept %u or /cancel %u the call.\n"),
278  GNUNET_GNSRECORD_pkey_to_zkey (caller_id),
281  cl = GNUNET_new (struct CallList);
282  cl->caller = caller;
283  cl->caller_id = *caller_id;
284  cl->caller_num = caller_num_gen++;
286  cl_tail,
287  cl);
288  break;
290  for (cl = cl_head; NULL != cl; cl = cl->next)
291  if (caller == cl->caller)
292  break;
293  if ( (NULL == cl) &&
294  (caller == cl_active->caller) )
295  cl = cl_active;
296  if (NULL == cl)
297  {
298  GNUNET_break (0);
299  return;
300  }
301  FPRINTF (stdout,
302  _("Call from `%s' terminated\n"),
304  if (cl == cl_active)
305  {
306  cl_active = NULL;
308  }
309  else
310  {
312  cl_tail,
313  cl);
314  }
315  GNUNET_free (cl);
316  break;
317  }
318 }
319 
320 
327 static void
330 {
331  struct CallList *cl = cls;
332 
333  switch (code)
334  {
336  FPRINTF (stdout,
337  _("Call from `%s' suspended by other user\n"),
339  break;
341  FPRINTF (stdout,
342  _("Call from `%s' resumed by other user\n"),
344  break;
345  }
346 }
347 
348 
352 static void
354 {
355  struct GNUNET_GNSRECORD_Data rd;
356 
357  if (NULL == my_caller_id)
358  {
359  FPRINTF (stderr,
360  _("Ego `%s' no longer available, phone is now down.\n"),
361  ego_name);
363  return;
364  }
365  GNUNET_assert (NULL == phone);
367  my_caller_id,
369  NULL);
370  /* FIXME: get record and print full GNS record info later here... */
371  if (NULL == phone)
372  {
373  FPRINTF (stderr,
374  "%s",
375  _("Failed to setup phone (internal error)\n"));
377  }
378  else
379  {
381  &rd);
384  rd.data,
385  rd.data_size);
386  FPRINTF (stdout,
387  _("Phone active at `%s'. Type `/help' for a list of available commands\n"),
388  address);
390  }
391 }
392 
393 
400 static void
403 {
404  (void) cls;
405 
406  switch (code)
407  {
410  FPRINTF (stdout,
411  _("Resolved address of `%s'. Now ringing other party.\n"),
412  peer_name);
414  break;
417  FPRINTF (stdout,
418  _("Connection established to `%s'\n"),
419  peer_name);
421  break;
424  FPRINTF (stdout,
425  _("Failed to resolve `%s'\n"),
426  peer_name);
428  peer_name = NULL;
429  call = NULL;
430  break;
432  FPRINTF (stdout,
433  _("Call to `%s' terminated\n"),
434  peer_name);
436  peer_name = NULL;
437  call = NULL;
438  break;
441  FPRINTF (stdout,
442  _("Connection to `%s' suspended (by other user)\n"),
443  peer_name);
444  break;
447  FPRINTF (stdout,
448  _("Connection to `%s' resumed (by other user)\n"),
449  peer_name);
450  break;
452  FPRINTF (stdout,
453  _("Error with the call, restarting it\n"));
455  peer_name = NULL;
456  call = NULL;
457  break;
458  }
459 }
460 
461 
467 typedef void
468 (*ActionFunction) (const char *arguments);
469 
470 
475 {
479  const char *command;
480 
485 
489  const char *helptext;
490 };
491 
492 
498 static void
499 do_help (const char *args);
500 
501 
507 static void
508 do_quit (const char *args)
509 {
510  (void) args;
512 }
513 
514 
520 static void
521 do_unknown (const char *msg)
522 {
523  FPRINTF (stderr,
524  _("Unknown command `%s'\n"),
525  msg);
526 }
527 
528 
534 static void
535 do_call (const char *arg)
536 {
537  if (NULL == my_caller_id)
538  {
539  FPRINTF (stderr,
540  _("Ego `%s' not available\n"),
541  ego_name);
542  return;
543  }
544  if (NULL != call)
545  {
546  FPRINTF (stderr,
547  _("You are calling someone else already, hang up first!\n"));
548  return;
549  }
550  switch (phone_state)
551  {
552  case PS_LOOKUP_EGO:
553  FPRINTF (stderr,
554  _("Ego `%s' not available\n"),
555  ego_name);
556  return;
557  case PS_LISTEN:
558  /* ok to call! */
559  break;
560  case PS_ACCEPTED:
561  FPRINTF (stderr,
562  _("You are answering call from `%s', hang up or suspend that call first!\n"),
564  return;
565  case PS_ERROR:
566  /* ok to call */
567  break;
568  }
569  if (NULL == arg)
570  {
571  FPRINTF (stderr,
572  _("Call recipient missing.\n"));
573  do_help ("/call");
574  return;
575  }
576  peer_name = GNUNET_strdup (arg);
578  GNUNET_assert (NULL == call);
579  call = GNUNET_CONVERSATION_call_start (cfg,
580  my_caller_id,
581  arg,
582  speaker,
583  mic,
584  &call_event_handler, NULL);
585 }
586 
587 
593 static void
594 do_accept (const char *args)
595 {
596  struct CallList *cl;
597  char buf[32];
598 
599  if ( (NULL != call) &&
600  (CS_SUSPENDED != call_state) )
601  {
602  FPRINTF (stderr,
603  _("You are calling someone else already, hang up first!\n"));
604  return;
605  }
606  switch (phone_state)
607  {
608  case PS_LOOKUP_EGO:
609  GNUNET_break (0);
610  break;
611  case PS_LISTEN:
612  /* this is the expected state */
613  break;
614  case PS_ACCEPTED:
615  FPRINTF (stderr,
616  _("You are answering call from `%s', hang up or suspend that call first!\n"),
618  return;
619  case PS_ERROR:
620  GNUNET_break (0);
621  break;
622  }
623  cl = cl_head;
624  if (NULL == cl)
625  {
626  FPRINTF (stderr,
627  _("There is no incoming call to accept here!\n"));
628  return;
629  }
630  if ( (NULL != cl->next) || (NULL != args) )
631  {
632  for (cl = cl_head; NULL != cl; cl = cl->next)
633  {
634  GNUNET_snprintf (buf, sizeof (buf),
635  "%u",
636  cl->caller_num);
637  if (0 == strcmp (buf, args))
638  break;
639  }
640  }
641  if (NULL == cl)
642  {
643  FPRINTF (stderr,
644  _("There is no incoming call `%s' to accept right now!\n"),
645  args);
646  return;
647  }
649  cl_tail,
650  cl);
651  cl_active = cl;
652  peer_key = cl->caller_id;
656  cl,
657  speaker,
658  mic);
659 }
660 
661 
667 static void
668 do_address (const char *args)
669 {
670  (void) args;
671  if (NULL == address)
672  {
673  FPRINTF (stdout,
674  "%s",
675  _("We currently do not have an address.\n"));
676  return;
677  }
678  FPRINTF (stdout,
679  "%s\n",
680  address);
681 }
682 
683 
689 static void
690 do_status (const char *args)
691 {
692  struct CallList *cl;
693 
694  (void) args;
695  switch (phone_state)
696  {
697  case PS_LOOKUP_EGO:
698  FPRINTF (stdout,
699  _("We are currently trying to locate the private key for the ego `%s'.\n"),
700  ego_name);
701  break;
702  case PS_LISTEN:
703  FPRINTF (stdout,
704  _("We are listening for incoming calls for ego `%s' on line `%s'.\n"),
705  ego_name,
706  line);
707  break;
708  case PS_ACCEPTED:
709  FPRINTF (stdout,
710  _("You are having a conversation with `%s'.\n"),
712  break;
713  case PS_ERROR:
714  FPRINTF (stdout,
715  _("We had an internal error setting up our phone line. You can still make calls.\n"));
716  break;
717  }
718  if (NULL != call)
719  {
720  switch (call_state)
721  {
722  case CS_RESOLVING:
723  FPRINTF (stdout,
724  _("We are trying to find the network address to call `%s'.\n"),
725  peer_name);
726  break;
727  case CS_RINGING:
728  FPRINTF (stdout,
729  _("We are calling `%s', their phone should be ringing.\n"),
730  peer_name);
731  break;
732  case CS_CONNECTED:
733  FPRINTF (stdout,
734  _("You are having a conversation with `%s'.\n"),
735  peer_name);
736  break;
737  case CS_SUSPENDED:
738  /* ok to accept incoming call right now */
739  break;
740  }
741  }
742  if ( (NULL != cl_head) &&
743  ( (cl_head != cl_active) ||
744  (cl_head != cl_tail) ) )
745  {
746  FPRINTF (stdout,
747  "%s",
748  _("Calls waiting:\n"));
749  for (cl = cl_head; NULL != cl; cl = cl->next)
750  {
751  if (cl == cl_active)
752  continue;
753  FPRINTF (stdout,
754  _("#%u: `%s'\n"),
755  cl->caller_num,
757  }
758  FPRINTF (stdout,
759  "%s",
760  "\n");
761  }
762 }
763 
764 
770 static void
771 do_suspend (const char *args)
772 {
773  (void) args;
774  if (NULL != call)
775  {
776  switch (call_state)
777  {
778  case CS_RESOLVING:
779  case CS_RINGING:
780  case CS_SUSPENDED:
781  FPRINTF (stderr,
782  "%s",
783  _("There is no call that could be suspended right now.\n"));
784  return;
785  case CS_CONNECTED:
788  return;
789  }
790  }
791  switch (phone_state)
792  {
793  case PS_LOOKUP_EGO:
794  case PS_LISTEN:
795  case PS_ERROR:
796  FPRINTF (stderr,
797  "%s",
798  _("There is no call that could be suspended right now.\n"));
799  return;
800  case PS_ACCEPTED:
801  /* expected state, do rejection logic */
802  break;
803  }
804  GNUNET_assert (NULL != cl_active);
806  cl_active = NULL;
808 }
809 
810 
816 static void
817 do_resume (const char *args)
818 {
819  struct CallList *cl;
820  char buf[32];
821 
822  if (NULL != call)
823  {
824  switch (call_state)
825  {
826  case CS_RESOLVING:
827  case CS_RINGING:
828  case CS_CONNECTED:
829  FPRINTF (stderr,
830  "%s",
831  _("There is no call that could be resumed right now.\n"));
832  return;
833  case CS_SUSPENDED:
836  speaker,
837  mic);
838  return;
839  }
840  }
841  switch (phone_state)
842  {
843  case PS_LOOKUP_EGO:
844  case PS_ERROR:
845  FPRINTF (stderr,
846  "%s",
847  _("There is no call that could be resumed right now.\n"));
848  return;
849  case PS_LISTEN:
850  /* expected state, do resume logic */
851  break;
852  case PS_ACCEPTED:
853  FPRINTF (stderr,
854  _("Already talking with `%s', cannot resume a call right now.\n"),
856  return;
857  }
858  GNUNET_assert (NULL == cl_active);
859  cl = cl_head;
860  if (NULL == cl)
861  {
862  FPRINTF (stderr,
863  _("There is no incoming call to resume here!\n"));
864  return;
865  }
866  if ( (NULL != cl->next) || (NULL != args) )
867  {
868  for (cl = cl_head; NULL != cl; cl = cl->next)
869  {
870  GNUNET_snprintf (buf, sizeof (buf),
871  "%u",
872  cl->caller_num);
873  if (0 == strcmp (buf, args))
874  break;
875  }
876  }
877  if (NULL == cl)
878  {
879  FPRINTF (stderr,
880  _("There is no incoming call `%s' to resume right now!\n"),
881  args);
882  return;
883  }
884  cl_active = cl;
886  speaker,
887  mic);
889 }
890 
891 
897 static void
898 do_reject (const char *args)
899 {
900  struct CallList *cl;
901  char buf[32];
902 
903  if (NULL != call)
904  {
906  call = NULL;
907  return;
908  }
909  switch (phone_state)
910  {
911  case PS_LOOKUP_EGO:
912  case PS_ERROR:
913  FPRINTF (stderr,
914  "%s",
915  _("There is no call that could be cancelled right now.\n"));
916  return;
917  case PS_LISTEN:
918  /* look for active incoming calls to refuse */
919  cl = cl_head;
920  if (NULL == cl)
921  {
922  FPRINTF (stderr,
923  _("There is no incoming call to refuse here!\n"));
924  return;
925  }
926  if ( (NULL != cl->next) || (NULL != args) )
927  {
928  for (cl = cl_head; NULL != cl; cl = cl->next)
929  {
930  GNUNET_snprintf (buf, sizeof (buf),
931  "%u",
932  cl->caller_num);
933  if (0 == strcmp (buf, args))
934  break;
935  }
936  }
937  if (NULL == cl)
938  {
939  FPRINTF (stderr,
940  _("There is no incoming call `%s' to refuse right now!\n"),
941  args);
942  return;
943  }
946  cl_tail,
947  cl);
948  GNUNET_free (cl);
949  break;
950  case PS_ACCEPTED:
951  /* expected state, do rejection logic */
952  GNUNET_assert (NULL != cl_active);
954  cl_active = NULL;
956  break;
957  }
958 }
959 
960 
964 static struct VoipCommand commands[] = {
965  {"/address", &do_address,
966  gettext_noop ("Use `/address' to find out which address this phone should have in GNS")},
967  {"/call", &do_call,
968  gettext_noop ("Use `/call USER.gnu' to call USER")},
969  {"/accept", &do_accept,
970  gettext_noop ("Use `/accept #NUM' to accept incoming call #NUM")},
971  {"/suspend", &do_suspend,
972  gettext_noop ("Use `/suspend' to suspend the active call")},
973  {"/resume", &do_resume,
974  gettext_noop ("Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming calls, no argument is needed to resume the current outgoing call.")},
975  {"/cancel", &do_reject,
976  gettext_noop ("Use `/cancel' to reject or terminate a call")},
977  {"/status", &do_status,
978  gettext_noop ("Use `/status' to print status information")},
979  {"/quit", &do_quit,
980  gettext_noop ("Use `/quit' to terminate gnunet-conversation")},
981  {"/help", &do_help,
982  gettext_noop ("Use `/help command' to get help for a specific command")},
983  {"", &do_unknown,
984  NULL},
985  {NULL, NULL, NULL},
986 };
987 
988 
994 static void
995 do_help (const char *args)
996 {
997  unsigned int i;
998 
999  i = 0;
1000  while ( (NULL != args) &&
1001  (0 != strlen (args)) &&
1002  (commands[i].Action != &do_help))
1003  {
1004  if (0 ==
1005  strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
1006  {
1007  FPRINTF (stdout,
1008  "%s\n",
1009  gettext (commands[i].helptext));
1010  return;
1011  }
1012  i++;
1013  }
1014  i = 0;
1015  FPRINTF (stdout,
1016  "%s",
1017  "Available commands:\n");
1018  while (commands[i].Action != &do_help)
1019  {
1020  FPRINTF (stdout,
1021  "%s\n",
1022  gettext (commands[i].command));
1023  i++;
1024  }
1025  FPRINTF (stdout,
1026  "%s",
1027  "\n");
1028  FPRINTF (stdout,
1029  "%s\n",
1030  gettext (commands[i].helptext));
1031 }
1032 
1033 
1039 static void
1040 do_stop_task (void *cls)
1041 {
1042  (void) cls;
1043 #ifdef WINDOWS
1044  if (NULL != stdin_hlp)
1045  {
1046  GNUNET_HELPER_stop (stdin_hlp, GNUNET_NO);
1047  stdin_hlp = NULL;
1048  }
1049 #endif
1050  if (NULL != call)
1051  {
1053  call = NULL;
1054  }
1055  if (NULL != phone)
1056  {
1058  phone = NULL;
1059  }
1060  if (NULL != handle_cmd_task)
1061  {
1062  GNUNET_SCHEDULER_cancel (handle_cmd_task);
1063  handle_cmd_task = NULL;
1064  }
1065  if (NULL != id)
1066  {
1068  id = NULL;
1069  }
1070  GNUNET_SPEAKER_destroy (speaker);
1071  speaker = NULL;
1073  mic = NULL;
1075  ego_name = NULL;
1077  peer_name = NULL;
1079 }
1080 
1081 
1088 static void
1089 handle_command_string (char *message,
1090  size_t str_len)
1091 {
1092  size_t i;
1093  const char *ptr;
1094 
1095  if (0 == str_len)
1096  return;
1097  if (message[str_len - 1] == '\n')
1098  message[str_len - 1] = '\0';
1099  if (message[str_len - 2] == '\r')
1100  message[str_len - 2] = '\0';
1101  if (0 == strlen (message))
1102  return;
1103  i = 0;
1104  while ((NULL != commands[i].command) &&
1105  (0 != strncasecmp (commands[i].command, message,
1106  strlen (commands[i].command))))
1107  i++;
1108  ptr = &message[strlen (commands[i].command)];
1109  while (isspace ((unsigned char) *ptr))
1110  ptr++;
1111  if ('\0' == *ptr)
1112  ptr = NULL;
1113  commands[i].Action (ptr);
1114 }
1115 
1116 
1117 #ifdef WINDOWS
1118 static int
1119 console_reader_chars (void *cls,
1120  void *client,
1121  const struct GNUNET_MessageHeader *message)
1122 {
1123  char *chars;
1124  size_t str_size;
1125 
1126  (void) cls;
1127  switch (ntohs (message->type))
1128  {
1130  chars = (char *) &message[1];
1131  str_size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
1132  if (chars[str_size - 1] != '\0')
1133  return GNUNET_SYSERR;
1134  /* FIXME: is it ok that we pass part of a const struct to
1135  * this function that may mangle the contents?
1136  */
1137  handle_command_string (chars, str_size - 1);
1138  break;
1139  default:
1140  GNUNET_break (0);
1141  break;
1142  }
1143  return GNUNET_OK;
1144 }
1145 #endif
1146 
1147 
1153 static void
1154 handle_command (void *cls)
1155 {
1156  char message[MAX_MESSAGE_LENGTH + 1];
1157 
1158  (void) cls;
1159  handle_cmd_task =
1161  stdin_fh,
1162  &handle_command, NULL);
1163  /* read message from command line and handle it */
1164  memset (message,
1165  0,
1166  MAX_MESSAGE_LENGTH + 1);
1167  if (NULL == fgets (message,
1169  stdin))
1170  return;
1171  handle_command_string (message,
1172  strlen (message));
1173 }
1174 
1175 
1184 static void
1185 identity_cb (void *cls,
1186  struct GNUNET_IDENTITY_Ego *ego,
1187  void **ctx,
1188  const char *name)
1189 {
1190  (void) cls;
1191  (void) ctx;
1192  if (NULL == name)
1193  return;
1194  if (ego == my_caller_id)
1195  {
1196  if (verbose)
1197  FPRINTF (stdout,
1198  _("Name of our ego changed to `%s'\n"),
1199  name);
1201  ego_name = GNUNET_strdup (name);
1202  return;
1203  }
1204  if (0 != strcmp (name,
1205  ego_name))
1206  return;
1207  if (NULL == ego)
1208  {
1209  if (verbose)
1210  FPRINTF (stdout,
1211  _("Our ego `%s' was deleted!\n"),
1212  ego_name);
1213  my_caller_id = NULL;
1214  return;
1215  }
1216  my_caller_id = ego;
1218  "CONVERSATION",
1219  "LINE",
1220  line);
1221  start_phone ();
1222 }
1223 
1224 
1233 static void
1234 run (void *cls,
1235  char *const *args,
1236  const char *cfgfile,
1237  const struct GNUNET_CONFIGURATION_Handle *c)
1238 {
1239  (void) cls;
1240  (void) args;
1241  (void) cfgfile;
1242  cfg = GNUNET_CONFIGURATION_dup (c);
1243  speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
1245  if (NULL == ego_name)
1246  {
1247  FPRINTF (stderr,
1248  "%s",
1249  _("You must specify the NAME of an ego to use\n"));
1250  return;
1251  }
1252  id = GNUNET_IDENTITY_connect (cfg,
1253  &identity_cb,
1254  NULL);
1255 #ifdef WINDOWS
1256  if (stdin_fh == NULL)
1257  {
1258  static char cpid[64];
1259  static char *args[] = {"gnunet-helper-w32-console.exe", "chars",
1261  snprintf (cpid, 64, "%d", GetCurrentProcessId ());
1262  stdin_hlp = GNUNET_HELPER_start (
1263  GNUNET_NO,
1264  "gnunet-helper-w32-console",
1265  args,
1266  console_reader_chars,
1267  NULL,
1268  NULL);
1269  if (NULL == stdin_hlp)
1270  {
1271  FPRINTF (stderr,
1272  "%s",
1273  _("Failed to start gnunet-helper-w32-console\n"));
1274  return;
1275  }
1276  }
1277  else
1278 #endif
1279  handle_cmd_task =
1281  &handle_command, NULL);
1283  NULL);
1284 }
1285 
1286 
1294 int
1295 main (int argc,
1296  char *const *argv)
1297 {
1298  struct GNUNET_GETOPT_CommandLineOption options[] = {
1300  "ego",
1301  "NAME",
1302  gettext_noop ("sets the NAME of the ego to use for the caller ID"),
1303  &ego_name),
1305  "phone",
1306  "LINE",
1307  gettext_noop ("sets the LINE to use for the phone"),
1308  &line),
1310  };
1311  int ret;
1312 #ifndef WINDOWS
1313  int flags;
1314  flags = fcntl (0, F_GETFL, 0);
1315  flags |= O_NONBLOCK;
1316  if (0 != fcntl (0, F_SETFL, flags))
1318  "fcntl");
1319  stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
1320 #else
1321  if (FILE_TYPE_CHAR == GetFileType ((HANDLE) _get_osfhandle (0)))
1322  {
1323  stdin_fh = NULL;
1324  }
1325  else
1326  stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
1327 #endif
1328 
1329  if (GNUNET_OK !=
1330  GNUNET_STRINGS_get_utf8_args (argc, argv,
1331  &argc, &argv))
1332  return 2;
1333  ret = GNUNET_PROGRAM_run (argc,
1334  argv,
1335  "gnunet-conversation",
1336  gettext_noop ("Enables having a conversation with other GNUnet users."),
1337  options,
1338  &run, NULL);
1339  GNUNET_free ((void *) argv);
1340  if (NULL != cfg)
1341  {
1343  cfg = NULL;
1344  }
1345  return (GNUNET_OK == ret) ? 0 : 1;
1346 }
1347 
1348 /* 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:528
#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 char * cpid
Which peer should we connect to?
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.
#define FPRINTF
Definition: plibc.h:683
List of incoming calls.
The handle to a helper process.
Definition: helper.c:80
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
Definition: helper.c:491
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:1293
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:1521
#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:160
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.
void GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
Kills the helper, closes the pipe, frees the handle and calls wait() on the helper process...
Definition: helper.c:569
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.
#define GNUNET_NO
Definition: gnunet_common.h:81
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:1643
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
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:208
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:245
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
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:1200
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:96
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:838
We are the caller and the callee called GNUNET_CONVERSATION_caller_hang_up.
#define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS
Chars from the console.
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.
#define XSTRINGIFY(x)
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:183
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:195
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:1937
configuration data
Definition: configuration.c:85
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:134
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:361
We are the caller and the callee suspended the call.
void(* ActionFunction)(const char *arguments)
Function declareation for executing a action.
Header for all communications.
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.
static int chars
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:143
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:173
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:965