-spell param(eter) correctly
[oweals/gnunet.git] / src / conversation / gnunet-service-conversation.c
1 /*
2                  This file is part of GNUnet.
3                  (C) 
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 /**
22  * @file conversation/gnunet-service-conversation.c
23  * @brief conversation service implementation
24  * @author Simon Dieterle
25  * @author Andreas Fuchs
26  * STRUCTURE:
27  * - Variables
28  * - AUXILIARY FUNCTIONS
29  * - SENDING FUNCTIONS CL -> SERVER
30  * - RECEIVE FUNCTIONS CL -> SERVER
31  * - SENDING FUNCTIONS MESH
32  * - RECEIVE FUNCTIONS MESH
33  * - HELPER
34  * - TUNNEL HANDLING
35  * - CLIENT HANDLING
36  */
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"
43
44 /******************************************************** 
45  * Ugly hack because of not working MESH API
46 */
47 typedef uint32_t MESH_TunnelNumber;
48 struct GNUNET_MESH_Tunnel
49 {
50   struct GNUNET_MESH_Tunnel *next;
51   struct GNUNET_MESH_Tunnel *prev;
52   struct GNUNET_MESH_Handle *mesh;
53   MESH_TunnelNumber tid;
54   uint32_t port;
55   GNUNET_PEER_Id peer;
56   void *ctx;
57   unsigned int packet_size;
58   int buffering;
59   int reliable;
60   int allow_send;
61 };
62
63
64 /**
65  * Our configuration.
66  */
67 static const struct GNUNET_CONFIGURATION_Handle *cfg;
68
69 /**
70  * Head of the list of current clients.
71  */
72 static struct GNUNET_CONTAINER_SList *clients;
73
74 /**
75  * Notification context containing all connected clients.
76  */
77 struct GNUNET_SERVER_NotificationContext *nc = NULL;
78
79 /**
80 * The connection status
81 */
82 static struct ConnectionStatus connection;
83
84 /**
85 * Handle for the record helper
86 */
87 static struct GNUNET_HELPER_Handle *record_helper;
88
89 /** Handle for the playback handler
90 *
91 */
92 static struct GNUNET_HELPER_Handle *playback_helper;
93
94 /**
95 * Handle for mesh
96 */
97 static struct GNUNET_MESH_Handle *mesh;
98
99 /**
100 * Transmit handle for audio messages
101 */
102 static struct GNUNET_MESH_TransmitHandle *mth = NULL;
103
104 /**
105 * Handle for the reliable tunnel (contol data)
106 */
107 static struct GNUNET_MESH_Tunnel *tunnel_reliable;
108
109 /**
110 * Handle for unreliable tunnel (audio data)
111 */
112 static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
113
114 /**
115 * List for missed calls
116 */
117 struct GNUNET_CONTAINER_SList *missed_calls;
118
119 /**
120 * List for peers to notify that we are available again
121 */
122 struct GNUNET_CONTAINER_SList *peers_to_notify;
123
124 /**
125 * Audio buffer (outgoing)
126 */
127 struct GNUNET_CONTAINER_SList *audio_buffer;
128
129 /**
130 * The pointer to the task for sending audio
131 */
132 GNUNET_SCHEDULER_TaskIdentifier audio_task;
133
134 /**
135 * The pointer to the task for checking timeouts an calling a peer
136 */
137 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
138
139 /**
140 * Sequencenumber for the pakets (for evaltuation purposes)
141 */
142 int SequenceNumber = 0;
143
144 /**
145 * Timestamp for call statistics
146 */
147 static struct GNUNET_TIME_Absolute start_time;
148
149 /**
150  * Number of payload packes sent
151  */
152 static int data_sent;
153 static int data_sent_size;
154
155 /**
156  * Number of payload packets received
157  */
158 static int data_received;
159 static int data_received_size;
160
161 /******************************************************************************/
162 /***********************     AUXILIARY FUNCTIONS      *************************/
163 /******************************************************************************/
164
165 /**
166 * Function which displays some call stats
167 */
168 static void
169 show_end_data (void)
170 {
171   static struct GNUNET_TIME_Absolute end_time;
172   static struct GNUNET_TIME_Relative total_time;
173
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,
179                                                    GNUNET_NO));
180   FPRINTF (stderr, "Test total packets: %d\n", 
181            data_sent);
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
186
187   FPRINTF (stderr, "\nResults of recv\n");
188   FPRINTF (stderr, "Test time %s\n",
189            GNUNET_STRINGS_relative_time_to_string (total_time,
190                                                    GNUNET_NO));
191   FPRINTF (stderr, "Test total packets: %d\n", 
192            data_received);
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
197 }
198
199 /**
200 * Function which sets the connection state to LISTEN
201 */
202 static void
203 status_to_listen (void)
204 {
205
206   if (CONNECTED == connection.status)
207     {
208       show_end_data ();
209     }
210
211   if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
212     {
213       GNUNET_SCHEDULER_cancel (timeout_task);
214       timeout_task = GNUNET_SCHEDULER_NO_TASK;
215     }
216
217   stop_helpers ();
218
219   connection.status = LISTEN;
220   connection.client = NULL;
221
222   data_sent = 0;
223   data_sent_size = 0;
224   data_received = 0;
225   data_received_size = 0;
226
227   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
228               "LISTEN");
229 }
230
231 /**
232 * Function to terminate the active call
233 */
234 static void
235 terminate_call ()
236 {
237   size_t msg_size;
238   msg_size = sizeof (struct MeshSessionTerminateMessage);
239   struct MeshSessionTerminateMessage *message_mesh_terminate =
240     (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
241
242   if (NULL == message_mesh_terminate)
243     {
244       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
245                   _("Could not create MeshSessionTerminateMessage\n"));
246       status_to_listen ();
247
248       return;
249     }
250
251   message_mesh_terminate->header.size = htons (msg_size);
252   message_mesh_terminate->header.type =
253     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
254
255   if (NULL ==
256       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
257                                          MAX_TRANSMIT_DELAY, msg_size,
258                                          &transmit_mesh_message,
259                                          (void *) message_mesh_terminate))
260     {
261       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
262                   _("Could not queue MeshSessionTerminateMessage\n"));
263       GNUNET_free (message_mesh_terminate);
264       status_to_listen ();
265     }
266 }
267
268 /**
269 * Function to reject a call
270 *
271 * @param tunnel the tunnel where to reject the incoming call
272 * @param reason te reson why the call is rejected
273 */
274 static void
275 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
276 {
277   size_t msg_size;
278   msg_size = sizeof (struct MeshSessionRejectMessage);
279   struct MeshSessionRejectMessage *message_mesh_reject =
280     (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
281
282   if (NULL == message_mesh_reject)
283     {
284       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
285                   _("Could not create MeshSessionRejectMessage\n"));
286       status_to_listen ();
287
288       return;
289     }
290
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);
295
296   if (NULL ==
297       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
298                                          MAX_TRANSMIT_DELAY, msg_size,
299                                          &transmit_mesh_message,
300                                          (void *) message_mesh_reject))
301     {
302       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303                   _("Could not queue MeshSessionRejectMessage\n"));
304       GNUNET_free (message_mesh_reject);
305       status_to_listen ();
306     }
307 }
308
309 /**
310  * Check for timeout when calling a peer
311  *
312  * @param cls closure, NULL
313  * @param tc the task context (can be NULL)
314  */
315 static void
316 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
317 {
318   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
319
320   if (NULL ==
321       GNUNET_SERVER_notify_transmit_ready (connection.client,
322                                            sizeof (struct
323                                                    ServerClientNoAnswerMessage),
324                                            MAX_TRANSMIT_DELAY,
325                                            &transmit_server_no_answer_message,
326                                            NULL))
327     {
328       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
329                   _("Could not queue ServerClientNoAnswerMessage\n"));
330     }
331
332   terminate_call ();
333 }
334
335 /******************************************************************************/
336 /***********************  SENDING FUNCTIONS CL -> SERVER    *******************/
337 /******************************************************************************/
338
339 /**
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
342  * the meantime.
343  *
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
348  */
349 static size_t
350 transmit_server_initiate_message (void *cls, size_t size, void *buf)
351 {
352   struct ServerClientSessionInitiateMessage *msg;
353   size_t msg_size;
354
355   msg_size = sizeof (struct ServerClientSessionInitiateMessage);
356
357   GNUNET_assert (size >= msg_size);
358
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));
364
365   return msg_size;
366 }
367
368 /**
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
371  * the meantime.
372  *
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
377  */
378 static size_t
379 transmit_server_accept_message (void *cls, size_t size, void *buf)
380 {
381   struct ServerClientSessionAcceptMessage *msg;
382   size_t msg_size;
383
384   msg_size = sizeof (struct ServerClientSessionAcceptMessage);
385
386   GNUNET_assert (size >= msg_size);
387
388   msg = (struct ServerClientSessionAcceptMessage *) buf;
389   msg->header.size = htons (msg_size);
390   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
391
392   return msg_size;
393 }
394
395 /**
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
398  * the meantime.
399  *
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
404  */
405 static size_t
406 transmit_server_reject_message (void *cls, size_t size, void *buf)
407 {
408   struct ServerClientSessionRejectMessage *msg;
409   size_t msg_size;
410
411   msg_size = sizeof (struct ServerClientSessionRejectMessage);
412
413   GNUNET_assert (size >= msg_size);
414
415   msg = (struct ServerClientSessionRejectMessage *) buf;
416   msg->header.size = htons (msg_size);
417   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
418
419   if (NULL == cls)
420     {
421       msg->reason = htons (REJECT_REASON_NOT_AVAILABLE);
422     }
423   else
424     {
425       msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
426     }
427
428   return msg_size;
429 }
430
431 /**
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
434  * the meantime.
435  *
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
440  */
441 static size_t
442 transmit_server_terminate_message (void *cls, size_t size, void *buf)
443 {
444   struct ServerClientSessionTerminateMessage *msg;
445   size_t msg_size;
446
447   msg_size = sizeof (struct ServerClientSessionTerminateMessage);
448
449   GNUNET_assert (size >= msg_size);
450
451   msg = (struct ServerClientSessionTerminateMessage *) buf;
452   msg->header.size = htons (msg_size);
453   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
454
455   return msg_size;
456 }
457
458 /**
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
461  * the meantime.
462  *
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
467  */
468 static size_t
469 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
470 {
471   struct ServerClientMissedCallMessage *msg;
472   msg = (struct ServerClientMissedCallMessage *) cls;
473
474   memcpy (buf, msg, size);
475   GNUNET_free (msg);
476
477   return size;
478 }
479
480 /**
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
483  * the meantime.
484  *
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
489  */
490 static size_t
491 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
492 {
493   struct ServerClientServiceBlockedMessage *msg;
494   size_t msg_size;
495
496   msg_size = sizeof (struct ServerClientServiceBlockedMessage);
497
498   GNUNET_assert (size >= msg_size);
499
500   msg = (struct ServerClientServiceBlockedMessage *) buf;
501   msg->header.size = htons (msg_size);
502   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
503
504   return msg_size;
505 }
506
507 /**
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
510  * the meantime.
511  *
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
516  */
517 static size_t
518 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
519 {
520   struct ServerClientPeerNotConnectedMessage *msg;
521   size_t msg_size;
522
523   msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
524
525   GNUNET_assert (size >= msg_size);
526
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);
530
531   return msg_size;
532 }
533
534 /**
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
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 peer no answer message
542  * @return number of bytes written to buf
543  */
544 static size_t
545 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
546 {
547   struct ServerClientNoAnswerMessage *msg;
548   size_t msg_size;
549
550   msg_size = sizeof (struct ServerClientNoAnswerMessage);
551
552   GNUNET_assert (size >= msg_size);
553
554   msg = (struct ServerClientNoAnswerMessage *) buf;
555   msg->header.size = htons (msg_size);
556   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
557
558   return msg_size;
559 }
560
561 /**
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
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 error message
569  * @return number of bytes written to buf
570  */
571 static size_t
572 transmit_server_error_message (void *cls, size_t size, void *buf)
573 {
574   struct ServerClientErrorMessage *msg;
575   size_t msg_size;
576
577   msg_size = sizeof (struct ServerClientErrorMessage);
578
579   GNUNET_assert (size >= msg_size);
580
581   msg = (struct ServerClientErrorMessage *) buf;
582   msg->header.size = htons (msg_size);
583   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
584
585   return msg_size;
586 }
587
588 /******************************************************************************/
589 /***********************  RECEIVE FUNCTIONS CL -> SERVER   ********************/
590 /******************************************************************************/
591
592 /**
593  * Function to handle a session initiate message from the client
594  *
595  * @param cls closure, NULL
596  * @param client the client from which the message is
597  * @param message the message from the client
598 */
599 static void
600 handle_session_initiate_message (void *cls,
601                                  struct GNUNET_SERVER_Client *client,
602                                  const struct GNUNET_MessageHeader *message)
603 {
604   static uint32_t port = 50002;
605   size_t msg_size;
606   struct ClientServerSessionInitiateMessage *msg =
607     (struct ClientServerSessionInitiateMessage *) message;
608   struct GNUNET_PeerIdentity *peer = &(msg->peer);
609
610   GNUNET_SERVER_receive_done (client, GNUNET_OK);
611
612   if (NULL != connection.client)
613     {
614       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
615                   _("There is already a peer in interaction\n"));
616       GNUNET_SERVER_notify_transmit_ready (client,
617                                            sizeof (struct
618                                                    ServerClientServiceBlockedMessage),
619                                            MAX_TRANSMIT_DELAY,
620                                            &transmit_server_service_blocked_message,
621                                            NULL);
622
623       return;
624     }
625
626   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
627               GNUNET_i2s_full (peer));
628   tunnel_reliable =
629     GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
630   if (NULL == tunnel_reliable)
631     {
632       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
633                   _("Could not create reliable tunnel\n"));
634       GNUNET_SERVER_notify_transmit_ready (client,
635                                            sizeof (struct
636                                                    ServerClientPeerNotConnectedMessage),
637                                            MAX_TRANSMIT_DELAY,
638                                            &transmit_server_peer_not_connected_message,
639                                            NULL);
640
641       return;
642     }
643
644   msg_size = sizeof (struct MeshSessionInitiateMessage);
645   struct MeshSessionInitiateMessage *message_mesh_initiate =
646     (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
647
648   if (NULL == message_mesh_initiate)
649     {
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,
655                                            sizeof (struct
656                                                    ServerClientErrorMessage),
657                                            MAX_TRANSMIT_DELAY,
658                                            &transmit_server_error_message,
659                                            NULL);
660
661       return;
662     }
663
664   message_mesh_initiate->header.size = htons (msg_size);
665   message_mesh_initiate->header.type =
666     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
667
668   if (NULL ==
669       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
670                                          MAX_TRANSMIT_DELAY, msg_size,
671                                          &transmit_mesh_message,
672                                          (void *) message_mesh_initiate))
673     {
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,
680                                            sizeof (struct
681                                                    ServerClientErrorMessage),
682                                            MAX_TRANSMIT_DELAY,
683                                            &transmit_server_error_message,
684                                            NULL);
685
686       return;
687     }
688
689   connection.status = CALLER;
690   connection.client = client;
691   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
692               connection.status);
693   memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
694
695   return;
696 }
697
698 /**
699  * Function to handle a session accept message from the client
700  *
701  * @param cls closure, NULL
702  * @param client the client from which the message is
703  * @param message the message from the client
704 */
705 static void
706 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
707                                const struct GNUNET_MessageHeader *message)
708 {
709   size_t msg_size;
710
711   GNUNET_SERVER_receive_done (client, GNUNET_OK);
712
713   if (connection.status != CALLEE)
714     {
715       // TODO send illegal command
716       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
717                   _
718                   ("handle_session_accept_message called when not allowed\n"));
719       return;
720     }
721
722   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
723               GNUNET_i2s_full (&(connection.peer)));
724
725   msg_size = sizeof (struct MeshSessionAcceptMessage);
726   struct MeshSessionAcceptMessage *message_mesh_accept =
727     (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
728
729   if (NULL == message_mesh_accept)
730     {
731       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
732                   _("Could not create MeshSessionAcceptMessage\n"));
733       return;
734     }
735
736   message_mesh_accept->header.size = htons (msg_size);
737   message_mesh_accept->header.type =
738     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
739
740   if (NULL ==
741       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
742                                          MAX_TRANSMIT_DELAY, msg_size,
743                                          &transmit_mesh_message,
744                                          (void *) message_mesh_accept))
745     {
746       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
747                   _("Could not queue MeshSessionAcceptMessage\n"));
748       GNUNET_free (message_mesh_accept);
749       return;
750     }
751
752   connection.status = CONNECTED;
753   connection.client = client;
754   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
755               connection.status);
756
757   return;
758 }
759
760 /**
761  * Function to handle a session reject message from the client
762  *
763  * @param cls closure, NULL
764  * @param client the client from which the message is
765  * @param message the message from the client
766 */
767 static void
768 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
769                                const struct GNUNET_MessageHeader *message)
770 {
771   struct ClientServerSessionRejectMessage *message_received;
772
773   GNUNET_SERVER_receive_done (client, GNUNET_OK);
774
775   if (connection.status != CALLEE)
776     {
777       // TODO send illegal command
778       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
779                   _
780                   ("handle_session_reject_message called when not allowed\n"));
781       return;
782     }
783
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));
788
789   return;
790 }
791
792 /**
793  * Function to handle a session terminate message from the client
794  *
795  * @param cls closure, NULL
796  * @param client the client from which the message is
797  * @param message the message from the client
798 */
799 static void
800 handle_session_terminate_message (void *cls,
801                                   struct GNUNET_SERVER_Client *client,
802                                   const struct GNUNET_MessageHeader *message)
803 {
804   GNUNET_SERVER_receive_done (client, GNUNET_OK);
805
806   if (connection.client == NULL || connection.status == CALLEE)
807     {
808       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
809                   _
810                   ("handle_session_terminate_message called when not allowed\n"));
811       return;
812     }
813
814   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
815               GNUNET_i2s_full (&(connection.peer)));
816   terminate_call ();
817 }
818
819 /******************************************************************************/
820 /***********************       SENDING FUNCTIONS MESH       *******************/
821 /******************************************************************************/
822
823 /**
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
829  */
830 static size_t
831 transmit_mesh_message (void *cls, size_t size, void *buf)
832 {
833   struct VoIPMeshMessageHeader *msg_header =
834     (struct VoIPMeshMessageHeader *) cls;
835   msg_header->SequenceNumber = SequenceNumber += 1;
836   msg_header->time = GNUNET_TIME_absolute_get ();
837
838   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
839
840   memcpy (buf, cls, size);
841   // Check if this is correct
842
843
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)))
848     {
849       status_to_listen ();
850     }
851   else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
852            ntohs (msg_header->header.type))
853     {
854       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
855       timeout_task =
856         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
857                                       (GNUNET_TIME_UNIT_SECONDS, 30),
858                                       &check_timeout, NULL);
859     }
860
861   GNUNET_free (cls);
862
863   return size;
864 }
865
866 /**
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
872  */
873 static size_t
874 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
875 {
876   struct AudioMessage *message = (struct AudioMessage *) cls;
877
878   if (size < sizeof (struct AudioMessage) || NULL == buf)
879     {
880       GNUNET_break (0);
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);
884       return 0;
885     }
886
887   memcpy (buf, message, size);
888
889   data_sent++;
890   data_sent_size += size;
891
892   GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
893
894   audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
895
896   return size;
897 }
898
899 /**
900  * Task to schedule a audio transmission.
901  * 
902  * @param cls Closure.
903  * @param tc Task Context.
904  */
905 static void
906 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
907 {
908   struct GNUNET_CONTAINER_SList_Iterator iterator;
909   struct AudioMessage *msg;
910   int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
911
912   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
913
914   if (NULL == cls)
915     {
916       if (0 == ab_length && CONNECTED == connection.status)
917         {
918           audio_task =
919             GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
920                                           (GNUNET_TIME_UNIT_MILLISECONDS, 10),
921                                           &transmit_audio_task, NULL);
922           return;
923         }
924
925       iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
926       msg =
927         (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
928       msg->SequenceNumber = SequenceNumber += 1;
929       msg->time = GNUNET_TIME_absolute_get ();
930
931       GNUNET_CONTAINER_slist_erase (&iterator);
932       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
933     }
934   else
935     {
936       msg = (struct AudioMessage *) cls;
937     }
938
939   if (NULL == tunnel_unreliable)
940     {
941       GNUNET_CONTAINER_slist_clear (audio_buffer);
942       return;
943     }
944
945   mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
946                                            MAX_TRANSMIT_DELAY,
947                                            sizeof (struct AudioMessage),
948                                            &transmit_mesh_audio_message,
949                                            (void *) msg);
950
951   if (NULL == mth)
952     {
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");
956       audio_task =
957         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
958                                       &transmit_audio_task, (void *) msg);
959     }
960 }
961
962 /******************************************************************************/
963 /***********************       RECEIVE FUNCTIONS MESH      ********************/
964 /******************************************************************************/
965
966 /**
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
972  * 
973  * @return GNUNET_OK
974 */
975 int
976 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
977                               void **tunnel_ctx,
978                               const struct GNUNET_MessageHeader *message)
979 {
980   int reject_reason;
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);
984
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);
989
990   if (LISTEN != connection.status
991       || 1 > GNUNET_CONTAINER_slist_count (clients))
992     {
993
994       if (CONNECTED == connection.status)
995         {
996           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
997                       _
998                       ("Rejected call from %s because there is an active call"),
999                       GNUNET_i2s_full (peer));
1000           reject_reason = htons (REJECT_REASON_ACTIVE_CALL);
1001
1002           // Notifying client about missed call
1003           size_t msg_size =
1004             sizeof (struct ServerClientMissedCallMessage) +
1005             sizeof (struct MissedCall);
1006           struct ServerClientMissedCallMessage *message =
1007             GNUNET_malloc (msg_size);
1008
1009           message->header.size = htons (msg_size);
1010           message->header.type =
1011             htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1012           message->number = 1;
1013
1014           memcpy (&(message->missed_call->peer), peer,
1015                   sizeof (struct GNUNET_PeerIdentity));
1016           message->missed_call->time = GNUNET_TIME_absolute_get ();
1017
1018           if (NULL ==
1019               GNUNET_SERVER_notify_transmit_ready (connection.client,
1020                                                    sizeof (struct
1021                                                            ServerClientMissedCallMessage),
1022                                                    MAX_TRANSMIT_DELAY,
1023                                                    &transmit_server_missed_call_message,
1024                                                    (void *) message))
1025             {
1026               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1027                           _
1028                           ("Could not queue ServerClientMissedCallMessage\n"));
1029               GNUNET_free (message);
1030             }
1031         }
1032
1033       if (1 > GNUNET_CONTAINER_slist_count (clients))
1034         {
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));
1046
1047         }
1048
1049       reject_call (tunnel, reject_reason);
1050     }
1051   else
1052     {
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));
1060
1061       struct GNUNET_CONTAINER_SList_Iterator iterator =
1062         GNUNET_CONTAINER_slist_begin (clients);
1063       do
1064         {
1065           struct VoipClient *conversation_client =
1066             (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1067                                                               NULL);
1068           struct GNUNET_SERVER_Client *client = conversation_client->client;
1069           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1070                       client);
1071
1072           if (NULL ==
1073               GNUNET_SERVER_notify_transmit_ready (client,
1074                                                    sizeof (struct
1075                                                            ServerClientSessionInitiateMessage),
1076                                                    MAX_TRANSMIT_DELAY,
1077                                                    &transmit_server_initiate_message,
1078                                                    (void *) peer))
1079             {
1080               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1081                           _
1082                           ("Could not queue ServerClientSessionInitiateMessage\n"));
1083             }
1084
1085           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1086         }
1087       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1088
1089       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1090
1091     }
1092
1093   return GNUNET_OK;
1094 }
1095
1096 /**
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
1102  * 
1103  * @return GNUNET_OK
1104 */
1105 int
1106 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1107                             void **tunnel_ctx,
1108                             const struct GNUNET_MessageHeader *message)
1109 {
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);
1114
1115   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1116               _
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);
1120
1121   if (0 ==
1122       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1123       && connection.status == CALLER)
1124     {
1125       tunnel_unreliable =
1126         GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1127                                    GNUNET_NO);
1128       if (NULL == tunnel_unreliable)
1129         {
1130           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1131                       _("Could not create unreliable tunnel\n"));
1132
1133           status_to_listen ();
1134
1135           GNUNET_SERVER_notify_transmit_ready (connection.client,
1136                                                sizeof (struct
1137                                                        ServerClientSessionRejectMessage),
1138                                                MAX_TRANSMIT_DELAY,
1139                                                &transmit_server_reject_message,
1140                                                NULL);
1141           return GNUNET_SYSERR;
1142         }
1143
1144       if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1145         {
1146           GNUNET_SCHEDULER_cancel (timeout_task);
1147           timeout_task = GNUNET_SCHEDULER_NO_TASK;
1148         }
1149
1150       connection.status = CONNECTED;
1151       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1152                   _("Changed connection status to %d\n"), connection.status);
1153
1154       if (NULL ==
1155           GNUNET_SERVER_notify_transmit_ready (connection.client,
1156                                                sizeof (struct
1157                                                        ServerClientSessionAcceptMessage),
1158                                                MAX_TRANSMIT_DELAY,
1159                                                &transmit_server_accept_message,
1160                                                (void *) message))
1161         {
1162           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1163                       _
1164                       ("Could not queue ServerClientSessionAcceptMessage\n"));
1165           return GNUNET_SYSERR;
1166         }
1167
1168       start_time = GNUNET_TIME_absolute_get ();
1169       start_helpers ();
1170       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1171     }
1172
1173   return GNUNET_OK;
1174 }
1175
1176 /**
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
1182  * 
1183  * @return GNUNET_OK
1184 */
1185 int
1186 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1187                             void **tunnel_ctx,
1188                             const struct GNUNET_MessageHeader *message)
1189 {
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);
1193
1194   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1195               _
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);
1199
1200   if (0 ==
1201       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1202       && connection.status == CALLER)
1203     {
1204       if (NULL ==
1205           GNUNET_SERVER_notify_transmit_ready (connection.client,
1206                                                sizeof (struct
1207                                                        ServerClientSessionRejectMessage),
1208                                                MAX_TRANSMIT_DELAY,
1209                                                &transmit_server_reject_message,
1210                                                (void *) message))
1211         {
1212           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1213                       _
1214                       ("Could not queue ServerClientSessionRejectMessage\n"));
1215         }
1216
1217       status_to_listen ();
1218
1219       if (NULL != tunnel_reliable)
1220         {
1221           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1222           tunnel_reliable = NULL;
1223         }
1224     }
1225
1226   return GNUNET_OK;
1227 }
1228
1229 /**
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
1235  * 
1236  * @return GNUNET_OK
1237 */
1238 int
1239 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1240                                void **tunnel_ctx,
1241                                const struct GNUNET_MessageHeader *message)
1242 {
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);
1246
1247   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1248               _
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);
1252
1253   if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1254       && (connection.status == CONNECTED || connection.status == CALLEE))
1255     {
1256       status_to_listen ();
1257
1258       if (NULL != tunnel_unreliable)
1259         {
1260           GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1261           tunnel_unreliable = NULL;
1262         }
1263
1264       if (NULL != tunnel_reliable)
1265         {
1266           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1267           tunnel_reliable = NULL;
1268         }
1269     }
1270
1271   return GNUNET_OK;
1272 }
1273
1274 /**
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
1280  * 
1281  * @return GNUNET_OK
1282 */
1283 int
1284 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1285                            void **tunnel_ctx,
1286                            const struct GNUNET_MessageHeader *message)
1287 {
1288
1289   GNUNET_MESH_receive_done (tunnel);
1290
1291   if (CONNECTED != connection.status)
1292     return GNUNET_OK;
1293
1294
1295   struct AudioMessage *audio;
1296   size_t msg_size;
1297   msg_size = sizeof (struct AudioMessage);
1298
1299   audio = (struct AudioMessage *) message;
1300
1301   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "[RECV] %dbytes\n", audio->length);
1302
1303   if (NULL == playback_helper)
1304     return GNUNET_OK;
1305
1306   (void) GNUNET_HELPER_send (playback_helper,
1307                              message, GNUNET_YES, NULL, NULL);
1308
1309   data_received++;
1310   data_received_size += msg_size;
1311
1312   return GNUNET_OK;
1313 }
1314
1315 /******************************************************************************/
1316 /***********************                      HELPER                *******************/
1317 /******************************************************************************/
1318
1319 /**
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
1324  * 
1325  * @return GNUNET_OK
1326 */
1327 static int
1328 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1329                          const struct GNUNET_MessageHeader *msg)
1330 {
1331   size_t msg_size;
1332   struct AudioMessage *message = (struct AudioMessage *) msg;
1333   msg_size = sizeof (struct AudioMessage);
1334
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,
1338                                   message, msg_size);
1339
1340   return GNUNET_OK;
1341 }
1342
1343 /**
1344 * Function to to start the playback helper
1345  * 
1346  * @return 0 ok, 1 on error
1347 */
1348 int
1349 start_playback_helper (void)
1350 {
1351   static char *playback_helper_argv[1];
1352   int success = 1;
1353
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,
1358                                          NULL, NULL, NULL);
1359
1360   if (NULL == playback_helper)
1361     {
1362       success = 0;
1363       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1364                   _("Could not start playback audio helper.\n"));
1365     }
1366
1367   return success;
1368 }
1369
1370 /**
1371 * Function to to start the record helper
1372  * 
1373  * @return 0 ok, 1 on error
1374 */
1375 int
1376 start_record_helper (void)
1377 {
1378   static char *record_helper_argv[1];
1379   int success = 1;
1380
1381   record_helper_argv[0] = "gnunet-helper-audio-record";
1382   record_helper = GNUNET_HELPER_start (GNUNET_NO,
1383                                        "gnunet-helper-audio-record",
1384                                        record_helper_argv,
1385                                        &process_record_messages, NULL, NULL);
1386
1387   if (NULL == record_helper)
1388     {
1389       success = 0;
1390       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1391                   _("Could not start record audio helper\n"));
1392     }
1393
1394   return success;
1395 }
1396
1397
1398 /**
1399 * Function to to start both helpers
1400  * 
1401  * @return 0 ok, 1 on error
1402 */
1403 int
1404 start_helpers (void)
1405 {
1406
1407   if (0 == start_playback_helper () || 0 == start_record_helper ())
1408     {
1409       stop_helpers ();
1410       return 0;
1411     }
1412
1413   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1414
1415   return 1;
1416 }
1417
1418 /**
1419 * Function to to stop the playback helper
1420 */
1421 void
1422 stop_playback_helper (void)
1423 {
1424   if (NULL != playback_helper)
1425     {
1426       GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1427       playback_helper = NULL;
1428
1429       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1430     }
1431 }
1432
1433 /**
1434 * Function to to stop the record helper
1435 */
1436 void
1437 stop_record_helper (void)
1438 {
1439   if (NULL != record_helper)
1440     {
1441       GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1442       record_helper = NULL;
1443
1444       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1445     }
1446 }
1447
1448 /**
1449 * Function to stop both audio helpers
1450 */
1451 void
1452 stop_helpers (void)
1453 {
1454   stop_playback_helper ();
1455   stop_record_helper ();
1456 }
1457
1458 /******************************************************************************/
1459 /***********************                 TUNNEL HANDLING            *******************/
1460 /******************************************************************************/
1461
1462 /**
1463  * Method called whenever another peer has added us to a tunnel
1464  * the other peer initiated.
1465  *
1466  * @param cls closure
1467  * @param tunnel new handle to the tunnel
1468  * @param initiator peer that started the tunnel
1469  * @param port port
1470  * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1471  */
1472 static void *
1473 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1474                 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1475 {
1476   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1477               _("Received incoming tunnel on port %d\n"), port);
1478   if (50003 == port)
1479     {
1480       tunnel_unreliable = tunnel;
1481
1482       start_time = GNUNET_TIME_absolute_get ();
1483
1484       start_helpers ();
1485       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1486     }
1487
1488   return NULL;
1489 }
1490
1491
1492 /**
1493  * Function called whenever an inbound tunnel is destroyed.  Should clean up
1494  * any associated state.
1495  *
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
1500  */
1501 static void
1502 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1503              void *tunnel_ctx)
1504 {
1505   if (tunnel == tunnel_unreliable)
1506     {
1507       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1508
1509       stop_helpers ();
1510       tunnel_unreliable = NULL;
1511     }
1512
1513   if (tunnel == tunnel_reliable)
1514     {
1515       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1516
1517       if (LISTEN != connection.status && NULL != connection.client)
1518         {
1519           if (NULL ==
1520               GNUNET_SERVER_notify_transmit_ready (connection.client,
1521                                                    sizeof (struct
1522                                                            ServerClientSessionTerminateMessage),
1523                                                    MAX_TRANSMIT_DELAY,
1524                                                    &transmit_server_terminate_message,
1525                                                    NULL))
1526             {
1527               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1528                           _
1529                           ("Could not queue ServerClientSessionTerminateMessage\n"));
1530             }
1531         }
1532
1533       status_to_listen ();
1534     }
1535 }
1536
1537 /******************************************************************************/
1538 /***********************          CLIENT HANDLING           *******************/
1539 /******************************************************************************/
1540
1541 /**
1542  * A client connected.
1543  *
1544  * @param cls closure, NULL
1545  * @param client identification of the client
1546  */
1547
1548 static void
1549 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1550 {
1551   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1552   struct ServerClientMissedCallMessage *message;
1553   size_t msg_size;
1554   struct VoipClient c;
1555   c.client = cl;
1556
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);
1561
1562   if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1563     {
1564       int i = 0;
1565       msg_size =
1566         sizeof (struct ServerClientMissedCallMessage) +
1567         GNUNET_CONTAINER_slist_count (missed_calls) *
1568         sizeof (struct MissedCall);
1569       message =
1570         (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1571
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);
1575
1576       struct GNUNET_CONTAINER_SList_Iterator iterator =
1577         GNUNET_CONTAINER_slist_begin (missed_calls);
1578       do
1579         {
1580           memcpy (&(message->missed_call[i]),
1581                   GNUNET_CONTAINER_slist_get (&iterator, NULL),
1582                   sizeof (struct MissedCall));
1583           i++;
1584         }
1585       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1586
1587       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1588       GNUNET_CONTAINER_slist_clear (missed_calls);
1589
1590
1591       if (NULL ==
1592           GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1593                                                MAX_TRANSMIT_DELAY,
1594                                                &transmit_server_missed_call_message,
1595                                                (void *) message))
1596         {
1597           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1598                       _("Could not queue ServerClientMissedCallMessage\n"));
1599           GNUNET_free (message);
1600         }
1601     }
1602
1603   return;
1604 }
1605
1606 /**
1607  * A client disconnected.  Remove all of its data structure entries.
1608  *
1609  * @param cls closure, NULL
1610  * @param client identification of the client
1611  */
1612 static void
1613 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1614 {
1615   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1616
1617   if (connection.client == cl)
1618     {
1619       if (CONNECTED == connection.status)
1620         {
1621           terminate_call ();
1622         }
1623       else
1624         {
1625           status_to_listen ();
1626         }
1627     }
1628
1629   struct GNUNET_CONTAINER_SList_Iterator iterator =
1630     GNUNET_CONTAINER_slist_begin (clients);
1631   do
1632     {
1633       if (((struct VoipClient *)
1634            GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1635         {
1636           GNUNET_CONTAINER_slist_erase (&iterator);
1637         }
1638     }
1639   while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1640
1641   GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1642
1643   return;
1644 }
1645
1646 /******************************************************************************/
1647 /***********************                      SERVICE               *******************/
1648 /******************************************************************************/
1649
1650 /**
1651  * Shutdown nicely
1652  * 
1653  * @param cls closure, NULL
1654  * @param tc the task context
1655  */
1656 static void
1657 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1658 {
1659   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1660
1661   stop_helpers ();
1662
1663   if (NULL != tunnel_reliable)
1664     {
1665       GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1666     }
1667
1668   if (NULL != tunnel_unreliable)
1669     {
1670       GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1671     }
1672
1673   if (NULL != mesh)
1674     {
1675       GNUNET_MESH_disconnect (mesh);
1676     }
1677
1678   if (NULL != nc)
1679     {
1680       GNUNET_SERVER_notification_context_destroy (nc);
1681       nc = NULL;
1682     }
1683
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);
1688 }
1689
1690
1691 /**
1692  * Handler array for traffic received
1693  */
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)},
1707   {NULL, 0, 0}
1708 };
1709
1710 /**
1711  * Main function that will be run by the scheduler.
1712  *
1713  * @param cls closure
1714  * @param server server handle
1715  * @param c configuration
1716  */
1717 static void
1718 run (void *cls, struct GNUNET_SERVER_Handle *server,
1719      const struct GNUNET_CONFIGURATION_Handle *c)
1720 {
1721
1722   static uint32_t ports[] = { 50002, 50003, 0 };
1723   cfg = c;
1724
1725   mesh = GNUNET_MESH_connect (cfg,
1726                               NULL,
1727                               &inbound_tunnel,
1728                               &inbound_end, mesh_handlers, ports);
1729
1730   if (NULL == mesh)
1731     {
1732       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1733       return;
1734     }
1735   else
1736     {
1737       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1738     }
1739
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)},
1753     {NULL, NULL, 0, 0}
1754   };
1755
1756   connection.status = LISTEN;
1757
1758   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1759               connection.status);
1760
1761   nc = GNUNET_SERVER_notification_context_create (server, 16);
1762
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,
1767                                 NULL);
1768
1769   clients = GNUNET_CONTAINER_slist_create ();
1770
1771   // Missed calls
1772   missed_calls = GNUNET_CONTAINER_slist_create ();
1773   peers_to_notify = GNUNET_CONTAINER_slist_create ();
1774   audio_buffer = GNUNET_CONTAINER_slist_create ();
1775
1776   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1777 }
1778
1779 /**
1780  * The main function for the conversation service.
1781  *
1782  * @param argc number of arguments from the command line
1783  * @param argv command line arguments
1784  * @return 0 ok, 1 on error
1785  */
1786 int
1787 main (int argc, char *const *argv)
1788 {
1789   return (GNUNET_OK ==
1790           GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1791                               &run, NULL)) ? 0 : 1;
1792 }
1793
1794 /* end of gnunet-service-conversation.c */