GNUnet  0.10.x
gnunet-service-conversation.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013, 2016, 2017 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  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_applications.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_signatures.h"
33 #include "gnunet_cadet_service.h"
35 #include "conversation.h"
36 
37 
43 #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
44 
45 
50 struct Line;
51 
60 
65 
70 
75 
80 
85 
90 };
91 
92 
99 struct Channel {
103  struct Channel *next;
104 
108  struct Channel *prev;
109 
113  struct Line *line;
114 
119 
124 
129 
133  uint32_t cid;
134 
139 
144 
149 };
150 
151 
155 struct Line {
160 
165 
170 
175 
180 
185  struct GNUNET_HashCode line_port;
186 
190  uint32_t cid_gen;
191 };
192 
193 
197 static const struct GNUNET_CONFIGURATION_Handle *cfg;
198 
202 static struct GNUNET_CADET_Handle *cadet;
203 
208 
209 
218 static struct Channel *
219 find_channel_by_line(struct Line *line, uint32_t cid)
220 {
221  for (struct Channel *ch = line->channel_head; NULL != ch; ch = ch->next)
222  if (cid == ch->cid)
223  return ch;
224  return NULL;
225 }
226 
227 
234 static void
236  const struct ClientPhonePickupMessage *msg)
237 {
238  struct Line *line = cls;
239  struct CadetPhonePickupMessage *mppm;
240  struct GNUNET_MQ_Envelope *env;
241  struct Channel *ch;
242 
243  if (NULL == line->port)
244  {
245  /* we never opened the port, bad client! */
246  GNUNET_break_op(0);
248  return;
249  }
250  for (ch = line->channel_head; NULL != ch; ch = ch->next)
251  if (msg->cid == ch->cid)
252  break;
253  if (NULL == ch)
254  {
255  /* could have been destroyed asynchronously, ignore message */
256  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid);
258  return;
259  }
260  switch (ch->status)
261  {
262  case CS_CALLEE_INIT:
263  GNUNET_break(0);
265  return;
266 
267  case CS_CALLEE_RINGING:
269  break;
270 
271  case CS_CALLEE_CONNECTED:
272  GNUNET_break(0);
274  return;
275 
276  case CS_CALLEE_SHUTDOWN:
278  "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
279  break;
280 
281  case CS_CALLER_CALLING:
282  case CS_CALLER_CONNECTED:
283  case CS_CALLER_SHUTDOWN:
284  GNUNET_break(0);
286  return;
287  }
289  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending PICK_UP message to cadet\n");
290  env =
292  GNUNET_MQ_send(ch->mq, env);
294 }
295 
296 
303 static void
305 {
306  struct Line *line = ch->line;
307  struct GNUNET_MQ_Envelope *env;
308  struct ClientPhoneHangupMessage *hup;
309 
310  switch (ch->status)
311  {
312  case CS_CALLEE_INIT:
313  case CS_CALLEE_SHUTDOWN:
314  case CS_CALLER_SHUTDOWN:
315  break;
316 
317  case CS_CALLEE_RINGING:
318  case CS_CALLEE_CONNECTED:
319  case CS_CALLER_CALLING:
320  case CS_CALLER_CONNECTED:
321  if (NULL != line)
322  {
323  env =
325  hup->cid = ch->cid;
326  GNUNET_MQ_send(line->mq, env);
327  }
328  break;
329  }
330  if (NULL != line)
332  GNUNET_free(ch);
333 }
334 
335 
341 static void
343 {
344  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Destroying cadet channels\n");
345  if (NULL != ch->channel)
346  {
348  ch->channel = NULL;
349  }
350  clean_up_channel(ch);
351 }
352 
353 
360 static void
362 {
363  struct Channel *ch = cls;
364 
365  switch (ch->status)
366  {
367  case CS_CALLEE_INIT:
368  GNUNET_break(0);
369  break;
370 
371  case CS_CALLEE_RINGING:
372  GNUNET_break(0);
373  break;
374 
375  case CS_CALLEE_CONNECTED:
376  GNUNET_break(0);
377  break;
378 
379  case CS_CALLEE_SHUTDOWN:
381  break;
382 
383  case CS_CALLER_CALLING:
384  GNUNET_break(0);
385  break;
386 
387  case CS_CALLER_CONNECTED:
388  GNUNET_break(0);
389  break;
390 
391  case CS_CALLER_SHUTDOWN:
393  break;
394  }
395 }
396 
397 
404 static void
406  const struct ClientPhoneHangupMessage *msg)
407 {
408  struct Line *line = cls;
409  struct GNUNET_MQ_Envelope *e;
410  struct CadetPhoneHangupMessage *mhum;
411  struct Channel *ch;
412 
413  for (ch = line->channel_head; NULL != ch; ch = ch->next)
414  if (msg->cid == ch->cid)
415  break;
416  if (NULL == ch)
417  {
418  /* could have been destroyed asynchronously, ignore message */
419  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid);
421  return;
422  }
424  "Received HANGUP for channel %u which is in state %d\n",
425  msg->cid,
426  ch->status);
427  switch (ch->status)
428  {
429  case CS_CALLEE_INIT:
430  GNUNET_break(0);
432  return;
433 
434  case CS_CALLEE_RINGING:
436  break;
437 
438  case CS_CALLEE_CONNECTED:
440  break;
441 
442  case CS_CALLEE_SHUTDOWN:
443  /* maybe the other peer closed asynchronously... */
445  return;
446 
447  case CS_CALLER_CALLING:
449  break;
450 
451  case CS_CALLER_CONNECTED:
453  break;
454 
455  case CS_CALLER_SHUTDOWN:
456  /* maybe the other peer closed asynchronously... */
458  return;
459  }
460  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending HANG_UP message via cadet\n");
461  e =
464  GNUNET_MQ_send(ch->mq, e);
466 }
467 
468 
475 static void
477  const struct ClientPhoneSuspendMessage *msg)
478 {
479  struct Line *line = cls;
480  struct GNUNET_MQ_Envelope *e;
481  struct CadetPhoneSuspendMessage *mhum;
482  struct Channel *ch;
483 
484  for (ch = line->channel_head; NULL != ch; ch = ch->next)
485  if (msg->cid == ch->cid)
486  break;
487  if (NULL == ch)
488  {
489  /* could have been destroyed asynchronously, ignore message */
490  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid);
492  return;
493  }
494  if (GNUNET_YES == ch->suspended_local)
495  {
496  GNUNET_break(0);
498  return;
499  }
501  "Received SUSPEND for channel %u which is in state %d\n",
502  msg->cid,
503  ch->status);
504  switch (ch->status)
505  {
506  case CS_CALLEE_INIT:
507  GNUNET_break(0);
509  return;
510 
511  case CS_CALLEE_RINGING:
512  GNUNET_break(0);
514  return;
515 
516  case CS_CALLEE_CONNECTED:
518  break;
519 
520  case CS_CALLEE_SHUTDOWN:
521  /* maybe the other peer closed asynchronously... */
523  return;
524 
525  case CS_CALLER_CALLING:
526  GNUNET_break(0);
528  return;
529 
530  case CS_CALLER_CONNECTED:
532  break;
533 
534  case CS_CALLER_SHUTDOWN:
535  /* maybe the other peer closed asynchronously... */
537  return;
538  }
539  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending SUSPEND message via cadet\n");
540  e =
542  GNUNET_MQ_send(ch->mq, e);
544 }
545 
546 
553 static void
555  const struct ClientPhoneResumeMessage *msg)
556 {
557  struct Line *line = cls;
558  struct GNUNET_MQ_Envelope *e;
559  struct CadetPhoneResumeMessage *mhum;
560  struct Channel *ch;
561 
562  for (ch = line->channel_head; NULL != ch; ch = ch->next)
563  if (msg->cid == ch->cid)
564  break;
565  if (NULL == ch)
566  {
567  /* could have been destroyed asynchronously, ignore message */
568  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid);
570  return;
571  }
572  if (GNUNET_YES != ch->suspended_local)
573  {
574  GNUNET_break(0);
576  return;
577  }
579  "Received RESUME for channel %u which is in state %d\n",
580  msg->cid,
581  ch->status);
582  switch (ch->status)
583  {
584  case CS_CALLEE_INIT:
585  GNUNET_break(0);
587  return;
588 
589  case CS_CALLEE_RINGING:
590  GNUNET_break(0);
592  return;
593 
594  case CS_CALLEE_CONNECTED:
596  break;
597 
598  case CS_CALLEE_SHUTDOWN:
599  /* maybe the other peer closed asynchronously... */
601  return;
602 
603  case CS_CALLER_CALLING:
604  GNUNET_break(0);
606  return;
607 
608  case CS_CALLER_CONNECTED:
610  break;
611 
612  case CS_CALLER_SHUTDOWN:
613  /* maybe the other peer closed asynchronously... */
615  return;
616  }
617  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending RESUME message via cadet\n");
619  GNUNET_MQ_send(ch->mq, e);
621 }
622 
623 
629 static void
631 {
632  struct Channel *ch = cls;
633 
634  ch->env = NULL;
635 }
636 
637 
645 static int
647 {
648  (void)cls;
649  (void)msg;
650  return GNUNET_OK;
651 }
652 
653 
660 static void
662 {
663  struct Line *line = cls;
664  struct CadetAudioMessage *mam;
665  struct Channel *ch;
666  size_t size;
667 
668  size = ntohs(msg->header.size) - sizeof(struct ClientAudioMessage);
669  ch = find_channel_by_line(line, msg->cid);
670  if (NULL == ch)
671  {
672  /* could have been destroyed asynchronously, ignore message */
673  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid);
675  return;
676  }
677 
678  switch (ch->status)
679  {
680  case CS_CALLEE_INIT:
681  case CS_CALLEE_RINGING:
682  case CS_CALLER_CALLING:
683  GNUNET_break(0);
685  return;
686 
687  case CS_CALLEE_CONNECTED:
688  case CS_CALLER_CONNECTED:
689  /* common case, handled below */
690  break;
691 
692  case CS_CALLEE_SHUTDOWN:
693  case CS_CALLER_SHUTDOWN:
695  "Cadet audio channel in shutdown; audio data dropped\n");
697  return;
698  }
699  if (GNUNET_YES == ch->suspended_local)
700  {
702  "This channel is suspended locally\n");
704  return;
705  }
706  if (NULL != ch->env)
707  {
708  /* NOTE: we may want to not do this and instead combine the data */
710  "Bandwidth insufficient; dropping previous audio data segment\n");
712  ch->env = NULL;
713  }
714 
716  "Received %u bytes of AUDIO data from client CID %u\n",
717  (unsigned int)size,
718  msg->cid);
719  ch->env = GNUNET_MQ_msg_extra(mam,
720  size,
722  GNUNET_memcpy(&mam[1], &msg[1], size);
723  /* FIXME: set options for unreliable transmission */
725  GNUNET_MQ_send(ch->mq, ch->env);
727 }
728 
729 
736 static void
738 {
739  struct Channel *ch = cls;
740  struct Line *line = ch->line;
741  struct GNUNET_MQ_Envelope *env;
742  struct ClientPhoneRingMessage *cring;
743  struct CadetPhoneRingInfoPS rs;
744 
746  rs.purpose.size = htonl(sizeof(struct CadetPhoneRingInfoPS));
747  rs.line_port = line->line_port;
750 
751  if (GNUNET_OK !=
753  &rs.purpose,
754  &msg->signature,
755  &msg->caller_id))
756  {
757  GNUNET_break_op(0);
759  return;
760  }
763  .rel_value_us)
764  {
765  /* ancient call, replay? */
766  GNUNET_break_op(0);
767  /* Note that our reliance on time here is awkward; better would be
768  to use a more complex challenge-response protocol against
769  replay attacks. Left for future work ;-). */
771  return;
772  }
773  if (CS_CALLEE_INIT != ch->status)
774  {
775  GNUNET_break_op(0);
777  return;
778  }
782  cring->cid = ch->cid;
783  cring->caller_id = msg->caller_id;
785  "Sending RING message to client. CID is %u\n",
786  (unsigned int)ch->cid);
787  GNUNET_MQ_send(line->mq, env);
788 }
789 
790 
797 static void
799  const struct CadetPhoneHangupMessage *message)
800 {
801  struct Channel *ch = cls;
802  struct Line *line = ch->line;
803  struct GNUNET_MQ_Envelope *env;
804  struct ClientPhoneHangupMessage *hup;
805  enum ChannelStatus status;
806  uint32_t cid;
807 
808  (void)message;
810  cid = ch->cid;
811  status = ch->status;
813  switch (status)
814  {
815  case CS_CALLEE_INIT:
816  GNUNET_break_op(0);
817  return;
818 
819  case CS_CALLEE_RINGING:
820  case CS_CALLEE_CONNECTED:
821  break;
822 
823  case CS_CALLEE_SHUTDOWN:
824  return;
825 
826  case CS_CALLER_CALLING:
827  case CS_CALLER_CONNECTED:
828  break;
829 
830  case CS_CALLER_SHUTDOWN:
831  return;
832  }
833  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending HANG UP message to client\n");
835  hup->cid = cid;
836  GNUNET_MQ_send(line->mq, env);
837 }
838 
839 
846 static void
848  const struct CadetPhonePickupMessage *message)
849 {
850  struct Channel *ch = cls;
851  struct Line *line = ch->line;
852  struct GNUNET_MQ_Envelope *env;
853  struct ClientPhonePickedupMessage *pick;
854 
855  (void)message;
857  switch (ch->status)
858  {
859  case CS_CALLEE_INIT:
860  case CS_CALLEE_RINGING:
861  case CS_CALLEE_CONNECTED:
862  GNUNET_break_op(0);
864  return;
865 
866  case CS_CALLEE_SHUTDOWN:
867  GNUNET_break_op(0);
869  return;
870 
871  case CS_CALLER_CALLING:
873  break;
874 
875  case CS_CALLER_CONNECTED:
876  GNUNET_break_op(0);
877  return;
878 
879  case CS_CALLER_SHUTDOWN:
880  GNUNET_break_op(0);
882  return;
883  }
884  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending PICKED UP message to client\n");
885  env =
887  pick->cid = ch->cid;
888  GNUNET_MQ_send(line->mq, env);
889 }
890 
891 
898 static void
900  const struct CadetPhoneSuspendMessage *message)
901 {
902  struct Channel *ch = cls;
903  struct Line *line = ch->line;
904  struct GNUNET_MQ_Envelope *env;
905  struct ClientPhoneSuspendMessage *suspend;
906 
907  (void)message;
909  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Suspending channel CID: %u\n", ch->cid);
910  switch (ch->status)
911  {
912  case CS_CALLEE_INIT:
913  GNUNET_break_op(0);
914  break;
915 
916  case CS_CALLEE_RINGING:
917  GNUNET_break_op(0);
918  break;
919 
920  case CS_CALLEE_CONNECTED:
922  break;
923 
924  case CS_CALLEE_SHUTDOWN:
925  return;
926 
927  case CS_CALLER_CALLING:
928  GNUNET_break_op(0);
929  break;
930 
931  case CS_CALLER_CONNECTED:
933  break;
934 
935  case CS_CALLER_SHUTDOWN:
936  return;
937  }
938  env =
940  suspend->cid = ch->cid;
941  GNUNET_MQ_send(line->mq, env);
942 }
943 
944 
951 static void
953  const struct CadetPhoneResumeMessage *msg)
954 {
955  struct Channel *ch = cls;
956  struct Line *line;
957  struct GNUNET_MQ_Envelope *env;
958  struct ClientPhoneResumeMessage *resume;
959 
960  (void)msg;
961  line = ch->line;
963  if (GNUNET_YES != ch->suspended_remote)
964  {
965  GNUNET_log(
967  "RESUME message received for non-suspended channel, dropping channel.\n");
969  return;
970  }
971  switch (ch->status)
972  {
973  case CS_CALLEE_INIT:
974  GNUNET_break(0);
975  break;
976 
977  case CS_CALLEE_RINGING:
978  GNUNET_break(0);
979  break;
980 
981  case CS_CALLEE_CONNECTED:
983  break;
984 
985  case CS_CALLEE_SHUTDOWN:
986  return;
987 
988  case CS_CALLER_CALLING:
989  GNUNET_break(0);
990  break;
991 
992  case CS_CALLER_CONNECTED:
994  break;
995 
996  case CS_CALLER_SHUTDOWN:
997  return;
998  }
999  env =
1001  resume->cid = ch->cid;
1002  GNUNET_MQ_send(line->mq, env);
1003 }
1004 
1005 
1013 static int
1015 {
1016  (void)cls;
1017  (void)msg;
1018  return GNUNET_OK; /* any payload is fine */
1019 }
1020 
1021 
1028 static void
1030 {
1031  struct Channel *ch = cls;
1032  size_t msize = ntohs(msg->header.size) - sizeof(struct CadetAudioMessage);
1033  struct GNUNET_MQ_Envelope *env;
1034  struct ClientAudioMessage *cam;
1035 
1037  if ((GNUNET_YES == ch->suspended_local) ||
1038  (GNUNET_YES == ch->suspended_remote))
1039  {
1040  GNUNET_log(
1042  "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n",
1043  (unsigned int)msize,
1044  ch->cid);
1045  return;
1046  }
1048  "Forwarding %u bytes of AUDIO data to client CID %u\n",
1049  (unsigned int)msize,
1050  ch->cid);
1051  env =
1053  cam->cid = ch->cid;
1054  GNUNET_memcpy(&cam[1], &msg[1], msize);
1055  GNUNET_MQ_send(ch->line->mq, env);
1056 }
1057 
1058 
1066 static void
1067 inbound_end(void *cls, const struct GNUNET_CADET_Channel *channel)
1068 {
1069  struct Channel *ch = cls;
1070 
1071  GNUNET_assert(channel == ch->channel);
1072  ch->channel = NULL;
1074  "Channel destroyed by CADET in state %d\n",
1075  ch->status);
1076  clean_up_channel(ch);
1077 }
1078 
1079 
1086 static void
1088 {
1089  struct Line *line = cls;
1090  struct Channel *ch = GNUNET_new(struct Channel);
1091  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1092  { GNUNET_MQ_hd_fixed_size(cadet_hangup_message,
1094  struct CadetPhoneHangupMessage,
1095  ch),
1096  GNUNET_MQ_hd_fixed_size(cadet_pickup_message,
1098  struct CadetPhonePickupMessage,
1099  ch),
1100  GNUNET_MQ_hd_fixed_size(cadet_suspend_message,
1102  struct CadetPhoneSuspendMessage,
1103  ch),
1104  GNUNET_MQ_hd_fixed_size(cadet_resume_message,
1106  struct CadetPhoneResumeMessage,
1107  ch),
1108  GNUNET_MQ_hd_var_size(cadet_audio_message,
1110  struct CadetAudioMessage,
1111  ch),
1113  struct GNUNET_MQ_Envelope *e;
1114  struct CadetPhoneRingMessage *ring;
1115  struct CadetPhoneRingInfoPS rs;
1116 
1117  line->line_port = msg->line_port;
1119  rs.purpose.size = htonl(sizeof(struct CadetPhoneRingInfoPS));
1120  rs.line_port = line->line_port;
1121  rs.target_peer = msg->target;
1122  rs.expiration_time =
1124  ch->line = line;
1126  ch->status = CS_CALLER_CALLING;
1128  ch,
1129  &msg->target,
1130  &msg->line_port,
1131  NULL,
1132  &inbound_end,
1133  cadet_handlers);
1134  ch->mq = GNUNET_CADET_get_mq(ch->channel);
1137  ring->expiration_time = rs.expiration_time;
1139  &rs.purpose,
1140  &ring->signature));
1141  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending RING message via CADET\n");
1142  GNUNET_MQ_send(ch->mq, e);
1144 }
1145 
1146 
1156 static void *
1158  struct GNUNET_CADET_Channel *channel,
1159  const struct GNUNET_PeerIdentity *initiator)
1160 {
1161  struct Line *line = cls;
1162  struct Channel *ch;
1163 
1164  (void)initiator;
1166  "Received incoming cadet channel on line %p\n",
1167  line);
1168  ch = GNUNET_new(struct Channel);
1169  ch->status = CS_CALLEE_INIT;
1170  ch->line = line;
1171  ch->channel = channel;
1172  ch->mq = GNUNET_CADET_get_mq(ch->channel);
1173  ch->cid = line->cid_gen++;
1175  return ch;
1176 }
1177 
1178 
1187 static void *
1189  struct GNUNET_SERVICE_Client *client,
1190  struct GNUNET_MQ_Handle *mq)
1191 {
1192  struct Line *line;
1193 
1194  (void)cls;
1195  line = GNUNET_new(struct Line);
1196  line->client = client;
1197  line->mq = mq;
1198  return line;
1199 }
1200 
1201 
1209 static void
1211  struct GNUNET_SERVICE_Client *client,
1212  void *app_ctx)
1213 {
1214  struct Line *line = app_ctx;
1215  struct Channel *chn;
1216 
1217  (void)cls;
1218  (void)client;
1219  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, closing line\n");
1220  if (NULL != line->port)
1221  {
1223  line->port = NULL;
1224  }
1225  for (struct Channel *ch = line->channel_head; NULL != ch; ch = chn)
1226  {
1227  chn = ch->next;
1228  ch->line = NULL;
1230  }
1231  GNUNET_free(line);
1232 }
1233 
1234 
1241 static void
1243  const struct ClientPhoneRegisterMessage *msg)
1244 {
1245  struct Line *line = cls;
1246  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1247  { GNUNET_MQ_hd_fixed_size(cadet_ring_message,
1249  struct CadetPhoneRingMessage,
1250  NULL),
1251  GNUNET_MQ_hd_fixed_size(cadet_hangup_message,
1253  struct CadetPhoneHangupMessage,
1254  NULL),
1255  GNUNET_MQ_hd_fixed_size(cadet_pickup_message,
1257  struct CadetPhonePickupMessage,
1258  NULL),
1259  GNUNET_MQ_hd_fixed_size(cadet_suspend_message,
1261  struct CadetPhoneSuspendMessage,
1262  NULL),
1263  GNUNET_MQ_hd_fixed_size(cadet_resume_message,
1265  struct CadetPhoneResumeMessage,
1266  NULL),
1267  GNUNET_MQ_hd_var_size(cadet_audio_message,
1269  struct CadetAudioMessage,
1270  NULL),
1272 
1273  line->line_port = msg->line_port;
1274  line->port = GNUNET_CADET_open_port(cadet,
1275  &msg->line_port,
1276  &inbound_channel,
1277  line,
1278  NULL,
1279  &inbound_end,
1280  cadet_handlers);
1281  if (NULL == line->port)
1282  {
1284  _("Could not open line, port %s already in use!\n"),
1285  GNUNET_h2s(&msg->line_port));
1287  return;
1288  }
1290 }
1291 
1292 
1298 static void
1300 {
1301  (void)cls;
1302  if (NULL != cadet)
1303  {
1304  GNUNET_CADET_disconnect(cadet);
1305  cadet = NULL;
1306  }
1307 }
1308 
1309 
1317 static void
1318 run(void *cls,
1319  const struct GNUNET_CONFIGURATION_Handle *c,
1321 {
1322  (void)cls;
1323  (void)service;
1324  cfg = c;
1327  cadet = GNUNET_CADET_connect(cfg);
1328  if (NULL == cadet)
1329  {
1330  GNUNET_break(0);
1332  return;
1333  }
1335 }
1336 
1337 
1342  "conversation",
1344  &run,
1347  NULL,
1348  GNUNET_MQ_hd_fixed_size(client_register_message,
1351  NULL),
1352  GNUNET_MQ_hd_fixed_size(client_pickup_message,
1354  struct ClientPhonePickupMessage,
1355  NULL),
1356  GNUNET_MQ_hd_fixed_size(client_suspend_message,
1359  NULL),
1360  GNUNET_MQ_hd_fixed_size(client_resume_message,
1362  struct ClientPhoneResumeMessage,
1363  NULL),
1364  GNUNET_MQ_hd_fixed_size(client_hangup_message,
1366  struct ClientPhoneHangupMessage,
1367  NULL),
1368  GNUNET_MQ_hd_fixed_size(client_call_message,
1370  struct ClientCallMessage,
1371  NULL),
1372  GNUNET_MQ_hd_var_size(client_audio_message,
1374  struct ClientAudioMessage,
1375  NULL),
1377 
1378 
1379 /* end of gnunet-service-conversation.c */
static void inbound_end(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called whenever an inbound channel is destroyed.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
uint32_t cid
CID, internal caller ID to identify which active call we are talking about.
Definition: conversation.h:138
Client -> Service message to call a phone.
Definition: conversation.h:199
struct Channel * prev
This is a DLL.
static struct GNUNET_CADET_Handle * cadet
Handle for cadet.
ChannelStatus
The possible connection status.
enum ChannelStatus status
Current status of this line.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:838
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
Cadet message to make a phone ring.
Definition: conversation.h:277
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
uint64_t rel_value_us
The actual value.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Main function that will be run by the scheduler.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
int GNUNET_CRYPTO_ecdsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EcdsaSignature *sig, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Verify ECDSA signature.
Definition: crypto_ecc.c:1048
static void handle_client_hangup_message(void *cls, const struct ClientPhoneHangupMessage *msg)
Function to handle a hangup request message from the client.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
#define RING_TIMEOUT
How long is our signature on a call valid? Needs to be long enough for time zone differences and netw...
Opaque handle to the service.
Definition: cadet_api.c:38
Handle to a service.
Definition: service.c:114
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
static int check_cadet_audio_message(void *cls, const struct CadetAudioMessage *msg)
Function to check an audio message incoming over cadet.
struct GNUNET_CRYPTO_EcdsaPublicKey caller_id
Who is calling us?
Definition: conversation.h:104
constants for network protocols
static void handle_cadet_resume_message(void *cls, const struct CadetPhoneResumeMessage *msg)
Function to handle a resume message incoming over cadet.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL
Client <- Server message to indicate a ringing phone.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
static void handle_cadet_pickup_message(void *cls, const struct CadetPhonePickupMessage *message)
Function to handle a pickup message incoming over cadet.
#define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING
Signature of a conversation ring.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
A struct Channel represents a cadet channel, which is a P2P connection to another conversation servic...
Information signed in a struct CadetPhoneRingMessage whereby the caller self-identifies to the receiv...
Definition: conversation.h:249
struct GNUNET_PeerIdentity target_peer
Which peer is the call for?
Definition: conversation.h:264
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO.
Definition: conversation.h:356
uint32_t cid
CID, internal caller ID to identify which active call we are talking about.
Definition: conversation.h:173
static void handle_client_audio_message(void *cls, const struct ClientAudioMessage *msg)
Function to handle audio data from the client.
static void handle_cadet_audio_message(void *cls, const struct CadetAudioMessage *msg)
Function to handle an audio message incoming over cadet.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO
Cadet: audio data.
struct GNUNET_PeerIdentity target
Which peer is hosting the line?
Definition: conversation.h:213
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND
Cadet: phone suspended.
static void channel_audio_sent_notify(void *cls)
Transmission of audio data via cadet channel finished.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
static struct Experiment * e
struct GNUNET_CADET_Port * port
Our open port.
Client -> Service message to register a phone.
Definition: conversation.h:68
#define GNUNET_NO
Definition: gnunet_common.h:78
Opaque handle to a channel.
Definition: cadet_api.c:79
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
struct GNUNET_CADET_Channel * channel
Handle for the channel.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP
Cadet: hang up / refuse call.
uint32_t cid_gen
Generator for channel IDs.
struct Channel * channel_tail
This is a DLL.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO
Client <-> Server message to send audio data.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP
Client -> Server message to reject/hangup a call.
Client -> Service pick up phone that is ringing.
Definition: conversation.h:145
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
struct GNUNET_CRYPTO_EcdsaPrivateKey caller_id
Identity of the caller.
Definition: conversation.h:223
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature over a struct CadetPhoneRingInfoPS
Definition: conversation.h:301
We&#39;re in shutdown, sending hangup messages before cleaning up.
static void handle_cadet_ring_message(void *cls, const struct CadetPhoneRingMessage *msg)
Function to handle a ring message incoming over cadet.
We are waiting for the phone to be picked up.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:973
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void handle_client_register_message(void *cls, const struct ClientPhoneRegisterMessage *msg)
Function to register a phone.
static void handle_client_call_message(void *cls, const struct ClientCallMessage *msg)
Function to handle call request from the client.
Handle to a client that is connected to a service.
Definition: service.c:246
int8_t suspended_local
GNUNET_YES if the channel was suspended by the local client.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING
Client <- Server message to indicate a ringing phone.
int GNUNET_CRYPTO_ecdsa_sign(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
ECDSA Sign a given block.
Definition: crypto_ecc.c:931
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
static void clean_up_channel(struct Channel *ch)
Channel went down, notify client and free data structure.
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incomming MQ-based channels.
Definition: cadet_api.c:1007
struct Line * line
Line associated with the channel.
void * cls
Closure for mv and cb.
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore...
Definition: mq.c:772
Client <-> Service hang up phone that may or may not be ringing.
Definition: conversation.h:163
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint32_t cid
Call ID of the corresponding GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL.
Definition: conversation.h:241
static void handle_client_suspend_message(void *cls, const struct ClientPhoneSuspendMessage *msg)
Function to handle a suspend request message from the client.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP
Service -> Client message to notify that phone was picked up.
struct GNUNET_MQ_Envelope * env
Temporary buffer for audio data in the mq.
We just got the connection, but no introduction yet.
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the signature expire?
Definition: conversation.h:269
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP
Cadet: pick up phone (establish audio channel)
Our phone is ringing, waiting for the client to pick up.
static void handle_cadet_hangup_message(void *cls, const struct CadetPhoneHangupMessage *message)
Function to handle a hangup message incoming over cadet.
static void destroy_line_cadet_channels(struct Channel *ch)
Destroy a channel.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME
Cadet: phone resumed.
static struct Channel * find_channel_by_line(struct Line *line, uint32_t cid)
Given a cid, find the corresponding channel given a line.
A 512-bit hashcode.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
Message handler for a specific message type.
static void mq_done_finish_caller_shutdown(void *cls)
We are done signalling shutdown to the other peer.
A struct Line connects a local client with cadet channels.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME
Client <-> Server message to resume connection.
static unsigned int size
Size of the "table".
Definition: peer.c:66
void GNUNET_CRYPTO_ecdsa_key_get_public(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:241
uint32_t cid
CID, internal caller ID number used in the future to identify which active call we are talking about...
Definition: conversation.h:99
struct GNUNET_MQ_Handle * mq
Message queue for client.
Cadet message for phone suspended.
Definition: conversation.h:330
struct GNUNET_HashCode line_port
Phone line / CADET port to register.
Definition: conversation.h:82
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose for the signature, must be GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING.
Definition: conversation.h:254
Service <-> Client message for phone was resumed.
Definition: conversation.h:128
Service -> Client: other peer has picked up the phone, we are now talking.
Definition: conversation.h:231
Handle to a message queue.
Definition: mq.c:84
static void handle_cadet_suspend_message(void *cls, const struct CadetPhoneSuspendMessage *message)
Function to handle a suspend message incoming over cadet.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected.
struct GNUNET_HashCode line_port
Port number we are listening on (to verify signatures).
struct GNUNET_SERVICE_Client * client
Handle to the line client.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_HashCode line_port
Which phone line to call at the peer?
Definition: conversation.h:218
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:951
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER
Client -> Server message to register a phone.
uint32_t cid
CID, internal caller ID to identify which active call we are talking about.
Definition: conversation.h:155
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition: cadet_api.c:1065
configuration data
Definition: configuration.c:83
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING
Cadet: call initiation.
Service -> Client message for phone is ringing.
Definition: conversation.h:89
Cadet message for phone resumed.
Definition: conversation.h:341
static void do_shutdown(void *cls)
Shutdown nicely.
struct Channel * channel_head
This is a DLL.
#define GNUNET_log(kind,...)
Message Client <-> Service to transmit the audio.
Definition: conversation.h:180
static void * inbound_channel(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Method called whenever another peer has added us to a channel the other peer initiated.
static int check_client_audio_message(void *cls, const struct ClientAudioMessage *msg)
Function to check audio data from the client.
Opaque handle to a port.
Definition: cadet_api.c:143
int GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host&#39;s peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
static void handle_client_resume_message(void *cls, const struct ClientPhoneResumeMessage *msg)
Function to handle a resume request message from the client.
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:871
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO.
Definition: conversation.h:184
#define GNUNET_YES
Definition: gnunet_common.h:77
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
Cadet message for hanging up.
Definition: conversation.h:308
We&#39;re in shutdown, sending hangup messages before cleaning up.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND
Client <-> Server message to suspend connection.
static void handle_client_pickup_message(void *cls, const struct ClientPhonePickupMessage *msg)
Function to handle a pickup request message from the client.
GNUNET_SERVICE_MAIN("conversation", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_register_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER, struct ClientPhoneRegisterMessage, NULL), GNUNET_MQ_hd_fixed_size(client_pickup_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP, struct ClientPhonePickupMessage, NULL), GNUNET_MQ_hd_fixed_size(client_suspend_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND, struct ClientPhoneSuspendMessage, NULL), GNUNET_MQ_hd_fixed_size(client_resume_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME, struct ClientPhoneResumeMessage, NULL), GNUNET_MQ_hd_fixed_size(client_hangup_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, struct ClientPhoneHangupMessage, NULL), GNUNET_MQ_hd_fixed_size(client_call_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL, struct ClientCallMessage, NULL), GNUNET_MQ_hd_var_size(client_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, struct ClientAudioMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
struct GNUNET_MQ_Handle * mq
Message queue for control messages.
Service <-> Client message for phone was suspended.
Definition: conversation.h:111
Cadet message for picking up.
Definition: conversation.h:319
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:655
void GNUNET_MQ_send_cancel(struct GNUNET_MQ_Envelope *ev)
Cancel sending the message.
Definition: mq.c:913
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:900
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
struct Channel * next
This is a DLL.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP
Client -> Server message to reject/hangup a call.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
int8_t suspended_remote
GNUNET_YES if the channel was suspended by the other peer.
uint32_t cid
CID, internal caller ID to identify which active call we are talking about.
Definition: conversation.h:121
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the signature expire?
Definition: conversation.h:296
Cadet message to transmit the audio.
Definition: conversation.h:352
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_CRYPTO_EcdsaPublicKey caller_id
Who is calling us? (also who is signing).
Definition: conversation.h:291
uint32_t cid
Channel identifier we use for this call with the client.
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected peer.
Definition: cadet_api.c:1116
struct GNUNET_HashCode line_port
Which port did the call go to?
Definition: conversation.h:259
uint32_t cid
CID, internal caller ID to identify which active call we are sending data to.
Definition: conversation.h:190