-note on todo
[oweals/gnunet.git] / src / conversation / gnunet-service-conversation.c
1 /*
2   This file is part of GNUnet.
3   (C) 2013 Christian Grothoff (and other contributing authors)
4   
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.
9   
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.
14   
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.
19 */
20 /**
21  * @file conversation/gnunet-service-conversation.c
22  * @brief conversation service implementation
23  * @author Simon Dieterle
24  * @author Andreas Fuchs
25  * STRUCTURE:
26  * - Variables
27  * - AUXILIARY FUNCTIONS
28  * - SENDING FUNCTIONS CL -> SERVER
29  * - RECEIVE FUNCTIONS CL -> SERVER
30  * - SENDING FUNCTIONS MESH
31  * - RECEIVE FUNCTIONS MESH
32  * - HELPER
33  * - TUNNEL HANDLING
34  * - CLIENT HANDLING
35  */
36 #include "platform.h"
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"
43
44
45
46 /*
47 * The possible connection status
48 */
49 enum connection_status
50 {
51   LISTEN,
52   CALLER,
53   CALLEE,
54   CONNECTED
55 };
56
57
58 /******************************************************** 
59  * Ugly hack because of not working MESH API
60 */
61 typedef uint32_t MESH_TunnelNumber;
62 struct GNUNET_MESH_Tunnel
63 {
64   struct GNUNET_MESH_Tunnel *next;
65   struct GNUNET_MESH_Tunnel *prev;
66   struct GNUNET_MESH_Handle *mesh;
67   MESH_TunnelNumber tid;
68   uint32_t port;
69   GNUNET_PEER_Id peer;
70   void *ctx;
71   unsigned int packet_size;
72   int buffering;
73   int reliable;
74   int allow_send;
75 };
76
77
78 /**
79  * Our configuration.
80  */
81 static const struct GNUNET_CONFIGURATION_Handle *cfg;
82
83 /**
84  * Head of the list of current clients.
85  */
86 static struct GNUNET_CONTAINER_SList *clients;
87
88 /**
89  * Notification context containing all connected clients.
90  */
91 struct GNUNET_SERVER_NotificationContext *nc = NULL;
92
93 /**
94 * The connection status
95 */
96 static struct ConnectionStatus connection;
97
98 /**
99 * Handle for the record helper
100 */
101 static struct GNUNET_HELPER_Handle *record_helper;
102
103 /** Handle for the playback handler
104 *
105 */
106 static struct GNUNET_HELPER_Handle *playback_helper;
107
108 /**
109 * Handle for mesh
110 */
111 static struct GNUNET_MESH_Handle *mesh;
112
113 /**
114 * Transmit handle for audio messages
115 */
116 static struct GNUNET_MESH_TransmitHandle *mth = NULL;
117
118 /**
119 * Handle for the reliable tunnel (contol data)
120 */
121 static struct GNUNET_MESH_Tunnel *tunnel_reliable;
122
123 /**
124 * Handle for unreliable tunnel (audio data)
125 */
126 static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
127
128 /**
129 * List for missed calls
130 */
131 static struct GNUNET_CONTAINER_SList *missed_calls;
132
133 /**
134 * List for peers to notify that we are available again
135 */
136 static struct GNUNET_CONTAINER_SList *peers_to_notify;
137
138 /**
139 * Audio buffer (outgoing)
140 */
141 static struct GNUNET_CONTAINER_SList *audio_buffer;
142
143 /**
144 * The pointer to the task for sending audio
145 */
146 static GNUNET_SCHEDULER_TaskIdentifier audio_task;
147
148 /**
149 * The pointer to the task for checking timeouts an calling a peer
150 */
151 static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
152
153 /**
154  * Timestamp for call statistics
155  */
156 static struct GNUNET_TIME_Absolute start_time;
157
158 /**
159  * Number of payload packes sent
160  */
161 static int data_sent;
162 static int data_sent_size;
163
164 /**
165  * Number of payload packets received
166  */
167 static int data_received;
168 static int data_received_size;
169
170
171 /**
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
177  */
178 static size_t transmit_mesh_message (void *cls, size_t size, void *buf);
179
180 /**
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
183  * the meantime.
184  *
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
189  */
190 static size_t
191 transmit_server_no_answer_message (void *cls, size_t size, void *buf);
192
193 /**
194  * Task to schedule a audio transmission.
195  * 
196  * @param cls Closure.
197  * @param tc Task Context.
198  */
199 static void
200 transmit_audio_task (void *cls,
201                      const struct GNUNET_SCHEDULER_TaskContext *tc);
202
203 /**
204 * Start the audio helpers
205 */
206 int start_helpers (void);
207
208 /**
209 * Stop the audio helpers
210 */
211 void stop_helpers (void);
212
213
214
215 /******************************************************************************/
216 /***********************     AUXILIARY FUNCTIONS      *************************/
217 /******************************************************************************/
218
219 /**
220 * Function which displays some call stats
221 */
222 static void
223 show_end_data (void)
224 {
225   static struct GNUNET_TIME_Absolute end_time;
226   static struct GNUNET_TIME_Relative total_time;
227
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,
233                                                    GNUNET_NO));
234   FPRINTF (stderr, "Test total packets: %d\n", 
235            data_sent);
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
240
241   FPRINTF (stderr, "\nResults of recv\n");
242   FPRINTF (stderr, "Test time %s\n",
243            GNUNET_STRINGS_relative_time_to_string (total_time,
244                                                    GNUNET_NO));
245   FPRINTF (stderr, "Test total packets: %d\n", 
246            data_received);
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
251 }
252
253 /**
254 * Function which sets the connection state to LISTEN
255 */
256 static void
257 status_to_listen (void)
258 {
259
260   if (CONNECTED == connection.status)
261     {
262       show_end_data ();
263     }
264
265   if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
266     {
267       GNUNET_SCHEDULER_cancel (timeout_task);
268       timeout_task = GNUNET_SCHEDULER_NO_TASK;
269     }
270
271   stop_helpers ();
272
273   connection.status = LISTEN;
274   connection.client = NULL;
275
276   data_sent = 0;
277   data_sent_size = 0;
278   data_received = 0;
279   data_received_size = 0;
280
281   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
282               "LISTEN");
283 }
284
285 /**
286 * Function to terminate the active call
287 */
288 static void
289 terminate_call ()
290 {
291   size_t msg_size;
292   msg_size = sizeof (struct MeshSessionTerminateMessage);
293   struct MeshSessionTerminateMessage *message_mesh_terminate =
294     (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
295
296   if (NULL == message_mesh_terminate)
297     {
298       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299                   _("Could not create MeshSessionTerminateMessage\n"));
300       status_to_listen ();
301
302       return;
303     }
304
305   message_mesh_terminate->header.size = htons (msg_size);
306   message_mesh_terminate->header.type =
307     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
308
309   if (NULL ==
310       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
311                                          MAX_TRANSMIT_DELAY, msg_size,
312                                          &transmit_mesh_message,
313                                          (void *) message_mesh_terminate))
314     {
315       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316                   _("Could not queue MeshSessionTerminateMessage\n"));
317       GNUNET_free (message_mesh_terminate);
318       status_to_listen ();
319     }
320 }
321
322 /**
323 * Function to reject a call
324 *
325 * @param tunnel the tunnel where to reject the incoming call
326 * @param reason te reson why the call is rejected
327 */
328 static void
329 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
330 {
331   size_t msg_size;
332   msg_size = sizeof (struct MeshSessionRejectMessage);
333   struct MeshSessionRejectMessage *message_mesh_reject =
334     (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
335
336   if (NULL == message_mesh_reject)
337     {
338       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
339                   _("Could not create MeshSessionRejectMessage\n"));
340       status_to_listen ();
341
342       return;
343     }
344
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);
349
350   if (NULL ==
351       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
352                                          MAX_TRANSMIT_DELAY, msg_size,
353                                          &transmit_mesh_message,
354                                          (void *) message_mesh_reject))
355     {
356       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357                   _("Could not queue MeshSessionRejectMessage\n"));
358       GNUNET_free (message_mesh_reject);
359       status_to_listen ();
360     }
361 }
362
363 /**
364  * Check for timeout when calling a peer
365  *
366  * @param cls closure, NULL
367  * @param tc the task context (can be NULL)
368  */
369 static void
370 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
371 {
372   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
373
374   if (NULL ==
375       GNUNET_SERVER_notify_transmit_ready (connection.client,
376                                            sizeof (struct
377                                                    ServerClientNoAnswerMessage),
378                                            MAX_TRANSMIT_DELAY,
379                                            &transmit_server_no_answer_message,
380                                            NULL))
381     {
382       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383                   _("Could not queue ServerClientNoAnswerMessage\n"));
384     }
385
386   terminate_call ();
387 }
388
389 /******************************************************************************/
390 /***********************  SENDING FUNCTIONS CL -> SERVER    *******************/
391 /******************************************************************************/
392
393 /**
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
396  * the meantime.
397  *
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
402  */
403 static size_t
404 transmit_server_initiate_message (void *cls, size_t size, void *buf)
405 {
406   struct ServerClientSessionInitiateMessage *msg;
407   size_t msg_size;
408
409   msg_size = sizeof (struct ServerClientSessionInitiateMessage);
410
411   GNUNET_assert (size >= msg_size);
412
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));
418
419   return msg_size;
420 }
421
422 /**
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
425  * the meantime.
426  *
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
431  */
432 static size_t
433 transmit_server_accept_message (void *cls, size_t size, void *buf)
434 {
435   struct ServerClientSessionAcceptMessage *msg;
436   size_t msg_size;
437
438   msg_size = sizeof (struct ServerClientSessionAcceptMessage);
439
440   GNUNET_assert (size >= msg_size);
441
442   msg = (struct ServerClientSessionAcceptMessage *) buf;
443   msg->header.size = htons (msg_size);
444   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
445
446   return msg_size;
447 }
448
449 /**
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
452  * the meantime.
453  *
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
458  */
459 static size_t
460 transmit_server_reject_message (void *cls, size_t size, void *buf)
461 {
462   struct ServerClientSessionRejectMessage *msg;
463   size_t msg_size;
464
465   msg_size = sizeof (struct ServerClientSessionRejectMessage);
466
467   GNUNET_assert (size >= msg_size);
468
469   msg = (struct ServerClientSessionRejectMessage *) buf;
470   msg->header.size = htons (msg_size);
471   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
472
473   if (NULL == cls)
474     {
475       msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE);
476     }
477   else
478     {
479       msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
480     }
481
482   return msg_size;
483 }
484
485 /**
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
488  * the meantime.
489  *
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
494  */
495 static size_t
496 transmit_server_terminate_message (void *cls, size_t size, void *buf)
497 {
498   struct ServerClientSessionTerminateMessage *msg;
499   size_t msg_size;
500
501   msg_size = sizeof (struct ServerClientSessionTerminateMessage);
502
503   GNUNET_assert (size >= msg_size);
504
505   msg = (struct ServerClientSessionTerminateMessage *) buf;
506   msg->header.size = htons (msg_size);
507   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
508
509   return msg_size;
510 }
511
512 /**
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
515  * the meantime.
516  *
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
521  */
522 static size_t
523 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
524 {
525   struct ServerClientMissedCallMessage *msg;
526   msg = (struct ServerClientMissedCallMessage *) cls;
527
528   memcpy (buf, msg, size);
529   GNUNET_free (msg);
530
531   return size;
532 }
533
534 /**
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
537  * the meantime.
538  *
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
543  */
544 static size_t
545 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
546 {
547   struct ServerClientServiceBlockedMessage *msg;
548   size_t msg_size;
549
550   msg_size = sizeof (struct ServerClientServiceBlockedMessage);
551
552   GNUNET_assert (size >= msg_size);
553
554   msg = (struct ServerClientServiceBlockedMessage *) buf;
555   msg->header.size = htons (msg_size);
556   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
557
558   return msg_size;
559 }
560
561 /**
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
564  * the meantime.
565  *
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
570  */
571 static size_t
572 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
573 {
574   struct ServerClientPeerNotConnectedMessage *msg;
575   size_t msg_size;
576
577   msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
578
579   GNUNET_assert (size >= msg_size);
580
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);
584
585   return msg_size;
586 }
587
588 /**
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
591  * the meantime.
592  *
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
597  */
598 static size_t
599 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
600 {
601   struct ServerClientNoAnswerMessage *msg;
602   size_t msg_size;
603
604   msg_size = sizeof (struct ServerClientNoAnswerMessage);
605
606   GNUNET_assert (size >= msg_size);
607
608   msg = (struct ServerClientNoAnswerMessage *) buf;
609   msg->header.size = htons (msg_size);
610   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
611
612   return msg_size;
613 }
614
615 /**
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
618  * the meantime.
619  *
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
624  */
625 static size_t
626 transmit_server_error_message (void *cls, size_t size, void *buf)
627 {
628   struct ServerClientErrorMessage *msg;
629   size_t msg_size;
630
631   msg_size = sizeof (struct ServerClientErrorMessage);
632
633   GNUNET_assert (size >= msg_size);
634
635   msg = (struct ServerClientErrorMessage *) buf;
636   msg->header.size = htons (msg_size);
637   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
638
639   return msg_size;
640 }
641
642 /******************************************************************************/
643 /***********************  RECEIVE FUNCTIONS CL -> SERVER   ********************/
644 /******************************************************************************/
645
646 /**
647  * Function to handle a session initiate message from the client
648  *
649  * @param cls closure, NULL
650  * @param client the client from which the message is
651  * @param message the message from the client
652 */
653 static void
654 handle_session_initiate_message (void *cls,
655                                  struct GNUNET_SERVER_Client *client,
656                                  const struct GNUNET_MessageHeader *message)
657 {
658   static uint32_t port = 50002;
659   size_t msg_size;
660   struct ClientServerSessionInitiateMessage *msg =
661     (struct ClientServerSessionInitiateMessage *) message;
662   struct GNUNET_PeerIdentity *peer = &(msg->peer);
663
664   GNUNET_SERVER_receive_done (client, GNUNET_OK);
665
666   if (NULL != connection.client)
667     {
668       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
669                   _("There is already a peer in interaction\n"));
670       GNUNET_SERVER_notify_transmit_ready (client,
671                                            sizeof (struct
672                                                    ServerClientServiceBlockedMessage),
673                                            MAX_TRANSMIT_DELAY,
674                                            &transmit_server_service_blocked_message,
675                                            NULL);
676
677       return;
678     }
679
680   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
681               GNUNET_i2s_full (peer));
682   tunnel_reliable =
683     GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
684   if (NULL == tunnel_reliable)
685     {
686       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
687                   _("Could not create reliable tunnel\n"));
688       GNUNET_SERVER_notify_transmit_ready (client,
689                                            sizeof (struct
690                                                    ServerClientPeerNotConnectedMessage),
691                                            MAX_TRANSMIT_DELAY,
692                                            &transmit_server_peer_not_connected_message,
693                                            NULL);
694
695       return;
696     }
697
698   msg_size = sizeof (struct MeshSessionInitiateMessage);
699   struct MeshSessionInitiateMessage *message_mesh_initiate =
700     (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
701
702   if (NULL == message_mesh_initiate)
703     {
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,
709                                            sizeof (struct
710                                                    ServerClientErrorMessage),
711                                            MAX_TRANSMIT_DELAY,
712                                            &transmit_server_error_message,
713                                            NULL);
714
715       return;
716     }
717
718   message_mesh_initiate->header.size = htons (msg_size);
719   message_mesh_initiate->header.type =
720     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
721
722   if (NULL ==
723       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
724                                          MAX_TRANSMIT_DELAY, msg_size,
725                                          &transmit_mesh_message,
726                                          (void *) message_mesh_initiate))
727     {
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,
734                                            sizeof (struct
735                                                    ServerClientErrorMessage),
736                                            MAX_TRANSMIT_DELAY,
737                                            &transmit_server_error_message,
738                                            NULL);
739
740       return;
741     }
742
743   connection.status = CALLER;
744   connection.client = client;
745   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
746               connection.status);
747   memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
748
749   return;
750 }
751
752 /**
753  * Function to handle a session accept message from the client
754  *
755  * @param cls closure, NULL
756  * @param client the client from which the message is
757  * @param message the message from the client
758 */
759 static void
760 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
761                                const struct GNUNET_MessageHeader *message)
762 {
763   size_t msg_size;
764
765   GNUNET_SERVER_receive_done (client, GNUNET_OK);
766
767   if (connection.status != CALLEE)
768     {
769       // TODO send illegal command
770       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
771                   _
772                   ("handle_session_accept_message called when not allowed\n"));
773       return;
774     }
775
776   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
777               GNUNET_i2s_full (&(connection.peer)));
778
779   msg_size = sizeof (struct MeshSessionAcceptMessage);
780   struct MeshSessionAcceptMessage *message_mesh_accept =
781     (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
782
783   if (NULL == message_mesh_accept)
784     {
785       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786                   _("Could not create MeshSessionAcceptMessage\n"));
787       return;
788     }
789
790   message_mesh_accept->header.size = htons (msg_size);
791   message_mesh_accept->header.type =
792     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
793
794   if (NULL ==
795       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
796                                          MAX_TRANSMIT_DELAY, msg_size,
797                                          &transmit_mesh_message,
798                                          (void *) message_mesh_accept))
799     {
800       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
801                   _("Could not queue MeshSessionAcceptMessage\n"));
802       GNUNET_free (message_mesh_accept);
803       return;
804     }
805
806   connection.status = CONNECTED;
807   connection.client = client;
808   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
809               connection.status);
810
811   return;
812 }
813
814 /**
815  * Function to handle a session reject message from the client
816  *
817  * @param cls closure, NULL
818  * @param client the client from which the message is
819  * @param message the message from the client
820 */
821 static void
822 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
823                                const struct GNUNET_MessageHeader *message)
824 {
825   struct ClientServerSessionRejectMessage *message_received;
826
827   GNUNET_SERVER_receive_done (client, GNUNET_OK);
828
829   if (connection.status != CALLEE)
830     {
831       // TODO send illegal command
832       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
833                   _
834                   ("handle_session_reject_message called when not allowed\n"));
835       return;
836     }
837
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));
842
843   return;
844 }
845
846 /**
847  * Function to handle a session terminate message from the client
848  *
849  * @param cls closure, NULL
850  * @param client the client from which the message is
851  * @param message the message from the client
852 */
853 static void
854 handle_session_terminate_message (void *cls,
855                                   struct GNUNET_SERVER_Client *client,
856                                   const struct GNUNET_MessageHeader *message)
857 {
858   GNUNET_SERVER_receive_done (client, GNUNET_OK);
859
860   if (connection.client == NULL || connection.status == CALLEE)
861     {
862       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
863                   _
864                   ("handle_session_terminate_message called when not allowed\n"));
865       return;
866     }
867
868   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
869               GNUNET_i2s_full (&(connection.peer)));
870   terminate_call ();
871 }
872
873 /******************************************************************************/
874 /***********************       SENDING FUNCTIONS MESH       *******************/
875 /******************************************************************************/
876
877 /**
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
883  */
884 static size_t
885 transmit_mesh_message (void *cls, size_t size, void *buf)
886 {
887   struct VoIPMeshMessageHeader *msg_header =
888     (struct VoIPMeshMessageHeader *) cls;
889
890   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
891
892   memcpy (buf, cls, size);
893   // Check if this is correct
894
895
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)))
900     {
901       status_to_listen ();
902     }
903   else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
904            ntohs (msg_header->header.type))
905     {
906       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
907       timeout_task =
908         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
909                                       (GNUNET_TIME_UNIT_SECONDS, 30),
910                                       &check_timeout, NULL);
911     }
912
913   GNUNET_free (cls);
914
915   return size;
916 }
917
918 /**
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
924  */
925 static size_t
926 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
927 {
928   struct AudioMessage *message = (struct AudioMessage *) cls;
929
930   if (size < sizeof (struct AudioMessage) || NULL == buf)
931     {
932       GNUNET_break (0);
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);
936       return 0;
937     }
938
939   memcpy (buf, message, size);
940
941   data_sent++;
942   data_sent_size += size;
943
944   GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
945
946   audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
947
948   return size;
949 }
950
951 /**
952  * Task to schedule a audio transmission.
953  * 
954  * @param cls Closure.
955  * @param tc Task Context.
956  */
957 static void
958 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
959 {
960   struct GNUNET_CONTAINER_SList_Iterator iterator;
961   struct AudioMessage *msg;
962   int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
963
964   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
965
966   if (NULL == cls)
967     {
968       if (0 == ab_length && CONNECTED == connection.status)
969         {
970           audio_task =
971             GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
972                                           (GNUNET_TIME_UNIT_MILLISECONDS, 10),
973                                           &transmit_audio_task, NULL);
974           return;
975         }
976
977       iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
978       msg =
979         (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
980       GNUNET_CONTAINER_slist_erase (&iterator);
981       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
982     }
983   else
984     {
985       msg = (struct AudioMessage *) cls;
986     }
987
988   if (NULL == tunnel_unreliable)
989     {
990       GNUNET_CONTAINER_slist_clear (audio_buffer);
991       return;
992     }
993
994   mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
995                                            MAX_TRANSMIT_DELAY,
996                                            sizeof (struct AudioMessage),
997                                            &transmit_mesh_audio_message,
998                                            (void *) msg);
999
1000   if (NULL == mth)
1001     {
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");
1005       audio_task =
1006         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1007                                       &transmit_audio_task, (void *) msg);
1008     }
1009 }
1010
1011 /******************************************************************************/
1012 /***********************       RECEIVE FUNCTIONS MESH      ********************/
1013 /******************************************************************************/
1014
1015 /**
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
1021  * 
1022  * @return GNUNET_OK
1023 */
1024 int
1025 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1026                               void **tunnel_ctx,
1027                               const struct GNUNET_MessageHeader *message)
1028 {
1029   int reject_reason;
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);
1033
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);
1038
1039   if (LISTEN != connection.status
1040       || 1 > GNUNET_CONTAINER_slist_count (clients))
1041     {
1042
1043       if (CONNECTED == connection.status)
1044         {
1045           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1046                       _
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);
1050
1051           // Notifying client about missed call
1052           size_t msg_size =
1053             sizeof (struct ServerClientMissedCallMessage) +
1054             sizeof (struct MissedCall);
1055           struct ServerClientMissedCallMessage *message =
1056             GNUNET_malloc (msg_size);
1057
1058           message->header.size = htons (msg_size);
1059           message->header.type =
1060             htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1061           message->number = 1;
1062
1063           memcpy (&(message->missed_call->peer), peer,
1064                   sizeof (struct GNUNET_PeerIdentity));
1065           message->missed_call->time = GNUNET_TIME_absolute_get ();
1066
1067           if (NULL ==
1068               GNUNET_SERVER_notify_transmit_ready (connection.client,
1069                                                    sizeof (struct
1070                                                            ServerClientMissedCallMessage),
1071                                                    MAX_TRANSMIT_DELAY,
1072                                                    &transmit_server_missed_call_message,
1073                                                    (void *) message))
1074             {
1075               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1076                           _
1077                           ("Could not queue ServerClientMissedCallMessage\n"));
1078               GNUNET_free (message);
1079             }
1080         }
1081
1082       if (1 > GNUNET_CONTAINER_slist_count (clients))
1083         {
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));
1095
1096         }
1097
1098       reject_call (tunnel, reject_reason);
1099     }
1100   else
1101     {
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));
1109
1110       struct GNUNET_CONTAINER_SList_Iterator iterator =
1111         GNUNET_CONTAINER_slist_begin (clients);
1112       do
1113         {
1114           struct VoipClient *conversation_client =
1115             (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1116                                                               NULL);
1117           struct GNUNET_SERVER_Client *client = conversation_client->client;
1118           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1119                       client);
1120
1121           if (NULL ==
1122               GNUNET_SERVER_notify_transmit_ready (client,
1123                                                    sizeof (struct
1124                                                            ServerClientSessionInitiateMessage),
1125                                                    MAX_TRANSMIT_DELAY,
1126                                                    &transmit_server_initiate_message,
1127                                                    (void *) peer))
1128             {
1129               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1130                           _
1131                           ("Could not queue ServerClientSessionInitiateMessage\n"));
1132             }
1133
1134           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1135         }
1136       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1137
1138       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1139
1140     }
1141
1142   return GNUNET_OK;
1143 }
1144
1145 /**
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
1151  * 
1152  * @return GNUNET_OK
1153 */
1154 int
1155 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1156                             void **tunnel_ctx,
1157                             const struct GNUNET_MessageHeader *message)
1158 {
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);
1163
1164   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1165               _
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);
1169
1170   if (0 ==
1171       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1172       && connection.status == CALLER)
1173     {
1174       tunnel_unreliable =
1175         GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1176                                    GNUNET_NO);
1177       if (NULL == tunnel_unreliable)
1178         {
1179           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1180                       _("Could not create unreliable tunnel\n"));
1181
1182           status_to_listen ();
1183
1184           GNUNET_SERVER_notify_transmit_ready (connection.client,
1185                                                sizeof (struct
1186                                                        ServerClientSessionRejectMessage),
1187                                                MAX_TRANSMIT_DELAY,
1188                                                &transmit_server_reject_message,
1189                                                NULL);
1190           return GNUNET_SYSERR;
1191         }
1192
1193       if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1194         {
1195           GNUNET_SCHEDULER_cancel (timeout_task);
1196           timeout_task = GNUNET_SCHEDULER_NO_TASK;
1197         }
1198
1199       connection.status = CONNECTED;
1200       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1201                   _("Changed connection status to %d\n"), connection.status);
1202
1203       if (NULL ==
1204           GNUNET_SERVER_notify_transmit_ready (connection.client,
1205                                                sizeof (struct
1206                                                        ServerClientSessionAcceptMessage),
1207                                                MAX_TRANSMIT_DELAY,
1208                                                &transmit_server_accept_message,
1209                                                (void *) message))
1210         {
1211           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1212                       _
1213                       ("Could not queue ServerClientSessionAcceptMessage\n"));
1214           return GNUNET_SYSERR;
1215         }
1216
1217       start_time = GNUNET_TIME_absolute_get ();
1218       start_helpers ();
1219       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1220     }
1221
1222   return GNUNET_OK;
1223 }
1224
1225 /**
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
1231  * 
1232  * @return GNUNET_OK
1233 */
1234 int
1235 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1236                             void **tunnel_ctx,
1237                             const struct GNUNET_MessageHeader *message)
1238 {
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);
1242
1243   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1244               _
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);
1248
1249   if (0 ==
1250       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1251       && connection.status == CALLER)
1252     {
1253       if (NULL ==
1254           GNUNET_SERVER_notify_transmit_ready (connection.client,
1255                                                sizeof (struct
1256                                                        ServerClientSessionRejectMessage),
1257                                                MAX_TRANSMIT_DELAY,
1258                                                &transmit_server_reject_message,
1259                                                (void *) message))
1260         {
1261           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1262                       _
1263                       ("Could not queue ServerClientSessionRejectMessage\n"));
1264         }
1265
1266       status_to_listen ();
1267
1268       if (NULL != tunnel_reliable)
1269         {
1270           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1271           tunnel_reliable = NULL;
1272         }
1273     }
1274
1275   return GNUNET_OK;
1276 }
1277
1278 /**
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
1284  * 
1285  * @return GNUNET_OK
1286 */
1287 int
1288 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1289                                void **tunnel_ctx,
1290                                const struct GNUNET_MessageHeader *message)
1291 {
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);
1295
1296   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1297               _
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);
1301
1302   if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1303       && (connection.status == CONNECTED || connection.status == CALLEE))
1304     {
1305       status_to_listen ();
1306
1307       if (NULL != tunnel_unreliable)
1308         {
1309           GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1310           tunnel_unreliable = NULL;
1311         }
1312
1313       if (NULL != tunnel_reliable)
1314         {
1315           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1316           tunnel_reliable = NULL;
1317         }
1318     }
1319
1320   return GNUNET_OK;
1321 }
1322
1323 /**
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
1329  * 
1330  * @return GNUNET_OK
1331 */
1332 int
1333 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1334                            void **tunnel_ctx,
1335                            const struct GNUNET_MessageHeader *message)
1336 {
1337   const struct AudioMessage *audio;
1338   audio = (const struct AudioMessage *) message;
1339
1340   GNUNET_MESH_receive_done (tunnel);
1341   if (CONNECTED != connection.status)
1342     return GNUNET_OK;
1343   GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1344               "[RECV] %dbytes\n", 
1345               ntohs (audio->header.size));
1346   if (NULL == playback_helper)
1347     return GNUNET_OK;
1348   (void) GNUNET_HELPER_send (playback_helper,
1349                              message, GNUNET_YES, NULL, NULL);
1350   return GNUNET_OK;
1351 }
1352
1353 /******************************************************************************/
1354 /***********************                      HELPER                *******************/
1355 /******************************************************************************/
1356
1357 /**
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
1362  * 
1363  * @return GNUNET_OK
1364 */
1365 static int
1366 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1367                          const struct GNUNET_MessageHeader *msg)
1368 {
1369   const struct AudioMessage *message = (const struct AudioMessage *) msg;
1370
1371   GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1372               " [REC] %dbyte\n", 
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));
1377
1378   return GNUNET_OK;
1379 }
1380
1381 /**
1382 * Function to to start the playback helper
1383  * 
1384  * @return 0 ok, 1 on error
1385 */
1386 int
1387 start_playback_helper (void)
1388 {
1389   static char *playback_helper_argv[1];
1390   int success = 1;
1391
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,
1396                                          NULL, NULL, NULL);
1397
1398   if (NULL == playback_helper)
1399     {
1400       success = 0;
1401       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1402                   _("Could not start playback audio helper.\n"));
1403     }
1404
1405   return success;
1406 }
1407
1408 /**
1409 * Function to to start the record helper
1410  * 
1411  * @return 0 ok, 1 on error
1412 */
1413 int
1414 start_record_helper (void)
1415 {
1416   static char *record_helper_argv[1];
1417   int success = 1;
1418
1419   record_helper_argv[0] = "gnunet-helper-audio-record";
1420   record_helper = GNUNET_HELPER_start (GNUNET_NO,
1421                                        "gnunet-helper-audio-record",
1422                                        record_helper_argv,
1423                                        &process_record_messages, NULL, NULL);
1424
1425   if (NULL == record_helper)
1426     {
1427       success = 0;
1428       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1429                   _("Could not start record audio helper\n"));
1430     }
1431
1432   return success;
1433 }
1434
1435
1436 /**
1437 * Function to to start both helpers
1438  * 
1439  * @return 0 ok, 1 on error
1440 */
1441 int
1442 start_helpers (void)
1443 {
1444
1445   if (0 == start_playback_helper () || 0 == start_record_helper ())
1446     {
1447       stop_helpers ();
1448       return 0;
1449     }
1450
1451   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1452
1453   return 1;
1454 }
1455
1456 /**
1457 * Function to to stop the playback helper
1458 */
1459 void
1460 stop_playback_helper (void)
1461 {
1462   if (NULL != playback_helper)
1463     {
1464       GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1465       playback_helper = NULL;
1466
1467       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1468     }
1469 }
1470
1471 /**
1472 * Function to to stop the record helper
1473 */
1474 void
1475 stop_record_helper (void)
1476 {
1477   if (NULL != record_helper)
1478     {
1479       GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1480       record_helper = NULL;
1481
1482       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1483     }
1484 }
1485
1486 /**
1487 * Function to stop both audio helpers
1488 */
1489 void
1490 stop_helpers (void)
1491 {
1492   stop_playback_helper ();
1493   stop_record_helper ();
1494 }
1495
1496 /******************************************************************************/
1497 /***********************                 TUNNEL HANDLING            *******************/
1498 /******************************************************************************/
1499
1500 /**
1501  * Method called whenever another peer has added us to a tunnel
1502  * the other peer initiated.
1503  *
1504  * @param cls closure
1505  * @param tunnel new handle to the tunnel
1506  * @param initiator peer that started the tunnel
1507  * @param port port
1508  * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1509  */
1510 static void *
1511 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1512                 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1513 {
1514   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515               _("Received incoming tunnel on port %d\n"), port);
1516   if (50003 == port)
1517     {
1518       tunnel_unreliable = tunnel;
1519
1520       start_time = GNUNET_TIME_absolute_get ();
1521
1522       start_helpers ();
1523       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1524     }
1525
1526   return NULL;
1527 }
1528
1529
1530 /**
1531  * Function called whenever an inbound tunnel is destroyed.  Should clean up
1532  * any associated state.
1533  *
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
1538  */
1539 static void
1540 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1541              void *tunnel_ctx)
1542 {
1543   if (tunnel == tunnel_unreliable)
1544     {
1545       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1546
1547       stop_helpers ();
1548       tunnel_unreliable = NULL;
1549     }
1550
1551   if (tunnel == tunnel_reliable)
1552     {
1553       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1554
1555       if (LISTEN != connection.status && NULL != connection.client)
1556         {
1557           if (NULL ==
1558               GNUNET_SERVER_notify_transmit_ready (connection.client,
1559                                                    sizeof (struct
1560                                                            ServerClientSessionTerminateMessage),
1561                                                    MAX_TRANSMIT_DELAY,
1562                                                    &transmit_server_terminate_message,
1563                                                    NULL))
1564             {
1565               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1566                           _
1567                           ("Could not queue ServerClientSessionTerminateMessage\n"));
1568             }
1569         }
1570
1571       status_to_listen ();
1572     }
1573 }
1574
1575 /******************************************************************************/
1576 /***********************          CLIENT HANDLING           *******************/
1577 /******************************************************************************/
1578
1579 /**
1580  * A client connected.
1581  *
1582  * @param cls closure, NULL
1583  * @param client identification of the client
1584  */
1585
1586 static void
1587 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1588 {
1589   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1590   struct ServerClientMissedCallMessage *message;
1591   size_t msg_size;
1592   struct VoipClient c;
1593   c.client = cl;
1594
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);
1599
1600   if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1601     {
1602       int i = 0;
1603       msg_size =
1604         sizeof (struct ServerClientMissedCallMessage) +
1605         GNUNET_CONTAINER_slist_count (missed_calls) *
1606         sizeof (struct MissedCall);
1607       message =
1608         (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1609
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);
1613
1614       struct GNUNET_CONTAINER_SList_Iterator iterator =
1615         GNUNET_CONTAINER_slist_begin (missed_calls);
1616       do
1617         {
1618           memcpy (&(message->missed_call[i]),
1619                   GNUNET_CONTAINER_slist_get (&iterator, NULL),
1620                   sizeof (struct MissedCall));
1621           i++;
1622         }
1623       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1624
1625       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1626       GNUNET_CONTAINER_slist_clear (missed_calls);
1627
1628
1629       if (NULL ==
1630           GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1631                                                MAX_TRANSMIT_DELAY,
1632                                                &transmit_server_missed_call_message,
1633                                                (void *) message))
1634         {
1635           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1636                       _("Could not queue ServerClientMissedCallMessage\n"));
1637           GNUNET_free (message);
1638         }
1639     }
1640
1641   return;
1642 }
1643
1644 /**
1645  * A client disconnected.  Remove all of its data structure entries.
1646  *
1647  * @param cls closure, NULL
1648  * @param client identification of the client
1649  */
1650 static void
1651 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1652 {
1653   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1654
1655   if (connection.client == cl)
1656     {
1657       if (CONNECTED == connection.status)
1658         {
1659           terminate_call ();
1660         }
1661       else
1662         {
1663           status_to_listen ();
1664         }
1665     }
1666
1667   struct GNUNET_CONTAINER_SList_Iterator iterator =
1668     GNUNET_CONTAINER_slist_begin (clients);
1669   do
1670     {
1671       if (((struct VoipClient *)
1672            GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1673         {
1674           GNUNET_CONTAINER_slist_erase (&iterator);
1675         }
1676     }
1677   while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1678
1679   GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1680
1681   return;
1682 }
1683
1684 /******************************************************************************/
1685 /***********************                      SERVICE               *******************/
1686 /******************************************************************************/
1687
1688 /**
1689  * Shutdown nicely
1690  * 
1691  * @param cls closure, NULL
1692  * @param tc the task context
1693  */
1694 static void
1695 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1696 {
1697   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1698
1699   stop_helpers ();
1700
1701   if (NULL != tunnel_reliable)
1702     {
1703       GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1704     }
1705
1706   if (NULL != tunnel_unreliable)
1707     {
1708       GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1709     }
1710
1711   if (NULL != mesh)
1712     {
1713       GNUNET_MESH_disconnect (mesh);
1714     }
1715
1716   if (NULL != nc)
1717     {
1718       GNUNET_SERVER_notification_context_destroy (nc);
1719       nc = NULL;
1720     }
1721
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);
1726 }
1727
1728
1729 /**
1730  * Handler array for traffic received
1731  */
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)},
1745   {NULL, 0, 0}
1746 };
1747
1748 /**
1749  * Main function that will be run by the scheduler.
1750  *
1751  * @param cls closure
1752  * @param server server handle
1753  * @param c configuration
1754  */
1755 static void
1756 run (void *cls, struct GNUNET_SERVER_Handle *server,
1757      const struct GNUNET_CONFIGURATION_Handle *c)
1758 {
1759
1760   static uint32_t ports[] = { 50002, 50003, 0 };
1761   cfg = c;
1762
1763   mesh = GNUNET_MESH_connect (cfg,
1764                               NULL,
1765                               &inbound_tunnel,
1766                               &inbound_end, mesh_handlers, ports);
1767
1768   if (NULL == mesh)
1769     {
1770       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1771       return;
1772     }
1773   else
1774     {
1775       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1776     }
1777
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)},
1791     {NULL, NULL, 0, 0}
1792   };
1793
1794   connection.status = LISTEN;
1795
1796   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1797               connection.status);
1798
1799   nc = GNUNET_SERVER_notification_context_create (server, 16);
1800
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,
1805                                 NULL);
1806
1807   clients = GNUNET_CONTAINER_slist_create ();
1808
1809   // Missed calls
1810   missed_calls = GNUNET_CONTAINER_slist_create ();
1811   peers_to_notify = GNUNET_CONTAINER_slist_create ();
1812   audio_buffer = GNUNET_CONTAINER_slist_create ();
1813
1814   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1815 }
1816
1817 /**
1818  * The main function for the conversation service.
1819  *
1820  * @param argc number of arguments from the command line
1821  * @param argv command line arguments
1822  * @return 0 ok, 1 on error
1823  */
1824 int
1825 main (int argc, char *const *argv)
1826 {
1827   return (GNUNET_OK ==
1828           GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1829                               &run, NULL)) ? 0 : 1;
1830 }
1831
1832 /* end of gnunet-service-conversation.c */