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
27 * - AUXILIARY FUNCTIONS
28 * - SENDING FUNCTIONS CL -> SERVER
29 * - RECEIVE FUNCTIONS CL -> SERVER
30 * - SENDING FUNCTIONS MESH
31 * - RECEIVE FUNCTIONS MESH
37 #include "gnunet_util_lib.h"
38 #include "gnunet_protocols.h"
39 #include "gnunet_constants.h"
40 #include "gnunet_mesh_service.h"
41 #include "gnunet_conversation_service.h"
42 #include "conversation.h"
47 * The possible connection status
49 enum connection_status
58 /********************************************************
59 * Ugly hack because of not working MESH API
61 typedef uint32_t MESH_TunnelNumber;
62 struct GNUNET_MESH_Tunnel
64 struct GNUNET_MESH_Tunnel *next;
65 struct GNUNET_MESH_Tunnel *prev;
66 struct GNUNET_MESH_Handle *mesh;
67 MESH_TunnelNumber tid;
71 unsigned int packet_size;
81 static const struct GNUNET_CONFIGURATION_Handle *cfg;
84 * Head of the list of current clients.
86 static struct GNUNET_CONTAINER_SList *clients;
89 * Notification context containing all connected clients.
91 struct GNUNET_SERVER_NotificationContext *nc = NULL;
94 * The connection status
96 static struct ConnectionStatus connection;
99 * Handle for the record helper
101 static struct GNUNET_HELPER_Handle *record_helper;
103 /** Handle for the playback handler
106 static struct GNUNET_HELPER_Handle *playback_helper;
111 static struct GNUNET_MESH_Handle *mesh;
114 * Transmit handle for audio messages
116 static struct GNUNET_MESH_TransmitHandle *mth = NULL;
119 * Handle for the reliable tunnel (contol data)
121 static struct GNUNET_MESH_Tunnel *tunnel_reliable;
124 * Handle for unreliable tunnel (audio data)
126 static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
129 * List for missed calls
131 struct GNUNET_CONTAINER_SList *missed_calls;
134 * List for peers to notify that we are available again
136 struct GNUNET_CONTAINER_SList *peers_to_notify;
139 * Audio buffer (outgoing)
141 struct GNUNET_CONTAINER_SList *audio_buffer;
144 * The pointer to the task for sending audio
146 GNUNET_SCHEDULER_TaskIdentifier audio_task;
149 * The pointer to the task for checking timeouts an calling a peer
151 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
154 * Sequencenumber for the pakets (for evaltuation purposes)
156 int SequenceNumber = 0;
159 * Timestamp for call statistics
161 static struct GNUNET_TIME_Absolute start_time;
164 * Number of payload packes sent
166 static int data_sent;
167 static int data_sent_size;
170 * Number of payload packets received
172 static int data_received;
173 static int data_received_size;
177 * Transmit a mesh message
178 * @param cls closure, NULL
179 * @param size number of bytes available in buf
180 * @param buf where the callee should write the error message
181 * @return number of bytes written to buf
183 static size_t transmit_mesh_message (void *cls, size_t size, void *buf);
186 * Function called to send a peer no answer message to the client.
187 * "buf" will be NULL and "size" zero if the socket was closed for writing in
190 * @param cls closure, NULL
191 * @param size number of bytes available in buf
192 * @param buf where the callee should write the peer no answer message
193 * @return number of bytes written to buf
196 transmit_server_no_answer_message (void *cls, size_t size, void *buf);
199 * Task to schedule a audio transmission.
201 * @param cls Closure.
202 * @param tc Task Context.
205 transmit_audio_task (void *cls,
206 const struct GNUNET_SCHEDULER_TaskContext *tc);
209 * Start the audio helpers
211 int start_helpers (void);
214 * Stop the audio helpers
216 void stop_helpers (void);
220 /******************************************************************************/
221 /*********************** AUXILIARY FUNCTIONS *************************/
222 /******************************************************************************/
225 * Function which displays some call stats
230 static struct GNUNET_TIME_Absolute end_time;
231 static struct GNUNET_TIME_Relative total_time;
233 end_time = GNUNET_TIME_absolute_get ();
234 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
235 FPRINTF (stderr, "\nResults of send\n");
236 FPRINTF (stderr, "Test time %s\n",
237 GNUNET_STRINGS_relative_time_to_string (total_time,
239 FPRINTF (stderr, "Test total packets: %d\n",
241 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
242 data_sent_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
243 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
244 data_sent * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
246 FPRINTF (stderr, "\nResults of recv\n");
247 FPRINTF (stderr, "Test time %s\n",
248 GNUNET_STRINGS_relative_time_to_string (total_time,
250 FPRINTF (stderr, "Test total packets: %d\n",
252 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
253 data_received_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
254 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
255 data_received * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
259 * Function which sets the connection state to LISTEN
262 status_to_listen (void)
265 if (CONNECTED == connection.status)
270 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
272 GNUNET_SCHEDULER_cancel (timeout_task);
273 timeout_task = GNUNET_SCHEDULER_NO_TASK;
278 connection.status = LISTEN;
279 connection.client = NULL;
284 data_received_size = 0;
286 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
291 * Function to terminate the active call
297 msg_size = sizeof (struct MeshSessionTerminateMessage);
298 struct MeshSessionTerminateMessage *message_mesh_terminate =
299 (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
301 if (NULL == message_mesh_terminate)
303 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
304 _("Could not create MeshSessionTerminateMessage\n"));
310 message_mesh_terminate->header.size = htons (msg_size);
311 message_mesh_terminate->header.type =
312 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
315 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
316 MAX_TRANSMIT_DELAY, msg_size,
317 &transmit_mesh_message,
318 (void *) message_mesh_terminate))
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 _("Could not queue MeshSessionTerminateMessage\n"));
322 GNUNET_free (message_mesh_terminate);
328 * Function to reject a call
330 * @param tunnel the tunnel where to reject the incoming call
331 * @param reason te reson why the call is rejected
334 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
337 msg_size = sizeof (struct MeshSessionRejectMessage);
338 struct MeshSessionRejectMessage *message_mesh_reject =
339 (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
341 if (NULL == message_mesh_reject)
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 _("Could not create MeshSessionRejectMessage\n"));
350 message_mesh_reject->header.size = htons (msg_size);
351 message_mesh_reject->header.type =
352 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
353 message_mesh_reject->reason = htons (reason);
356 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
357 MAX_TRANSMIT_DELAY, msg_size,
358 &transmit_mesh_message,
359 (void *) message_mesh_reject))
361 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
362 _("Could not queue MeshSessionRejectMessage\n"));
363 GNUNET_free (message_mesh_reject);
369 * Check for timeout when calling a peer
371 * @param cls closure, NULL
372 * @param tc the task context (can be NULL)
375 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
377 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
380 GNUNET_SERVER_notify_transmit_ready (connection.client,
382 ServerClientNoAnswerMessage),
384 &transmit_server_no_answer_message,
387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
388 _("Could not queue ServerClientNoAnswerMessage\n"));
394 /******************************************************************************/
395 /*********************** SENDING FUNCTIONS CL -> SERVER *******************/
396 /******************************************************************************/
399 * Function called to send a session initiate message to the client.
400 * "buf" will be NULL and "size" zero if the socket was closed for writing in
403 * @param cls closure, NULL
404 * @param size number of bytes available in buf
405 * @param buf where the callee should write the initiate message
406 * @return number of bytes written to buf
409 transmit_server_initiate_message (void *cls, size_t size, void *buf)
411 struct ServerClientSessionInitiateMessage *msg;
414 msg_size = sizeof (struct ServerClientSessionInitiateMessage);
416 GNUNET_assert (size >= msg_size);
418 msg = (struct ServerClientSessionInitiateMessage *) buf;
419 msg->header.size = htons (msg_size);
420 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
421 memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
422 sizeof (struct GNUNET_PeerIdentity));
428 * Function called to send a session accept message to the client.
429 * "buf" will be NULL and "size" zero if the socket was closed for writing in
432 * @param cls closure, NULL
433 * @param size number of bytes available in buf
434 * @param buf where the callee should write the accept message
435 * @return number of bytes written to buf
438 transmit_server_accept_message (void *cls, size_t size, void *buf)
440 struct ServerClientSessionAcceptMessage *msg;
443 msg_size = sizeof (struct ServerClientSessionAcceptMessage);
445 GNUNET_assert (size >= msg_size);
447 msg = (struct ServerClientSessionAcceptMessage *) buf;
448 msg->header.size = htons (msg_size);
449 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
455 * Function called to send a session reject message to the client.
456 * "buf" will be NULL and "size" zero if the socket was closed for writing in
459 * @param cls closure, NULL
460 * @param size number of bytes available in buf
461 * @param buf where the callee should write the reject message
462 * @return number of bytes written to buf
465 transmit_server_reject_message (void *cls, size_t size, void *buf)
467 struct ServerClientSessionRejectMessage *msg;
470 msg_size = sizeof (struct ServerClientSessionRejectMessage);
472 GNUNET_assert (size >= msg_size);
474 msg = (struct ServerClientSessionRejectMessage *) buf;
475 msg->header.size = htons (msg_size);
476 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
480 msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE);
484 msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
491 * Function called to send a session terminate message to the client.
492 * "buf" will be NULL and "size" zero if the socket was closed for writing in
495 * @param cls closure, NULL
496 * @param size number of bytes available in buf
497 * @param buf where the callee should write the terminate message
498 * @return number of bytes written to buf
501 transmit_server_terminate_message (void *cls, size_t size, void *buf)
503 struct ServerClientSessionTerminateMessage *msg;
506 msg_size = sizeof (struct ServerClientSessionTerminateMessage);
508 GNUNET_assert (size >= msg_size);
510 msg = (struct ServerClientSessionTerminateMessage *) buf;
511 msg->header.size = htons (msg_size);
512 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
518 * Function called to send a missed call message to the client.
519 * "buf" will be NULL and "size" zero if the socket was closed for writing in
522 * @param cls closure, NULL
523 * @param size number of bytes available in buf
524 * @param buf where the callee should write the missed call message
525 * @return number of bytes written to buf
528 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
530 struct ServerClientMissedCallMessage *msg;
531 msg = (struct ServerClientMissedCallMessage *) cls;
533 memcpy (buf, msg, size);
540 * Function called to send a service blocked message to the client.
541 * "buf" will be NULL and "size" zero if the socket was closed for writing in
544 * @param cls closure, NULL
545 * @param size number of bytes available in buf
546 * @param buf where the callee should write the service blocked message
547 * @return number of bytes written to buf
550 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
552 struct ServerClientServiceBlockedMessage *msg;
555 msg_size = sizeof (struct ServerClientServiceBlockedMessage);
557 GNUNET_assert (size >= msg_size);
559 msg = (struct ServerClientServiceBlockedMessage *) buf;
560 msg->header.size = htons (msg_size);
561 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
567 * Function called to send a peer not connected message to the client.
568 * "buf" will be NULL and "size" zero if the socket was closed for writing in
571 * @param cls closure, NULL
572 * @param size number of bytes available in buf
573 * @param buf where the callee should write the peer not connected message
574 * @return number of bytes written to buf
577 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
579 struct ServerClientPeerNotConnectedMessage *msg;
582 msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
584 GNUNET_assert (size >= msg_size);
586 msg = (struct ServerClientPeerNotConnectedMessage *) buf;
587 msg->header.size = htons (msg_size);
588 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
594 * Function called to send a peer no answer message to the client.
595 * "buf" will be NULL and "size" zero if the socket was closed for writing in
598 * @param cls closure, NULL
599 * @param size number of bytes available in buf
600 * @param buf where the callee should write the peer no answer message
601 * @return number of bytes written to buf
604 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
606 struct ServerClientNoAnswerMessage *msg;
609 msg_size = sizeof (struct ServerClientNoAnswerMessage);
611 GNUNET_assert (size >= msg_size);
613 msg = (struct ServerClientNoAnswerMessage *) buf;
614 msg->header.size = htons (msg_size);
615 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
621 * Function called to send a error message to the client.
622 * "buf" will be NULL and "size" zero if the socket was closed for writing in
625 * @param cls closure, NULL
626 * @param size number of bytes available in buf
627 * @param buf where the callee should write the error message
628 * @return number of bytes written to buf
631 transmit_server_error_message (void *cls, size_t size, void *buf)
633 struct ServerClientErrorMessage *msg;
636 msg_size = sizeof (struct ServerClientErrorMessage);
638 GNUNET_assert (size >= msg_size);
640 msg = (struct ServerClientErrorMessage *) buf;
641 msg->header.size = htons (msg_size);
642 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
647 /******************************************************************************/
648 /*********************** RECEIVE FUNCTIONS CL -> SERVER ********************/
649 /******************************************************************************/
652 * Function to handle a session initiate message from the client
654 * @param cls closure, NULL
655 * @param client the client from which the message is
656 * @param message the message from the client
659 handle_session_initiate_message (void *cls,
660 struct GNUNET_SERVER_Client *client,
661 const struct GNUNET_MessageHeader *message)
663 static uint32_t port = 50002;
665 struct ClientServerSessionInitiateMessage *msg =
666 (struct ClientServerSessionInitiateMessage *) message;
667 struct GNUNET_PeerIdentity *peer = &(msg->peer);
669 GNUNET_SERVER_receive_done (client, GNUNET_OK);
671 if (NULL != connection.client)
673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
674 _("There is already a peer in interaction\n"));
675 GNUNET_SERVER_notify_transmit_ready (client,
677 ServerClientServiceBlockedMessage),
679 &transmit_server_service_blocked_message,
685 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
686 GNUNET_i2s_full (peer));
688 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
689 if (NULL == tunnel_reliable)
691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692 _("Could not create reliable tunnel\n"));
693 GNUNET_SERVER_notify_transmit_ready (client,
695 ServerClientPeerNotConnectedMessage),
697 &transmit_server_peer_not_connected_message,
703 msg_size = sizeof (struct MeshSessionInitiateMessage);
704 struct MeshSessionInitiateMessage *message_mesh_initiate =
705 (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
707 if (NULL == message_mesh_initiate)
709 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
710 _("Could not create MeshSessionInitiateMessage\n"));
711 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
712 tunnel_reliable = NULL;
713 GNUNET_SERVER_notify_transmit_ready (client,
715 ServerClientErrorMessage),
717 &transmit_server_error_message,
723 message_mesh_initiate->header.size = htons (msg_size);
724 message_mesh_initiate->header.type =
725 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
728 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
729 MAX_TRANSMIT_DELAY, msg_size,
730 &transmit_mesh_message,
731 (void *) message_mesh_initiate))
733 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
734 _("Could not queue MeshSessionInitiateMessage\n"));
735 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
736 tunnel_reliable = NULL;
737 GNUNET_free (message_mesh_initiate);
738 GNUNET_SERVER_notify_transmit_ready (client,
740 ServerClientErrorMessage),
742 &transmit_server_error_message,
748 connection.status = CALLER;
749 connection.client = client;
750 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
752 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
758 * Function to handle a session accept message from the client
760 * @param cls closure, NULL
761 * @param client the client from which the message is
762 * @param message the message from the client
765 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
766 const struct GNUNET_MessageHeader *message)
770 GNUNET_SERVER_receive_done (client, GNUNET_OK);
772 if (connection.status != CALLEE)
774 // TODO send illegal command
775 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
777 ("handle_session_accept_message called when not allowed\n"));
781 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
782 GNUNET_i2s_full (&(connection.peer)));
784 msg_size = sizeof (struct MeshSessionAcceptMessage);
785 struct MeshSessionAcceptMessage *message_mesh_accept =
786 (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
788 if (NULL == message_mesh_accept)
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791 _("Could not create MeshSessionAcceptMessage\n"));
795 message_mesh_accept->header.size = htons (msg_size);
796 message_mesh_accept->header.type =
797 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
800 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
801 MAX_TRANSMIT_DELAY, msg_size,
802 &transmit_mesh_message,
803 (void *) message_mesh_accept))
805 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
806 _("Could not queue MeshSessionAcceptMessage\n"));
807 GNUNET_free (message_mesh_accept);
811 connection.status = CONNECTED;
812 connection.client = client;
813 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
820 * Function to handle a session reject message from the client
822 * @param cls closure, NULL
823 * @param client the client from which the message is
824 * @param message the message from the client
827 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
828 const struct GNUNET_MessageHeader *message)
830 struct ClientServerSessionRejectMessage *message_received;
832 GNUNET_SERVER_receive_done (client, GNUNET_OK);
834 if (connection.status != CALLEE)
836 // TODO send illegal command
837 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
839 ("handle_session_reject_message called when not allowed\n"));
843 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"),
844 GNUNET_i2s_full (&(connection.peer)));
845 message_received = (struct ClientServerSessionRejectMessage *) message;
846 reject_call (tunnel_reliable, ntohs (message_received->reason));
852 * Function to handle a session terminate message from the client
854 * @param cls closure, NULL
855 * @param client the client from which the message is
856 * @param message the message from the client
859 handle_session_terminate_message (void *cls,
860 struct GNUNET_SERVER_Client *client,
861 const struct GNUNET_MessageHeader *message)
863 GNUNET_SERVER_receive_done (client, GNUNET_OK);
865 if (connection.client == NULL || connection.status == CALLEE)
867 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
869 ("handle_session_terminate_message called when not allowed\n"));
873 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
874 GNUNET_i2s_full (&(connection.peer)));
878 /******************************************************************************/
879 /*********************** SENDING FUNCTIONS MESH *******************/
880 /******************************************************************************/
883 * Transmit a mesh message
884 * @param cls closure, NULL
885 * @param size number of bytes available in buf
886 * @param buf where the callee should write the message
887 * @return number of bytes written to buf
890 transmit_mesh_message (void *cls, size_t size, void *buf)
892 struct VoIPMeshMessageHeader *msg_header =
893 (struct VoIPMeshMessageHeader *) cls;
894 msg_header->SequenceNumber = SequenceNumber += 1;
895 msg_header->time = GNUNET_TIME_absolute_get ();
897 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
899 memcpy (buf, cls, size);
900 // Check if this is correct
903 if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
904 ntohs (msg_header->header.type))
905 || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
906 ntohs (msg_header->header.type)))
910 else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
911 ntohs (msg_header->header.type))
913 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
915 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
916 (GNUNET_TIME_UNIT_SECONDS, 30),
917 &check_timeout, NULL);
926 * Transmit a audo message over mesh
927 * @param cls closure, NULL
928 * @param size number of bytes available in buf
929 * @param buf where the callee should write the message
930 * @return number of bytes written to buf
933 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
935 struct AudioMessage *message = (struct AudioMessage *) cls;
937 if (size < sizeof (struct AudioMessage) || NULL == buf)
940 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
941 "size %u, buf %p, data_sent %u, data_received %u\n",
942 size, buf, data_sent, data_received);
946 memcpy (buf, message, size);
949 data_sent_size += size;
951 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
953 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
959 * Task to schedule a audio transmission.
961 * @param cls Closure.
962 * @param tc Task Context.
965 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
967 struct GNUNET_CONTAINER_SList_Iterator iterator;
968 struct AudioMessage *msg;
969 int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
971 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
975 if (0 == ab_length && CONNECTED == connection.status)
978 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
979 (GNUNET_TIME_UNIT_MILLISECONDS, 10),
980 &transmit_audio_task, NULL);
984 iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
986 (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
987 msg->SequenceNumber = SequenceNumber += 1;
988 msg->time = GNUNET_TIME_absolute_get ();
990 GNUNET_CONTAINER_slist_erase (&iterator);
991 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
995 msg = (struct AudioMessage *) cls;
998 if (NULL == tunnel_unreliable)
1000 GNUNET_CONTAINER_slist_clear (audio_buffer);
1004 mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
1006 sizeof (struct AudioMessage),
1007 &transmit_mesh_audio_message,
1012 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1013 "Need to retransmit audio packet\n");
1014 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
1016 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1017 &transmit_audio_task, (void *) msg);
1021 /******************************************************************************/
1022 /*********************** RECEIVE FUNCTIONS MESH ********************/
1023 /******************************************************************************/
1026 * Function to handle a initiation messaage incoming over mesh
1027 * @param cls closure, NULL
1028 * @param tunnel the tunnel over which the message arrived
1029 * @param tunnel_ctx the tunnel context, can be NULL
1030 * @param message the incoming message
1035 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1037 const struct GNUNET_MessageHeader *message)
1040 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1041 const struct GNUNET_PeerIdentity *peer =
1042 GNUNET_PEER_resolve2 (tunnel->peer);
1044 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1045 _("Handling MeshSessionInitiateMessage from peer: %s\n"),
1046 GNUNET_i2s_full (peer));
1047 GNUNET_MESH_receive_done (tunnel);
1049 if (LISTEN != connection.status
1050 || 1 > GNUNET_CONTAINER_slist_count (clients))
1053 if (CONNECTED == connection.status)
1055 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1057 ("Rejected call from %s because there is an active call"),
1058 GNUNET_i2s_full (peer));
1059 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_ACTIVE_CALL);
1061 // Notifying client about missed call
1063 sizeof (struct ServerClientMissedCallMessage) +
1064 sizeof (struct MissedCall);
1065 struct ServerClientMissedCallMessage *message =
1066 GNUNET_malloc (msg_size);
1068 message->header.size = htons (msg_size);
1069 message->header.type =
1070 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1071 message->number = 1;
1073 memcpy (&(message->missed_call->peer), peer,
1074 sizeof (struct GNUNET_PeerIdentity));
1075 message->missed_call->time = GNUNET_TIME_absolute_get ();
1078 GNUNET_SERVER_notify_transmit_ready (connection.client,
1080 ServerClientMissedCallMessage),
1082 &transmit_server_missed_call_message,
1085 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087 ("Could not queue ServerClientMissedCallMessage\n"));
1088 GNUNET_free (message);
1092 if (1 > GNUNET_CONTAINER_slist_count (clients))
1094 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1095 _("Got a call from %s while no client connected.\n"),
1096 GNUNET_i2s_full (peer));
1097 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NO_CLIENT);
1098 // Store missed calls
1099 struct MissedCall call;
1100 memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1101 call.time = GNUNET_TIME_absolute_get ();
1102 GNUNET_CONTAINER_slist_add_end (missed_calls,
1103 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1104 &call, sizeof (struct MissedCall));
1108 reject_call (tunnel, reject_reason);
1112 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
1113 GNUNET_i2s_full (peer));
1114 tunnel_reliable = tunnel;
1115 connection.status = CALLEE;
1116 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1117 _("Changed connection status to %d\n"), connection.status);
1118 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1120 struct GNUNET_CONTAINER_SList_Iterator iterator =
1121 GNUNET_CONTAINER_slist_begin (clients);
1124 struct VoipClient *conversation_client =
1125 (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1127 struct GNUNET_SERVER_Client *client = conversation_client->client;
1128 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1132 GNUNET_SERVER_notify_transmit_ready (client,
1134 ServerClientSessionInitiateMessage),
1136 &transmit_server_initiate_message,
1139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1141 ("Could not queue ServerClientSessionInitiateMessage\n"));
1144 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1146 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1148 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1156 * Function to handle an accept messaage incoming over mesh
1157 * @param cls closure, NULL
1158 * @param tunnel the tunnel over which the message arrived
1159 * @param tunnel_ctx the tunnel context, can be NULL
1160 * @param message the incoming message
1165 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1167 const struct GNUNET_MessageHeader *message)
1169 static uint32_t port = 50003;
1170 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1171 const struct GNUNET_PeerIdentity *peer =
1172 GNUNET_PEER_resolve2 (tunnel->peer);
1174 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1176 ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"),
1177 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1178 GNUNET_MESH_receive_done (tunnel);
1181 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1182 && connection.status == CALLER)
1185 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1187 if (NULL == tunnel_unreliable)
1189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1190 _("Could not create unreliable tunnel\n"));
1192 status_to_listen ();
1194 GNUNET_SERVER_notify_transmit_ready (connection.client,
1196 ServerClientSessionRejectMessage),
1198 &transmit_server_reject_message,
1200 return GNUNET_SYSERR;
1203 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1205 GNUNET_SCHEDULER_cancel (timeout_task);
1206 timeout_task = GNUNET_SCHEDULER_NO_TASK;
1209 connection.status = CONNECTED;
1210 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1211 _("Changed connection status to %d\n"), connection.status);
1214 GNUNET_SERVER_notify_transmit_ready (connection.client,
1216 ServerClientSessionAcceptMessage),
1218 &transmit_server_accept_message,
1221 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1223 ("Could not queue ServerClientSessionAcceptMessage\n"));
1224 return GNUNET_SYSERR;
1227 start_time = GNUNET_TIME_absolute_get ();
1229 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1236 * Function to handle a reject messaage incoming over mesh
1237 * @param cls closure, NULL
1238 * @param tunnel the tunnel over which the message arrived
1239 * @param tunnel_ctx the tunnel context, can be NULL
1240 * @param message the incoming message
1245 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1247 const struct GNUNET_MessageHeader *message)
1249 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1250 const struct GNUNET_PeerIdentity *peer =
1251 GNUNET_PEER_resolve2 (tunnel->peer);
1253 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1255 ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"),
1256 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1257 GNUNET_MESH_receive_done (tunnel);
1260 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1261 && connection.status == CALLER)
1264 GNUNET_SERVER_notify_transmit_ready (connection.client,
1266 ServerClientSessionRejectMessage),
1268 &transmit_server_reject_message,
1271 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1273 ("Could not queue ServerClientSessionRejectMessage\n"));
1276 status_to_listen ();
1278 if (NULL != tunnel_reliable)
1280 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1281 tunnel_reliable = NULL;
1289 * Function to handle a terminate messaage incoming over mesh
1290 * @param cls closure, NULL
1291 * @param tunnel the tunnel over which the message arrived
1292 * @param tunnel_ctx the tunnel context, can be NULL
1293 * @param message the incoming message
1298 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1300 const struct GNUNET_MessageHeader *message)
1302 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1303 const struct GNUNET_PeerIdentity *peer =
1304 GNUNET_PEER_resolve2 (tunnel->peer);
1306 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1308 ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"),
1309 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1310 GNUNET_MESH_receive_done (tunnel);
1312 if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1313 && (connection.status == CONNECTED || connection.status == CALLEE))
1315 status_to_listen ();
1317 if (NULL != tunnel_unreliable)
1319 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1320 tunnel_unreliable = NULL;
1323 if (NULL != tunnel_reliable)
1325 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1326 tunnel_reliable = NULL;
1334 * Function to handle a audio messaage incoming over mesh
1335 * @param cls closure, NULL
1336 * @param tunnel the tunnel over which the message arrived
1337 * @param tunnel_ctx the tunnel context, can be NULL
1338 * @param message the incoming message
1343 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1345 const struct GNUNET_MessageHeader *message)
1348 GNUNET_MESH_receive_done (tunnel);
1350 if (CONNECTED != connection.status)
1354 struct AudioMessage *audio;
1356 msg_size = sizeof (struct AudioMessage);
1358 audio = (struct AudioMessage *) message;
1360 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "[RECV] %dbytes\n", audio->length);
1362 if (NULL == playback_helper)
1365 (void) GNUNET_HELPER_send (playback_helper,
1366 message, GNUNET_YES, NULL, NULL);
1369 data_received_size += msg_size;
1374 /******************************************************************************/
1375 /*********************** HELPER *******************/
1376 /******************************************************************************/
1379 * Function to process the audio from the record helper
1380 * @param cls closure, NULL
1381 * @param client NULL
1382 * @param msg the message from the helper
1387 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1388 const struct GNUNET_MessageHeader *msg)
1391 struct AudioMessage *message = (struct AudioMessage *) msg;
1392 msg_size = sizeof (struct AudioMessage);
1394 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " [REC] %dbyte\n", message->length);
1395 GNUNET_CONTAINER_slist_add_end (audio_buffer,
1396 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1403 * Function to to start the playback helper
1405 * @return 0 ok, 1 on error
1408 start_playback_helper (void)
1410 static char *playback_helper_argv[1];
1413 playback_helper_argv[0] = "gnunet-helper-audio-playback";
1414 playback_helper = GNUNET_HELPER_start (GNUNET_NO,
1415 "gnunet-helper-audio-playback",
1416 playback_helper_argv,
1419 if (NULL == playback_helper)
1422 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1423 _("Could not start playback audio helper.\n"));
1430 * Function to to start the record helper
1432 * @return 0 ok, 1 on error
1435 start_record_helper (void)
1437 static char *record_helper_argv[1];
1440 record_helper_argv[0] = "gnunet-helper-audio-record";
1441 record_helper = GNUNET_HELPER_start (GNUNET_NO,
1442 "gnunet-helper-audio-record",
1444 &process_record_messages, NULL, NULL);
1446 if (NULL == record_helper)
1449 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1450 _("Could not start record audio helper\n"));
1458 * Function to to start both helpers
1460 * @return 0 ok, 1 on error
1463 start_helpers (void)
1466 if (0 == start_playback_helper () || 0 == start_record_helper ())
1472 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1478 * Function to to stop the playback helper
1481 stop_playback_helper (void)
1483 if (NULL != playback_helper)
1485 GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1486 playback_helper = NULL;
1488 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1493 * Function to to stop the record helper
1496 stop_record_helper (void)
1498 if (NULL != record_helper)
1500 GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1501 record_helper = NULL;
1503 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1508 * Function to stop both audio helpers
1513 stop_playback_helper ();
1514 stop_record_helper ();
1517 /******************************************************************************/
1518 /*********************** TUNNEL HANDLING *******************/
1519 /******************************************************************************/
1522 * Method called whenever another peer has added us to a tunnel
1523 * the other peer initiated.
1525 * @param cls closure
1526 * @param tunnel new handle to the tunnel
1527 * @param initiator peer that started the tunnel
1529 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1532 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1533 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1535 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1536 _("Received incoming tunnel on port %d\n"), port);
1539 tunnel_unreliable = tunnel;
1541 start_time = GNUNET_TIME_absolute_get ();
1544 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1552 * Function called whenever an inbound tunnel is destroyed. Should clean up
1553 * any associated state.
1555 * @param cls closure (set from GNUNET_MESH_connect)
1556 * @param tunnel connection to the other end (henceforth invalid)
1557 * @param tunnel_ctx place where local state associated
1558 * with the tunnel is stored
1561 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1564 if (tunnel == tunnel_unreliable)
1566 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1569 tunnel_unreliable = NULL;
1572 if (tunnel == tunnel_reliable)
1574 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1576 if (LISTEN != connection.status && NULL != connection.client)
1579 GNUNET_SERVER_notify_transmit_ready (connection.client,
1581 ServerClientSessionTerminateMessage),
1583 &transmit_server_terminate_message,
1586 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1588 ("Could not queue ServerClientSessionTerminateMessage\n"));
1592 status_to_listen ();
1596 /******************************************************************************/
1597 /*********************** CLIENT HANDLING *******************/
1598 /******************************************************************************/
1601 * A client connected.
1603 * @param cls closure, NULL
1604 * @param client identification of the client
1608 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1610 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1611 struct ServerClientMissedCallMessage *message;
1613 struct VoipClient c;
1616 GNUNET_CONTAINER_slist_add_end (clients,
1617 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1618 &c, sizeof (struct VoipClient));
1619 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
1621 if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1625 sizeof (struct ServerClientMissedCallMessage) +
1626 GNUNET_CONTAINER_slist_count (missed_calls) *
1627 sizeof (struct MissedCall);
1629 (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1631 message->header.size = htons (msg_size);
1632 message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1633 message->number = GNUNET_CONTAINER_slist_count (missed_calls);
1635 struct GNUNET_CONTAINER_SList_Iterator iterator =
1636 GNUNET_CONTAINER_slist_begin (missed_calls);
1639 memcpy (&(message->missed_call[i]),
1640 GNUNET_CONTAINER_slist_get (&iterator, NULL),
1641 sizeof (struct MissedCall));
1644 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1646 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1647 GNUNET_CONTAINER_slist_clear (missed_calls);
1651 GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1653 &transmit_server_missed_call_message,
1656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1657 _("Could not queue ServerClientMissedCallMessage\n"));
1658 GNUNET_free (message);
1666 * A client disconnected. Remove all of its data structure entries.
1668 * @param cls closure, NULL
1669 * @param client identification of the client
1672 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1674 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1676 if (connection.client == cl)
1678 if (CONNECTED == connection.status)
1684 status_to_listen ();
1688 struct GNUNET_CONTAINER_SList_Iterator iterator =
1689 GNUNET_CONTAINER_slist_begin (clients);
1692 if (((struct VoipClient *)
1693 GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1695 GNUNET_CONTAINER_slist_erase (&iterator);
1698 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1700 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1705 /******************************************************************************/
1706 /*********************** SERVICE *******************/
1707 /******************************************************************************/
1712 * @param cls closure, NULL
1713 * @param tc the task context
1716 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1718 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1722 if (NULL != tunnel_reliable)
1724 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1727 if (NULL != tunnel_unreliable)
1729 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1734 GNUNET_MESH_disconnect (mesh);
1739 GNUNET_SERVER_notification_context_destroy (nc);
1743 GNUNET_CONTAINER_slist_destroy (audio_buffer);
1744 GNUNET_CONTAINER_slist_destroy (clients);
1745 GNUNET_CONTAINER_slist_destroy (missed_calls);
1746 GNUNET_CONTAINER_slist_destroy (peers_to_notify);
1751 * Handler array for traffic received
1753 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1754 {&handle_mesh_initiate_message,
1755 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
1756 sizeof (struct MeshSessionInitiateMessage)},
1757 {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
1758 sizeof (struct MeshSessionAcceptMessage)},
1759 {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
1760 sizeof (struct MeshSessionRejectMessage)},
1761 {&handle_mesh_terminate_message,
1762 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
1763 sizeof (struct MeshSessionTerminateMessage)},
1764 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
1765 sizeof (struct AudioMessage)},
1770 * Main function that will be run by the scheduler.
1772 * @param cls closure
1773 * @param server server handle
1774 * @param c configuration
1777 run (void *cls, struct GNUNET_SERVER_Handle *server,
1778 const struct GNUNET_CONFIGURATION_Handle *c)
1781 static uint32_t ports[] = { 50002, 50003, 0 };
1784 mesh = GNUNET_MESH_connect (cfg,
1787 &inbound_end, mesh_handlers, ports);
1791 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1796 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1799 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1800 {&handle_session_initiate_message, NULL,
1801 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
1802 sizeof (struct ClientServerSessionInitiateMessage)},
1803 {&handle_session_accept_message, NULL,
1804 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
1805 sizeof (struct ClientServerSessionAcceptMessage)},
1806 {&handle_session_reject_message, NULL,
1807 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
1808 sizeof (struct ClientServerSessionRejectMessage)},
1809 {&handle_session_terminate_message, NULL,
1810 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
1811 sizeof (struct ClientServerSessionTerminateMessage)},
1815 connection.status = LISTEN;
1817 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1820 nc = GNUNET_SERVER_notification_context_create (server, 16);
1822 GNUNET_SERVER_add_handlers (server, server_handlers);
1823 GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
1824 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1825 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
1828 clients = GNUNET_CONTAINER_slist_create ();
1831 missed_calls = GNUNET_CONTAINER_slist_create ();
1832 peers_to_notify = GNUNET_CONTAINER_slist_create ();
1833 audio_buffer = GNUNET_CONTAINER_slist_create ();
1835 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1839 * The main function for the conversation service.
1841 * @param argc number of arguments from the command line
1842 * @param argv command line arguments
1843 * @return 0 ok, 1 on error
1846 main (int argc, char *const *argv)
1848 return (GNUNET_OK ==
1849 GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1850 &run, NULL)) ? 0 : 1;
1853 /* end of gnunet-service-conversation.c */