-adjust includes, add missing licenses
[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 struct GNUNET_CONTAINER_SList *missed_calls;
132
133 /**
134 * List for peers to notify that we are available again
135 */
136 struct GNUNET_CONTAINER_SList *peers_to_notify;
137
138 /**
139 * Audio buffer (outgoing)
140 */
141 struct GNUNET_CONTAINER_SList *audio_buffer;
142
143 /**
144 * The pointer to the task for sending audio
145 */
146 GNUNET_SCHEDULER_TaskIdentifier audio_task;
147
148 /**
149 * The pointer to the task for checking timeouts an calling a peer
150 */
151 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
152
153 /**
154 * Sequencenumber for the pakets (for evaltuation purposes)
155 */
156 int SequenceNumber = 0;
157
158 /**
159 * Timestamp for call statistics
160 */
161 static struct GNUNET_TIME_Absolute start_time;
162
163 /**
164  * Number of payload packes sent
165  */
166 static int data_sent;
167 static int data_sent_size;
168
169 /**
170  * Number of payload packets received
171  */
172 static int data_received;
173 static int data_received_size;
174
175
176 /**
177 * Transmit a mesh message
178  * @param cls closure, NULL
179  * @param size number of bytes available in buf
180  * @param buf where the callee should write the error message
181  * @return number of bytes written to buf
182  */
183 static size_t transmit_mesh_message (void *cls, size_t size, void *buf);
184
185 /**
186  * Function called to send a peer no answer message to the client.
187  * "buf" will be NULL and "size" zero if the socket was closed for writing in
188  * the meantime.
189  *
190  * @param cls closure, NULL
191  * @param size number of bytes available in buf
192  * @param buf where the callee should write the peer no answer message
193  * @return number of bytes written to buf
194  */
195 static size_t
196 transmit_server_no_answer_message (void *cls, size_t size, void *buf);
197
198 /**
199  * Task to schedule a audio transmission.
200  * 
201  * @param cls Closure.
202  * @param tc Task Context.
203  */
204 static void
205 transmit_audio_task (void *cls,
206                      const struct GNUNET_SCHEDULER_TaskContext *tc);
207
208 /**
209 * Start the audio helpers
210 */
211 int start_helpers (void);
212
213 /**
214 * Stop the audio helpers
215 */
216 void stop_helpers (void);
217
218
219
220 /******************************************************************************/
221 /***********************     AUXILIARY FUNCTIONS      *************************/
222 /******************************************************************************/
223
224 /**
225 * Function which displays some call stats
226 */
227 static void
228 show_end_data (void)
229 {
230   static struct GNUNET_TIME_Absolute end_time;
231   static struct GNUNET_TIME_Relative total_time;
232
233   end_time = GNUNET_TIME_absolute_get ();
234   total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
235   FPRINTF (stderr, "\nResults of send\n");
236   FPRINTF (stderr, "Test time %s\n",
237            GNUNET_STRINGS_relative_time_to_string (total_time,
238                                                    GNUNET_NO));
239   FPRINTF (stderr, "Test total packets: %d\n", 
240            data_sent);
241   FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 
242            data_sent_size * 1000.0 / (total_time.rel_value_us + 1));    // 4bytes * us
243   FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
244            data_sent * 1000000.0 / (total_time.rel_value_us + 1));      // packets * us
245
246   FPRINTF (stderr, "\nResults of recv\n");
247   FPRINTF (stderr, "Test time %s\n",
248            GNUNET_STRINGS_relative_time_to_string (total_time,
249                                                    GNUNET_NO));
250   FPRINTF (stderr, "Test total packets: %d\n", 
251            data_received);
252   FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 
253            data_received_size * 1000.0 / (total_time.rel_value_us + 1));        // 4bytes * us
254   FPRINTF (stderr, "Test throughput: %f packets/s\n\n", 
255            data_received * 1000000.0 / (total_time.rel_value_us + 1));  // packets * us
256 }
257
258 /**
259 * Function which sets the connection state to LISTEN
260 */
261 static void
262 status_to_listen (void)
263 {
264
265   if (CONNECTED == connection.status)
266     {
267       show_end_data ();
268     }
269
270   if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
271     {
272       GNUNET_SCHEDULER_cancel (timeout_task);
273       timeout_task = GNUNET_SCHEDULER_NO_TASK;
274     }
275
276   stop_helpers ();
277
278   connection.status = LISTEN;
279   connection.client = NULL;
280
281   data_sent = 0;
282   data_sent_size = 0;
283   data_received = 0;
284   data_received_size = 0;
285
286   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
287               "LISTEN");
288 }
289
290 /**
291 * Function to terminate the active call
292 */
293 static void
294 terminate_call ()
295 {
296   size_t msg_size;
297   msg_size = sizeof (struct MeshSessionTerminateMessage);
298   struct MeshSessionTerminateMessage *message_mesh_terminate =
299     (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
300
301   if (NULL == message_mesh_terminate)
302     {
303       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
304                   _("Could not create MeshSessionTerminateMessage\n"));
305       status_to_listen ();
306
307       return;
308     }
309
310   message_mesh_terminate->header.size = htons (msg_size);
311   message_mesh_terminate->header.type =
312     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
313
314   if (NULL ==
315       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
316                                          MAX_TRANSMIT_DELAY, msg_size,
317                                          &transmit_mesh_message,
318                                          (void *) message_mesh_terminate))
319     {
320       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321                   _("Could not queue MeshSessionTerminateMessage\n"));
322       GNUNET_free (message_mesh_terminate);
323       status_to_listen ();
324     }
325 }
326
327 /**
328 * Function to reject a call
329 *
330 * @param tunnel the tunnel where to reject the incoming call
331 * @param reason te reson why the call is rejected
332 */
333 static void
334 reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
335 {
336   size_t msg_size;
337   msg_size = sizeof (struct MeshSessionRejectMessage);
338   struct MeshSessionRejectMessage *message_mesh_reject =
339     (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
340
341   if (NULL == message_mesh_reject)
342     {
343       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344                   _("Could not create MeshSessionRejectMessage\n"));
345       status_to_listen ();
346
347       return;
348     }
349
350   message_mesh_reject->header.size = htons (msg_size);
351   message_mesh_reject->header.type =
352     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
353   message_mesh_reject->reason = htons (reason);
354
355   if (NULL ==
356       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
357                                          MAX_TRANSMIT_DELAY, msg_size,
358                                          &transmit_mesh_message,
359                                          (void *) message_mesh_reject))
360     {
361       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
362                   _("Could not queue MeshSessionRejectMessage\n"));
363       GNUNET_free (message_mesh_reject);
364       status_to_listen ();
365     }
366 }
367
368 /**
369  * Check for timeout when calling a peer
370  *
371  * @param cls closure, NULL
372  * @param tc the task context (can be NULL)
373  */
374 static void
375 check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
376 {
377   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
378
379   if (NULL ==
380       GNUNET_SERVER_notify_transmit_ready (connection.client,
381                                            sizeof (struct
382                                                    ServerClientNoAnswerMessage),
383                                            MAX_TRANSMIT_DELAY,
384                                            &transmit_server_no_answer_message,
385                                            NULL))
386     {
387       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
388                   _("Could not queue ServerClientNoAnswerMessage\n"));
389     }
390
391   terminate_call ();
392 }
393
394 /******************************************************************************/
395 /***********************  SENDING FUNCTIONS CL -> SERVER    *******************/
396 /******************************************************************************/
397
398 /**
399  * Function called to send a session initiate message to the client.
400  * "buf" will be NULL and "size" zero if the socket was closed for writing in
401  * the meantime.
402  *
403  * @param cls closure, NULL
404  * @param size number of bytes available in buf
405  * @param buf where the callee should write the initiate message
406  * @return number of bytes written to buf
407  */
408 static size_t
409 transmit_server_initiate_message (void *cls, size_t size, void *buf)
410 {
411   struct ServerClientSessionInitiateMessage *msg;
412   size_t msg_size;
413
414   msg_size = sizeof (struct ServerClientSessionInitiateMessage);
415
416   GNUNET_assert (size >= msg_size);
417
418   msg = (struct ServerClientSessionInitiateMessage *) buf;
419   msg->header.size = htons (msg_size);
420   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
421   memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
422           sizeof (struct GNUNET_PeerIdentity));
423
424   return msg_size;
425 }
426
427 /**
428  * Function called to send a session accept message to the client.
429  * "buf" will be NULL and "size" zero if the socket was closed for writing in
430  * the meantime.
431  *
432  * @param cls closure, NULL
433  * @param size number of bytes available in buf
434  * @param buf where the callee should write the accept message
435  * @return number of bytes written to buf
436  */
437 static size_t
438 transmit_server_accept_message (void *cls, size_t size, void *buf)
439 {
440   struct ServerClientSessionAcceptMessage *msg;
441   size_t msg_size;
442
443   msg_size = sizeof (struct ServerClientSessionAcceptMessage);
444
445   GNUNET_assert (size >= msg_size);
446
447   msg = (struct ServerClientSessionAcceptMessage *) buf;
448   msg->header.size = htons (msg_size);
449   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
450
451   return msg_size;
452 }
453
454 /**
455  * Function called to send a session reject message to the client.
456  * "buf" will be NULL and "size" zero if the socket was closed for writing in
457  * the meantime.
458  *
459  * @param cls closure, NULL
460  * @param size number of bytes available in buf
461  * @param buf where the callee should write the reject message
462  * @return number of bytes written to buf
463  */
464 static size_t
465 transmit_server_reject_message (void *cls, size_t size, void *buf)
466 {
467   struct ServerClientSessionRejectMessage *msg;
468   size_t msg_size;
469
470   msg_size = sizeof (struct ServerClientSessionRejectMessage);
471
472   GNUNET_assert (size >= msg_size);
473
474   msg = (struct ServerClientSessionRejectMessage *) buf;
475   msg->header.size = htons (msg_size);
476   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
477
478   if (NULL == cls)
479     {
480       msg->reason = htons (REJECT_REASON_NOT_AVAILABLE);
481     }
482   else
483     {
484       msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
485     }
486
487   return msg_size;
488 }
489
490 /**
491  * Function called to send a session terminate message to the client.
492  * "buf" will be NULL and "size" zero if the socket was closed for writing in
493  * the meantime.
494  *
495  * @param cls closure, NULL
496  * @param size number of bytes available in buf
497  * @param buf where the callee should write the terminate message
498  * @return number of bytes written to buf
499  */
500 static size_t
501 transmit_server_terminate_message (void *cls, size_t size, void *buf)
502 {
503   struct ServerClientSessionTerminateMessage *msg;
504   size_t msg_size;
505
506   msg_size = sizeof (struct ServerClientSessionTerminateMessage);
507
508   GNUNET_assert (size >= msg_size);
509
510   msg = (struct ServerClientSessionTerminateMessage *) buf;
511   msg->header.size = htons (msg_size);
512   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
513
514   return msg_size;
515 }
516
517 /**
518  * Function called to send a missed call message to the client.
519  * "buf" will be NULL and "size" zero if the socket was closed for writing in
520  * the meantime.
521  *
522  * @param cls closure, NULL
523  * @param size number of bytes available in buf
524  * @param buf where the callee should write the missed call message
525  * @return number of bytes written to buf
526  */
527 static size_t
528 transmit_server_missed_call_message (void *cls, size_t size, void *buf)
529 {
530   struct ServerClientMissedCallMessage *msg;
531   msg = (struct ServerClientMissedCallMessage *) cls;
532
533   memcpy (buf, msg, size);
534   GNUNET_free (msg);
535
536   return size;
537 }
538
539 /**
540  * Function called to send a service blocked message to the client.
541  * "buf" will be NULL and "size" zero if the socket was closed for writing in
542  * the meantime.
543  *
544  * @param cls closure, NULL
545  * @param size number of bytes available in buf
546  * @param buf where the callee should write the service blocked message
547  * @return number of bytes written to buf
548  */
549 static size_t
550 transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
551 {
552   struct ServerClientServiceBlockedMessage *msg;
553   size_t msg_size;
554
555   msg_size = sizeof (struct ServerClientServiceBlockedMessage);
556
557   GNUNET_assert (size >= msg_size);
558
559   msg = (struct ServerClientServiceBlockedMessage *) buf;
560   msg->header.size = htons (msg_size);
561   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
562
563   return msg_size;
564 }
565
566 /**
567  * Function called to send a peer not connected message to the client.
568  * "buf" will be NULL and "size" zero if the socket was closed for writing in
569  * the meantime.
570  *
571  * @param cls closure, NULL
572  * @param size number of bytes available in buf
573  * @param buf where the callee should write the peer not connected message
574  * @return number of bytes written to buf
575  */
576 static size_t
577 transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
578 {
579   struct ServerClientPeerNotConnectedMessage *msg;
580   size_t msg_size;
581
582   msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
583
584   GNUNET_assert (size >= msg_size);
585
586   msg = (struct ServerClientPeerNotConnectedMessage *) buf;
587   msg->header.size = htons (msg_size);
588   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
589
590   return msg_size;
591 }
592
593 /**
594  * Function called to send a peer no answer message to the client.
595  * "buf" will be NULL and "size" zero if the socket was closed for writing in
596  * the meantime.
597  *
598  * @param cls closure, NULL
599  * @param size number of bytes available in buf
600  * @param buf where the callee should write the peer no answer message
601  * @return number of bytes written to buf
602  */
603 static size_t
604 transmit_server_no_answer_message (void *cls, size_t size, void *buf)
605 {
606   struct ServerClientNoAnswerMessage *msg;
607   size_t msg_size;
608
609   msg_size = sizeof (struct ServerClientNoAnswerMessage);
610
611   GNUNET_assert (size >= msg_size);
612
613   msg = (struct ServerClientNoAnswerMessage *) buf;
614   msg->header.size = htons (msg_size);
615   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
616
617   return msg_size;
618 }
619
620 /**
621  * Function called to send a error message to the client.
622  * "buf" will be NULL and "size" zero if the socket was closed for writing in
623  * the meantime.
624  *
625  * @param cls closure, NULL
626  * @param size number of bytes available in buf
627  * @param buf where the callee should write the error message
628  * @return number of bytes written to buf
629  */
630 static size_t
631 transmit_server_error_message (void *cls, size_t size, void *buf)
632 {
633   struct ServerClientErrorMessage *msg;
634   size_t msg_size;
635
636   msg_size = sizeof (struct ServerClientErrorMessage);
637
638   GNUNET_assert (size >= msg_size);
639
640   msg = (struct ServerClientErrorMessage *) buf;
641   msg->header.size = htons (msg_size);
642   msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
643
644   return msg_size;
645 }
646
647 /******************************************************************************/
648 /***********************  RECEIVE FUNCTIONS CL -> SERVER   ********************/
649 /******************************************************************************/
650
651 /**
652  * Function to handle a session initiate message from the client
653  *
654  * @param cls closure, NULL
655  * @param client the client from which the message is
656  * @param message the message from the client
657 */
658 static void
659 handle_session_initiate_message (void *cls,
660                                  struct GNUNET_SERVER_Client *client,
661                                  const struct GNUNET_MessageHeader *message)
662 {
663   static uint32_t port = 50002;
664   size_t msg_size;
665   struct ClientServerSessionInitiateMessage *msg =
666     (struct ClientServerSessionInitiateMessage *) message;
667   struct GNUNET_PeerIdentity *peer = &(msg->peer);
668
669   GNUNET_SERVER_receive_done (client, GNUNET_OK);
670
671   if (NULL != connection.client)
672     {
673       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
674                   _("There is already a peer in interaction\n"));
675       GNUNET_SERVER_notify_transmit_ready (client,
676                                            sizeof (struct
677                                                    ServerClientServiceBlockedMessage),
678                                            MAX_TRANSMIT_DELAY,
679                                            &transmit_server_service_blocked_message,
680                                            NULL);
681
682       return;
683     }
684
685   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
686               GNUNET_i2s_full (peer));
687   tunnel_reliable =
688     GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
689   if (NULL == tunnel_reliable)
690     {
691       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692                   _("Could not create reliable tunnel\n"));
693       GNUNET_SERVER_notify_transmit_ready (client,
694                                            sizeof (struct
695                                                    ServerClientPeerNotConnectedMessage),
696                                            MAX_TRANSMIT_DELAY,
697                                            &transmit_server_peer_not_connected_message,
698                                            NULL);
699
700       return;
701     }
702
703   msg_size = sizeof (struct MeshSessionInitiateMessage);
704   struct MeshSessionInitiateMessage *message_mesh_initiate =
705     (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
706
707   if (NULL == message_mesh_initiate)
708     {
709       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
710                   _("Could not create MeshSessionInitiateMessage\n"));
711       GNUNET_MESH_tunnel_destroy (tunnel_reliable);
712       tunnel_reliable = NULL;
713       GNUNET_SERVER_notify_transmit_ready (client,
714                                            sizeof (struct
715                                                    ServerClientErrorMessage),
716                                            MAX_TRANSMIT_DELAY,
717                                            &transmit_server_error_message,
718                                            NULL);
719
720       return;
721     }
722
723   message_mesh_initiate->header.size = htons (msg_size);
724   message_mesh_initiate->header.type =
725     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
726
727   if (NULL ==
728       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
729                                          MAX_TRANSMIT_DELAY, msg_size,
730                                          &transmit_mesh_message,
731                                          (void *) message_mesh_initiate))
732     {
733       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
734                   _("Could not queue MeshSessionInitiateMessage\n"));
735       GNUNET_MESH_tunnel_destroy (tunnel_reliable);
736       tunnel_reliable = NULL;
737       GNUNET_free (message_mesh_initiate);
738       GNUNET_SERVER_notify_transmit_ready (client,
739                                            sizeof (struct
740                                                    ServerClientErrorMessage),
741                                            MAX_TRANSMIT_DELAY,
742                                            &transmit_server_error_message,
743                                            NULL);
744
745       return;
746     }
747
748   connection.status = CALLER;
749   connection.client = client;
750   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
751               connection.status);
752   memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
753
754   return;
755 }
756
757 /**
758  * Function to handle a session accept message from the client
759  *
760  * @param cls closure, NULL
761  * @param client the client from which the message is
762  * @param message the message from the client
763 */
764 static void
765 handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
766                                const struct GNUNET_MessageHeader *message)
767 {
768   size_t msg_size;
769
770   GNUNET_SERVER_receive_done (client, GNUNET_OK);
771
772   if (connection.status != CALLEE)
773     {
774       // TODO send illegal command
775       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
776                   _
777                   ("handle_session_accept_message called when not allowed\n"));
778       return;
779     }
780
781   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
782               GNUNET_i2s_full (&(connection.peer)));
783
784   msg_size = sizeof (struct MeshSessionAcceptMessage);
785   struct MeshSessionAcceptMessage *message_mesh_accept =
786     (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
787
788   if (NULL == message_mesh_accept)
789     {
790       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
791                   _("Could not create MeshSessionAcceptMessage\n"));
792       return;
793     }
794
795   message_mesh_accept->header.size = htons (msg_size);
796   message_mesh_accept->header.type =
797     htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
798
799   if (NULL ==
800       GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
801                                          MAX_TRANSMIT_DELAY, msg_size,
802                                          &transmit_mesh_message,
803                                          (void *) message_mesh_accept))
804     {
805       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
806                   _("Could not queue MeshSessionAcceptMessage\n"));
807       GNUNET_free (message_mesh_accept);
808       return;
809     }
810
811   connection.status = CONNECTED;
812   connection.client = client;
813   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
814               connection.status);
815
816   return;
817 }
818
819 /**
820  * Function to handle a session reject message from the client
821  *
822  * @param cls closure, NULL
823  * @param client the client from which the message is
824  * @param message the message from the client
825 */
826 static void
827 handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
828                                const struct GNUNET_MessageHeader *message)
829 {
830   struct ClientServerSessionRejectMessage *message_received;
831
832   GNUNET_SERVER_receive_done (client, GNUNET_OK);
833
834   if (connection.status != CALLEE)
835     {
836       // TODO send illegal command
837       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
838                   _
839                   ("handle_session_reject_message called when not allowed\n"));
840       return;
841     }
842
843   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"),
844               GNUNET_i2s_full (&(connection.peer)));
845   message_received = (struct ClientServerSessionRejectMessage *) message;
846   reject_call (tunnel_reliable, ntohs (message_received->reason));
847
848   return;
849 }
850
851 /**
852  * Function to handle a session terminate message from the client
853  *
854  * @param cls closure, NULL
855  * @param client the client from which the message is
856  * @param message the message from the client
857 */
858 static void
859 handle_session_terminate_message (void *cls,
860                                   struct GNUNET_SERVER_Client *client,
861                                   const struct GNUNET_MessageHeader *message)
862 {
863   GNUNET_SERVER_receive_done (client, GNUNET_OK);
864
865   if (connection.client == NULL || connection.status == CALLEE)
866     {
867       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
868                   _
869                   ("handle_session_terminate_message called when not allowed\n"));
870       return;
871     }
872
873   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
874               GNUNET_i2s_full (&(connection.peer)));
875   terminate_call ();
876 }
877
878 /******************************************************************************/
879 /***********************       SENDING FUNCTIONS MESH       *******************/
880 /******************************************************************************/
881
882 /**
883 * Transmit a mesh message
884  * @param cls closure, NULL
885  * @param size number of bytes available in buf
886  * @param buf where the callee should write the message
887  * @return number of bytes written to buf
888  */
889 static size_t
890 transmit_mesh_message (void *cls, size_t size, void *buf)
891 {
892   struct VoIPMeshMessageHeader *msg_header =
893     (struct VoIPMeshMessageHeader *) cls;
894   msg_header->SequenceNumber = SequenceNumber += 1;
895   msg_header->time = GNUNET_TIME_absolute_get ();
896
897   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
898
899   memcpy (buf, cls, size);
900   // Check if this is correct
901
902
903   if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
904        ntohs (msg_header->header.type))
905       || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
906           ntohs (msg_header->header.type)))
907     {
908       status_to_listen ();
909     }
910   else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
911            ntohs (msg_header->header.type))
912     {
913       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
914       timeout_task =
915         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
916                                       (GNUNET_TIME_UNIT_SECONDS, 30),
917                                       &check_timeout, NULL);
918     }
919
920   GNUNET_free (cls);
921
922   return size;
923 }
924
925 /**
926 * Transmit a audo message over mesh
927  * @param cls closure, NULL
928  * @param size number of bytes available in buf
929  * @param buf where the callee should write the message
930  * @return number of bytes written to buf
931  */
932 static size_t
933 transmit_mesh_audio_message (void *cls, size_t size, void *buf)
934 {
935   struct AudioMessage *message = (struct AudioMessage *) cls;
936
937   if (size < sizeof (struct AudioMessage) || NULL == buf)
938     {
939       GNUNET_break (0);
940       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
941                   "size %u, buf %p, data_sent %u, data_received %u\n",
942                   size, buf, data_sent, data_received);
943       return 0;
944     }
945
946   memcpy (buf, message, size);
947
948   data_sent++;
949   data_sent_size += size;
950
951   GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
952
953   audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
954
955   return size;
956 }
957
958 /**
959  * Task to schedule a audio transmission.
960  * 
961  * @param cls Closure.
962  * @param tc Task Context.
963  */
964 static void
965 transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
966 {
967   struct GNUNET_CONTAINER_SList_Iterator iterator;
968   struct AudioMessage *msg;
969   int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
970
971   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
972
973   if (NULL == cls)
974     {
975       if (0 == ab_length && CONNECTED == connection.status)
976         {
977           audio_task =
978             GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
979                                           (GNUNET_TIME_UNIT_MILLISECONDS, 10),
980                                           &transmit_audio_task, NULL);
981           return;
982         }
983
984       iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
985       msg =
986         (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
987       msg->SequenceNumber = SequenceNumber += 1;
988       msg->time = GNUNET_TIME_absolute_get ();
989
990       GNUNET_CONTAINER_slist_erase (&iterator);
991       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
992     }
993   else
994     {
995       msg = (struct AudioMessage *) cls;
996     }
997
998   if (NULL == tunnel_unreliable)
999     {
1000       GNUNET_CONTAINER_slist_clear (audio_buffer);
1001       return;
1002     }
1003
1004   mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
1005                                            MAX_TRANSMIT_DELAY,
1006                                            sizeof (struct AudioMessage),
1007                                            &transmit_mesh_audio_message,
1008                                            (void *) msg);
1009
1010   if (NULL == mth)
1011     {
1012       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1013                   "Need to retransmit audio packet\n");
1014       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
1015       audio_task =
1016         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1017                                       &transmit_audio_task, (void *) msg);
1018     }
1019 }
1020
1021 /******************************************************************************/
1022 /***********************       RECEIVE FUNCTIONS MESH      ********************/
1023 /******************************************************************************/
1024
1025 /**
1026 * Function to handle a initiation messaage incoming over mesh
1027  * @param cls closure, NULL
1028  * @param tunnel the tunnel over which the message arrived
1029  * @param tunnel_ctx the tunnel context, can be NULL
1030  * @param message the incoming message
1031  * 
1032  * @return GNUNET_OK
1033 */
1034 int
1035 handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1036                               void **tunnel_ctx,
1037                               const struct GNUNET_MessageHeader *message)
1038 {
1039   int reject_reason;
1040   //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1041   const struct GNUNET_PeerIdentity *peer =
1042     GNUNET_PEER_resolve2 (tunnel->peer);
1043
1044   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1045               _("Handling MeshSessionInitiateMessage from peer: %s\n"),
1046               GNUNET_i2s_full (peer));
1047   GNUNET_MESH_receive_done (tunnel);
1048
1049   if (LISTEN != connection.status
1050       || 1 > GNUNET_CONTAINER_slist_count (clients))
1051     {
1052
1053       if (CONNECTED == connection.status)
1054         {
1055           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1056                       _
1057                       ("Rejected call from %s because there is an active call"),
1058                       GNUNET_i2s_full (peer));
1059           reject_reason = htons (REJECT_REASON_ACTIVE_CALL);
1060
1061           // Notifying client about missed call
1062           size_t msg_size =
1063             sizeof (struct ServerClientMissedCallMessage) +
1064             sizeof (struct MissedCall);
1065           struct ServerClientMissedCallMessage *message =
1066             GNUNET_malloc (msg_size);
1067
1068           message->header.size = htons (msg_size);
1069           message->header.type =
1070             htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1071           message->number = 1;
1072
1073           memcpy (&(message->missed_call->peer), peer,
1074                   sizeof (struct GNUNET_PeerIdentity));
1075           message->missed_call->time = GNUNET_TIME_absolute_get ();
1076
1077           if (NULL ==
1078               GNUNET_SERVER_notify_transmit_ready (connection.client,
1079                                                    sizeof (struct
1080                                                            ServerClientMissedCallMessage),
1081                                                    MAX_TRANSMIT_DELAY,
1082                                                    &transmit_server_missed_call_message,
1083                                                    (void *) message))
1084             {
1085               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1086                           _
1087                           ("Could not queue ServerClientMissedCallMessage\n"));
1088               GNUNET_free (message);
1089             }
1090         }
1091
1092       if (1 > GNUNET_CONTAINER_slist_count (clients))
1093         {
1094           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1095                       _("Got a call from %s while no client connected.\n"),
1096                       GNUNET_i2s_full (peer));
1097           reject_reason = htons (REJECT_REASON_NO_CLIENT);
1098           // Store missed calls
1099           struct MissedCall call;
1100           memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1101           call.time = GNUNET_TIME_absolute_get ();
1102           GNUNET_CONTAINER_slist_add_end (missed_calls,
1103                                           GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1104                                           &call, sizeof (struct MissedCall));
1105
1106         }
1107
1108       reject_call (tunnel, reject_reason);
1109     }
1110   else
1111     {
1112       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
1113                   GNUNET_i2s_full (peer));
1114       tunnel_reliable = tunnel;
1115       connection.status = CALLEE;
1116       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1117                   _("Changed connection status to %d\n"), connection.status);
1118       memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
1119
1120       struct GNUNET_CONTAINER_SList_Iterator iterator =
1121         GNUNET_CONTAINER_slist_begin (clients);
1122       do
1123         {
1124           struct VoipClient *conversation_client =
1125             (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
1126                                                               NULL);
1127           struct GNUNET_SERVER_Client *client = conversation_client->client;
1128           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
1129                       client);
1130
1131           if (NULL ==
1132               GNUNET_SERVER_notify_transmit_ready (client,
1133                                                    sizeof (struct
1134                                                            ServerClientSessionInitiateMessage),
1135                                                    MAX_TRANSMIT_DELAY,
1136                                                    &transmit_server_initiate_message,
1137                                                    (void *) peer))
1138             {
1139               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1140                           _
1141                           ("Could not queue ServerClientSessionInitiateMessage\n"));
1142             }
1143
1144           GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
1145         }
1146       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1147
1148       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1149
1150     }
1151
1152   return GNUNET_OK;
1153 }
1154
1155 /**
1156 * Function to handle an accept messaage incoming over mesh
1157  * @param cls closure, NULL
1158  * @param tunnel the tunnel over which the message arrived
1159  * @param tunnel_ctx the tunnel context, can be NULL
1160  * @param message the incoming message
1161  * 
1162  * @return GNUNET_OK
1163 */
1164 int
1165 handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1166                             void **tunnel_ctx,
1167                             const struct GNUNET_MessageHeader *message)
1168 {
1169   static uint32_t port = 50003;
1170   //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1171   const struct GNUNET_PeerIdentity *peer =
1172     GNUNET_PEER_resolve2 (tunnel->peer);
1173
1174   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1175               _
1176               ("Handling MeshSessionAccpetMessage from peer: %s (connection.peer: %s)\n"),
1177               GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1178   GNUNET_MESH_receive_done (tunnel);
1179
1180   if (0 ==
1181       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1182       && connection.status == CALLER)
1183     {
1184       tunnel_unreliable =
1185         GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
1186                                    GNUNET_NO);
1187       if (NULL == tunnel_unreliable)
1188         {
1189           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1190                       _("Could not create unreliable tunnel\n"));
1191
1192           status_to_listen ();
1193
1194           GNUNET_SERVER_notify_transmit_ready (connection.client,
1195                                                sizeof (struct
1196                                                        ServerClientSessionRejectMessage),
1197                                                MAX_TRANSMIT_DELAY,
1198                                                &transmit_server_reject_message,
1199                                                NULL);
1200           return GNUNET_SYSERR;
1201         }
1202
1203       if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
1204         {
1205           GNUNET_SCHEDULER_cancel (timeout_task);
1206           timeout_task = GNUNET_SCHEDULER_NO_TASK;
1207         }
1208
1209       connection.status = CONNECTED;
1210       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1211                   _("Changed connection status to %d\n"), connection.status);
1212
1213       if (NULL ==
1214           GNUNET_SERVER_notify_transmit_ready (connection.client,
1215                                                sizeof (struct
1216                                                        ServerClientSessionAcceptMessage),
1217                                                MAX_TRANSMIT_DELAY,
1218                                                &transmit_server_accept_message,
1219                                                (void *) message))
1220         {
1221           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1222                       _
1223                       ("Could not queue ServerClientSessionAcceptMessage\n"));
1224           return GNUNET_SYSERR;
1225         }
1226
1227       start_time = GNUNET_TIME_absolute_get ();
1228       start_helpers ();
1229       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1230     }
1231
1232   return GNUNET_OK;
1233 }
1234
1235 /**
1236 * Function to handle a reject messaage incoming over mesh
1237  * @param cls closure, NULL
1238  * @param tunnel the tunnel over which the message arrived
1239  * @param tunnel_ctx the tunnel context, can be NULL
1240  * @param message the incoming message
1241  * 
1242  * @return GNUNET_OK
1243 */
1244 int
1245 handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1246                             void **tunnel_ctx,
1247                             const struct GNUNET_MessageHeader *message)
1248 {
1249   //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1250   const struct GNUNET_PeerIdentity *peer =
1251     GNUNET_PEER_resolve2 (tunnel->peer);
1252
1253   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1254               _
1255               ("Handling MeshSessionRejectMessage from peer: %s (connection.peer: %s)\n"),
1256               GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1257   GNUNET_MESH_receive_done (tunnel);
1258
1259   if (0 ==
1260       memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1261       && connection.status == CALLER)
1262     {
1263       if (NULL ==
1264           GNUNET_SERVER_notify_transmit_ready (connection.client,
1265                                                sizeof (struct
1266                                                        ServerClientSessionRejectMessage),
1267                                                MAX_TRANSMIT_DELAY,
1268                                                &transmit_server_reject_message,
1269                                                (void *) message))
1270         {
1271           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1272                       _
1273                       ("Could not queue ServerClientSessionRejectMessage\n"));
1274         }
1275
1276       status_to_listen ();
1277
1278       if (NULL != tunnel_reliable)
1279         {
1280           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1281           tunnel_reliable = NULL;
1282         }
1283     }
1284
1285   return GNUNET_OK;
1286 }
1287
1288 /**
1289 * Function to handle a terminate messaage incoming over mesh
1290  * @param cls closure, NULL
1291  * @param tunnel the tunnel over which the message arrived
1292  * @param tunnel_ctx the tunnel context, can be NULL
1293  * @param message the incoming message
1294  * 
1295  * @return GNUNET_OK
1296 */
1297 int
1298 handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1299                                void **tunnel_ctx,
1300                                const struct GNUNET_MessageHeader *message)
1301 {
1302   //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, GNUNET_MESH_OPTION_PEER))->peer;
1303   const struct GNUNET_PeerIdentity *peer =
1304     GNUNET_PEER_resolve2 (tunnel->peer);
1305
1306   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1307               _
1308               ("Handling MeshSessionTerminateMessage from peer: %s (connection.peer: %s)\n"),
1309               GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
1310   GNUNET_MESH_receive_done (tunnel);
1311
1312   if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
1313       && (connection.status == CONNECTED || connection.status == CALLEE))
1314     {
1315       status_to_listen ();
1316
1317       if (NULL != tunnel_unreliable)
1318         {
1319           GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1320           tunnel_unreliable = NULL;
1321         }
1322
1323       if (NULL != tunnel_reliable)
1324         {
1325           GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1326           tunnel_reliable = NULL;
1327         }
1328     }
1329
1330   return GNUNET_OK;
1331 }
1332
1333 /**
1334 * Function to handle a audio messaage incoming over mesh
1335  * @param cls closure, NULL
1336  * @param tunnel the tunnel over which the message arrived
1337  * @param tunnel_ctx the tunnel context, can be NULL
1338  * @param message the incoming message
1339  * 
1340  * @return GNUNET_OK
1341 */
1342 int
1343 handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1344                            void **tunnel_ctx,
1345                            const struct GNUNET_MessageHeader *message)
1346 {
1347
1348   GNUNET_MESH_receive_done (tunnel);
1349
1350   if (CONNECTED != connection.status)
1351     return GNUNET_OK;
1352
1353
1354   struct AudioMessage *audio;
1355   size_t msg_size;
1356   msg_size = sizeof (struct AudioMessage);
1357
1358   audio = (struct AudioMessage *) message;
1359
1360   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "[RECV] %dbytes\n", audio->length);
1361
1362   if (NULL == playback_helper)
1363     return GNUNET_OK;
1364
1365   (void) GNUNET_HELPER_send (playback_helper,
1366                              message, GNUNET_YES, NULL, NULL);
1367
1368   data_received++;
1369   data_received_size += msg_size;
1370
1371   return GNUNET_OK;
1372 }
1373
1374 /******************************************************************************/
1375 /***********************                      HELPER                *******************/
1376 /******************************************************************************/
1377
1378 /**
1379 * Function to process the audio from the record helper
1380  * @param cls closure, NULL
1381  * @param client NULL
1382  * @param msg the message from the helper
1383  * 
1384  * @return GNUNET_OK
1385 */
1386 static int
1387 process_record_messages (void *cls GNUNET_UNUSED, void *client,
1388                          const struct GNUNET_MessageHeader *msg)
1389 {
1390   size_t msg_size;
1391   struct AudioMessage *message = (struct AudioMessage *) msg;
1392   msg_size = sizeof (struct AudioMessage);
1393
1394   GNUNET_log (GNUNET_ERROR_TYPE_INFO, " [REC] %dbyte\n", message->length);
1395   GNUNET_CONTAINER_slist_add_end (audio_buffer,
1396                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1397                                   message, msg_size);
1398
1399   return GNUNET_OK;
1400 }
1401
1402 /**
1403 * Function to to start the playback helper
1404  * 
1405  * @return 0 ok, 1 on error
1406 */
1407 int
1408 start_playback_helper (void)
1409 {
1410   static char *playback_helper_argv[1];
1411   int success = 1;
1412
1413   playback_helper_argv[0] = "gnunet-helper-audio-playback";
1414   playback_helper = GNUNET_HELPER_start (GNUNET_NO,
1415                                          "gnunet-helper-audio-playback",
1416                                          playback_helper_argv,
1417                                          NULL, NULL, NULL);
1418
1419   if (NULL == playback_helper)
1420     {
1421       success = 0;
1422       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1423                   _("Could not start playback audio helper.\n"));
1424     }
1425
1426   return success;
1427 }
1428
1429 /**
1430 * Function to to start the record helper
1431  * 
1432  * @return 0 ok, 1 on error
1433 */
1434 int
1435 start_record_helper (void)
1436 {
1437   static char *record_helper_argv[1];
1438   int success = 1;
1439
1440   record_helper_argv[0] = "gnunet-helper-audio-record";
1441   record_helper = GNUNET_HELPER_start (GNUNET_NO,
1442                                        "gnunet-helper-audio-record",
1443                                        record_helper_argv,
1444                                        &process_record_messages, NULL, NULL);
1445
1446   if (NULL == record_helper)
1447     {
1448       success = 0;
1449       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1450                   _("Could not start record audio helper\n"));
1451     }
1452
1453   return success;
1454 }
1455
1456
1457 /**
1458 * Function to to start both helpers
1459  * 
1460  * @return 0 ok, 1 on error
1461 */
1462 int
1463 start_helpers (void)
1464 {
1465
1466   if (0 == start_playback_helper () || 0 == start_record_helper ())
1467     {
1468       stop_helpers ();
1469       return 0;
1470     }
1471
1472   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
1473
1474   return 1;
1475 }
1476
1477 /**
1478 * Function to to stop the playback helper
1479 */
1480 void
1481 stop_playback_helper (void)
1482 {
1483   if (NULL != playback_helper)
1484     {
1485       GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
1486       playback_helper = NULL;
1487
1488       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
1489     }
1490 }
1491
1492 /**
1493 * Function to to stop the record helper
1494 */
1495 void
1496 stop_record_helper (void)
1497 {
1498   if (NULL != record_helper)
1499     {
1500       GNUNET_HELPER_stop (record_helper, GNUNET_NO);
1501       record_helper = NULL;
1502
1503       GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
1504     }
1505 }
1506
1507 /**
1508 * Function to stop both audio helpers
1509 */
1510 void
1511 stop_helpers (void)
1512 {
1513   stop_playback_helper ();
1514   stop_record_helper ();
1515 }
1516
1517 /******************************************************************************/
1518 /***********************                 TUNNEL HANDLING            *******************/
1519 /******************************************************************************/
1520
1521 /**
1522  * Method called whenever another peer has added us to a tunnel
1523  * the other peer initiated.
1524  *
1525  * @param cls closure
1526  * @param tunnel new handle to the tunnel
1527  * @param initiator peer that started the tunnel
1528  * @param port port
1529  * @return initial tunnel context for the tunnel (can be NULL -- that's not an error)
1530  */
1531 static void *
1532 inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1533                 const struct GNUNET_PeerIdentity *initiator, uint32_t port)
1534 {
1535   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1536               _("Received incoming tunnel on port %d\n"), port);
1537   if (50003 == port)
1538     {
1539       tunnel_unreliable = tunnel;
1540
1541       start_time = GNUNET_TIME_absolute_get ();
1542
1543       start_helpers ();
1544       audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
1545     }
1546
1547   return NULL;
1548 }
1549
1550
1551 /**
1552  * Function called whenever an inbound tunnel is destroyed.  Should clean up
1553  * any associated state.
1554  *
1555  * @param cls closure (set from GNUNET_MESH_connect)
1556  * @param tunnel connection to the other end (henceforth invalid)
1557  * @param tunnel_ctx place where local state associated
1558  *                   with the tunnel is stored
1559  */
1560 static void
1561 inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
1562              void *tunnel_ctx)
1563 {
1564   if (tunnel == tunnel_unreliable)
1565     {
1566       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
1567
1568       stop_helpers ();
1569       tunnel_unreliable = NULL;
1570     }
1571
1572   if (tunnel == tunnel_reliable)
1573     {
1574       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
1575
1576       if (LISTEN != connection.status && NULL != connection.client)
1577         {
1578           if (NULL ==
1579               GNUNET_SERVER_notify_transmit_ready (connection.client,
1580                                                    sizeof (struct
1581                                                            ServerClientSessionTerminateMessage),
1582                                                    MAX_TRANSMIT_DELAY,
1583                                                    &transmit_server_terminate_message,
1584                                                    NULL))
1585             {
1586               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1587                           _
1588                           ("Could not queue ServerClientSessionTerminateMessage\n"));
1589             }
1590         }
1591
1592       status_to_listen ();
1593     }
1594 }
1595
1596 /******************************************************************************/
1597 /***********************          CLIENT HANDLING           *******************/
1598 /******************************************************************************/
1599
1600 /**
1601  * A client connected.
1602  *
1603  * @param cls closure, NULL
1604  * @param client identification of the client
1605  */
1606
1607 static void
1608 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
1609 {
1610   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
1611   struct ServerClientMissedCallMessage *message;
1612   size_t msg_size;
1613   struct VoipClient c;
1614   c.client = cl;
1615
1616   GNUNET_CONTAINER_slist_add_end (clients,
1617                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1618                                   &c, sizeof (struct VoipClient));
1619   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
1620
1621   if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
1622     {
1623       int i = 0;
1624       msg_size =
1625         sizeof (struct ServerClientMissedCallMessage) +
1626         GNUNET_CONTAINER_slist_count (missed_calls) *
1627         sizeof (struct MissedCall);
1628       message =
1629         (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
1630
1631       message->header.size = htons (msg_size);
1632       message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
1633       message->number = GNUNET_CONTAINER_slist_count (missed_calls);
1634
1635       struct GNUNET_CONTAINER_SList_Iterator iterator =
1636         GNUNET_CONTAINER_slist_begin (missed_calls);
1637       do
1638         {
1639           memcpy (&(message->missed_call[i]),
1640                   GNUNET_CONTAINER_slist_get (&iterator, NULL),
1641                   sizeof (struct MissedCall));
1642           i++;
1643         }
1644       while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1645
1646       GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1647       GNUNET_CONTAINER_slist_clear (missed_calls);
1648
1649
1650       if (NULL ==
1651           GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
1652                                                MAX_TRANSMIT_DELAY,
1653                                                &transmit_server_missed_call_message,
1654                                                (void *) message))
1655         {
1656           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1657                       _("Could not queue ServerClientMissedCallMessage\n"));
1658           GNUNET_free (message);
1659         }
1660     }
1661
1662   return;
1663 }
1664
1665 /**
1666  * A client disconnected.  Remove all of its data structure entries.
1667  *
1668  * @param cls closure, NULL
1669  * @param client identification of the client
1670  */
1671 static void
1672 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
1673 {
1674   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
1675
1676   if (connection.client == cl)
1677     {
1678       if (CONNECTED == connection.status)
1679         {
1680           terminate_call ();
1681         }
1682       else
1683         {
1684           status_to_listen ();
1685         }
1686     }
1687
1688   struct GNUNET_CONTAINER_SList_Iterator iterator =
1689     GNUNET_CONTAINER_slist_begin (clients);
1690   do
1691     {
1692       if (((struct VoipClient *)
1693            GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
1694         {
1695           GNUNET_CONTAINER_slist_erase (&iterator);
1696         }
1697     }
1698   while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
1699
1700   GNUNET_CONTAINER_slist_iter_destroy (&iterator);
1701
1702   return;
1703 }
1704
1705 /******************************************************************************/
1706 /***********************                      SERVICE               *******************/
1707 /******************************************************************************/
1708
1709 /**
1710  * Shutdown nicely
1711  * 
1712  * @param cls closure, NULL
1713  * @param tc the task context
1714  */
1715 static void
1716 do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1717 {
1718   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
1719
1720   stop_helpers ();
1721
1722   if (NULL != tunnel_reliable)
1723     {
1724       GNUNET_MESH_tunnel_destroy (tunnel_reliable);
1725     }
1726
1727   if (NULL != tunnel_unreliable)
1728     {
1729       GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
1730     }
1731
1732   if (NULL != mesh)
1733     {
1734       GNUNET_MESH_disconnect (mesh);
1735     }
1736
1737   if (NULL != nc)
1738     {
1739       GNUNET_SERVER_notification_context_destroy (nc);
1740       nc = NULL;
1741     }
1742
1743   GNUNET_CONTAINER_slist_destroy (audio_buffer);
1744   GNUNET_CONTAINER_slist_destroy (clients);
1745   GNUNET_CONTAINER_slist_destroy (missed_calls);
1746   GNUNET_CONTAINER_slist_destroy (peers_to_notify);
1747 }
1748
1749
1750 /**
1751  * Handler array for traffic received
1752  */
1753 static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
1754   {&handle_mesh_initiate_message,
1755    GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
1756    sizeof (struct MeshSessionInitiateMessage)},
1757   {&handle_mesh_accept_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
1758    sizeof (struct MeshSessionAcceptMessage)},
1759   {&handle_mesh_reject_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
1760    sizeof (struct MeshSessionRejectMessage)},
1761   {&handle_mesh_terminate_message,
1762    GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
1763    sizeof (struct MeshSessionTerminateMessage)},
1764   {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
1765    sizeof (struct AudioMessage)},
1766   {NULL, 0, 0}
1767 };
1768
1769 /**
1770  * Main function that will be run by the scheduler.
1771  *
1772  * @param cls closure
1773  * @param server server handle
1774  * @param c configuration
1775  */
1776 static void
1777 run (void *cls, struct GNUNET_SERVER_Handle *server,
1778      const struct GNUNET_CONFIGURATION_Handle *c)
1779 {
1780
1781   static uint32_t ports[] = { 50002, 50003, 0 };
1782   cfg = c;
1783
1784   mesh = GNUNET_MESH_connect (cfg,
1785                               NULL,
1786                               &inbound_tunnel,
1787                               &inbound_end, mesh_handlers, ports);
1788
1789   if (NULL == mesh)
1790     {
1791       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
1792       return;
1793     }
1794   else
1795     {
1796       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
1797     }
1798
1799   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1800     {&handle_session_initiate_message, NULL,
1801      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
1802      sizeof (struct ClientServerSessionInitiateMessage)},
1803     {&handle_session_accept_message, NULL,
1804      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
1805      sizeof (struct ClientServerSessionAcceptMessage)},
1806     {&handle_session_reject_message, NULL,
1807      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
1808      sizeof (struct ClientServerSessionRejectMessage)},
1809     {&handle_session_terminate_message, NULL,
1810      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
1811      sizeof (struct ClientServerSessionTerminateMessage)},
1812     {NULL, NULL, 0, 0}
1813   };
1814
1815   connection.status = LISTEN;
1816
1817   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
1818               connection.status);
1819
1820   nc = GNUNET_SERVER_notification_context_create (server, 16);
1821
1822   GNUNET_SERVER_add_handlers (server, server_handlers);
1823   GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
1824   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1825   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
1826                                 NULL);
1827
1828   clients = GNUNET_CONTAINER_slist_create ();
1829
1830   // Missed calls
1831   missed_calls = GNUNET_CONTAINER_slist_create ();
1832   peers_to_notify = GNUNET_CONTAINER_slist_create ();
1833   audio_buffer = GNUNET_CONTAINER_slist_create ();
1834
1835   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
1836 }
1837
1838 /**
1839  * The main function for the conversation service.
1840  *
1841  * @param argc number of arguments from the command line
1842  * @param argv command line arguments
1843  * @return 0 ok, 1 on error
1844  */
1845 int
1846 main (int argc, char *const *argv)
1847 {
1848   return (GNUNET_OK ==
1849           GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE,
1850                               &run, NULL)) ? 0 : 1;
1851 }
1852
1853 /* end of gnunet-service-conversation.c */