2 This file is part of GNUnet.
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.
22 * @file conversation/gnunet-service-conversation.c
23 * @brief conversation service implementation
24 * @author Simon Dieterle
25 * @author Andreas Fuchs
28 * - AUXILIARY FUNCTIONS
29 * - SENDING FUNCTIONS CL -> SERVER
30 * - RECEIVE FUNCTIONS CL -> SERVER
31 * - SENDING FUNCTIONS MESH
32 * - RECEIVE FUNCTIONS MESH
37 #include <gnunet/platform.h>
38 #include <gnunet/gnunet_util_lib.h>
39 #include <gnunet/gnunet_constants.h>
40 #include <gnunet/gnunet_mesh_service.h>
41 #include "gnunet_conversation.h"
42 #include "gnunet_protocols_conversation.h"
44 /********************************************************
45 * Ugly hack because of not working MESH API
47 typedef uint32_t MESH_TunnelNumber;
48 struct GNUNET_MESH_Tunnel
50 struct GNUNET_MESH_Tunnel *next;
51 struct GNUNET_MESH_Tunnel *prev;
52 struct GNUNET_MESH_Handle *mesh;
53 MESH_TunnelNumber tid;
57 unsigned int packet_size;
67 static const struct GNUNET_CONFIGURATION_Handle *cfg;
70 * Head of the list of current clients.
72 static struct GNUNET_CONTAINER_SList *clients;
75 * Notification context containing all connected clients.
77 struct GNUNET_SERVER_NotificationContext *nc = NULL;
80 * The connection status
82 static struct ConnectionStatus connection;
85 * Handle for the record helper
87 static struct GNUNET_HELPER_Handle *record_helper;
89 /** Handle for the playback handler
92 static struct GNUNET_HELPER_Handle *playback_helper;
97 static struct GNUNET_MESH_Handle *mesh;
100 * Transmit handle for audio messages
102 static struct GNUNET_MESH_TransmitHandle *mth = NULL;
105 * Handle for the reliable tunnel (contol data)
107 static struct GNUNET_MESH_Tunnel *tunnel_reliable;
110 * Handle for unreliable tunnel (audio data)
112 static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
115 * List for missed calls
117 struct GNUNET_CONTAINER_SList *missed_calls;
120 * List for peers to notify that we are available again
122 struct GNUNET_CONTAINER_SList *peers_to_notify;
125 * Audio buffer (outgoing)
127 struct GNUNET_CONTAINER_SList *audio_buffer;
130 * The pointer to the task for sending audio
132 GNUNET_SCHEDULER_TaskIdentifier audio_task;
135 * The pointer to the task for checking timeouts an calling a peer
137 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
140 * Sequencenumber for the pakets (for evaltuation purposes)
142 int SequenceNumber = 0;
145 * Timestamp for call statistics
147 static struct GNUNET_TIME_Absolute start_time;
150 * Number of payload packes sent
152 static int data_sent;
153 static int data_sent_size;
156 * Number of payload packets received
158 static int data_received;
159 static int data_received_size;
161 /******************************************************************************/
162 /*********************** AUXILIARY FUNCTIONS *************************/
163 /******************************************************************************/
166 * Function which displays some call stats
171 static struct GNUNET_TIME_Absolute end_time;
172 static struct GNUNET_TIME_Relative total_time;
174 end_time = GNUNET_TIME_absolute_get ();
175 total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
176 FPRINTF (stderr, "\nResults of send\n");
177 FPRINTF (stderr, "Test time %s\n",
178 GNUNET_STRINGS_relative_time_to_string (total_time,
180 FPRINTF (stderr, "Test total packets: %d\n",
182 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
183 data_sent_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
184 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
185 data_sent * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
187 FPRINTF (stderr, "\nResults of recv\n");
188 FPRINTF (stderr, "Test time %s\n",
189 GNUNET_STRINGS_relative_time_to_string (total_time,
191 FPRINTF (stderr, "Test total packets: %d\n",
193 FPRINTF (stderr, "Test bandwidth: %f kb/s\n",
194 data_received_size * 1000.0 / (total_time.rel_value_us + 1)); // 4bytes * us
195 FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
196 data_received * 1000000.0 / (total_time.rel_value_us + 1)); // packets * us
200 * Function which sets the connection state to LISTEN
203 status_to_listen (void)
206 if (CONNECTED == connection.status)
211 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
213 GNUNET_SCHEDULER_cancel (timeout_task);
214 timeout_task = GNUNET_SCHEDULER_NO_TASK;
219 connection.status = LISTEN;
220 connection.client = NULL;
225 data_received_size = 0;
227 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
232 * Function to terminate the active call
238 msg_size = sizeof (struct MeshSessionTerminateMessage);
239 struct MeshSessionTerminateMessage *message_mesh_terminate =
240 (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
242 if (NULL == message_mesh_terminate)
244 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
245 _("Could not create MeshSessionTerminateMessage\n"));
251 message_mesh_terminate->header.size = htons (msg_size);
252 message_mesh_terminate->header.type =
253 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
256 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
257 MAX_TRANSMIT_DELAY, msg_size,
258 &transmit_mesh_message,
259 (void *) message_mesh_terminate))
261 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
262 _("Could not queue MeshSessionTerminateMessage\n"));
263 GNUNET_free (message_mesh_terminate);
269 * Function to reject a call
271 * @param tunnel the tunnel where to reject the incoming call
272 * @param reason te reson why the call is rejected
275 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
278 msg_size = sizeof (struct MeshSessionRejectMessage);
279 struct MeshSessionRejectMessage *message_mesh_reject =
280 (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
282 if (NULL == message_mesh_reject)
284 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285 _("Could not create MeshSessionRejectMessage\n"));
291 message_mesh_reject->header.size = htons (msg_size);
292 message_mesh_reject->header.type =
293 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
294 message_mesh_reject->reason = htons (reason);
297 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
298 MAX_TRANSMIT_DELAY, msg_size,
299 &transmit_mesh_message,
300 (void *) message_mesh_reject))
302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303 _("Could not queue MeshSessionRejectMessage\n"));
304 GNUNET_free (message_mesh_reject);
310 * Check for timeout when calling a peer
312 * @param cls closure, NULL
313 * @param tc the task context (can be NULL)
316 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
318 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
321 GNUNET_SERVER_notify_transmit_ready (connection.client,
323 ServerClientNoAnswerMessage),
325 &transmit_server_no_answer_message,
328 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
329 _("Could not queue ServerClientNoAnswerMessage\n"));
335 /******************************************************************************/
336 /*********************** SENDING FUNCTIONS CL -> SERVER *******************/
337 /******************************************************************************/
340 * Function called to send a session initiate message to the client.
341 * "buf" will be NULL and "size" zero if the socket was closed for writing in
344 * @param cls closure, NULL
345 * @param size number of bytes available in buf
346 * @param buf where the callee should write the initiate message
347 * @return number of bytes written to buf
350 transmit_server_initiate_message (void *cls, size_t size, void *buf)
352 struct ServerClientSessionInitiateMessage *msg;
355 msg_size = sizeof (struct ServerClientSessionInitiateMessage);
357 GNUNET_assert (size >= msg_size);
359 msg = (struct ServerClientSessionInitiateMessage *) buf;
360 msg->header.size = htons (msg_size);
361 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
362 memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
363 sizeof (struct GNUNET_PeerIdentity));
369 * Function called to send a session accept message to the client.
370 * "buf" will be NULL and "size" zero if the socket was closed for writing in
373 * @param cls closure, NULL
374 * @param size number of bytes available in buf
375 * @param buf where the callee should write the accept message
376 * @return number of bytes written to buf
379 transmit_server_accept_message (void *cls, size_t size, void *buf)
381 struct ServerClientSessionAcceptMessage *msg;
384 msg_size = sizeof (struct ServerClientSessionAcceptMessage);
386 GNUNET_assert (size >= msg_size);
388 msg = (struct ServerClientSessionAcceptMessage *) buf;
389 msg->header.size = htons (msg_size);
390 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
396 * Function called to send a session reject message to the client.
397 * "buf" will be NULL and "size" zero if the socket was closed for writing in
400 * @param cls closure, NULL
401 * @param size number of bytes available in buf
402 * @param buf where the callee should write the reject message
403 * @return number of bytes written to buf
406 transmit_server_reject_message (void *cls, size_t size, void *buf)
408 struct ServerClientSessionRejectMessage *msg;
411 msg_size = sizeof (struct ServerClientSessionRejectMessage);
413 GNUNET_assert (size >= msg_size);
415 msg = (struct ServerClientSessionRejectMessage *) buf;
416 msg->header.size = htons (msg_size);
417 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
421 msg->reason = htons (REJECT_REASON_NOT_AVAILABLE);
425 msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
432 * Function called to send a session terminate message to the client.
433 * "buf" will be NULL and "size" zero if the socket was closed for writing in
436 * @param cls closure, NULL
437 * @param size number of bytes available in buf
438 * @param buf where the callee should write the terminate message
439 * @return number of bytes written to buf
442 transmit_server_terminate_message (void *cls, size_t size, void *buf)
444 struct ServerClientSessionTerminateMessage *msg;
447 msg_size = sizeof (struct ServerClientSessionTerminateMessage);
449 GNUNET_assert (size >= msg_size);
451 msg = (struct ServerClientSessionTerminateMessage *) buf;
452 msg->header.size = htons (msg_size);
453 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
459 * Function called to send a missed call message to the client.
460 * "buf" will be NULL and "size" zero if the socket was closed for writing in
463 * @param cls closure, NULL
464 * @param size number of bytes available in buf
465 * @param buf where the callee should write the missed call message
466 * @return number of bytes written to buf
469 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
471 struct ServerClientMissedCallMessage *msg;
472 msg = (struct ServerClientMissedCallMessage *) cls;
474 memcpy (buf, msg, size);
481 * Function called to send a service blocked message to the client.
482 * "buf" will be NULL and "size" zero if the socket was closed for writing in
485 * @param cls closure, NULL
486 * @param size number of bytes available in buf
487 * @param buf where the callee should write the service blocked message
488 * @return number of bytes written to buf
491 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
493 struct ServerClientServiceBlockedMessage *msg;
496 msg_size = sizeof (struct ServerClientServiceBlockedMessage);
498 GNUNET_assert (size >= msg_size);
500 msg = (struct ServerClientServiceBlockedMessage *) buf;
501 msg->header.size = htons (msg_size);
502 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
508 * Function called to send a peer not connected message to the client.
509 * "buf" will be NULL and "size" zero if the socket was closed for writing in
512 * @param cls closure, NULL
513 * @param size number of bytes available in buf
514 * @param buf where the callee should write the peer not connected message
515 * @return number of bytes written to buf
518 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
520 struct ServerClientPeerNotConnectedMessage *msg;
523 msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
525 GNUNET_assert (size >= msg_size);
527 msg = (struct ServerClientPeerNotConnectedMessage *) buf;
528 msg->header.size = htons (msg_size);
529 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
535 * Function called to send a peer no answer 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 peer no answer message
542 * @return number of bytes written to buf
545 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
547 struct ServerClientNoAnswerMessage *msg;
550 msg_size = sizeof (struct ServerClientNoAnswerMessage);
552 GNUNET_assert (size >= msg_size);
554 msg = (struct ServerClientNoAnswerMessage *) buf;
555 msg->header.size = htons (msg_size);
556 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
562 * Function called to send a error 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 error message
569 * @return number of bytes written to buf
572 transmit_server_error_message (void *cls, size_t size, void *buf)
574 struct ServerClientErrorMessage *msg;
577 msg_size = sizeof (struct ServerClientErrorMessage);
579 GNUNET_assert (size >= msg_size);
581 msg = (struct ServerClientErrorMessage *) buf;
582 msg->header.size = htons (msg_size);
583 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
588 /******************************************************************************/
589 /*********************** RECEIVE FUNCTIONS CL -> SERVER ********************/
590 /******************************************************************************/
593 * Function to handle a session initiate message from the client
595 * @param cls closure, NULL
596 * @param client the client from which the message is
597 * @param message the message from the client
600 handle_session_initiate_message (void *cls,
601 struct GNUNET_SERVER_Client *client,
602 const struct GNUNET_MessageHeader *message)
604 static uint32_t port = 50002;
606 struct ClientServerSessionInitiateMessage *msg =
607 (struct ClientServerSessionInitiateMessage *) message;
608 struct GNUNET_PeerIdentity *peer = &(msg->peer);
610 GNUNET_SERVER_receive_done (client, GNUNET_OK);
612 if (NULL != connection.client)
614 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
615 _("There is already a peer in interaction\n"));
616 GNUNET_SERVER_notify_transmit_ready (client,
618 ServerClientServiceBlockedMessage),
620 &transmit_server_service_blocked_message,
626 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
627 GNUNET_i2s_full (peer));
629 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
630 if (NULL == tunnel_reliable)
632 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
633 _("Could not create reliable tunnel\n"));
634 GNUNET_SERVER_notify_transmit_ready (client,
636 ServerClientPeerNotConnectedMessage),
638 &transmit_server_peer_not_connected_message,
644 msg_size = sizeof (struct MeshSessionInitiateMessage);
645 struct MeshSessionInitiateMessage *message_mesh_initiate =
646 (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
648 if (NULL == message_mesh_initiate)
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
651 _("Could not create MeshSessionInitiateMessage\n"));
652 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
653 tunnel_reliable = NULL;
654 GNUNET_SERVER_notify_transmit_ready (client,
656 ServerClientErrorMessage),
658 &transmit_server_error_message,
664 message_mesh_initiate->header.size = htons (msg_size);
665 message_mesh_initiate->header.type =
666 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
669 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
670 MAX_TRANSMIT_DELAY, msg_size,
671 &transmit_mesh_message,
672 (void *) message_mesh_initiate))
674 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
675 _("Could not queue MeshSessionInitiateMessage\n"));
676 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
677 tunnel_reliable = NULL;
678 GNUNET_free (message_mesh_initiate);
679 GNUNET_SERVER_notify_transmit_ready (client,
681 ServerClientErrorMessage),
683 &transmit_server_error_message,
689 connection.status = CALLER;
690 connection.client = client;
691 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
693 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
699 * Function to handle a session accept message from the client
701 * @param cls closure, NULL
702 * @param client the client from which the message is
703 * @param message the message from the client
706 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
707 const struct GNUNET_MessageHeader *message)
711 GNUNET_SERVER_receive_done (client, GNUNET_OK);
713 if (connection.status != CALLEE)
715 // TODO send illegal command
716 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
718 ("handle_session_accept_message called when not allowed\n"));
722 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
723 GNUNET_i2s_full (&(connection.peer)));
725 msg_size = sizeof (struct MeshSessionAcceptMessage);
726 struct MeshSessionAcceptMessage *message_mesh_accept =
727 (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
729 if (NULL == message_mesh_accept)
731 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
732 _("Could not create MeshSessionAcceptMessage\n"));
736 message_mesh_accept->header.size = htons (msg_size);
737 message_mesh_accept->header.type =
738 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
741 GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
742 MAX_TRANSMIT_DELAY, msg_size,
743 &transmit_mesh_message,
744 (void *) message_mesh_accept))
746 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
747 _("Could not queue MeshSessionAcceptMessage\n"));
748 GNUNET_free (message_mesh_accept);
752 connection.status = CONNECTED;
753 connection.client = client;
754 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
761 * Function to handle a session reject message from the client
763 * @param cls closure, NULL
764 * @param client the client from which the message is
765 * @param message the message from the client
768 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
769 const struct GNUNET_MessageHeader *message)
771 struct ClientServerSessionRejectMessage *message_received;
773 GNUNET_SERVER_receive_done (client, GNUNET_OK);
775 if (connection.status != CALLEE)
777 // TODO send illegal command
778 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
780 ("handle_session_reject_message called when not allowed\n"));
784 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"),
785 GNUNET_i2s_full (&(connection.peer)));
786 message_received = (struct ClientServerSessionRejectMessage *) message;
787 reject_call (tunnel_reliable, ntohs (message_received->reason));
793 * Function to handle a session terminate message from the client
795 * @param cls closure, NULL
796 * @param client the client from which the message is
797 * @param message the message from the client
800 handle_session_terminate_message (void *cls,
801 struct GNUNET_SERVER_Client *client,
802 const struct GNUNET_MessageHeader *message)
804 GNUNET_SERVER_receive_done (client, GNUNET_OK);
806 if (connection.client == NULL || connection.status == CALLEE)
808 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
810 ("handle_session_terminate_message called when not allowed\n"));
814 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
815 GNUNET_i2s_full (&(connection.peer)));
819 /******************************************************************************/
820 /*********************** SENDING FUNCTIONS MESH *******************/
821 /******************************************************************************/
824 * Transmit a mesh message
825 * @param cls closure, NULL
826 * @param size number of bytes available in buf
827 * @param buf where the callee should write the message
828 * @return number of bytes written to buf
831 transmit_mesh_message (void *cls, size_t size, void *buf)
833 struct VoIPMeshMessageHeader *msg_header =
834 (struct VoIPMeshMessageHeader *) cls;
835 msg_header->SequenceNumber = SequenceNumber += 1;
836 msg_header->time = GNUNET_TIME_absolute_get ();
838 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
840 memcpy (buf, cls, size);
841 // Check if this is correct
844 if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
845 ntohs (msg_header->header.type))
846 || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
847 ntohs (msg_header->header.type)))
851 else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
852 ntohs (msg_header->header.type))
854 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
856 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
857 (GNUNET_TIME_UNIT_SECONDS, 30),
858 &check_timeout, NULL);
867 * Transmit a audo message over mesh
868 * @param cls closure, NULL
869 * @param size number of bytes available in buf
870 * @param buf where the callee should write the message
871 * @return number of bytes written to buf
874 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
876 struct AudioMessage *message = (struct AudioMessage *) cls;
878 if (size < sizeof (struct AudioMessage) || NULL == buf)
881 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
882 "size %u, buf %p, data_sent %u, data_received %u\n",
883 size, buf, data_sent, data_received);
887 memcpy (buf, message, size);
890 data_sent_size += size;
892 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
894 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
900 * Task to schedule a audio transmission.
902 * @param cls Closure.
903 * @param tc Task Context.
906 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
908 struct GNUNET_CONTAINER_SList_Iterator iterator;
909 struct AudioMessage *msg;
910 int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
912 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
916 if (0 == ab_length && CONNECTED == connection.status)
919 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
920 (GNUNET_TIME_UNIT_MILLISECONDS, 10),
921 &transmit_audio_task, NULL);
925 iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
927 (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
928 msg->SequenceNumber = SequenceNumber += 1;
929 msg->time = GNUNET_TIME_absolute_get ();
931 GNUNET_CONTAINER_slist_erase (&iterator);
932 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
936 msg = (struct AudioMessage *) cls;
939 if (NULL == tunnel_unreliable)
941 GNUNET_CONTAINER_slist_clear (audio_buffer);
945 mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
947 sizeof (struct AudioMessage),
948 &transmit_mesh_audio_message,
953 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
954 "Need to retransmit audio packet\n");
955 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n");
957 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
958 &transmit_audio_task, (void *) msg);
962 /******************************************************************************/
963 /*********************** RECEIVE FUNCTIONS MESH ********************/
964 /******************************************************************************/
967 * Function to handle a initiation messaage incoming over mesh
968 * @param cls closure, NULL
969 * @param tunnel the tunnel over which the message arrived
970 * @param tunnel_ctx the tunnel context, can be NULL
971 * @param message the incoming message
976 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
978 const struct GNUNET_MessageHeader *message)
981 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
982 const struct GNUNET_PeerIdentity *peer =
983 GNUNET_PEER_resolve2 (tunnel->peer);
985 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
986 _("Handling MeshSessionInitiateMessage from peer: %s\n"),
987 GNUNET_i2s_full (peer));
988 GNUNET_MESH_receive_done (tunnel);
990 if (LISTEN != connection.status
991 || 1 > GNUNET_CONTAINER_slist_count (clients))
994 if (CONNECTED == connection.status)
996 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
998 ("Rejected call from %s because there is an active call"),
999 GNUNET_i2s_full (peer));
1000 reject_reason = htons (REJECT_REASON_ACTIVE_CALL);
1002 // Notifying client about missed call
1004 sizeof (struct ServerClientMissedCallMessage) +
1005 sizeof (struct MissedCall);
1006 struct ServerClientMissedCallMessage *message =
1007 GNUNET_malloc (msg_size);
1009 message->header.size = htons (msg_size);
1010 message->header.type =
1011 htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1012 message->number = 1;
1014 memcpy (&(message->missed_call->peer), peer,
1015 sizeof (struct GNUNET_PeerIdentity));
1016 message->missed_call->time = GNUNET_TIME_absolute_get ();
1019 GNUNET_SERVER_notify_transmit_ready (connection.client,
1021 ServerClientMissedCallMessage),
1023 &transmit_server_missed_call_message,
1026 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1028 ("Could not queue ServerClientMissedCallMessage\n"));
1029 GNUNET_free (message);
1033 if (1 > GNUNET_CONTAINER_slist_count (clients))
1035 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1036 _("Got a call from %s while no client connected.\n"),
1037 GNUNET_i2s_full (peer));
1038 reject_reason = htons (REJECT_REASON_NO_CLIENT);
1039 // Store missed calls
1040 struct MissedCall call;
1041 memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1042 call.time = GNUNET_TIME_absolute_get ();
1043 GNUNET_CONTAINER_slist_add_end (missed_calls,
1044 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1045 &call, sizeof (struct MissedCall));
1049 reject_call (tunnel, reject_reason);
1053 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
1054 GNUNET_i2s_full (peer));
1055 tunnel_reliable = tunnel;
1056 connection.status = CALLEE;
1057 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1058 _("Changed connection status to %d\n"), connection.status);
1059 memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1061 struct GNUNET_CONTAINER_SList_Iterator iterator =
1062 GNUNET_CONTAINER_slist_begin (clients);
1065 struct VoipClient *conversation_client =
1066 (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1068 struct GNUNET_SERVER_Client *client = conversation_client->client;
1069 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1073 GNUNET_SERVER_notify_transmit_ready (client,
1075 ServerClientSessionInitiateMessage),
1077 &transmit_server_initiate_message,
1080 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1082 ("Could not queue ServerClientSessionInitiateMessage\n"));
1085 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1087 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1089 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1097 * Function to handle an accept messaage incoming over mesh
1098 * @param cls closure, NULL
1099 * @param tunnel the tunnel over which the message arrived
1100 * @param tunnel_ctx the tunnel context, can be NULL
1101 * @param message the incoming message
1106 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1108 const struct GNUNET_MessageHeader *message)
1110 static uint32_t port = 50003;
1111 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1112 const struct GNUNET_PeerIdentity *peer =
1113 GNUNET_PEER_resolve2 (tunnel->peer);
1115 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1117 ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"),
1118 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1119 GNUNET_MESH_receive_done (tunnel);
1122 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1123 && connection.status == CALLER)
1126 GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1128 if (NULL == tunnel_unreliable)
1130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1131 _("Could not create unreliable tunnel\n"));
1133 status_to_listen ();
1135 GNUNET_SERVER_notify_transmit_ready (connection.client,
1137 ServerClientSessionRejectMessage),
1139 &transmit_server_reject_message,
1141 return GNUNET_SYSERR;
1144 if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1146 GNUNET_SCHEDULER_cancel (timeout_task);
1147 timeout_task = GNUNET_SCHEDULER_NO_TASK;
1150 connection.status = CONNECTED;
1151 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1152 _("Changed connection status to %d\n"), connection.status);
1155 GNUNET_SERVER_notify_transmit_ready (connection.client,
1157 ServerClientSessionAcceptMessage),
1159 &transmit_server_accept_message,
1162 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1164 ("Could not queue ServerClientSessionAcceptMessage\n"));
1165 return GNUNET_SYSERR;
1168 start_time = GNUNET_TIME_absolute_get ();
1170 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1177 * Function to handle a reject messaage incoming over mesh
1178 * @param cls closure, NULL
1179 * @param tunnel the tunnel over which the message arrived
1180 * @param tunnel_ctx the tunnel context, can be NULL
1181 * @param message the incoming message
1186 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1188 const struct GNUNET_MessageHeader *message)
1190 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1191 const struct GNUNET_PeerIdentity *peer =
1192 GNUNET_PEER_resolve2 (tunnel->peer);
1194 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1196 ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"),
1197 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1198 GNUNET_MESH_receive_done (tunnel);
1201 memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1202 && connection.status == CALLER)
1205 GNUNET_SERVER_notify_transmit_ready (connection.client,
1207 ServerClientSessionRejectMessage),
1209 &transmit_server_reject_message,
1212 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1214 ("Could not queue ServerClientSessionRejectMessage\n"));
1217 status_to_listen ();
1219 if (NULL != tunnel_reliable)
1221 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1222 tunnel_reliable = NULL;
1230 * Function to handle a terminate messaage incoming over mesh
1231 * @param cls closure, NULL
1232 * @param tunnel the tunnel over which the message arrived
1233 * @param tunnel_ctx the tunnel context, can be NULL
1234 * @param message the incoming message
1239 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1241 const struct GNUNET_MessageHeader *message)
1243 //struct GNUNET_PeerIdentity *peer = (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1244 const struct GNUNET_PeerIdentity *peer =
1245 GNUNET_PEER_resolve2 (tunnel->peer);
1247 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1249 ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"),
1250 GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1251 GNUNET_MESH_receive_done (tunnel);
1253 if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1254 && (connection.status == CONNECTED || connection.status == CALLEE))
1256 status_to_listen ();
1258 if (NULL != tunnel_unreliable)
1260 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1261 tunnel_unreliable = NULL;
1264 if (NULL != tunnel_reliable)
1266 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1267 tunnel_reliable = NULL;
1275 * Function to handle a audio messaage incoming over mesh
1276 * @param cls closure, NULL
1277 * @param tunnel the tunnel over which the message arrived
1278 * @param tunnel_ctx the tunnel context, can be NULL
1279 * @param message the incoming message
1284 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1286 const struct GNUNET_MessageHeader *message)
1289 GNUNET_MESH_receive_done (tunnel);
1291 if (CONNECTED != connection.status)
1295 struct AudioMessage *audio;
1297 msg_size = sizeof (struct AudioMessage);
1299 audio = (struct AudioMessage *) message;
1301 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "[RECV] %dbytes\n", audio->length);
1303 if (NULL == playback_helper)
1306 (void) GNUNET_HELPER_send (playback_helper,
1307 message, GNUNET_YES, NULL, NULL);
1310 data_received_size += msg_size;
1315 /******************************************************************************/
1316 /*********************** HELPER *******************/
1317 /******************************************************************************/
1320 * Function to process the audio from the record helper
1321 * @param cls closure, NULL
1322 * @param client NULL
1323 * @param msg the message from the helper
1328 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1329 const struct GNUNET_MessageHeader *msg)
1332 struct AudioMessage *message = (struct AudioMessage *) msg;
1333 msg_size = sizeof (struct AudioMessage);
1335 GNUNET_log (GNUNET_ERROR_TYPE_INFO, " [REC] %dbyte\n", message->length);
1336 GNUNET_CONTAINER_slist_add_end (audio_buffer,
1337 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1344 * Function to to start the playback helper
1346 * @return 0 ok, 1 on error
1349 start_playback_helper (void)
1351 static char *playback_helper_argv[1];
1354 playback_helper_argv[0] = "gnunet-helper-audio-playback";
1355 playback_helper = GNUNET_HELPER_start (GNUNET_NO,
1356 "gnunet-helper-audio-playback",
1357 playback_helper_argv,
1360 if (NULL == playback_helper)
1363 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1364 _("Could not start playback audio helper.\n"));
1371 * Function to to start the record helper
1373 * @return 0 ok, 1 on error
1376 start_record_helper (void)
1378 static char *record_helper_argv[1];
1381 record_helper_argv[0] = "gnunet-helper-audio-record";
1382 record_helper = GNUNET_HELPER_start (GNUNET_NO,
1383 "gnunet-helper-audio-record",
1385 &process_record_messages, NULL, NULL);
1387 if (NULL == record_helper)
1390 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1391 _("Could not start record audio helper\n"));
1399 * Function to to start both helpers
1401 * @return 0 ok, 1 on error
1404 start_helpers (void)
1407 if (0 == start_playback_helper () || 0 == start_record_helper ())
1413 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1419 * Function to to stop the playback helper
1422 stop_playback_helper (void)
1424 if (NULL != playback_helper)
1426 GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1427 playback_helper = NULL;
1429 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1434 * Function to to stop the record helper
1437 stop_record_helper (void)
1439 if (NULL != record_helper)
1441 GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1442 record_helper = NULL;
1444 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1449 * Function to stop both audio helpers
1454 stop_playback_helper ();
1455 stop_record_helper ();
1458 /******************************************************************************/
1459 /*********************** TUNNEL HANDLING *******************/
1460 /******************************************************************************/
1463 * Method called whenever another peer has added us to a tunnel
1464 * the other peer initiated.
1466 * @param cls closure
1467 * @param tunnel new handle to the tunnel
1468 * @param initiator peer that started the tunnel
1470 * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1473 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1474 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1476 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1477 _("Received incoming tunnel on port %d\n"), port);
1480 tunnel_unreliable = tunnel;
1482 start_time = GNUNET_TIME_absolute_get ();
1485 audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1493 * Function called whenever an inbound tunnel is destroyed. Should clean up
1494 * any associated state.
1496 * @param cls closure (set from GNUNET_MESH_connect)
1497 * @param tunnel connection to the other end (henceforth invalid)
1498 * @param tunnel_ctx place where local state associated
1499 * with the tunnel is stored
1502 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1505 if (tunnel == tunnel_unreliable)
1507 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1510 tunnel_unreliable = NULL;
1513 if (tunnel == tunnel_reliable)
1515 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1517 if (LISTEN != connection.status && NULL != connection.client)
1520 GNUNET_SERVER_notify_transmit_ready (connection.client,
1522 ServerClientSessionTerminateMessage),
1524 &transmit_server_terminate_message,
1527 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1529 ("Could not queue ServerClientSessionTerminateMessage\n"));
1533 status_to_listen ();
1537 /******************************************************************************/
1538 /*********************** CLIENT HANDLING *******************/
1539 /******************************************************************************/
1542 * A client connected.
1544 * @param cls closure, NULL
1545 * @param client identification of the client
1549 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1551 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1552 struct ServerClientMissedCallMessage *message;
1554 struct VoipClient c;
1557 GNUNET_CONTAINER_slist_add_end (clients,
1558 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1559 &c, sizeof (struct VoipClient));
1560 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
1562 if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1566 sizeof (struct ServerClientMissedCallMessage) +
1567 GNUNET_CONTAINER_slist_count (missed_calls) *
1568 sizeof (struct MissedCall);
1570 (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1572 message->header.size = htons (msg_size);
1573 message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1574 message->number = GNUNET_CONTAINER_slist_count (missed_calls);
1576 struct GNUNET_CONTAINER_SList_Iterator iterator =
1577 GNUNET_CONTAINER_slist_begin (missed_calls);
1580 memcpy (&(message->missed_call[i]),
1581 GNUNET_CONTAINER_slist_get (&iterator, NULL),
1582 sizeof (struct MissedCall));
1585 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1587 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1588 GNUNET_CONTAINER_slist_clear (missed_calls);
1592 GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1594 &transmit_server_missed_call_message,
1597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1598 _("Could not queue ServerClientMissedCallMessage\n"));
1599 GNUNET_free (message);
1607 * A client disconnected. Remove all of its data structure entries.
1609 * @param cls closure, NULL
1610 * @param client identification of the client
1613 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1615 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1617 if (connection.client == cl)
1619 if (CONNECTED == connection.status)
1625 status_to_listen ();
1629 struct GNUNET_CONTAINER_SList_Iterator iterator =
1630 GNUNET_CONTAINER_slist_begin (clients);
1633 if (((struct VoipClient *)
1634 GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1636 GNUNET_CONTAINER_slist_erase (&iterator);
1639 while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1641 GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1646 /******************************************************************************/
1647 /*********************** SERVICE *******************/
1648 /******************************************************************************/
1653 * @param cls closure, NULL
1654 * @param tc the task context
1657 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1659 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1663 if (NULL != tunnel_reliable)
1665 GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1668 if (NULL != tunnel_unreliable)
1670 GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1675 GNUNET_MESH_disconnect (mesh);
1680 GNUNET_SERVER_notification_context_destroy (nc);
1684 GNUNET_CONTAINER_slist_destroy (audio_buffer);
1685 GNUNET_CONTAINER_slist_destroy (clients);
1686 GNUNET_CONTAINER_slist_destroy (missed_calls);
1687 GNUNET_CONTAINER_slist_destroy (peers_to_notify);
1692 * Handler array for traffic received
1694 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1695 {&handle_mesh_initiate_message,
1696 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
1697 sizeof (struct MeshSessionInitiateMessage)},
1698 {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
1699 sizeof (struct MeshSessionAcceptMessage)},
1700 {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
1701 sizeof (struct MeshSessionRejectMessage)},
1702 {&handle_mesh_terminate_message,
1703 GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
1704 sizeof (struct MeshSessionTerminateMessage)},
1705 {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
1706 sizeof (struct AudioMessage)},
1711 * Main function that will be run by the scheduler.
1713 * @param cls closure
1714 * @param server server handle
1715 * @param c configuration
1718 run (void *cls, struct GNUNET_SERVER_Handle *server,
1719 const struct GNUNET_CONFIGURATION_Handle *c)
1722 static uint32_t ports[] = { 50002, 50003, 0 };
1725 mesh = GNUNET_MESH_connect (cfg,
1728 &inbound_end, mesh_handlers, ports);
1732 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1737 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1740 static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1741 {&handle_session_initiate_message, NULL,
1742 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
1743 sizeof (struct ClientServerSessionInitiateMessage)},
1744 {&handle_session_accept_message, NULL,
1745 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
1746 sizeof (struct ClientServerSessionAcceptMessage)},
1747 {&handle_session_reject_message, NULL,
1748 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
1749 sizeof (struct ClientServerSessionRejectMessage)},
1750 {&handle_session_terminate_message, NULL,
1751 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
1752 sizeof (struct ClientServerSessionTerminateMessage)},
1756 connection.status = LISTEN;
1758 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1761 nc = GNUNET_SERVER_notification_context_create (server, 16);
1763 GNUNET_SERVER_add_handlers (server, server_handlers);
1764 GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
1765 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1766 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
1769 clients = GNUNET_CONTAINER_slist_create ();
1772 missed_calls = GNUNET_CONTAINER_slist_create ();
1773 peers_to_notify = GNUNET_CONTAINER_slist_create ();
1774 audio_buffer = GNUNET_CONTAINER_slist_create ();
1776 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1780 * The main function for the conversation service.
1782 * @param argc number of arguments from the command line
1783 * @param argv command line arguments
1784 * @return 0 ok, 1 on error
1787 main (int argc, char *const *argv)
1789 return (GNUNET_OK ==
1790 GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1791 &run, NULL)) ? 0 : 1;
1794 /* end of gnunet-service-conversation.c */