2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, 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_mesh_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 * The possible connection status
52 * We are waiting for incoming calls.
57 * Our phone is ringing, waiting for the client to pick up.
67 * We're in shutdown, sending hangup messages before cleaning up.
72 * We are waiting for the phone to be picked up.
82 * We're in shutdown, sending hangup messages before cleaning up.
89 * A line connects a local client with a mesh tunnel (or, if it is an
90 * open line, is waiting for a mesh tunnel).
105 * Handle for the reliable tunnel (contol data)
107 struct GNUNET_MESH_Tunnel *tunnel_reliable;
110 * Handle for unreliable tunnel (audio data)
112 struct GNUNET_MESH_Tunnel *tunnel_unreliable;
115 * Transmit handle for pending audio messages
117 struct GNUNET_MESH_TransmitHandle *unreliable_mth;
120 * Message queue for control messages
122 struct GNUNET_MQ_Handle *reliable_mq;
125 * Handle to the line client.
127 struct GNUNET_SERVER_Client *client;
130 * Target of the line, if we are the caller.
132 struct GNUNET_PeerIdentity target;
140 * Remote line number.
142 uint32_t remote_line;
145 * Current status of this line.
147 enum LineStatus status;
155 static const struct GNUNET_CONFIGURATION_Handle *cfg;
158 * Notification context containing all connected clients.
160 static struct GNUNET_SERVER_NotificationContext *nc;
165 static struct GNUNET_MESH_Handle *mesh;
168 * Identity of this peer.
170 static struct GNUNET_PeerIdentity my_identity;
173 * Head of DLL of active lines.
175 static struct Line *lines_head;
178 * Tail of DLL of active lines.
180 static struct Line *lines_tail;
183 * Counter for generating local line numbers.
184 * FIXME: randomize generation in the future
185 * to eliminate information leakage.
187 static uint32_t local_line_cnt;
191 * Function to register a phone.
193 * @param cls closure, NULL
194 * @param client the client from which the message is
195 * @param message the message from the client
198 handle_client_register_message (void *cls,
199 struct GNUNET_SERVER_Client *client,
200 const struct GNUNET_MessageHeader *message)
202 const struct ClientPhoneRegisterMessage *msg;
205 msg = (struct ClientPhoneRegisterMessage *) message;
206 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
210 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
213 line = GNUNET_new (struct Line);
214 line->client = client;
215 GNUNET_SERVER_notification_context_add (nc, client);
216 GNUNET_CONTAINER_DLL_insert (lines_head,
219 line->local_line = ntohl (msg->line);
220 GNUNET_SERVER_client_set_user_context (client, line);
221 GNUNET_SERVER_receive_done (client, GNUNET_OK);
226 * Function to handle a pickup request message from the client
228 * @param cls closure, NULL
229 * @param client the client from which the message is
230 * @param message the message from the client
233 handle_client_pickup_message (void *cls,
234 struct GNUNET_SERVER_Client *client,
235 const struct GNUNET_MessageHeader *message)
237 const struct ClientPhonePickupMessage *msg;
238 struct GNUNET_MQ_Envelope *e;
239 struct MeshPhonePickupMessage *mppm;
244 msg = (struct ClientPhonePickupMessage *) message;
245 meta = (const char *) &msg[1];
246 len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
248 ('\0' != meta[len - 1]) )
253 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
257 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
260 switch (line->status)
262 case LS_CALLEE_LISTEN:
263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264 "Ignoring client's PICKUP message, caller has HUNG UP already\n");
265 GNUNET_SERVER_receive_done (client, GNUNET_OK);
267 case LS_CALLEE_RINGING:
268 line->status = LS_CALLEE_CONNECTED;
270 case LS_CALLEE_CONNECTED:
272 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
274 case LS_CALLEE_SHUTDOWN:
275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276 "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
277 GNUNET_SERVER_receive_done (client, GNUNET_OK);
279 case LS_CALLER_CALLING:
280 case LS_CALLER_CONNECTED:
281 case LS_CALLER_SHUTDOWN:
283 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
286 line->status = LS_CALLEE_CONNECTED;
287 e = GNUNET_MQ_msg_extra (mppm,
289 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP);
290 memcpy (&mppm[1], meta, len);
291 GNUNET_MQ_send (line->reliable_mq, e);
292 GNUNET_SERVER_receive_done (client, GNUNET_OK);
297 * Destroy the mesh tunnels of a line.
299 * @param line line to shutdown tunnels of
302 destroy_line_mesh_tunnels (struct Line *line)
304 if (NULL != line->reliable_mq)
306 GNUNET_MQ_destroy (line->reliable_mq);
307 line->reliable_mq = NULL;
309 if (NULL != line->tunnel_unreliable)
311 GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable);
312 line->tunnel_unreliable = NULL;
314 if (NULL != line->tunnel_reliable)
316 GNUNET_MESH_tunnel_destroy (line->tunnel_reliable);
317 line->tunnel_reliable = NULL;
323 * We are done signalling shutdown to the other peer. Close down
324 * (or reset) the line.
326 * @param cls the `struct Line` to reset/terminate
329 mq_done_finish_caller_shutdown (void *cls)
331 struct Line *line = cls;
333 switch (line->status)
335 case LS_CALLEE_LISTEN:
338 case LS_CALLEE_RINGING:
341 case LS_CALLEE_CONNECTED:
344 case LS_CALLEE_SHUTDOWN:
345 line->status = LS_CALLEE_LISTEN;
346 destroy_line_mesh_tunnels (line);
348 case LS_CALLER_CALLING:
349 line->status = LS_CALLER_SHUTDOWN;
351 case LS_CALLER_CONNECTED:
352 line->status = LS_CALLER_SHUTDOWN;
354 case LS_CALLER_SHUTDOWN:
355 destroy_line_mesh_tunnels (line);
356 GNUNET_CONTAINER_DLL_remove (lines_head,
366 * Function to handle a hangup request message from the client
368 * @param cls closure, NULL
369 * @param client the client from which the message is
370 * @param message the message from the client
373 handle_client_hangup_message (void *cls,
374 struct GNUNET_SERVER_Client *client,
375 const struct GNUNET_MessageHeader *message)
377 const struct ClientPhoneHangupMessage *msg;
378 struct GNUNET_MQ_Envelope *e;
379 struct MeshPhoneHangupMessage *mhum;
384 msg = (struct ClientPhoneHangupMessage *) message;
385 meta = (const char *) &msg[1];
386 len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
388 ('\0' != meta[len - 1]) )
393 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
397 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
400 switch (line->status)
402 case LS_CALLEE_LISTEN:
404 GNUNET_SERVER_receive_done (client, GNUNET_OK);
406 case LS_CALLEE_RINGING:
407 line->status = LS_CALLEE_SHUTDOWN;
409 case LS_CALLEE_CONNECTED:
410 line->status = LS_CALLEE_SHUTDOWN;
412 case LS_CALLEE_SHUTDOWN:
414 GNUNET_SERVER_receive_done (client, GNUNET_OK);
416 case LS_CALLER_CALLING:
417 line->status = LS_CALLER_SHUTDOWN;
419 case LS_CALLER_CONNECTED:
420 line->status = LS_CALLER_SHUTDOWN;
422 case LS_CALLER_SHUTDOWN:
424 GNUNET_SERVER_receive_done (client, GNUNET_OK);
427 e = GNUNET_MQ_msg_extra (mhum,
429 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
430 memcpy (&mhum[1], meta, len);
431 GNUNET_MQ_notify_sent (e,
432 &mq_done_finish_caller_shutdown,
434 GNUNET_MQ_send (line->reliable_mq, e);
435 GNUNET_SERVER_receive_done (client, GNUNET_OK);
440 * Function to handle call request the client
442 * @param cls closure, NULL
443 * @param client the client from which the message is
444 * @param message the message from the client
447 handle_client_call_message (void *cls,
448 struct GNUNET_SERVER_Client *client,
449 const struct GNUNET_MessageHeader *message)
451 const struct ClientCallMessage *msg;
453 struct GNUNET_MQ_Envelope *e;
454 struct MeshPhoneRingMessage *ring;
456 msg = (struct ClientCallMessage *) message;
457 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
460 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
463 line = GNUNET_new (struct Line);
464 line->target = msg->target;
465 GNUNET_CONTAINER_DLL_insert (lines_head,
468 line->remote_line = ntohl (msg->line);
469 line->status = LS_CALLER_CALLING;
470 line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
473 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
476 line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
477 line->local_line = local_line_cnt++;
478 e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
479 ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
480 ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
481 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
482 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
483 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
484 GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
486 ring->remote_line = msg->line;
487 ring->source_line = line->local_line;
488 ring->target = msg->target;
489 ring->source = my_identity;
490 ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
491 GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
494 GNUNET_MQ_send (line->reliable_mq, e);
495 GNUNET_SERVER_client_set_user_context (client, line);
496 GNUNET_SERVER_receive_done (client, GNUNET_OK);
501 * Function to handle audio data from the client
503 * @param cls closure, NULL
504 * @param client the client from which the message is
505 * @param message the message from the client
508 handle_client_audio_message (void *cls,
509 struct GNUNET_SERVER_Client *client,
510 const struct GNUNET_MessageHeader *message)
512 const struct ClientAudioMessage *msg;
514 msg = (struct ClientAudioMessage *) message;
515 GNUNET_break (0); // FIXME
516 GNUNET_SERVER_receive_done (client, GNUNET_OK);
521 * We are done signalling shutdown to the other peer.
522 * Destroy the tunnel.
524 * @param cls the `struct GNUNET_MESH_tunnel` to destroy
527 mq_done_destroy_tunnel (void *cls)
529 struct GNUNET_MESH_Tunnel *tunnel = cls;
531 GNUNET_MESH_tunnel_destroy (tunnel);
536 * Function to handle a ring message incoming over mesh
538 * @param cls closure, NULL
539 * @param tunnel the tunnel over which the message arrived
540 * @param tunnel_ctx the tunnel context, can be NULL
541 * @param message the incoming message
545 handle_mesh_ring_message (void *cls,
546 struct GNUNET_MESH_Tunnel *tunnel,
548 const struct GNUNET_MessageHeader *message)
550 const struct MeshPhoneRingMessage *msg;
552 struct GNUNET_MQ_Envelope *e;
553 struct MeshPhoneBusyMessage *busy;
554 struct ClientPhoneRingMessage cring;
556 msg = (const struct MeshPhoneRingMessage *) message;
557 if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
558 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
559 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
560 sizeof (struct GNUNET_CRYPTO_EccPublicSignKey))) ||
562 GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
568 return GNUNET_SYSERR;
570 for (line = lines_head; NULL != line; line = line->next)
571 if ( (line->local_line == ntohl (msg->remote_line)) &&
572 (LS_CALLEE_LISTEN == line->status) )
576 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
577 _("No available phone for incoming call on line %u, sending BUSY signal\n"),
578 ntohl (msg->remote_line));
579 e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
580 GNUNET_MQ_notify_sent (e,
581 &mq_done_destroy_tunnel,
583 GNUNET_MQ_send (line->reliable_mq, e);
584 GNUNET_MESH_receive_done (tunnel); /* needed? */
587 line->status = LS_CALLEE_RINGING;
588 line->remote_line = ntohl (msg->source_line);
589 line->tunnel_reliable = tunnel;
590 line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
592 cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
593 cring.header.size = htons (sizeof (cring));
594 cring.reserved = htonl (0);
595 cring.caller_id = msg->caller_id;
596 GNUNET_SERVER_notification_context_unicast (nc,
600 GNUNET_MESH_receive_done (tunnel);
606 * Function to handle a hangup message incoming over mesh
608 * @param cls closure, NULL
609 * @param tunnel the tunnel over which the message arrived
610 * @param tunnel_ctx the tunnel context, can be NULL
611 * @param message the incoming message
615 handle_mesh_hangup_message (void *cls,
616 struct GNUNET_MESH_Tunnel *tunnel,
618 const struct GNUNET_MessageHeader *message)
620 struct Line *line = *tunnel_ctx;
621 const struct MeshPhoneHangupMessage *msg;
623 size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage);
624 char buf[len + sizeof (struct ClientPhoneHangupMessage)];
625 struct ClientPhoneHangupMessage *hup;
627 msg = (const struct MeshPhoneHangupMessage *) message;
628 len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage);
629 reason = (const char *) &msg[1];
631 ('\0' != reason[len - 1]) )
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
639 "HANGUP message received for non-existing line, dropping tunnel.\n");
640 return GNUNET_SYSERR;
643 switch (line->status)
645 case LS_CALLEE_LISTEN:
647 return GNUNET_SYSERR;
648 case LS_CALLEE_RINGING:
649 line->status = LS_CALLEE_LISTEN;
650 destroy_line_mesh_tunnels (line);
652 case LS_CALLEE_CONNECTED:
653 line->status = LS_CALLEE_LISTEN;
654 destroy_line_mesh_tunnels (line);
656 case LS_CALLEE_SHUTDOWN:
657 line->status = LS_CALLEE_LISTEN;
658 destroy_line_mesh_tunnels (line);
660 case LS_CALLER_CALLING:
661 line->status = LS_CALLER_SHUTDOWN;
662 mq_done_finish_caller_shutdown (line);
664 case LS_CALLER_CONNECTED:
665 line->status = LS_CALLER_SHUTDOWN;
666 mq_done_finish_caller_shutdown (line);
668 case LS_CALLER_SHUTDOWN:
669 mq_done_finish_caller_shutdown (line);
672 hup = (struct ClientPhoneHangupMessage *) buf;
673 hup->header.size = sizeof (buf);
674 hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
675 memcpy (&hup[1], reason, len);
676 GNUNET_SERVER_notification_context_unicast (nc,
680 GNUNET_MESH_receive_done (tunnel);
686 * Function to handle a pickup message incoming over mesh
688 * @param cls closure, NULL
689 * @param tunnel the tunnel over which the message arrived
690 * @param tunnel_ctx the tunnel context, can be NULL
691 * @param message the incoming message
695 handle_mesh_pickup_message (void *cls,
696 struct GNUNET_MESH_Tunnel *tunnel,
698 const struct GNUNET_MessageHeader *message)
700 const struct MeshPhonePickupMessage *msg;
701 struct Line *line = *tunnel_ctx;
702 const char *metadata;
703 size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage);
704 char buf[len + sizeof (struct ClientPhonePickupMessage)];
705 struct ClientPhonePickupMessage *pick;
707 msg = (const struct MeshPhonePickupMessage *) message;
708 len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage);
709 metadata = (const char *) &msg[1];
711 ('\0' != metadata[len - 1]) )
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719 "PICKUP message received for non-existing line, dropping tunnel.\n");
720 return GNUNET_SYSERR;
722 GNUNET_MESH_receive_done (tunnel);
723 switch (line->status)
725 case LS_CALLEE_LISTEN:
727 return GNUNET_SYSERR;
728 case LS_CALLEE_RINGING:
729 case LS_CALLEE_CONNECTED:
731 destroy_line_mesh_tunnels (line);
732 line->status = LS_CALLEE_LISTEN;
733 return GNUNET_SYSERR;
734 case LS_CALLEE_SHUTDOWN:
736 line->status = LS_CALLEE_LISTEN;
737 destroy_line_mesh_tunnels (line);
739 case LS_CALLER_CALLING:
740 line->status = LS_CALLER_CONNECTED;
742 case LS_CALLER_CONNECTED:
745 case LS_CALLER_SHUTDOWN:
747 mq_done_finish_caller_shutdown (line);
748 return GNUNET_SYSERR;
750 pick = (struct ClientPhonePickupMessage *) buf;
751 pick->header.size = sizeof (buf);
752 pick->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
753 memcpy (&pick[1], metadata, len);
754 GNUNET_SERVER_notification_context_unicast (nc,
758 line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
761 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
769 * Function to handle a busy message incoming over mesh
771 * @param cls closure, NULL
772 * @param tunnel the tunnel over which the message arrived
773 * @param tunnel_ctx the tunnel context, can be NULL
774 * @param message the incoming message
778 handle_mesh_busy_message (void *cls,
779 struct GNUNET_MESH_Tunnel *tunnel,
781 const struct GNUNET_MessageHeader *message)
783 struct Line *line = *tunnel_ctx;
784 struct ClientPhoneBusyMessage busy;
788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
789 "HANGUP message received for non-existing line, dropping tunnel.\n");
790 return GNUNET_SYSERR;
792 busy.header.size = sizeof (busy);
793 busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
794 GNUNET_SERVER_notification_context_unicast (nc,
798 GNUNET_MESH_receive_done (tunnel);
800 switch (line->status)
802 case LS_CALLEE_LISTEN:
804 return GNUNET_SYSERR;
805 case LS_CALLEE_RINGING:
808 case LS_CALLEE_CONNECTED:
811 case LS_CALLEE_SHUTDOWN:
814 case LS_CALLER_CALLING:
815 line->status = LS_CALLER_SHUTDOWN;
816 mq_done_finish_caller_shutdown (line);
818 case LS_CALLER_CONNECTED:
819 line->status = LS_CALLER_SHUTDOWN;
820 mq_done_finish_caller_shutdown (line);
822 case LS_CALLER_SHUTDOWN:
823 mq_done_finish_caller_shutdown (line);
831 * Function to handle an audio message incoming over mesh
833 * @param cls closure, NULL
834 * @param tunnel the tunnel over which the message arrived
835 * @param tunnel_ctx the tunnel context, can be NULL
836 * @param message the incoming message
840 handle_mesh_audio_message (void *cls,
841 struct GNUNET_MESH_Tunnel *tunnel,
843 const struct GNUNET_MessageHeader *message)
845 const struct MeshAudioMessage *msg;
846 struct Line *line = *tunnel_ctx;
847 struct GNUNET_PeerIdentity sender;
848 size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
849 char buf[msize + sizeof (struct ClientAudioMessage)];
850 struct ClientAudioMessage *cam;
852 msg = (const struct MeshAudioMessage *) message;
855 sender = *GNUNET_MESH_tunnel_get_info (tunnel,
856 GNUNET_MESH_OPTION_PEER)->peer;
857 for (line = lines_head; NULL != line; line = line->next)
858 if ( (line->local_line == ntohl (msg->remote_line)) &&
859 (LS_CALLEE_CONNECTED == line->status) &&
860 (0 == memcmp (&line->target,
862 sizeof (struct GNUNET_PeerIdentity))) &&
863 (NULL == line->tunnel_unreliable) )
867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
868 "Received AUDIO data for non-existing line %u, dropping.\n",
869 ntohl (msg->remote_line));
870 return GNUNET_SYSERR;
872 line->tunnel_unreliable = tunnel;
875 cam = (struct ClientAudioMessage *) buf;
876 cam->header.size = htons (sizeof (buf));
877 cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
878 memcpy (&cam[1], &msg[1], msize);
879 GNUNET_SERVER_notification_context_unicast (nc,
883 GNUNET_MESH_receive_done (tunnel);
889 * Method called whenever another peer has added us to a tunnel
890 * the other peer initiated.
893 * @param tunnel new handle to the tunnel
894 * @param initiator peer that started the tunnel
896 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
899 inbound_tunnel (void *cls,
900 struct GNUNET_MESH_Tunnel *tunnel,
901 const struct GNUNET_PeerIdentity *initiator,
904 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
905 _("Received incoming tunnel on port %d\n"),
912 * Function called whenever an inbound tunnel is destroyed. Should clean up
913 * any associated state.
915 * @param cls closure (set from #GNUNET_MESH_connect)
916 * @param tunnel connection to the other end (henceforth invalid)
917 * @param tunnel_ctx place where local state associated
918 * with the tunnel is stored
921 inbound_end (void *cls,
922 const struct GNUNET_MESH_Tunnel *tunnel,
925 struct Line *line = tunnel_ctx;
926 struct ClientPhoneHangupMessage hup;
930 if (line->tunnel_unreliable == tunnel)
932 line->tunnel_unreliable = NULL;
935 hup.header.size = sizeof (hup);
936 hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
937 switch (line->status)
939 case LS_CALLEE_LISTEN:
942 case LS_CALLEE_RINGING:
943 case LS_CALLEE_CONNECTED:
944 GNUNET_SERVER_notification_context_unicast (nc,
948 line->status = LS_CALLEE_LISTEN;
950 case LS_CALLEE_SHUTDOWN:
951 line->status = LS_CALLEE_LISTEN;
952 destroy_line_mesh_tunnels (line);
954 case LS_CALLER_CALLING:
955 case LS_CALLER_CONNECTED:
956 GNUNET_SERVER_notification_context_unicast (nc,
960 destroy_line_mesh_tunnels (line);
961 GNUNET_CONTAINER_DLL_remove (lines_head,
966 case LS_CALLER_SHUTDOWN:
967 destroy_line_mesh_tunnels (line);
968 GNUNET_CONTAINER_DLL_remove (lines_head,
978 * A client disconnected. Remove all of its data structure entries.
980 * @param cls closure, NULL
981 * @param client identification of the client
984 handle_client_disconnect (void *cls,
985 struct GNUNET_SERVER_Client *client)
989 line = GNUNET_SERVER_client_get_user_context (client, struct Line);
992 GNUNET_CONTAINER_DLL_remove (lines_head,
996 GNUNET_SERVER_client_set_user_context (client, NULL);
1003 * @param cls closure, NULL
1004 * @param tc the task context
1007 do_shutdown (void *cls,
1008 const struct GNUNET_SCHEDULER_TaskContext *tc)
1012 GNUNET_MESH_disconnect (mesh);
1017 GNUNET_SERVER_notification_context_destroy (nc);
1024 * Main function that will be run by the scheduler.
1026 * @param cls closure
1027 * @param server server handle
1028 * @param c configuration
1032 struct GNUNET_SERVER_Handle *server,
1033 const struct GNUNET_CONFIGURATION_Handle *c)
1035 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1036 {&handle_client_register_message, NULL,
1037 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
1038 sizeof (struct ClientPhoneRegisterMessage)},
1039 {&handle_client_pickup_message, NULL,
1040 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
1042 {&handle_client_hangup_message, NULL,
1043 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
1045 {&handle_client_call_message, NULL,
1046 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
1048 {&handle_client_audio_message, NULL,
1049 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
1053 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1054 {&handle_mesh_ring_message,
1055 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
1056 sizeof (struct MeshPhoneRingMessage)},
1057 {&handle_mesh_hangup_message,
1058 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
1060 {&handle_mesh_pickup_message,
1061 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
1063 {&handle_mesh_busy_message,
1064 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
1065 sizeof (struct MeshPhoneBusyMessage)},
1066 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
1070 static uint32_t ports[] = {
1071 GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
1072 GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
1077 GNUNET_assert (GNUNET_OK ==
1078 GNUNET_CRYPTO_get_host_identity (cfg,
1080 mesh = GNUNET_MESH_connect (cfg,
1090 GNUNET_SCHEDULER_shutdown ();
1093 nc = GNUNET_SERVER_notification_context_create (server, 16);
1094 GNUNET_SERVER_add_handlers (server, server_handlers);
1095 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1096 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1103 * The main function for the conversation service.
1105 * @param argc number of arguments from the command line
1106 * @param argv command line arguments
1107 * @return 0 ok, 1 on error
1113 return (GNUNET_OK ==
1114 GNUNET_SERVICE_run (argc, argv,
1116 GNUNET_SERVICE_OPTION_NONE,
1117 &run, NULL)) ? 0 : 1;
1120 /* end of gnunet-service-conversation.c */