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 static struct GNUNET_CONTAINER_SList *missed_calls;
134 * List for peers to notify that we are available again
136 static struct GNUNET_CONTAINER_SList *peers_to_notify;
139 * Audio buffer (outgoing)
141 static struct GNUNET_CONTAINER_SList *audio_buffer;
144 * The pointer to the task for sending audio
146 static GNUNET_SCHEDULER_TaskIdentifier audio_task;
149 * The pointer to the task for checking timeouts an calling a peer
151 static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
154 * Timestamp for call statistics
156 static struct GNUNET_TIME_Absolute start_time;
159 * Number of payload packes sent
161 static int data_sent;
162 static int data_sent_size;
165 * Number of payload packets received
167 static int data_received;
168 static int data_received_size;
172 * Transmit a mesh message
173 * @param cls closure, NULL
174 * @param size number of bytes available in buf
175 * @param buf where the callee should write the error message
176 * @return number of bytes written to buf
178 static size_t transmit_mesh_message (void *cls, size_t size, void *buf);
181 * Function called to send a peer no answer message to the client.
182 * "buf" will be NULL and "size" zero if the socket was closed for writing in
185 * @param cls closure, NULL
186 * @param size number of bytes available in buf
187 * @param buf where the callee should write the peer no answer message
188 * @return number of bytes written to buf
191 transmit_server_no_answer_message (void *cls, size_t size, void *buf);
194 * Task to schedule a audio transmission.
196 * @param cls Closure.
197 * @param tc Task Context.
200 transmit_audio_task (void *cls,
201 const struct GNUNET_SCHEDULER_TaskContext *tc);
204 * Start the audio helpers
206 int start_helpers (void);
209 * Stop the audio helpers
211 void stop_helpers (void);
215 /******************************************************************************/
216 /*********************** AUXILIARY FUNCTIONS *************************/
217 /******************************************************************************/
220 * Function which displays some call stats
225 static struct GNUNET_TIME_Absolute end_time;
226 static struct GNUNET_TIME_Relative total_time;
228 end_time = GNUNET_TIME_absolute_get ();
229 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
230 FPRINTF (stderr, "\nResults of send\n");
231 FPRINTF (stderr, "Test time %s\n",
232 GNUNET_STRINGS_relative_time_to_string (total_time,
234 FPRINTF (stderr, "Test total packets: %d\n",
236 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
237 data_sent_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
238 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
239 data_sent * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
241 FPRINTF (stderr, "\nResults of recv\n");
242 FPRINTF (stderr, "Test time %s\n",
243 GNUNET_STRINGS_relative_time_to_string (total_time,
245 FPRINTF (stderr, "Test total packets: %d\n",
247 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
248 data_received_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
249 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
250 data_received * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
254 * Function which sets the connection state to LISTEN
257 status_to_listen (void)
260 if (CONNECTED == connection.status)
265 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
267 GNUNET_SCHEDULER_cancel (timeout_task);
268 timeout_task = GNUNET_SCHEDULER_NO_TASK;
273 connection.status = LISTEN;
274 connection.client = NULL;
279 data_received_size = 0;
281 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
286 * Function to terminate the active call
292 msg_size = sizeof (struct MeshSessionTerminateMessage);
293 struct MeshSessionTerminateMessage *message_mesh_terminate =
294 (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
296 if (NULL == message_mesh_terminate)
298 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299 _("Could not create MeshSessionTerminateMessage\n"));
305 message_mesh_terminate->header.size = htons (msg_size);
306 message_mesh_terminate->header.type =
307 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
310 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
311 MAX_TRANSMIT_DELAY, msg_size,
312 &transmit_mesh_message,
313 (void *) message_mesh_terminate))
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316 _("Could not queue MeshSessionTerminateMessage\n"));
317 GNUNET_free (message_mesh_terminate);
323 * Function to reject a call
325 * @param tunnel the tunnel where to reject the incoming call
326 * @param reason te reson why the call is rejected
329 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
332 msg_size = sizeof (struct MeshSessionRejectMessage);
333 struct MeshSessionRejectMessage *message_mesh_reject =
334 (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
336 if (NULL == message_mesh_reject)
338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339 _("Could not create MeshSessionRejectMessage\n"));
345 message_mesh_reject->header.size = htons (msg_size);
346 message_mesh_reject->header.type =
347 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
348 message_mesh_reject->reason = htons (reason);
351 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
352 MAX_TRANSMIT_DELAY, msg_size,
353 &transmit_mesh_message,
354 (void *) message_mesh_reject))
356 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357 _("Could not queue MeshSessionRejectMessage\n"));
358 GNUNET_free (message_mesh_reject);
364 * Check for timeout when calling a peer
366 * @param cls closure, NULL
367 * @param tc the task context (can be NULL)
370 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
372 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
375 GNUNET_SERVER_notify_transmit_ready (connection.client,
377 ServerClientNoAnswerMessage),
379 &transmit_server_no_answer_message,
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383 _("Could not queue ServerClientNoAnswerMessage\n"));
389 /******************************************************************************/
390 /*********************** SENDING FUNCTIONS CL -> SERVER *******************/
391 /******************************************************************************/
394 * Function called to send a session initiate message to the client.
395 * "buf" will be NULL and "size" zero if the socket was closed for writing in
398 * @param cls closure, NULL
399 * @param size number of bytes available in buf
400 * @param buf where the callee should write the initiate message
401 * @return number of bytes written to buf
404 transmit_server_initiate_message (void *cls, size_t size, void *buf)
406 struct ServerClientSessionInitiateMessage *msg;
409 msg_size = sizeof (struct ServerClientSessionInitiateMessage);
411 GNUNET_assert (size >= msg_size);
413 msg = (struct ServerClientSessionInitiateMessage *) buf;
414 msg->header.size = htons (msg_size);
415 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
416 memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
417 sizeof (struct GNUNET_PeerIdentity));
423 * Function called to send a session accept message to the client.
424 * "buf" will be NULL and "size" zero if the socket was closed for writing in
427 * @param cls closure, NULL
428 * @param size number of bytes available in buf
429 * @param buf where the callee should write the accept message
430 * @return number of bytes written to buf
433 transmit_server_accept_message (void *cls, size_t size, void *buf)
435 struct ServerClientSessionAcceptMessage *msg;
438 msg_size = sizeof (struct ServerClientSessionAcceptMessage);
440 GNUNET_assert (size >= msg_size);
442 msg = (struct ServerClientSessionAcceptMessage *) buf;
443 msg->header.size = htons (msg_size);
444 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
450 * Function called to send a session reject message to the client.
451 * "buf" will be NULL and "size" zero if the socket was closed for writing in
454 * @param cls closure, NULL
455 * @param size number of bytes available in buf
456 * @param buf where the callee should write the reject message
457 * @return number of bytes written to buf
460 transmit_server_reject_message (void *cls, size_t size, void *buf)
462 struct ServerClientSessionRejectMessage *msg;
465 msg_size = sizeof (struct ServerClientSessionRejectMessage);
467 GNUNET_assert (size >= msg_size);
469 msg = (struct ServerClientSessionRejectMessage *) buf;
470 msg->header.size = htons (msg_size);
471 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
475 msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE);
479 msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
486 * Function called to send a session terminate message to the client.
487 * "buf" will be NULL and "size" zero if the socket was closed for writing in
490 * @param cls closure, NULL
491 * @param size number of bytes available in buf
492 * @param buf where the callee should write the terminate message
493 * @return number of bytes written to buf
496 transmit_server_terminate_message (void *cls, size_t size, void *buf)
498 struct ServerClientSessionTerminateMessage *msg;
501 msg_size = sizeof (struct ServerClientSessionTerminateMessage);
503 GNUNET_assert (size >= msg_size);
505 msg = (struct ServerClientSessionTerminateMessage *) buf;
506 msg->header.size = htons (msg_size);
507 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
513 * Function called to send a missed call message to the client.
514 * "buf" will be NULL and "size" zero if the socket was closed for writing in
517 * @param cls closure, NULL
518 * @param size number of bytes available in buf
519 * @param buf where the callee should write the missed call message
520 * @return number of bytes written to buf
523 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
525 struct ServerClientMissedCallMessage *msg;
526 msg = (struct ServerClientMissedCallMessage *) cls;
528 memcpy (buf, msg, size);
535 * Function called to send a service blocked message to the client.
536 * "buf" will be NULL and "size" zero if the socket was closed for writing in
539 * @param cls closure, NULL
540 * @param size number of bytes available in buf
541 * @param buf where the callee should write the service blocked message
542 * @return number of bytes written to buf
545 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
547 struct ServerClientServiceBlockedMessage *msg;
550 msg_size = sizeof (struct ServerClientServiceBlockedMessage);
552 GNUNET_assert (size >= msg_size);
554 msg = (struct ServerClientServiceBlockedMessage *) buf;
555 msg->header.size = htons (msg_size);
556 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
562 * Function called to send a peer not connected message to the client.
563 * "buf" will be NULL and "size" zero if the socket was closed for writing in
566 * @param cls closure, NULL
567 * @param size number of bytes available in buf
568 * @param buf where the callee should write the peer not connected message
569 * @return number of bytes written to buf
572 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
574 struct ServerClientPeerNotConnectedMessage *msg;
577 msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
579 GNUNET_assert (size >= msg_size);
581 msg = (struct ServerClientPeerNotConnectedMessage *) buf;
582 msg->header.size = htons (msg_size);
583 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
589 * Function called to send a peer no answer message to the client.
590 * "buf" will be NULL and "size" zero if the socket was closed for writing in
593 * @param cls closure, NULL
594 * @param size number of bytes available in buf
595 * @param buf where the callee should write the peer no answer message
596 * @return number of bytes written to buf
599 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
601 struct ServerClientNoAnswerMessage *msg;
604 msg_size = sizeof (struct ServerClientNoAnswerMessage);
606 GNUNET_assert (size >= msg_size);
608 msg = (struct ServerClientNoAnswerMessage *) buf;
609 msg->header.size = htons (msg_size);
610 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
616 * Function called to send a error message to the client.
617 * "buf" will be NULL and "size" zero if the socket was closed for writing in
620 * @param cls closure, NULL
621 * @param size number of bytes available in buf
622 * @param buf where the callee should write the error message
623 * @return number of bytes written to buf
626 transmit_server_error_message (void *cls, size_t size, void *buf)
628 struct ServerClientErrorMessage *msg;
631 msg_size = sizeof (struct ServerClientErrorMessage);
633 GNUNET_assert (size >= msg_size);
635 msg = (struct ServerClientErrorMessage *) buf;
636 msg->header.size = htons (msg_size);
637 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
642 /******************************************************************************/
643 /*********************** RECEIVE FUNCTIONS CL -> SERVER ********************/
644 /******************************************************************************/
647 * Function to handle a session initiate message from the client
649 * @param cls closure, NULL
650 * @param client the client from which the message is
651 * @param message the message from the client
654 handle_session_initiate_message (void *cls,
655 struct GNUNET_SERVER_Client *client,
656 const struct GNUNET_MessageHeader *message)
658 static uint32_t port = 50002;
660 struct ClientServerSessionInitiateMessage *msg =
661 (struct ClientServerSessionInitiateMessage *) message;
662 struct GNUNET_PeerIdentity *peer = &(msg->peer);
664 GNUNET_SERVER_receive_done (client, GNUNET_OK);
666 if (NULL != connection.client)
668 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669 _("There is already a peer in interaction\n"));
670 GNUNET_SERVER_notify_transmit_ready (client,
672 ServerClientServiceBlockedMessage),
674 &transmit_server_service_blocked_message,
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
681 GNUNET_i2s_full (peer));
683 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
684 if (NULL == tunnel_reliable)
686 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687 _("Could not create reliable tunnel\n"));
688 GNUNET_SERVER_notify_transmit_ready (client,
690 ServerClientPeerNotConnectedMessage),
692 &transmit_server_peer_not_connected_message,
698 msg_size = sizeof (struct MeshSessionInitiateMessage);
699 struct MeshSessionInitiateMessage *message_mesh_initiate =
700 (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
702 if (NULL == message_mesh_initiate)
704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
705 _("Could not create MeshSessionInitiateMessage\n"));
706 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
707 tunnel_reliable = NULL;
708 GNUNET_SERVER_notify_transmit_ready (client,
710 ServerClientErrorMessage),
712 &transmit_server_error_message,
718 message_mesh_initiate->header.size = htons (msg_size);
719 message_mesh_initiate->header.type =
720 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
723 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
724 MAX_TRANSMIT_DELAY, msg_size,
725 &transmit_mesh_message,
726 (void *) message_mesh_initiate))
728 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
729 _("Could not queue MeshSessionInitiateMessage\n"));
730 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
731 tunnel_reliable = NULL;
732 GNUNET_free (message_mesh_initiate);
733 GNUNET_SERVER_notify_transmit_ready (client,
735 ServerClientErrorMessage),
737 &transmit_server_error_message,
743 connection.status = CALLER;
744 connection.client = client;
745 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
747 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
753 * Function to handle a session accept message from the client
755 * @param cls closure, NULL
756 * @param client the client from which the message is
757 * @param message the message from the client
760 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
761 const struct GNUNET_MessageHeader *message)
765 GNUNET_SERVER_receive_done (client, GNUNET_OK);
767 if (connection.status != CALLEE)
769 // TODO send illegal command
770 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
772 ("handle_session_accept_message called when not allowed\n"));
776 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
777 GNUNET_i2s_full (&(connection.peer)));
779 msg_size = sizeof (struct MeshSessionAcceptMessage);
780 struct MeshSessionAcceptMessage *message_mesh_accept =
781 (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
783 if (NULL == message_mesh_accept)
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 _("Could not create MeshSessionAcceptMessage\n"));
790 message_mesh_accept->header.size = htons (msg_size);
791 message_mesh_accept->header.type =
792 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
795 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
796 MAX_TRANSMIT_DELAY, msg_size,
797 &transmit_mesh_message,
798 (void *) message_mesh_accept))
800 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
801 _("Could not queue MeshSessionAcceptMessage\n"));
802 GNUNET_free (message_mesh_accept);
806 connection.status = CONNECTED;
807 connection.client = client;
808 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
815 * Function to handle a session reject message from the client
817 * @param cls closure, NULL
818 * @param client the client from which the message is
819 * @param message the message from the client
822 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
823 const struct GNUNET_MessageHeader *message)
825 struct ClientServerSessionRejectMessage *message_received;
827 GNUNET_SERVER_receive_done (client, GNUNET_OK);
829 if (connection.status != CALLEE)
831 // TODO send illegal command
832 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
834 ("handle_session_reject_message called when not allowed\n"));
838 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"),
839 GNUNET_i2s_full (&(connection.peer)));
840 message_received = (struct ClientServerSessionRejectMessage *) message;
841 reject_call (tunnel_reliable, ntohs (message_received->reason));
847 * Function to handle a session terminate message from the client
849 * @param cls closure, NULL
850 * @param client the client from which the message is
851 * @param message the message from the client
854 handle_session_terminate_message (void *cls,
855 struct GNUNET_SERVER_Client *client,
856 const struct GNUNET_MessageHeader *message)
858 GNUNET_SERVER_receive_done (client, GNUNET_OK);
860 if (connection.client == NULL || connection.status == CALLEE)
862 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
864 ("handle_session_terminate_message called when not allowed\n"));
868 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
869 GNUNET_i2s_full (&(connection.peer)));
873 /******************************************************************************/
874 /*********************** SENDING FUNCTIONS MESH *******************/
875 /******************************************************************************/
878 * Transmit a mesh message
879 * @param cls closure, NULL
880 * @param size number of bytes available in buf
881 * @param buf where the callee should write the message
882 * @return number of bytes written to buf
885 transmit_mesh_message (void *cls, size_t size, void *buf)
887 struct VoIPMeshMessageHeader *msg_header =
888 (struct VoIPMeshMessageHeader *) cls;
890 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
892 memcpy (buf, cls, size);
893 // Check if this is correct
896 if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
897 ntohs (msg_header->header.type))
898 || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
899 ntohs (msg_header->header.type)))
903 else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
904 ntohs (msg_header->header.type))
906 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
908 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
909 (GNUNET_TIME_UNIT_SECONDS, 30),
910 &check_timeout, NULL);
919 * Transmit a audo message over mesh
920 * @param cls closure, NULL
921 * @param size number of bytes available in buf
922 * @param buf where the callee should write the message
923 * @return number of bytes written to buf
926 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
928 struct AudioMessage *message = (struct AudioMessage *) cls;
930 if (size < sizeof (struct AudioMessage) || NULL == buf)
933 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
934 "size %u, buf %p, data_sent %u, data_received %u\n",
935 size, buf, data_sent, data_received);
939 memcpy (buf, message, size);
942 data_sent_size += size;
944 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
946 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
952 * Task to schedule a audio transmission.
954 * @param cls Closure.
955 * @param tc Task Context.
958 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
960 struct GNUNET_CONTAINER_SList_Iterator iterator;
961 struct AudioMessage *msg;
962 int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
964 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
968 if (0 == ab_length && CONNECTED == connection.status)
971 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
972 (GNUNET_TIME_UNIT_MILLISECONDS, 10),
973 &transmit_audio_task, NULL);
977 iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
979 (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
980 GNUNET_CONTAINER_slist_erase (&iterator);
981 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
985 msg = (struct AudioMessage *) cls;
988 if (NULL == tunnel_unreliable)
990 GNUNET_CONTAINER_slist_clear (audio_buffer);
994 mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
996 sizeof (struct AudioMessage),
997 &transmit_mesh_audio_message,
1002 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1003 "Need to retransmit audio packet\n");
1004 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
1006 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1007 &transmit_audio_task, (void *) msg);
1011 /******************************************************************************/
1012 /*********************** RECEIVE FUNCTIONS MESH ********************/
1013 /******************************************************************************/
1016 * Function to handle a initiation messaage incoming over mesh
1017 * @param cls closure, NULL
1018 * @param tunnel the tunnel over which the message arrived
1019 * @param tunnel_ctx the tunnel context, can be NULL
1020 * @param message the incoming message
1025 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1027 const struct GNUNET_MessageHeader *message)
1030 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1031 const struct GNUNET_PeerIdentity *peer =
1032 GNUNET_PEER_resolve2 (tunnel->peer);
1034 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1035 _("Handling MeshSessionInitiateMessage from peer: %s\n"),
1036 GNUNET_i2s_full (peer));
1037 GNUNET_MESH_receive_done (tunnel);
1039 if (LISTEN != connection.status
1040 || 1 > GNUNET_CONTAINER_slist_count (clients))
1043 if (CONNECTED == connection.status)
1045 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1047 ("Rejected call from %s because there is an active call"),
1048 GNUNET_i2s_full (peer));
1049 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_ACTIVE_CALL);
1051 // Notifying client about missed call
1053 sizeof (struct ServerClientMissedCallMessage) +
1054 sizeof (struct MissedCall);
1055 struct ServerClientMissedCallMessage *message =
1056 GNUNET_malloc (msg_size);
1058 message->header.size = htons (msg_size);
1059 message->header.type =
1060 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1061 message->number = 1;
1063 memcpy (&(message->missed_call->peer), peer,
1064 sizeof (struct GNUNET_PeerIdentity));
1065 message->missed_call->time = GNUNET_TIME_absolute_get ();
1068 GNUNET_SERVER_notify_transmit_ready (connection.client,
1070 ServerClientMissedCallMessage),
1072 &transmit_server_missed_call_message,
1075 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1077 ("Could not queue ServerClientMissedCallMessage\n"));
1078 GNUNET_free (message);
1082 if (1 > GNUNET_CONTAINER_slist_count (clients))
1084 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1085 _("Got a call from %s while no client connected.\n"),
1086 GNUNET_i2s_full (peer));
1087 reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NO_CLIENT);
1088 // Store missed calls
1089 struct MissedCall call;
1090 memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1091 call.time = GNUNET_TIME_absolute_get ();
1092 GNUNET_CONTAINER_slist_add_end (missed_calls,
1093 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1094 &call, sizeof (struct MissedCall));
1098 reject_call (tunnel, reject_reason);
1102 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
1103 GNUNET_i2s_full (peer));
1104 tunnel_reliable = tunnel;
1105 connection.status = CALLEE;
1106 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1107 _("Changed connection status to %d\n"), connection.status);
1108 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1110 struct GNUNET_CONTAINER_SList_Iterator iterator =
1111 GNUNET_CONTAINER_slist_begin (clients);
1114 struct VoipClient *conversation_client =
1115 (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1117 struct GNUNET_SERVER_Client *client = conversation_client->client;
1118 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1122 GNUNET_SERVER_notify_transmit_ready (client,
1124 ServerClientSessionInitiateMessage),
1126 &transmit_server_initiate_message,
1129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1131 ("Could not queue ServerClientSessionInitiateMessage\n"));
1134 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1136 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1138 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1146 * Function to handle an accept messaage incoming over mesh
1147 * @param cls closure, NULL
1148 * @param tunnel the tunnel over which the message arrived
1149 * @param tunnel_ctx the tunnel context, can be NULL
1150 * @param message the incoming message
1155 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1157 const struct GNUNET_MessageHeader *message)
1159 static uint32_t port = 50003;
1160 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1161 const struct GNUNET_PeerIdentity *peer =
1162 GNUNET_PEER_resolve2 (tunnel->peer);
1164 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1166 ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"),
1167 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1168 GNUNET_MESH_receive_done (tunnel);
1171 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1172 && connection.status == CALLER)
1175 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1177 if (NULL == tunnel_unreliable)
1179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1180 _("Could not create unreliable tunnel\n"));
1182 status_to_listen ();
1184 GNUNET_SERVER_notify_transmit_ready (connection.client,
1186 ServerClientSessionRejectMessage),
1188 &transmit_server_reject_message,
1190 return GNUNET_SYSERR;
1193 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1195 GNUNET_SCHEDULER_cancel (timeout_task);
1196 timeout_task = GNUNET_SCHEDULER_NO_TASK;
1199 connection.status = CONNECTED;
1200 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1201 _("Changed connection status to %d\n"), connection.status);
1204 GNUNET_SERVER_notify_transmit_ready (connection.client,
1206 ServerClientSessionAcceptMessage),
1208 &transmit_server_accept_message,
1211 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1213 ("Could not queue ServerClientSessionAcceptMessage\n"));
1214 return GNUNET_SYSERR;
1217 start_time = GNUNET_TIME_absolute_get ();
1219 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1226 * Function to handle a reject messaage incoming over mesh
1227 * @param cls closure, NULL
1228 * @param tunnel the tunnel over which the message arrived
1229 * @param tunnel_ctx the tunnel context, can be NULL
1230 * @param message the incoming message
1235 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1237 const struct GNUNET_MessageHeader *message)
1239 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1240 const struct GNUNET_PeerIdentity *peer =
1241 GNUNET_PEER_resolve2 (tunnel->peer);
1243 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1245 ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"),
1246 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1247 GNUNET_MESH_receive_done (tunnel);
1250 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1251 && connection.status == CALLER)
1254 GNUNET_SERVER_notify_transmit_ready (connection.client,
1256 ServerClientSessionRejectMessage),
1258 &transmit_server_reject_message,
1261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 ("Could not queue ServerClientSessionRejectMessage\n"));
1266 status_to_listen ();
1268 if (NULL != tunnel_reliable)
1270 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1271 tunnel_reliable = NULL;
1279 * Function to handle a terminate messaage incoming over mesh
1280 * @param cls closure, NULL
1281 * @param tunnel the tunnel over which the message arrived
1282 * @param tunnel_ctx the tunnel context, can be NULL
1283 * @param message the incoming message
1288 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1290 const struct GNUNET_MessageHeader *message)
1292 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1293 const struct GNUNET_PeerIdentity *peer =
1294 GNUNET_PEER_resolve2 (tunnel->peer);
1296 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1298 ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"),
1299 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1300 GNUNET_MESH_receive_done (tunnel);
1302 if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1303 && (connection.status == CONNECTED || connection.status == CALLEE))
1305 status_to_listen ();
1307 if (NULL != tunnel_unreliable)
1309 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1310 tunnel_unreliable = NULL;
1313 if (NULL != tunnel_reliable)
1315 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1316 tunnel_reliable = NULL;
1324 * Function to handle a audio messaage incoming over mesh
1325 * @param cls closure, NULL
1326 * @param tunnel the tunnel over which the message arrived
1327 * @param tunnel_ctx the tunnel context, can be NULL
1328 * @param message the incoming message
1333 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1335 const struct GNUNET_MessageHeader *message)
1337 const struct AudioMessage *audio;
1338 audio = (const struct AudioMessage *) message;
1340 GNUNET_MESH_receive_done (tunnel);
1341 if (CONNECTED != connection.status)
1343 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1345 ntohs (audio->header.size));
1346 if (NULL == playback_helper)
1348 (void) GNUNET_HELPER_send (playback_helper,
1349 message, GNUNET_YES, NULL, NULL);
1353 /******************************************************************************/
1354 /*********************** HELPER *******************/
1355 /******************************************************************************/
1358 * Function to process the audio from the record helper
1359 * @param cls closure, NULL
1360 * @param client NULL
1361 * @param msg the message from the helper
1366 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1367 const struct GNUNET_MessageHeader *msg)
1369 const struct AudioMessage *message = (const struct AudioMessage *) msg;
1371 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1373 ntohs (message->header.size));
1374 GNUNET_CONTAINER_slist_add_end (audio_buffer,
1375 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1376 message, ntohs (message->header.size));
1382 * Function to to start the playback helper
1384 * @return 0 ok, 1 on error
1387 start_playback_helper (void)
1389 static char *playback_helper_argv[1];
1392 playback_helper_argv[0] = "gnunet-helper-audio-playback";
1393 playback_helper = GNUNET_HELPER_start (GNUNET_NO,
1394 "gnunet-helper-audio-playback",
1395 playback_helper_argv,
1398 if (NULL == playback_helper)
1401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1402 _("Could not start playback audio helper.\n"));
1409 * Function to to start the record helper
1411 * @return 0 ok, 1 on error
1414 start_record_helper (void)
1416 static char *record_helper_argv[1];
1419 record_helper_argv[0] = "gnunet-helper-audio-record";
1420 record_helper = GNUNET_HELPER_start (GNUNET_NO,
1421 "gnunet-helper-audio-record",
1423 &process_record_messages, NULL, NULL);
1425 if (NULL == record_helper)
1428 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1429 _("Could not start record audio helper\n"));
1437 * Function to to start both helpers
1439 * @return 0 ok, 1 on error
1442 start_helpers (void)
1445 if (0 == start_playback_helper () || 0 == start_record_helper ())
1451 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1457 * Function to to stop the playback helper
1460 stop_playback_helper (void)
1462 if (NULL != playback_helper)
1464 GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1465 playback_helper = NULL;
1467 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1472 * Function to to stop the record helper
1475 stop_record_helper (void)
1477 if (NULL != record_helper)
1479 GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1480 record_helper = NULL;
1482 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1487 * Function to stop both audio helpers
1492 stop_playback_helper ();
1493 stop_record_helper ();
1496 /******************************************************************************/
1497 /*********************** TUNNEL HANDLING *******************/
1498 /******************************************************************************/
1501 * Method called whenever another peer has added us to a tunnel
1502 * the other peer initiated.
1504 * @param cls closure
1505 * @param tunnel new handle to the tunnel
1506 * @param initiator peer that started the tunnel
1508 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1511 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1512 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1514 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515 _("Received incoming tunnel on port %d\n"), port);
1518 tunnel_unreliable = tunnel;
1520 start_time = GNUNET_TIME_absolute_get ();
1523 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1531 * Function called whenever an inbound tunnel is destroyed. Should clean up
1532 * any associated state.
1534 * @param cls closure (set from GNUNET_MESH_connect)
1535 * @param tunnel connection to the other end (henceforth invalid)
1536 * @param tunnel_ctx place where local state associated
1537 * with the tunnel is stored
1540 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1543 if (tunnel == tunnel_unreliable)
1545 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1548 tunnel_unreliable = NULL;
1551 if (tunnel == tunnel_reliable)
1553 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1555 if (LISTEN != connection.status && NULL != connection.client)
1558 GNUNET_SERVER_notify_transmit_ready (connection.client,
1560 ServerClientSessionTerminateMessage),
1562 &transmit_server_terminate_message,
1565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1567 ("Could not queue ServerClientSessionTerminateMessage\n"));
1571 status_to_listen ();
1575 /******************************************************************************/
1576 /*********************** CLIENT HANDLING *******************/
1577 /******************************************************************************/
1580 * A client connected.
1582 * @param cls closure, NULL
1583 * @param client identification of the client
1587 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1589 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1590 struct ServerClientMissedCallMessage *message;
1592 struct VoipClient c;
1595 GNUNET_CONTAINER_slist_add_end (clients,
1596 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1597 &c, sizeof (struct VoipClient));
1598 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
1600 if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1604 sizeof (struct ServerClientMissedCallMessage) +
1605 GNUNET_CONTAINER_slist_count (missed_calls) *
1606 sizeof (struct MissedCall);
1608 (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1610 message->header.size = htons (msg_size);
1611 message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1612 message->number = GNUNET_CONTAINER_slist_count (missed_calls);
1614 struct GNUNET_CONTAINER_SList_Iterator iterator =
1615 GNUNET_CONTAINER_slist_begin (missed_calls);
1618 memcpy (&(message->missed_call[i]),
1619 GNUNET_CONTAINER_slist_get (&iterator, NULL),
1620 sizeof (struct MissedCall));
1623 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1625 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1626 GNUNET_CONTAINER_slist_clear (missed_calls);
1630 GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1632 &transmit_server_missed_call_message,
1635 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1636 _("Could not queue ServerClientMissedCallMessage\n"));
1637 GNUNET_free (message);
1645 * A client disconnected. Remove all of its data structure entries.
1647 * @param cls closure, NULL
1648 * @param client identification of the client
1651 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1653 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1655 if (connection.client == cl)
1657 if (CONNECTED == connection.status)
1663 status_to_listen ();
1667 struct GNUNET_CONTAINER_SList_Iterator iterator =
1668 GNUNET_CONTAINER_slist_begin (clients);
1671 if (((struct VoipClient *)
1672 GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1674 GNUNET_CONTAINER_slist_erase (&iterator);
1677 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1679 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1684 /******************************************************************************/
1685 /*********************** SERVICE *******************/
1686 /******************************************************************************/
1691 * @param cls closure, NULL
1692 * @param tc the task context
1695 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1697 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1701 if (NULL != tunnel_reliable)
1703 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1706 if (NULL != tunnel_unreliable)
1708 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1713 GNUNET_MESH_disconnect (mesh);
1718 GNUNET_SERVER_notification_context_destroy (nc);
1722 GNUNET_CONTAINER_slist_destroy (audio_buffer);
1723 GNUNET_CONTAINER_slist_destroy (clients);
1724 GNUNET_CONTAINER_slist_destroy (missed_calls);
1725 GNUNET_CONTAINER_slist_destroy (peers_to_notify);
1730 * Handler array for traffic received
1732 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1733 {&handle_mesh_initiate_message,
1734 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
1735 sizeof (struct MeshSessionInitiateMessage)},
1736 {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
1737 sizeof (struct MeshSessionAcceptMessage)},
1738 {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
1739 sizeof (struct MeshSessionRejectMessage)},
1740 {&handle_mesh_terminate_message,
1741 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
1742 sizeof (struct MeshSessionTerminateMessage)},
1743 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
1744 sizeof (struct AudioMessage)},
1749 * Main function that will be run by the scheduler.
1751 * @param cls closure
1752 * @param server server handle
1753 * @param c configuration
1756 run (void *cls, struct GNUNET_SERVER_Handle *server,
1757 const struct GNUNET_CONFIGURATION_Handle *c)
1760 static uint32_t ports[] = { 50002, 50003, 0 };
1763 mesh = GNUNET_MESH_connect (cfg,
1766 &inbound_end, mesh_handlers, ports);
1770 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1775 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1778 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1779 {&handle_session_initiate_message, NULL,
1780 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
1781 sizeof (struct ClientServerSessionInitiateMessage)},
1782 {&handle_session_accept_message, NULL,
1783 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
1784 sizeof (struct ClientServerSessionAcceptMessage)},
1785 {&handle_session_reject_message, NULL,
1786 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
1787 sizeof (struct ClientServerSessionRejectMessage)},
1788 {&handle_session_terminate_message, NULL,
1789 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
1790 sizeof (struct ClientServerSessionTerminateMessage)},
1794 connection.status = LISTEN;
1796 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1799 nc = GNUNET_SERVER_notification_context_create (server, 16);
1801 GNUNET_SERVER_add_handlers (server, server_handlers);
1802 GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
1803 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1804 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
1807 clients = GNUNET_CONTAINER_slist_create ();
1810 missed_calls = GNUNET_CONTAINER_slist_create ();
1811 peers_to_notify = GNUNET_CONTAINER_slist_create ();
1812 audio_buffer = GNUNET_CONTAINER_slist_create ();
1814 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1818 * The main function for the conversation service.
1820 * @param argc number of arguments from the command line
1821 * @param argv command line arguments
1822 * @return 0 ok, 1 on error
1825 main (int argc, char *const *argv)
1827 return (GNUNET_OK ==
1828 GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1829 &run, NULL)) ? 0 : 1;
1832 /* end of gnunet-service-conversation.c */