2 This file is part of GNUnet.
3 Copyright (C) 2013, 2016, 2017 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 * @file conversation/gnunet-service-conversation.c
22 * @brief conversation service implementation
23 * @author Simon Dieterle
24 * @author Andreas Fuchs
25 * @author Christian Grothoff
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"
34 #include "gnunet_conversation_service.h"
35 #include "conversation.h"
39 * How long is our signature on a call valid? Needs to be long enough for time zone
40 * differences and network latency to not matter. No strong need for it to be short,
41 * but we simply like all signatures to eventually expire.
43 #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
47 * A line connects a local client with a cadet channel (or, if it is an
48 * open line, is waiting for a cadet channel).
53 * The possible connection status
58 * We just got the connection, but no introduction yet.
63 * Our phone is ringing, waiting for the client to pick up.
73 * We're in shutdown, sending hangup messages before cleaning up.
78 * We are waiting for the phone to be picked up.
88 * We're in shutdown, sending hangup messages before cleaning up.
96 * A `struct Channel` represents a cadet channel, which is a P2P
97 * connection to another conversation service. Multiple channels can
98 * be attached the the same `struct Line`, which represents a local
99 * client. We keep them in a linked list.
107 struct Channel *next;
112 struct Channel *prev;
115 * Line associated with the channel.
120 * Handle for the channel.
122 struct GNUNET_CADET_Channel *channel;
125 * Message queue for control messages
127 struct GNUNET_MQ_Handle *mq;
130 * Temporary buffer for audio data in the @e mq.
132 struct GNUNET_MQ_Envelope *env;
135 * Channel identifier we use for this call with the client.
140 * Current status of this line.
142 enum ChannelStatus status;
145 * #GNUNET_YES if the channel was suspended by the other peer.
147 int8_t suspended_remote;
150 * #GNUNET_YES if the channel was suspended by the local client.
152 int8_t suspended_local;
158 * A `struct Line` connects a local client with cadet channels.
165 struct Channel *channel_head;
170 struct Channel *channel_tail;
173 * Handle to the line client.
175 struct GNUNET_SERVICE_Client *client;
178 * Message queue for @e client.
180 struct GNUNET_MQ_Handle *mq;
185 struct GNUNET_CADET_Port *port;
188 * Port number we are listening on (to verify signatures).
189 * Only valid if @e port is non-NULL.
191 struct GNUNET_HashCode line_port;
194 * Generator for channel IDs.
204 static const struct GNUNET_CONFIGURATION_Handle *cfg;
209 static struct GNUNET_CADET_Handle *cadet;
212 * Identity of this peer.
214 static struct GNUNET_PeerIdentity my_identity;
218 * Given a @a cid, find the corresponding channel given
221 * @param line a line to search
222 * @param cid what to search for
223 * @return NULL for not found
225 static struct Channel *
226 find_channel_by_line (struct Line *line,
229 for (struct Channel *ch = line->channel_head;
239 * Function to handle a pickup request message from the client
241 * @param cls the `struct Line` of the client from which the message is
242 * @param msg the message from the client
245 handle_client_pickup_message (void *cls,
246 const struct ClientPhonePickupMessage *msg)
248 struct Line *line = cls;
249 struct CadetPhonePickupMessage *mppm;
250 struct GNUNET_MQ_Envelope *env;
253 if (NULL == line->port)
255 /* we never opened the port, bad client! */
257 GNUNET_SERVICE_client_drop (line->client);
260 for (ch = line->channel_head; NULL != ch; ch = ch->next)
261 if (msg->cid == ch->cid)
265 /* could have been destroyed asynchronously, ignore message */
266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
267 "Channel %u not found\n",
269 GNUNET_SERVICE_client_continue (line->client);
276 GNUNET_SERVICE_client_drop (line->client);
278 case CS_CALLEE_RINGING:
279 ch->status = CS_CALLEE_CONNECTED;
281 case CS_CALLEE_CONNECTED:
283 GNUNET_SERVICE_client_drop (line->client);
285 case CS_CALLEE_SHUTDOWN:
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
287 "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
289 case CS_CALLER_CALLING:
290 case CS_CALLER_CONNECTED:
291 case CS_CALLER_SHUTDOWN:
293 GNUNET_SERVICE_client_drop (line->client);
296 GNUNET_break (CS_CALLEE_CONNECTED == ch->status);
297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
298 "Sending PICK_UP message to cadet\n");
299 env = GNUNET_MQ_msg (mppm,
300 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP);
301 GNUNET_MQ_send (ch->mq,
303 GNUNET_SERVICE_client_continue (line->client);
310 * @param ch channel to destroy.
313 destroy_line_cadet_channels (struct Channel *ch)
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Destroying cadet channels\n");
317 if (NULL != ch->channel)
318 GNUNET_CADET_channel_destroy (ch->channel);
323 * We are done signalling shutdown to the other peer. Close down
326 * @param cls the `struct Channel` to reset/terminate
329 mq_done_finish_caller_shutdown (void *cls)
331 struct Channel *ch = cls;
338 case CS_CALLEE_RINGING:
341 case CS_CALLEE_CONNECTED:
344 case CS_CALLEE_SHUTDOWN:
345 destroy_line_cadet_channels (ch);
347 case CS_CALLER_CALLING:
350 case CS_CALLER_CONNECTED:
353 case CS_CALLER_SHUTDOWN:
354 destroy_line_cadet_channels (ch);
361 * Function to handle a hangup request message from the client
363 * @param cls the `struct Line` the hangup is for
364 * @param msg the message from the client
367 handle_client_hangup_message (void *cls,
368 const struct ClientPhoneHangupMessage *msg)
370 struct Line *line = cls;
371 struct GNUNET_MQ_Envelope *e;
372 struct CadetPhoneHangupMessage *mhum;
375 for (ch = line->channel_head; NULL != ch; ch = ch->next)
376 if (msg->cid == ch->cid)
380 /* could have been destroyed asynchronously, ignore message */
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382 "Channel %u not found\n",
384 GNUNET_SERVICE_client_continue (line->client);
387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
388 "Received HANGUP for channel %u which is in state %d\n",
395 GNUNET_SERVICE_client_drop (line->client);
397 case CS_CALLEE_RINGING:
398 ch->status = CS_CALLEE_SHUTDOWN;
400 case CS_CALLEE_CONNECTED:
401 ch->status = CS_CALLEE_SHUTDOWN;
403 case CS_CALLEE_SHUTDOWN:
404 /* maybe the other peer closed asynchronously... */
405 GNUNET_SERVICE_client_continue (line->client);
407 case CS_CALLER_CALLING:
408 ch->status = CS_CALLER_SHUTDOWN;
410 case CS_CALLER_CONNECTED:
411 ch->status = CS_CALLER_SHUTDOWN;
413 case CS_CALLER_SHUTDOWN:
414 /* maybe the other peer closed asynchronously... */
415 GNUNET_SERVICE_client_continue (line->client);
418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
419 "Sending HANG_UP message via cadet\n");
420 e = GNUNET_MQ_msg (mhum,
421 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
422 GNUNET_MQ_notify_sent (e,
423 &mq_done_finish_caller_shutdown,
425 GNUNET_MQ_send (ch->mq,
427 GNUNET_SERVICE_client_continue (line->client);
432 * Function to handle a suspend request message from the client
434 * @param cls the `struct Line` the message is about
435 * @param msg the message from the client
438 handle_client_suspend_message (void *cls,
439 const struct ClientPhoneSuspendMessage *msg)
441 struct Line *line = cls;
442 struct GNUNET_MQ_Envelope *e;
443 struct CadetPhoneSuspendMessage *mhum;
446 for (ch = line->channel_head; NULL != ch; ch = ch->next)
447 if (msg->cid == ch->cid)
451 /* could have been destroyed asynchronously, ignore message */
452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
453 "Channel %u not found\n",
455 GNUNET_SERVICE_client_continue (line->client);
458 if (GNUNET_YES == ch->suspended_local)
461 GNUNET_SERVICE_client_drop (line->client);
464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465 "Received SUSPEND for channel %u which is in state %d\n",
472 GNUNET_SERVICE_client_drop (line->client);
474 case CS_CALLEE_RINGING:
476 GNUNET_SERVICE_client_drop (line->client);
478 case CS_CALLEE_CONNECTED:
479 ch->suspended_local = GNUNET_YES;
481 case CS_CALLEE_SHUTDOWN:
482 /* maybe the other peer closed asynchronously... */
483 GNUNET_SERVICE_client_continue (line->client);
485 case CS_CALLER_CALLING:
487 GNUNET_SERVICE_client_drop (line->client);
489 case CS_CALLER_CONNECTED:
490 ch->suspended_local = GNUNET_YES;
492 case CS_CALLER_SHUTDOWN:
493 /* maybe the other peer closed asynchronously... */
494 GNUNET_SERVICE_client_continue (line->client);
497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
498 "Sending SUSPEND message via cadet\n");
499 e = GNUNET_MQ_msg (mhum,
500 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND);
501 GNUNET_MQ_send (ch->mq,
503 GNUNET_SERVICE_client_continue (line->client);
508 * Function to handle a resume request message from the client
510 * @param cls the `struct Line` the message is about
511 * @param msg the message from the client
514 handle_client_resume_message (void *cls,
515 const struct ClientPhoneResumeMessage *msg)
517 struct Line *line = cls;
518 struct GNUNET_MQ_Envelope *e;
519 struct CadetPhoneResumeMessage *mhum;
522 for (ch = line->channel_head; NULL != ch; ch = ch->next)
523 if (msg->cid == ch->cid)
527 /* could have been destroyed asynchronously, ignore message */
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Channel %u not found\n",
531 GNUNET_SERVICE_client_continue (line->client);
534 if (GNUNET_YES != ch->suspended_local)
537 GNUNET_SERVICE_client_drop (line->client);
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
541 "Received RESUME for channel %u which is in state %d\n",
548 GNUNET_SERVICE_client_drop (line->client);
550 case CS_CALLEE_RINGING:
552 GNUNET_SERVICE_client_drop (line->client);
554 case CS_CALLEE_CONNECTED:
555 ch->suspended_local = GNUNET_NO;
557 case CS_CALLEE_SHUTDOWN:
558 /* maybe the other peer closed asynchronously... */
559 GNUNET_SERVICE_client_continue (line->client);
561 case CS_CALLER_CALLING:
563 GNUNET_SERVICE_client_drop (line->client);
565 case CS_CALLER_CONNECTED:
566 ch->suspended_local = GNUNET_NO;
568 case CS_CALLER_SHUTDOWN:
569 /* maybe the other peer closed asynchronously... */
570 GNUNET_SERVICE_client_drop (line->client);
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 "Sending RESUME message via cadet\n");
575 e = GNUNET_MQ_msg (mhum,
576 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME);
577 GNUNET_MQ_send (ch->mq,
579 GNUNET_SERVICE_client_continue (line->client);
584 * Transmission of audio data via cadet channel finished.
586 * @param cls the `struct Channel` we are transmitting for
589 channel_audio_sent_notify (void *cls)
591 struct Channel *ch = cls;
598 * Function to check audio data from the client
600 * @param cls the `struct Line` the message is about
601 * @param msg the message from the client
602 * @return #GNUNET_OK (any data is ok)
605 check_client_audio_message (void *cls,
606 const struct ClientAudioMessage *msg)
613 * Function to handle audio data from the client
615 * @param cls the `struct Line` the message is about
616 * @param msg the message from the client
619 handle_client_audio_message (void *cls,
620 const struct ClientAudioMessage *msg)
622 struct Line *line = cls;
623 struct CadetAudioMessage *mam;
627 size = ntohs (msg->header.size) - sizeof (struct ClientAudioMessage);
628 ch = find_channel_by_line (line,
632 /* could have been destroyed asynchronously, ignore message */
633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
634 "Channel %u not found\n",
636 GNUNET_SERVICE_client_continue (line->client);
643 case CS_CALLEE_RINGING:
644 case CS_CALLER_CALLING:
646 GNUNET_SERVICE_client_drop (line->client);
648 case CS_CALLEE_CONNECTED:
649 case CS_CALLER_CONNECTED:
650 /* common case, handled below */
652 case CS_CALLEE_SHUTDOWN:
653 case CS_CALLER_SHUTDOWN:
654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
655 "Cadet audio channel in shutdown; audio data dropped\n");
656 GNUNET_SERVICE_client_continue (line->client);
659 if (GNUNET_YES == ch->suspended_local)
661 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
662 "This channel is suspended locally\n");
663 GNUNET_SERVICE_client_drop (line->client);
668 /* NOTE: we may want to not do this and instead combine the data */
669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
670 "Bandwidth insufficient; dropping previous audio data segment\n");
671 GNUNET_MQ_send_cancel (ch->env);
675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
676 "Received %u bytes of AUDIO data from client CID %u\n",
679 ch->env = GNUNET_MQ_msg_extra (mam,
681 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO);
682 GNUNET_memcpy (&mam[1],
685 /* FIXME: set options for unreliable transmission */
686 GNUNET_MQ_notify_sent (ch->env,
687 &channel_audio_sent_notify,
689 GNUNET_MQ_send (ch->mq,
691 GNUNET_SERVICE_client_continue (line->client);
696 * Function to handle a ring message incoming over cadet
698 * @param cls closure, NULL
699 * @param msg the incoming message
702 handle_cadet_ring_message (void *cls,
703 const struct CadetPhoneRingMessage *msg)
705 struct Channel *ch = cls;
706 struct Line *line = ch->line;
707 struct GNUNET_MQ_Envelope *env;
708 struct ClientPhoneRingMessage *cring;
709 struct CadetPhoneRingInfoPS rs;
711 rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
712 rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
713 rs.line_port = line->line_port;
714 rs.target_peer = my_identity;
715 rs.expiration_time = msg->expiration_time;
718 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
724 destroy_line_cadet_channels (ch);
727 if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (msg->expiration_time)).rel_value_us)
729 /* ancient call, replay? */
731 /* Note that our reliance on time here is awkward; better would be
732 to use a more complex challenge-response protocol against
733 replay attacks. Left for future work ;-). */
734 destroy_line_cadet_channels (ch);
737 if (CS_CALLEE_INIT != ch->status)
740 destroy_line_cadet_channels (ch);
743 GNUNET_CADET_receive_done (ch->channel);
744 ch->status = CS_CALLEE_RINGING;
745 env = GNUNET_MQ_msg (cring,
746 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
747 cring->cid = ch->cid;
748 cring->caller_id = msg->caller_id;
749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
750 "Sending RING message to client. CID is %u\n",
751 (unsigned int) ch->cid);
752 GNUNET_MQ_send (line->mq,
758 * Function to handle a hangup message incoming over cadet
760 * @param cls closure, our `struct Channel *`
761 * @param message the incoming message
764 handle_cadet_hangup_message (void *cls,
765 const struct CadetPhoneHangupMessage *message)
767 struct Channel *ch = cls;
768 struct Line *line = ch->line;
769 struct GNUNET_MQ_Envelope *env;
770 struct ClientPhoneHangupMessage *hup;
771 enum ChannelStatus status;
774 GNUNET_CADET_receive_done (ch->channel);
777 destroy_line_cadet_channels (ch);
782 destroy_line_cadet_channels (ch);
784 case CS_CALLEE_RINGING:
785 case CS_CALLEE_CONNECTED:
787 case CS_CALLEE_SHUTDOWN:
789 case CS_CALLER_CALLING:
790 case CS_CALLER_CONNECTED:
792 case CS_CALLER_SHUTDOWN:
795 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
796 "Sending HANG UP message to client\n");
797 env = GNUNET_MQ_msg (hup,
798 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
800 GNUNET_MQ_send (line->mq,
806 * Function to handle a pickup message incoming over cadet
808 * @param cls closure, our `struct Channel *`
809 * @param message the incoming message
812 handle_cadet_pickup_message (void *cls,
813 const struct CadetPhonePickupMessage *message)
815 struct Channel *ch = cls;
816 struct Line *line = ch->line;
817 struct GNUNET_MQ_Envelope *env;
818 struct ClientPhonePickedupMessage *pick;
820 GNUNET_CADET_receive_done (ch->channel);
824 case CS_CALLEE_RINGING:
825 case CS_CALLEE_CONNECTED:
827 destroy_line_cadet_channels (ch);
829 case CS_CALLEE_SHUTDOWN:
831 destroy_line_cadet_channels (ch);
833 case CS_CALLER_CALLING:
834 ch->status = CS_CALLER_CONNECTED;
836 case CS_CALLER_CONNECTED:
839 case CS_CALLER_SHUTDOWN:
841 mq_done_finish_caller_shutdown (ch);
844 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
845 "Sending PICKED UP message to client\n");
846 env = GNUNET_MQ_msg (pick,
847 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP);
849 GNUNET_MQ_send (line->mq,
855 * Function to handle a suspend message incoming over cadet
857 * @param cls closure, our `struct Channel *`
858 * @param message the incoming message
861 handle_cadet_suspend_message (void *cls,
862 const struct CadetPhoneSuspendMessage *message)
864 struct Channel *ch = cls;
865 struct Line *line = ch->line;
866 struct GNUNET_MQ_Envelope *env;
867 struct ClientPhoneSuspendMessage *suspend;
869 GNUNET_CADET_receive_done (ch->channel);
870 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
871 "Suspending channel CID: %u\n",
878 case CS_CALLEE_RINGING:
881 case CS_CALLEE_CONNECTED:
882 ch->suspended_remote = GNUNET_YES;
884 case CS_CALLEE_SHUTDOWN:
886 case CS_CALLER_CALLING:
889 case CS_CALLER_CONNECTED:
890 ch->suspended_remote = GNUNET_YES;
892 case CS_CALLER_SHUTDOWN:
895 env = GNUNET_MQ_msg (suspend,
896 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
897 suspend->cid = ch->cid;
898 GNUNET_MQ_send (line->mq,
904 * Function to handle a resume message incoming over cadet
906 * @param cls closure, our `struct Channel *`
907 * @param msg the incoming message
910 handle_cadet_resume_message (void *cls,
911 const struct CadetPhoneResumeMessage *msg)
913 struct Channel *ch = cls;
915 struct GNUNET_MQ_Envelope *env;
916 struct ClientPhoneResumeMessage *resume;
919 GNUNET_CADET_receive_done (ch->channel);
920 if (GNUNET_YES != ch->suspended_remote)
922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
923 "RESUME message received for non-suspended channel, dropping channel.\n");
924 destroy_line_cadet_channels (ch);
932 case CS_CALLEE_RINGING:
935 case CS_CALLEE_CONNECTED:
936 ch->suspended_remote = GNUNET_NO;
938 case CS_CALLEE_SHUTDOWN:
940 case CS_CALLER_CALLING:
943 case CS_CALLER_CONNECTED:
944 ch->suspended_remote = GNUNET_NO;
946 case CS_CALLER_SHUTDOWN:
949 env = GNUNET_MQ_msg (resume,
950 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
951 resume->cid = ch->cid;
952 GNUNET_MQ_send (line->mq,
958 * Function to check an audio message incoming over cadet
960 * @param cls closure, our `struct Channel *`
961 * @param msg the incoming message
962 * @return #GNUNET_OK (always)
965 check_cadet_audio_message (void *cls,
966 const struct CadetAudioMessage *msg)
968 return GNUNET_OK; /* any payload is fine */
973 * Function to handle an audio message incoming over cadet
975 * @param cls closure, our `struct Channel *`
976 * @param msg the incoming message
979 handle_cadet_audio_message (void *cls,
980 const struct CadetAudioMessage *msg)
982 struct Channel *ch = cls;
983 size_t msize = ntohs (msg->header.size) - sizeof (struct CadetAudioMessage);
984 struct GNUNET_MQ_Envelope *env;
985 struct ClientAudioMessage *cam;
987 GNUNET_CADET_receive_done (ch->channel);
988 if ( (GNUNET_YES == ch->suspended_local) ||
989 (GNUNET_YES == ch->suspended_remote) )
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992 "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n",
993 (unsigned int) msize,
997 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
998 "Forwarding %u bytes of AUDIO data to client CID %u\n",
999 (unsigned int) msize,
1001 env = GNUNET_MQ_msg_extra (cam,
1003 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
1005 GNUNET_memcpy (&cam[1],
1008 GNUNET_MQ_send (ch->line->mq,
1014 * Function called whenever an inbound channel is destroyed. Should clean up
1015 * any associated state.
1017 * @param cls closure (set from #GNUNET_CADET_connect)
1018 * @param channel connection to the other end (henceforth invalid)
1021 inbound_end (void *cls,
1022 const struct GNUNET_CADET_Channel *channel)
1024 struct Channel *ch = cls;
1025 struct Line *line = ch->line;
1026 struct GNUNET_MQ_Envelope *env;
1027 struct ClientPhoneHangupMessage *hup;
1029 GNUNET_assert (channel == ch->channel);
1031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1032 "Channel destroyed by CADET in state %d\n",
1036 case CS_CALLEE_INIT:
1037 case CS_CALLEE_SHUTDOWN:
1038 case CS_CALLER_SHUTDOWN:
1040 case CS_CALLEE_RINGING:
1041 case CS_CALLEE_CONNECTED:
1042 case CS_CALLER_CALLING:
1043 case CS_CALLER_CONNECTED:
1046 env = GNUNET_MQ_msg (hup,
1047 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
1049 GNUNET_MQ_send (line->mq,
1055 GNUNET_CONTAINER_DLL_remove (line->channel_head,
1063 * Function to handle call request from the client
1065 * @param cls the `struct Line` the message is about
1066 * @param msg the message from the client
1069 handle_client_call_message (void *cls,
1070 const struct ClientCallMessage *msg)
1072 struct Line *line = cls;
1073 struct Channel *ch = GNUNET_new (struct Channel);
1074 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1075 GNUNET_MQ_hd_fixed_size (cadet_hangup_message,
1076 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP,
1077 struct CadetPhoneHangupMessage,
1079 GNUNET_MQ_hd_fixed_size (cadet_pickup_message,
1080 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP,
1081 struct CadetPhonePickupMessage,
1083 GNUNET_MQ_hd_fixed_size (cadet_suspend_message,
1084 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND,
1085 struct CadetPhoneSuspendMessage,
1087 GNUNET_MQ_hd_fixed_size (cadet_resume_message,
1088 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME,
1089 struct CadetPhoneResumeMessage,
1091 GNUNET_MQ_hd_var_size (cadet_audio_message,
1092 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO,
1093 struct CadetAudioMessage,
1095 GNUNET_MQ_handler_end ()
1097 struct GNUNET_MQ_Envelope *e;
1098 struct CadetPhoneRingMessage *ring;
1099 struct CadetPhoneRingInfoPS rs;
1101 line->line_port = msg->line_port;
1102 rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
1103 rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
1104 rs.line_port = line->line_port;
1105 rs.target_peer = msg->target;
1107 = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
1109 GNUNET_CONTAINER_DLL_insert (line->channel_head,
1112 ch->status = CS_CALLER_CALLING;
1113 ch->channel = GNUNET_CADET_channel_creatE (cadet,
1117 GNUNET_CADET_OPTION_RELIABLE,
1121 ch->mq = GNUNET_CADET_get_mq (ch->channel);
1122 e = GNUNET_MQ_msg (ring,
1123 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING);
1124 GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id,
1126 ring->expiration_time = rs.expiration_time;
1127 GNUNET_assert (GNUNET_OK ==
1128 GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id,
1131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132 "Sending RING message via CADET\n");
1133 GNUNET_MQ_send (ch->mq,
1135 GNUNET_SERVICE_client_continue (line->client);
1140 * Method called whenever another peer has added us to a channel
1141 * the other peer initiated.
1143 * @param cls the `struct Line` receiving a connection
1144 * @param channel new handle to the channel
1145 * @param initiator peer that started the channel
1146 * @return initial channel context for the channel
1149 inbound_channel (void *cls,
1150 struct GNUNET_CADET_Channel *channel,
1151 const struct GNUNET_PeerIdentity *initiator)
1153 struct Line *line = cls;
1156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1157 "Received incoming cadet channel on line %p\n",
1159 ch = GNUNET_new (struct Channel);
1160 ch->status = CS_CALLEE_INIT;
1162 ch->channel = channel;
1163 ch->mq = GNUNET_CADET_get_mq (ch->channel);
1164 ch->cid = line->cid_gen++;
1165 GNUNET_CONTAINER_DLL_insert (line->channel_head,
1173 * A client connected. Initialize the `struct Line` data structure.
1175 * @param cls closure, NULL
1176 * @param client identification of the client
1177 * @param mq message queue for @a client
1178 * @return the `struct Line` for the client
1181 client_connect_cb (void *cls,
1182 struct GNUNET_SERVICE_Client *client,
1183 struct GNUNET_MQ_Handle *mq)
1187 line = GNUNET_new (struct Line);
1188 line->client = client;
1195 * A client disconnected. Remove all of its data structure entries.
1197 * @param cls closure, NULL
1198 * @param client identification of the client
1199 * @param app_ctx our `struct Line *` for @a client
1202 client_disconnect_cb (void *cls,
1203 struct GNUNET_SERVICE_Client *client,
1206 struct Line *line = app_ctx;
1208 struct Channel *chn;
1210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211 "Client disconnected, closing line\n");
1212 if (NULL != line->port)
1214 GNUNET_CADET_close_port (line->port);
1217 for (ch = line->channel_head; NULL != ch; ch = chn)
1221 destroy_line_cadet_channels (ch);
1228 * Function to register a phone.
1230 * @param cls the `struct Line` of the client from which the message is
1231 * @param msg the message from the client
1234 handle_client_register_message (void *cls,
1235 const struct ClientPhoneRegisterMessage *msg)
1237 struct Line *line = cls;
1238 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1239 GNUNET_MQ_hd_fixed_size (cadet_ring_message,
1240 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING,
1241 struct CadetPhoneRingMessage,
1243 GNUNET_MQ_hd_fixed_size (cadet_hangup_message,
1244 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP,
1245 struct CadetPhoneHangupMessage,
1247 GNUNET_MQ_hd_fixed_size (cadet_pickup_message,
1248 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP,
1249 struct CadetPhonePickupMessage,
1251 GNUNET_MQ_hd_fixed_size (cadet_suspend_message,
1252 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND,
1253 struct CadetPhoneSuspendMessage,
1255 GNUNET_MQ_hd_fixed_size (cadet_resume_message,
1256 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME,
1257 struct CadetPhoneResumeMessage,
1259 GNUNET_MQ_hd_var_size (cadet_audio_message,
1260 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO,
1261 struct CadetAudioMessage,
1263 GNUNET_MQ_handler_end ()
1266 line->line_port = msg->line_port;
1267 line->port = GNUNET_CADET_open_porT (cadet,
1274 GNUNET_SERVICE_client_continue (line->client);
1281 * @param cls closure, NULL
1284 do_shutdown (void *cls)
1288 GNUNET_CADET_disconnect (cadet);
1295 * Main function that will be run by the scheduler.
1297 * @param cls closure
1298 * @param c configuration
1299 * @param service service handle
1303 const struct GNUNET_CONFIGURATION_Handle *c,
1304 struct GNUNET_SERVICE_Handle *service)
1307 GNUNET_assert (GNUNET_OK ==
1308 GNUNET_CRYPTO_get_peer_identity (cfg,
1310 cadet = GNUNET_CADET_connecT (cfg);
1314 GNUNET_SCHEDULER_shutdown ();
1317 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1323 * Define "main" method using service macro.
1327 GNUNET_SERVICE_OPTION_NONE,
1330 &client_disconnect_cb,
1332 GNUNET_MQ_hd_fixed_size (client_register_message,
1333 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
1334 struct ClientPhoneRegisterMessage,
1336 GNUNET_MQ_hd_fixed_size (client_pickup_message,
1337 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
1338 struct ClientPhonePickupMessage,
1340 GNUNET_MQ_hd_fixed_size (client_suspend_message,
1341 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
1342 struct ClientPhoneSuspendMessage,
1344 GNUNET_MQ_hd_fixed_size (client_resume_message,
1345 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
1346 struct ClientPhoneResumeMessage,
1348 GNUNET_MQ_hd_fixed_size (client_hangup_message,
1349 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
1350 struct ClientPhoneHangupMessage,
1352 GNUNET_MQ_hd_fixed_size (client_call_message,
1353 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
1354 struct ClientCallMessage,
1356 GNUNET_MQ_hd_var_size (client_audio_message,
1357 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
1358 struct ClientAudioMessage,
1360 GNUNET_MQ_handler_end ());
1363 /* end of gnunet-service-conversation.c */