gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r29861 - gnunet/src/conversation


From: gnunet
Subject: [GNUnet-SVN] r29861 - gnunet/src/conversation
Date: Sat, 5 Oct 2013 15:10:53 +0200

Author: grothoff
Date: 2013-10-05 15:10:53 +0200 (Sat, 05 Oct 2013)
New Revision: 29861

Added:
   gnunet/src/conversation/conversation_api.c
   gnunet/src/conversation/gnunet-conversation.c
   gnunet/src/conversation/gnunet-service-conversation.c
Removed:
   gnunet/src/conversation/conversation_api.c
   gnunet/src/conversation/conversation_api2.c
   gnunet/src/conversation/gnunet-conversation-new.c
   gnunet/src/conversation/gnunet-conversation.c
   gnunet/src/conversation/gnunet-service-conversation-new.c
   gnunet/src/conversation/gnunet-service-conversation.c
Modified:
   gnunet/src/conversation/Makefile.am
Log:
-rename fest: new to default

Modified: gnunet/src/conversation/Makefile.am
===================================================================
--- gnunet/src/conversation/Makefile.am 2013-10-05 13:08:47 UTC (rev 29860)
+++ gnunet/src/conversation/Makefile.am 2013-10-05 13:10:53 UTC (rev 29861)
@@ -7,13 +7,6 @@
 AM_CPPFLAGS = \
   $(GNUNET_CPPFLAGS)
 
-# Set this variable if you are using GNUNET libraries for all programs and
-# libraries. You don't then need to target-specific _LDFLAGS with 
GNUNET_LDFLAGS
-# AM_LDFLAGS = \
-#   $(GNUNET_LDFLAGS) \
-#   $(WINFLAGS) \
-#   -export-dynamic
-
 lib_LTLIBRARIES = \
  libgnunetmicrophone.la \
  libgnunetspeaker.la \
@@ -41,8 +34,7 @@
 
 
 libgnunetconversation_la_SOURCES = \
-  conversation_api.c \
-  conversation_api2.c 
+  conversation_api.c 
 libgnunetconversation_la_LIBADD = \
   $(top_builddir)/src/gns/libgnunetgns.la \
   $(top_builddir)/src/namestore/libgnunetnamestore.la \
@@ -56,12 +48,10 @@
 
 bin_PROGRAMS = \
  gnunet-conversation-test \
- gnunet-conversation \
- gnunet-conversation-new
+ gnunet-conversation 
 
 libexec_PROGRAMS = \
-  gnunet-service-conversation \
-  gnunet-service-conversation-new 
+  gnunet-service-conversation 
 
 if HAVE_PULSE
 if HAVE_OPUS
@@ -100,39 +90,18 @@
 gnunet_service_conversation_SOURCES = \
   gnunet-service-conversation.c
 gnunet_service_conversation_LDADD = \
-  $(top_builddir)/src/gns/libgnunetgns.la \
-  $(top_builddir)/src/mesh/libgnunetmesh.la \
-  $(top_builddir)/src/namestore/libgnunetnamestore.la \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(INTLLIBS) 
-gnunet_service_conversation_LDFLAGS = \
-  $(GNUNET_LDFLAGS)  $(WINFLAGS) 
-
-gnunet_service_conversation_new_SOURCES = \
-  gnunet-service-conversation-new.c
-gnunet_service_conversation_new_LDADD = \
   libgnunetconversation.la \
   libgnunetspeaker.la \
   libgnunetmicrophone.la \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(INTLLIBS) 
-
-gnunet_service_conversation_new_LDFLAGS = \
+gnunet_service_conversation_LDFLAGS = \
   $(GNUNET_LDFLAGS)  $(WINFLAGS) 
 
 gnunet_conversation_SOURCES = \
   gnunet-conversation.c
 gnunet_conversation_LDADD = \
-  libgnunetconversation.la \
-  $(top_builddir)/src/util/libgnunetutil.la \
-  $(INTLLIBS) 
-gnunet_conversation_LDFLAGS = \
- $(GNUNET_LDFLAGS) $(WINFLAGS) 
-
-gnunet_conversation_new_SOURCES = \
-  gnunet-conversation-new.c
-gnunet_conversation_new_LDADD = \
   libgnunetmicrophone.la \
   libgnunetspeaker.la \
   libgnunetconversation.la \
@@ -141,7 +110,7 @@
   $(top_builddir)/src/identity/libgnunetidentity.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(INTLLIBS) 
-gnunet_conversation_new_LDFLAGS = \
+gnunet_conversation_LDFLAGS = \
  $(GNUNET_LDFLAGS) $(WINFLAGS) 
 
 gnunet_conversation_test_SOURCES = \

Deleted: gnunet/src/conversation/conversation_api.c
===================================================================
--- gnunet/src/conversation/conversation_api.c  2013-10-05 13:08:47 UTC (rev 
29860)
+++ gnunet/src/conversation/conversation_api.c  2013-10-05 13:10:53 UTC (rev 
29861)
@@ -1,770 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C  2013 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file conversation/conversation_api.c
- * @brief API for conversation
- * @author Simon Dieterle
- * @author Andreas Fuchs
- * STRUCTURE:
- * - DATA STRUCTURES
- * - DECLARATIONS
- * - AUXILIARY FUNCTIONS
- * - RECEIVE HANDLERS
- * - SEND FUNCTIONS
- * - API CALL DEFINITIONS
- *
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_dnsparser_lib.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_protocols.h"
-#include "conversation.h"
-#include "gnunet_conversation_service.h"
-
-#define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 60)
-
-/******************************************************************************/
-/************************      DATA STRUCTURES     
****************************/
-/******************************************************************************/
-
-enum GNUNET_CONVERSATION_CallType
-{
-  CALLER = 0,
-  CALLEE
-};
-
-/**
-* Information about a call
-*/
-struct GNUNET_CONVERSATION_CallInformation
-{
-
-       /**
-       * Peer interacting with
-       */
-  struct GNUNET_PeerIdentity peer;
-
-       /**
-       * Type of call (incoming or outgoing)
-       */
-  int type;
-
-       /**
-       * Shows if the call ist fully established
-       */
-  int established;
-};
-
-/**
- * Opaque handle to the service.
- */
-struct GNUNET_CONVERSATION_Handle
-{
-
-  /**
-   * Our configuration.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Handle to the server connection, to send messages later
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * GNS handle
-   */
-  struct GNUNET_GNS_Handle *gns;
-
-  /**
-   * Namestore handle
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore;
-
-  /**
-   * TXT record for gns
-   */
-  int txt_record_set;
-
-  /**
-   * Callback for incoming calls
-   */
-  GNUNET_CONVERSATION_CallHandler *call_handler;
-
-  /**
-   * Callback for rejected calls
-   */
-  GNUNET_CONVERSATION_RejectHandler *reject_handler;
-  
-  /**
-   * Callback for notifications
-   */
-  GNUNET_CONVERSATION_NotificationHandler *notification_handler;
-
-  /**
-   * Callback for missed calls
-   */
-  GNUNET_CONVERSATION_MissedCallHandler *missed_call_handler;
-
-  /**
-   * The pointer to the call
-   */
-  struct GNUNET_CONVERSATION_CallInformation *call;
-};
-
-/******************************************************************************/
-/***********************     AUXILIARY FUNCTIONS      
*************************/
-/******************************************************************************/
-
-/**
-* Initialize the conversation txt record in GNS
-*/
-static void
-setup_gns_txt (struct GNUNET_CONVERSATION_Handle *handle)
-{
-  struct GNUNET_CRYPTO_EccPublicSignKey zone_pkey;
-  struct GNUNET_CRYPTO_EccPrivateKey *zone_key;
-  struct GNUNET_CRYPTO_EccPrivateKey *peer_key;
-  struct GNUNET_NAMESTORE_RecordData rd;
-  struct GNUNET_PeerIdentity peer;
-
-  char *zone_keyfile;
-  char *peer_keyfile;
-
-  rd.expiration_time = UINT64_MAX;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (handle->cfg, "gns", "ZONEKEY",
-                                              &zone_keyfile))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
-      return;
-    }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (handle->cfg, "PEER",
-                                              "PRIVATE_KEY", &peer_keyfile))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
-      return;
-    }
-
-  zone_key = GNUNET_CRYPTO_ecc_key_create_from_file (zone_keyfile);
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (zone_key, &zone_pkey);
-  peer_key = GNUNET_CRYPTO_ecc_key_create_from_file (peer_keyfile);
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (peer_key,
-                                                 &peer.public_key);
-  const char *h = GNUNET_i2s_full (&peer);
-
-  rd.data_size = strlen (h) + 1;
-  rd.data = h;
-  rd.record_type = GNUNET_DNSPARSER_TYPE_TXT;
-  rd.flags = GNUNET_NAMESTORE_RF_NONE;
-
-  /* FIXME: continuation? return value? */
-  GNUNET_NAMESTORE_records_store (handle->namestore, 
-                                 zone_key,
-                                 "conversation", 
-                                 1, &rd,
-                                 NULL, NULL);
-}
-
-/**
-* Callback for checking the conversation txt gns record
-*
-* @param cls closure
-* @param rd_count
-* @param rd
-*/
-static void
-check_gns_cb (void *cls, uint32_t rd_count,
-             const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) 
cls;
-
-  if (0 == rd_count)
-    {
-      setup_gns_txt (h);
-    }
-  else
-    {
-      h->txt_record_set = GNUNET_YES;
-    }
-}
-
-
-/**
- * Check if the gns txt record for conversation exits
- */
-static void
-check_gns (struct GNUNET_CONVERSATION_Handle *h)
-{
-  GNUNET_GNS_lookup (h->gns, "conversation.gns", 
-                    NULL /* FIXME_ZONE */,
-                    GNUNET_DNSPARSER_TYPE_TXT,
-                    GNUNET_NO, 
-                    NULL, 
-                    &check_gns_cb, h);
-}
-
-
-/******************************************************************************/
-/***********************      RECEIVE HANDLERS     
****************************/
-/******************************************************************************/
-
-/**
- * Function to process all messages received from the service
- *
- * @param cls closure
- * @param msg message received, NULL on timeout or fatal error
- */
-static void
-receive_message_cb (void *cls, 
-                   const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Handle *h = cls;
-  struct ServerClientSessionInitiateMessage *imsg;
-  struct ServerClientSessionRejectMessage *rmsg;
-  struct GNUNET_CONVERSATION_MissedCallNotification *missed_calls;
-
-  if (NULL != msg)
-    {
-      switch (ntohs (msg->type))
-       {
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("%s has accepted your call.\n"),
-                     GNUNET_i2s_full (&(h->call->peer)));
-
-         h->notification_handler (NULL, h, 
GNUNET_CONVERSATION_NT_CALL_ACCEPTED,
-                                  &(h->call->peer));
-         h->call->type = CALLEE;
-
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("%s has rejected your call.\n"),
-                     GNUNET_i2s_full (&(h->call->peer)));
-
-         rmsg = (struct ServerClientSessionRejectMessage *) msg;
-         h->reject_handler (NULL, h, ntohs (rmsg->reason), &(h->call->peer));
-         GNUNET_free (h->call);
-         h->call = NULL;
-
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("%s has terminated the call.\n"),
-                     GNUNET_i2s_full (&(h->call->peer)));
-
-         h->notification_handler (NULL, h, 
GNUNET_CONVERSATION_NT_CALL_TERMINATED,
-                                  &(h->call->peer));
-         GNUNET_free (h->call);
-         h->call = NULL;
-
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE:
-         imsg = (struct ServerClientSessionInitiateMessage *) msg;
-
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%s wants to call you.\n"),
-                     GNUNET_i2s_full (&(imsg->peer)));
-
-         h->call =
-           (struct GNUNET_CONVERSATION_CallInformation *)
-           GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_CallInformation));
-         memcpy (&(h->call->peer), &(imsg->peer),
-                 sizeof (struct GNUNET_PeerIdentity));
-         h->call_handler (NULL, h, &(h->call->peer));
-         h->call->type = CALLEE;
-
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL:
-         missed_calls =
-           (struct GNUNET_CONVERSATION_MissedCallNotification *) (msg +
-                                                          (sizeof
-                                                           (struct
-                                                            
GNUNET_MessageHeader)));
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("You &d have missed a calls.\n"),
-                     missed_calls->number);
-         h->missed_call_handler (NULL, h, missed_calls);
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("The service is blocked.\n"));
-         h->notification_handler (NULL, h, 
GNUNET_CONVERSATION_NT_SERVICE_BLOCKED,
-                                  NULL);
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("The peer you are calling is not connected.\n"));
-         h->notification_handler (NULL, h, GNUNET_CONVERSATION_NT_NO_PEER, 
NULL);
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("The peer you are calling does not answer.\n"));
-         h->notification_handler (NULL, h, GNUNET_CONVERSATION_NT_NO_ANSWER,
-                                  &(h->call->peer));
-         break;
-
-       case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Generic error occured.\n"));
-         break;
-
-       default:
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("Got unknown message type.\n"));
-         break;
-       }
-
-    }
-
-  GNUNET_CLIENT_receive (h->client, &receive_message_cb, h,
-                        GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-/******************************************************************************/
-/************************       SEND FUNCTIONS     
****************************/
-/******************************************************************************/
-
-/**
- * Function called to send a session initiate message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the initiate message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_session_initiate_message (void *cls, size_t size, void *buf)
-{
-  size_t msg_size;
-  struct ClientServerSessionInitiateMessage *msg;
-  struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) 
cls;
-
-  msg_size = sizeof (struct ClientServerSessionInitiateMessage);
-
-  GNUNET_assert (size >= msg_size);
-  msg = buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE);
-  memcpy (&msg->peer, &(h->call->peer), sizeof (struct GNUNET_PeerIdentity));
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Sending ClientServerSessionInitiateMessage to the service for 
peer: %s\n"),
-             GNUNET_i2s_full (&(h->call->peer)));
-
-  h->call->type = CALLER;
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session accept message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the accept message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_session_accept_message (void *cls, size_t size, void *buf)
-{
-  size_t msg_size;
-  struct ClientServerSessionAcceptMessage *msg;
-  struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) 
cls;
-
-  msg_size = sizeof (struct ClientServerSessionAcceptMessage);
-
-  GNUNET_assert (size >= msg_size);
-  msg = buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Sending ClienServerSessionAcceptMessage to the service for 
peer: %s\n"),
-             GNUNET_i2s_full (&(h->call->peer)));
-
-  h->call->established = GNUNET_YES;
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session reject message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the reject message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_session_reject_message (void *cls, size_t size, void *buf)
-{
-  size_t msg_size;
-  struct ClientServerSessionRejectMessage *msg;
-  struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) 
cls;
-
-  msg_size = sizeof (struct ClientServerSessionRejectMessage);
-
-  GNUNET_assert (size >= msg_size);
-  msg = buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT);
-  msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_WANTED);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Sending ClientServerSessionRejectMessage to the service for 
peer: %s\n"),
-             GNUNET_i2s_full (&(h->call->peer)));
-
-  GNUNET_free (h->call);
-  h->call = NULL;
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session terminate message to the service.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the terminate message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_session_terminate_message (void *cls, size_t size, void *buf)
-{
-  size_t msg_size;
-  struct ClientServerSessionTerminateMessage *msg;
-  struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) 
cls;
-
-  msg_size = sizeof (struct ClientServerSessionTerminateMessage);
-
-  GNUNET_assert (size >= msg_size);
-  msg = buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Sending ClientServerSessionTerminateMessage to the service for 
peer: %s\n"),
-             GNUNET_i2s_full (&(h->call->peer)));
-
-  GNUNET_free (h->call);
-  h->call = NULL;
-
-  return msg_size;
-}
-
-/**
- * Auxiliary function to call a peer.
- * 
- * @param h conversation handle
- * @return 
- */
-static void
-initiate_call (struct GNUNET_CONVERSATION_Handle *h, struct 
GNUNET_PeerIdentity peer)
-{
-  h->call =
-    (struct GNUNET_CONVERSATION_CallInformation *)
-    GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_CallInformation));
-  memcpy (&(h->call->peer), &peer, sizeof (struct GNUNET_PeerIdentity));
-
-  GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                      sizeof (struct
-                                              
ClientServerSessionInitiateMessage),
-                                      MAX_TRANSMIT_DELAY, GNUNET_YES,
-                                      &transmit_session_initiate_message, h);
-
-  return;
-}
-
-/**
- * Auxiliary function to accept a call.
- * 
- * @param h conversation handle
- */
-static void
-accept_call (struct GNUNET_CONVERSATION_Handle *h)
-{
-  GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                      sizeof (struct
-                                              
ClientServerSessionAcceptMessage),
-                                      MAX_TRANSMIT_DELAY, GNUNET_YES,
-                                      &transmit_session_accept_message, h);
-}
-
-
-/**
- * Auxiliary function to reject a call.
- * 
- * @param h conversation handle
- */
-static void
-reject_call (struct GNUNET_CONVERSATION_Handle *h)
-{
-  GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                      sizeof (struct
-                                              
ClientServerSessionRejectMessage),
-                                      MAX_TRANSMIT_DELAY, GNUNET_YES,
-                                      &transmit_session_reject_message, h);
-}
-
-
-/**
- * Auxiliary function to terminate a call.
- * 
- * @param h conversation handle
- */
-static void
-terminate_call (struct GNUNET_CONVERSATION_Handle *h)
-{
-  GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                      sizeof (struct
-                                              
ClientServerSessionTerminateMessage),
-                                      MAX_TRANSMIT_DELAY, GNUNET_YES,
-                                      &transmit_session_terminate_message,
-                                      h);
-}
-
-
-/**
- *
- */
-static void
-gns_call_cb (void *cls, uint32_t rd_count,
-            const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  struct GNUNET_CONVERSATION_Handle *handle = cls;
-  struct GNUNET_PeerIdentity peer;
-  unsigned int i;
-
-  for (i=0;i<rd_count;i++)
-  {
-    switch (rd[i].record_type)
-    {
-    case GNUNET_DNSPARSER_TYPE_TXT: /* FIXME:  use fresh record type for 
voide... */
-      if (GNUNET_OK !=
-         GNUNET_CRYPTO_ecc_public_sign_key_from_string (rd[i].data,
-                                                        rd[i].data_size,
-                                                        &peer.public_key))
-      {
-       GNUNET_break_op (0);
-       continue;
-      }      
-      initiate_call (handle, peer);
-      return;
-    default:
-      break;
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             "Lookup failed\n");
-  handle->notification_handler (NULL, handle, 
-                               GNUNET_CONVERSATION_NT_NO_PEER,
-                               NULL);
-}
-
-
-/**
-* GNS lookup
-*/
-static void
-gns_lookup_and_call (struct GNUNET_CONVERSATION_Handle *h, const char *callee)
-{
-  char domain[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
-  char *pos;
-
-  pos = domain;
-  strcpy (pos, "conversation");
-  pos += strlen ("conversation");
-  strcpy (pos, ".");
-  pos++;
-  strcpy (pos, callee);
-  pos += strlen (callee);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Lookup for %s\n", domain);
-
-  GNUNET_GNS_lookup (h->gns,
-                    domain,
-                    NULL /* FIXME: ZONE! */,
-                    GNUNET_DNSPARSER_TYPE_TXT,
-                    GNUNET_NO, 
-                    NULL,
-                    &gns_call_cb, h);
-}
-
-
-/******************************************************************************/
-/**********************      API CALL DEFINITIONS     
*************************/
-/******************************************************************************/
-
-struct GNUNET_CONVERSATION_Handle *
-GNUNET_CONVERSATION_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 
-                            void *cls,
-                            GNUNET_CONVERSATION_CallHandler call_handler,
-                            GNUNET_CONVERSATION_RejectHandler reject_handler,
-                            GNUNET_CONVERSATION_NotificationHandler 
notification_handler,
-                            GNUNET_CONVERSATION_MissedCallHandler 
missed_call_handler)
-{
-  struct GNUNET_CONVERSATION_Handle *h;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             "GNUNET_CONVERSATION_connect()\n");
-  h = GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_Handle));
-
-  h->cfg = cfg;
-  h->call_handler = call_handler;
-  h->reject_handler = reject_handler;
-  h->notification_handler = notification_handler;
-  h->missed_call_handler = missed_call_handler;
-
-  if (NULL == (h->client = GNUNET_CLIENT_connect ("conversation", cfg)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not access CONVERSATION 
service\n");
-      GNUNET_break (0);
-      GNUNET_free (h);
-
-      return NULL;
-    }
-
-  if (NULL == (h->gns = GNUNET_GNS_connect (cfg)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not access GNS service\n");
-      GNUNET_break (0);
-      GNUNET_CLIENT_disconnect (h->client);
-      GNUNET_free (h);
-
-      return NULL;
-    }
-
-  if (NULL == (h->namestore = GNUNET_NAMESTORE_connect (cfg)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Could not access NAMESTORE service\n");
-      GNUNET_break (0);
-      GNUNET_CLIENT_disconnect (h->client);
-      GNUNET_GNS_disconnect (h->gns);
-      GNUNET_free (h);
-
-      return NULL;
-    }
-
-  check_gns (h);
-  GNUNET_CLIENT_receive (h->client, &receive_message_cb, h,
-                        GNUNET_TIME_UNIT_FOREVER_REL);
-
-  return h;
-}
-
-
-void
-GNUNET_CONVERSATION_disconnect (struct GNUNET_CONVERSATION_Handle *handle)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CONVERSATION DISCONNECT\n");
-
-  GNUNET_CLIENT_disconnect (handle->client);
-  GNUNET_GNS_disconnect (handle->gns);
-
-  GNUNET_free (handle);
-  handle = NULL;
-}
-
-
-void
-GNUNET_CONVERSATION_call (struct GNUNET_CONVERSATION_Handle *h, 
-                         const char *callee,
-                         int doGnsLookup)
-{
-  struct GNUNET_PeerIdentity peer;
-
-  if (NULL == h || NULL == h->client)
-    return;
-
-  if (GNUNET_YES == doGnsLookup)
-  {
-    gns_lookup_and_call (h, callee);
-    return;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_ecc_public_sign_key_from_string (callee, 
-                                                    strlen (callee),
-                                                    &peer.public_key))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-               _("`%s'  is not a valid public key\n"),
-               callee);
-    h->notification_handler (NULL, h, GNUNET_CONVERSATION_NT_NO_PEER, NULL);
-    return;
-  }  
-  initiate_call (h, peer);
-}
-
-
-void
-GNUNET_CONVERSATION_hangup (struct GNUNET_CONVERSATION_Handle *h)
-{
-  if (NULL == h || NULL == h->client)
-    return;
-
-  terminate_call (h);
-}
-
-
-void
-GNUNET_CONVERSATION_accept (struct GNUNET_CONVERSATION_Handle *h)
-{
-  if (NULL == h || NULL == h->client)
-    return;
-
-  accept_call (h);
-}
-
-
-void
-GNUNET_CONVERSATION_reject (struct GNUNET_CONVERSATION_Handle *h)
-{
-  if (NULL == h || NULL == h->client)
-    return;
-
-  reject_call (h);
-}
-
-/* end of conversation_api.c */

Copied: gnunet/src/conversation/conversation_api.c (from rev 29856, 
gnunet/src/conversation/conversation_api2.c)
===================================================================
--- gnunet/src/conversation/conversation_api.c                          (rev 0)
+++ gnunet/src/conversation/conversation_api.c  2013-10-05 13:10:53 UTC (rev 
29861)
@@ -0,0 +1,1132 @@
+/*
+  This file is part of GNUnet
+  (C) 2013 Christian Grothoff (and other contributing authors)
+  
+  GNUnet is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+  
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+  Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file conversation/conversation_api2.c
+ * @brief API to the conversation service
+ * @author Simon Dieterle
+ * @author Andreas Fuchs
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_conversation_service.h"
+#include "gnunet_gns_service.h"
+#include "conversation.h"
+
+
+/**
+ * A phone record specifies which peer is hosting a given user and
+ * may also specify the phone line that is used (typically zero).
+ * The version is also right now always zero.
+ */
+struct PhoneRecord
+{
+
+  /**
+   * Version of the phone record, for now always zero.  We may
+   * use other versions for anonymously hosted phone lines in
+   * the future.
+   */
+  uint32_t version GNUNET_PACKED;
+
+  /**
+   * Phone line to use at the peer.
+   */
+  uint32_t line GNUNET_PACKED;
+
+  /**
+   * Identity of the peer hosting the phone service.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+};
+
+
+/**
+ * Possible states of the phone.
+ */
+enum PhoneState
+{
+  /**
+   * We still need to register the phone.
+   */
+  PS_REGISTER = 0,
+
+  /**
+   * We are waiting for a call.
+   */
+  PS_WAITING,
+
+  /**
+   * The phone is ringing.
+   */
+  PS_RINGING,
+
+  /**
+   * The phone is in an active conversation.
+   */
+  PS_ACTIVE
+};
+
+
+/**
+ * A phone is a device that can ring to signal an incoming call and
+ * that you can pick up to answer the call and hang up to terminate
+ * the call.  You can also hang up a ringing phone immediately
+ * (without picking it up) to stop it from ringing.  Phones have
+ * caller ID.  You can ask the phone for its record and make that
+ * record available (via GNS) to enable others to call you.
+ * Multiple phones maybe connected to the same line (the line is
+ * something rather internal to a phone and not obvious from it).
+ * You can only have one conversation per phone at any time.
+ */
+struct GNUNET_CONVERSATION_Phone
+{
+  /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  
+  /**
+   * Handle to talk with CONVERSATION service.
+   */
+  struct GNUNET_CLIENT_Connection *client;
+
+  /**
+   * Function to call for phone events.
+   */
+  GNUNET_CONVERSATION_EventHandler event_handler;
+
+  /**
+   * Closure for @e event_handler
+   */
+  void *event_handler_cls;
+
+  /**
+   * Speaker, or NULL if none is attached.
+   */
+  struct GNUNET_SPEAKER_Handle *speaker;
+
+  /**
+   * Microphone, or NULL if none is attached.
+   */
+  struct GNUNET_MICROPHONE_Handle *mic;
+
+  /**
+   * Connection to NAMESTORE (for reverse lookup).
+   */ 
+  struct GNUNET_NAMESTORE_Handle *ns;
+
+  /**
+   * Active NAMESTORE lookup (or NULL).
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *qe;
+
+  /**
+   * Handle for transmitting to the CONVERSATION service.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * This phone's record.
+   */
+  struct PhoneRecord my_record;  
+
+  /**
+   * My GNS zone.
+   */
+  struct GNUNET_CRYPTO_EccPrivateKey my_zone;
+
+  /**
+   * Identity of the person calling us (valid while in state #PS_RINGING).
+   */
+  struct GNUNET_CRYPTO_EccPublicSignKey caller_id;
+
+  /**
+   * State machine for the phone.
+   */
+  enum PhoneState state;
+
+};
+
+
+/**
+ * The phone got disconnected, reconnect to the service.
+ *
+ * @param phone phone to reconnect
+ */
+static void
+reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone);
+
+
+/**
+ * We have resolved the caller ID using our name service.
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Phone`
+ * @param zone our zone used for resolution
+ * @param label name of the caller
+ * @param rd_count number of records we have in @a rd
+ * @param rd records we have for the caller's label
+ */
+static void
+handle_caller_name (void *cls,
+                    const struct GNUNET_CRYPTO_EccPrivateKey *zone,
+                    const char *label,
+                    unsigned int rd_count,
+                    const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+  char *name;
+
+  phone->qe = NULL;
+  if (NULL == label)
+    name = GNUNET_strdup (GNUNET_NAMESTORE_pkey_to_zkey (&phone->caller_id));
+  else
+    GNUNET_asprintf (&name, "%.gnu", label);
+  phone->event_handler (phone->event_handler_cls,
+                        GNUNET_CONVERSATION_EC_RING,
+                        name);
+  GNUNET_free (name);
+}
+
+
+/**
+ * We received a `struct ClientPhoneRingMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Phone`
+ * @param msg the message
+ */
+static void
+handle_phone_ring (void *cls,
+                   const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+  const struct ClientPhoneRingMessage *ring;
+
+  ring = (const struct ClientPhoneRingMessage *) msg;
+  switch (phone->state)
+  {
+  case PS_REGISTER:
+    GNUNET_assert (0);
+    break;
+  case PS_WAITING:
+    phone->state = PS_RINGING;
+    phone->caller_id = ring->caller_id;
+    phone->qe = GNUNET_NAMESTORE_zone_to_name (phone->ns,
+                                               &phone->my_zone,
+                                               &ring->caller_id,
+                                               &handle_caller_name,
+                                               phone);
+    break;
+  case PS_RINGING:
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    break;
+  case PS_ACTIVE:
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    break;
+  }
+}
+
+
+/**
+ * We received a `struct ClientPhoneHangupMessage`.
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Phone`
+ * @param msg the message
+ */
+static void
+handle_phone_hangup (void *cls,
+                     const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+  const struct ClientPhoneHangupMessage *hang;
+  size_t len;
+  const char *reason;
+
+  hang = (const struct ClientPhoneHangupMessage *) msg;
+  reason = (const char *) &hang[1];
+  len = htons (hang->header.size) - sizeof (struct ClientPhoneHangupMessage);
+  if ( (0 == len) ||
+       ('\0' != reason[len-1]) )
+  {
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    return;
+  }
+  switch (phone->state)
+  {
+  case PS_REGISTER:
+    GNUNET_assert (0);
+    break;
+  case PS_WAITING:
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    break;
+  case PS_RINGING:
+    if (NULL != phone->qe)
+    {
+      GNUNET_NAMESTORE_cancel (phone->qe);
+      phone->qe = NULL;
+      phone->state = PS_WAITING;
+      break;
+    }
+    phone->state = PS_WAITING;
+    phone->event_handler (phone->event_handler_cls,
+                          GNUNET_CONVERSATION_EC_TERMINATED,
+                          reason);
+    break;
+  case PS_ACTIVE:
+    GNUNET_break (NULL == phone->qe);
+    phone->state = PS_WAITING;
+    phone->event_handler (phone->event_handler_cls,
+                          GNUNET_CONVERSATION_EC_TERMINATED,
+                          reason);
+    break;
+  }
+}
+
+
+/**
+ * We received a `struct ClientAudioMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Phone`
+ * @param msg the message
+ */
+static void
+handle_phone_audio_message (void *cls,
+                            const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+  const struct ClientAudioMessage *am;
+
+  am = (const struct ClientAudioMessage *) msg;
+  switch (phone->state)
+  {
+  case PS_REGISTER:
+    GNUNET_assert (0);
+    break;
+  case PS_WAITING:
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    break;
+  case PS_RINGING:
+    GNUNET_break (0);
+    reconnect_phone (phone);
+    break;
+  case PS_ACTIVE:
+    phone->speaker->play (phone->speaker->cls,
+                          ntohs (msg->size) - sizeof (struct 
ClientAudioMessage),
+                          &am[1]);
+    break;
+  }
+}
+
+
+/**
+ * We encountered an error talking with the conversation service. 
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Phone`
+ * @param error details about the error
+ */
+static void
+phone_error_handler (void *cls,
+                     enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+
+  GNUNET_break (0);
+  reconnect_phone (phone);
+}
+
+
+/**
+ * The phone got disconnected, reconnect to the service.
+ *
+ * @param phone phone to reconnect
+ */
+static void
+reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
+{
+  static struct GNUNET_MQ_MessageHandler handlers[] =
+  {
+    { &handle_phone_ring,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING, 
+      sizeof (struct ClientPhoneRingMessage) },
+    { &handle_phone_hangup,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
+      0 },
+    { &handle_phone_audio_message,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
+      0 },    
+    { NULL, 0, 0 }    
+  };
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhoneRegisterMessage *reg;
+
+  if (NULL != phone->mq)
+  {
+    GNUNET_MQ_destroy (phone->mq);
+    phone->mq = NULL;
+  }
+  if (NULL != phone->client)
+  {
+    GNUNET_CLIENT_disconnect (phone->client);
+    phone->client = NULL;
+  }
+  phone->state = PS_REGISTER;
+  phone->client = GNUNET_CLIENT_connect ("conversation", phone->cfg);
+  if (NULL == phone->client)
+    return;
+  phone->mq = GNUNET_MQ_queue_for_connection_client (phone->client,
+                                                     handlers,
+                                                     &phone_error_handler,
+                                                     phone);
+  e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
+  reg->line = phone->my_record.line;
+  GNUNET_MQ_send (phone->mq, e);
+  phone->state = PS_WAITING;
+}
+
+
+/**
+ * Create a new phone.
+ *
+ * @param cfg configuration for the phone; specifies the phone service and
+ *        which line the phone is to be connected to
+ * @param ego ego to use for name resolution (when determining caller ID)
+ * @param event_handler how to notify the owner of the phone about events
+ * @param event_handler_cls closure for @a event_handler
+ */
+struct GNUNET_CONVERSATION_Phone *
+GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+                                  const struct GNUNET_IDENTITY_Ego *ego,
+                                  GNUNET_CONVERSATION_EventHandler 
event_handler,
+                                 void *event_handler_cls)
+{
+  struct GNUNET_CONVERSATION_Phone *phone;
+  unsigned long long line;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, 
+                                             "CONVERSATION",
+                                             "LINE",
+                                             &line))
+    return NULL;
+  phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_get_host_identity (cfg,
+                                       &phone->my_record.peer))
+  {
+    GNUNET_break (0);
+    GNUNET_free (phone);
+    return NULL;
+  }
+  phone->cfg = cfg;
+  phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
+  phone->event_handler = event_handler;
+  phone->event_handler_cls = event_handler_cls;
+  phone->ns = GNUNET_NAMESTORE_connect (cfg);
+  phone->my_record.line = htonl ((uint32_t) line);
+  phone->my_record.version = htonl (0);
+  reconnect_phone (phone);
+  if ( (NULL == phone->client) ||
+       (NULL == phone->ns) )
+  {
+    GNUNET_break (0);
+    GNUNET_CONVERSATION_phone_destroy (phone);
+    return NULL;
+  }
+  return phone;
+}
+
+
+/**
+ * Fill in a namestore record with the contact information
+ * for this phone.  Note that the filled in "data" value
+ * is only valid until the phone is destroyed.
+ *
+ * @param phone phone to create a record for
+ * @param rd namestore record to fill in
+ */
+void
+GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone,
+                                     struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  rd->data = &phone->my_record;
+  rd->expiration_time = 0;
+  rd->data_size = sizeof (struct PhoneRecord);
+  rd->record_type = GNUNET_NAMESTORE_TYPE_PHONE;
+  rd->flags = GNUNET_NAMESTORE_RF_NONE;
+}
+
+
+/**
+ * Process recorded audio data.
+ *
+ * @param cls closure with the `struct GNUNET_CONVERSATION_Phone`
+ * @param data_size number of bytes in @a data
+ * @param data audio data to play
+ */
+static void
+transmit_phone_audio (void *cls,
+                      size_t data_size,
+                      const void *data)
+{
+  struct GNUNET_CONVERSATION_Phone *phone = cls;
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientAudioMessage *am;
+
+  GNUNET_assert (PS_ACTIVE == phone->state);
+  e = GNUNET_MQ_msg_extra (am, 
+                           data_size,
+                           GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
+  memcpy (&am[1], data, data_size);
+  GNUNET_MQ_send (phone->mq, e);
+}
+
+
+/**
+ * Picks up a (ringing) phone.  This will connect the speaker 
+ * to the microphone of the other party, and vice versa.
+ *
+ * @param phone phone to pick up
+ * @param metadata meta data to give to the other user about the pick up event
+ * @param speaker speaker to use
+ * @param mic microphone to use
+ */
+void
+GNUNET_CONVERSATION_phone_pick_up (struct GNUNET_CONVERSATION_Phone *phone,
+                                   const char *metadata,
+                                   struct GNUNET_SPEAKER_Handle *speaker,
+                                   struct GNUNET_MICROPHONE_Handle *mic)
+{
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhonePickupMessage *pick;
+  size_t slen;
+
+  GNUNET_assert (PS_RINGING == phone->state);
+  phone->speaker = speaker;
+  phone->mic = mic;
+  slen = strlen (metadata) + 1;
+  e = GNUNET_MQ_msg_extra (pick, slen, 
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
+  memcpy (&pick[1], metadata, slen);
+  GNUNET_MQ_send (phone->mq, e);
+  phone->state = PS_ACTIVE;
+  phone->speaker->enable_speaker (phone->speaker->cls);
+  phone->mic->enable_microphone (phone->mic->cls,
+                                 &transmit_phone_audio,
+                                 phone);
+}
+
+
+/**
+ * Hang up up a (possibly ringing) phone.  This will notify the other
+ * party that we are no longer interested in talking with them.
+ *
+ * @param phone phone to pick up
+ * @param reason text we give to the other party about why we terminated the 
conversation
+ */
+void
+GNUNET_CONVERSATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone,
+                                   const char *reason)
+{
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhoneHangupMessage *hang;
+  size_t slen;
+
+  GNUNET_assert ( (PS_RINGING == phone->state) ||
+                  (PS_ACTIVE == phone->state) );
+  phone->speaker->disable_speaker (phone->speaker->cls);
+  phone->mic->disable_microphone (phone->mic->cls);
+  phone->speaker = NULL;
+  phone->mic = NULL;
+  slen = strlen (reason) + 1;
+  e = GNUNET_MQ_msg_extra (hang, slen, 
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
+  memcpy (&hang[1], reason, slen);
+  GNUNET_MQ_send (phone->mq, e);
+  phone->state = PS_WAITING;
+}
+
+
+/**
+ * Destroys a phone.
+ *
+ * @param phone phone to destroy
+ */
+void
+GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone)
+{
+  if (NULL != phone->speaker)
+  {
+    phone->speaker->disable_speaker (phone->speaker->cls);
+    phone->speaker = NULL;
+  }
+  if (NULL != phone->mic)
+  {
+    phone->mic->disable_microphone (phone->mic->cls);
+    phone->mic = NULL;
+  }
+  if (NULL != phone->qe)
+  {
+    GNUNET_NAMESTORE_cancel (phone->qe);
+    phone->qe = NULL;
+  }
+  if (NULL != phone->ns)
+  {
+    GNUNET_NAMESTORE_disconnect (phone->ns);
+    phone->ns = NULL;
+  }
+  if (NULL != phone->mq)
+  {
+    GNUNET_MQ_destroy (phone->mq);
+    phone->mq = NULL;
+  }
+  if (NULL != phone->client)
+  {
+    GNUNET_CLIENT_disconnect (phone->client);
+    phone->client = NULL;
+  }
+  GNUNET_free (phone);
+}
+
+
+/* ******************************* Call API *************************** */
+
+/**
+ * Possible states of the phone.
+ */
+enum CallState
+{
+  /**
+   * We still need to lookup the callee.
+   */
+  CS_LOOKUP = 0,
+
+  /**
+   * The call is ringing.
+   */
+  CS_RINGING,
+
+  /**
+   * The call is in an active conversation.
+   */
+  CS_ACTIVE,
+
+  /**
+   * The call is in termination.
+   */
+  CS_SHUTDOWN
+};
+
+
+/**
+ * Handle for an outgoing call.
+ */
+struct GNUNET_CONVERSATION_Call
+{
+
+  /**
+   * Our configuration.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  
+  /**
+   * Handle to talk with CONVERSATION service.
+   */
+  struct GNUNET_CLIENT_Connection *client;
+
+  /**
+   * Our caller identity.
+   */
+  struct GNUNET_IDENTITY_Ego *caller_id;
+
+  /**
+   * Target callee as a GNS address/name.
+   */
+  char *callee;
+
+  /**
+   * Our speaker.
+   */
+  struct GNUNET_SPEAKER_Handle *speaker;
+
+  /**
+   * Our microphone.
+   */
+  struct GNUNET_MICROPHONE_Handle *mic;
+  
+  /**
+   * Function to call with events.
+   */
+  GNUNET_CONVERSATION_EventHandler event_handler;
+
+  /**
+   * Closure for @e event_handler
+   */
+  void *event_handler_cls;
+
+  /**
+   * Handle for transmitting to the CONVERSATION service.
+   */
+  struct GNUNET_MQ_Handle *mq;
+
+  /**
+   * Connection to GNS (can be NULL).
+   */ 
+  struct GNUNET_GNS_Handle *gns;
+
+  /**
+   * Active GNS lookup (or NULL).
+   */
+  struct GNUNET_GNS_LookupRequest *gns_lookup;
+
+  /**
+   * Target phone record, only valid after the lookup is done.
+   */
+  struct PhoneRecord phone_record;
+
+  /**
+   * State machine for the call.
+   */
+  enum CallState state;
+
+};
+
+
+/**
+ * The call got disconnected, reconnect to the service.
+ *
+ * @param call call to reconnect
+ */
+static void
+reconnect_call (struct GNUNET_CONVERSATION_Call *call);
+
+
+/**
+ * We received a `struct ClientPhoneBusyMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Call`
+ * @param msg the message
+ */
+static void
+handle_call_busy (void *cls,
+                  const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+
+  switch (call->state)
+  {
+  case CS_LOOKUP:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_RINGING:
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_BUSY);
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    break;
+  case CS_ACTIVE:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_SHUTDOWN:
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    break;
+  }
+}
+
+
+/**
+ * Process recorded audio data.
+ *
+ * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
+ * @param data_size number of bytes in @a data
+ * @param data audio data to play
+ */
+static void
+transmit_call_audio (void *cls,
+                     size_t data_size,
+                     const void *data)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientAudioMessage *am;
+
+  GNUNET_assert (CS_ACTIVE == call->state);
+  e = GNUNET_MQ_msg_extra (am, 
+                           data_size,
+                           GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
+  memcpy (&am[1], data, data_size);
+  GNUNET_MQ_send (call->mq, e);
+}
+
+
+/**
+ * We received a `struct ClientPhonePickedupMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Call`
+ * @param msg the message
+ */
+static void
+handle_call_picked_up (void *cls,
+                       const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+  const struct ClientPhonePickedupMessage *am;
+  const char *metadata;
+  size_t size;
+
+  am = (const struct ClientPhonePickedupMessage *) msg;
+  size = ntohs (am->header.size) - sizeof (struct ClientPhonePickedupMessage);
+  metadata = (const char *) &am[1];
+  if ( (0 == size) ||
+       ('\0' != metadata[size - 1]) )
+    metadata = NULL;  
+  switch (call->state)
+  {
+  case CS_LOOKUP:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_RINGING:
+    call->state = CS_ACTIVE;
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_READY,
+                         metadata);
+    call->speaker->enable_speaker (call->speaker->cls);
+    call->mic->enable_microphone (call->mic->cls,
+                                  &transmit_call_audio,
+                                  call);
+    break;
+  case CS_ACTIVE:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_SHUTDOWN:
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    break;
+  }
+}
+
+
+/**
+ * We received a `struct ClientPhoneHangupMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Call`
+ * @param msg the message
+ */
+static void
+handle_call_hangup (void *cls,
+                    const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+  const struct ClientPhoneHangupMessage *am;
+  const char *reason;
+  size_t size;
+
+  am = (const struct ClientPhoneHangupMessage *) msg;
+  size = ntohs (am->header.size) - sizeof (struct ClientPhoneHangupMessage);
+  reason = (const char *) &am[1];
+  if ( (0 == size) ||
+       ('\0' != reason[size - 1]) )
+    reason = NULL;  
+  switch (call->state)
+  {
+  case CS_LOOKUP:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_RINGING:
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_TERMINATED,
+                         reason);
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    return;
+  case CS_ACTIVE:
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_TERMINATED,
+                         reason);
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    return;
+  case CS_SHUTDOWN:
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    break;
+  }
+}
+
+
+/**
+ * We received a `struct ClientAudioMessage`
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Call`
+ * @param msg the message
+ */
+static void
+handle_call_audio_message (void *cls,
+                           const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+  const struct ClientAudioMessage *am;
+
+  am = (const struct ClientAudioMessage *) msg;
+  switch (call->state)
+  {
+  case CS_LOOKUP:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_RINGING:
+    GNUNET_break (0);
+    reconnect_call (call);
+    break;
+  case CS_ACTIVE:
+    call->speaker->play (call->speaker->cls,
+                         ntohs (msg->size) - sizeof (struct 
ClientAudioMessage),
+                         &am[1]);
+    break;
+  case CS_SHUTDOWN:
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    break;
+
+  }
+}
+
+
+/**
+ * Iterator called on obtained result for a GNS lookup.
+ *
+ * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
+ * @param rd_count number of records in @a rd
+ * @param rd the records in reply
+ */
+static void 
+handle_gns_response (void *cls,
+                     uint32_t rd_count,
+                     const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+  uint32_t i;
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientCallMessage *ccm;
+
+  for (i=0;i<rd_count;i++)
+  {
+    if (GNUNET_NAMESTORE_TYPE_PHONE == rd[i].record_type)
+    {
+      if (rd[i].data_size != sizeof (struct PhoneRecord))
+      {
+        GNUNET_break_op (0);
+        continue;
+      }      
+      memcpy (&call->phone_record,
+              rd[i].data,
+              rd[i].data_size);
+      e = GNUNET_MQ_msg (ccm, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL);
+      ccm->line = call->phone_record.line;
+      ccm->target = call->phone_record.peer;
+      ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id);
+      GNUNET_MQ_send (call->mq, e);
+      call->state = CS_RINGING;
+      call->event_handler (call->event_handler_cls,
+                           GNUNET_CONVERSATION_EC_RINGING);
+      return;
+    }
+  }
+  /* not found */
+  call->event_handler (call->event_handler_cls,
+                       GNUNET_CONVERSATION_EC_GNS_FAIL);
+  GNUNET_CONVERSATION_call_stop (call, NULL);
+}
+
+
+/**
+ * We encountered an error talking with the conversation service. 
+ *
+ * @param cls the `struct GNUNET_CONVERSATION_Call`
+ * @param error details about the error
+ */
+static void
+call_error_handler (void *cls,
+                    enum GNUNET_MQ_Error error)
+{
+  struct GNUNET_CONVERSATION_Call *call = cls;
+
+  GNUNET_break (0);
+  reconnect_call (call);
+}
+
+
+/**
+ * The call got disconnected, reconnect to the service.
+ *
+ * @param call call to reconnect
+ */
+static void
+reconnect_call (struct GNUNET_CONVERSATION_Call *call)
+{
+  static struct GNUNET_MQ_MessageHandler handlers[] =
+  {
+    { &handle_call_busy,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY, 
+      sizeof (struct ClientPhoneBusyMessage) },
+    { &handle_call_picked_up,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP, 
+      0 },
+    { &handle_call_hangup,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
+      0 },
+    { &handle_call_audio_message,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
+      0 },    
+    { NULL, 0, 0 }    
+  };
+ if (NULL != call->mq)
+  {
+    GNUNET_MQ_destroy (call->mq);
+    call->mq = NULL;
+  }
+  if (NULL != call->client)
+  {
+    GNUNET_CLIENT_disconnect (call->client);
+    call->client = NULL;
+  }
+  call->client = GNUNET_CLIENT_connect ("conversation", call->cfg);
+  if (NULL == call->client)
+    return;
+  call->mq = GNUNET_MQ_queue_for_connection_client (call->client,
+                                                    handlers,
+                                                    &call_error_handler,
+                                                    call);
+}
+
+
+/**
+ * Call the phone of another user.
+ *
+ * @param cfg configuration to use, specifies our phone service
+ * @param caller_id identity of the caller
+ * @param callee GNS name of the callee (used to locate the callee's record)
+ * @param speaker speaker to use (will be used automatically immediately once 
the
+ *        #GNUNET_CONVERSATION_EC_READY event is generated); we will NOT 
generate
+ *        a ring tone on the speaker
+ * @param mic microphone to use (will be used automatically immediately once 
the
+ *        #GNUNET_CONVERSATION_EC_READY event is generated)
+ * @param event_handler how to notify the owner of the phone about events
+ * @param event_handler_cls closure for @a event_handler
+ */
+struct GNUNET_CONVERSATION_Call *
+GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                               struct GNUNET_IDENTITY_Ego *caller_id,
+                               const char *callee,
+                               struct GNUNET_SPEAKER_Handle *speaker,
+                               struct GNUNET_MICROPHONE_Handle *mic,
+                               GNUNET_CONVERSATION_EventHandler event_handler,
+                               void *event_handler_cls)
+{
+  struct GNUNET_CONVERSATION_Call *call;
+  struct GNUNET_CRYPTO_EccPublicSignKey my_zone;
+
+  GNUNET_IDENTITY_ego_get_public_key (caller_id,
+                                      &my_zone);
+  call = GNUNET_new (struct GNUNET_CONVERSATION_Call);
+  call->cfg = cfg;
+  call->caller_id = caller_id;
+  call->callee = GNUNET_strdup (callee);
+  call->speaker = speaker;
+  call->mic = mic;
+  call->event_handler = event_handler;
+  call->event_handler_cls = event_handler_cls;
+  call->gns = GNUNET_GNS_connect (cfg);
+  reconnect_call (call);
+
+  if ( (NULL == call->client) ||
+       (NULL == call->gns) )
+  {
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    return NULL;
+  }
+  call->gns_lookup = GNUNET_GNS_lookup (call->gns, callee,
+                                        &my_zone,
+                                        GNUNET_NAMESTORE_TYPE_PHONE,
+                                        GNUNET_NO,
+                                        NULL /* FIXME: add shortening support 
*/,
+                                        &handle_gns_response, call);
+  GNUNET_assert (NULL != call->gns_lookup);
+  return call;
+}
+
+
+/**
+ * Terminate a call.  The call may be ringing or ready at this time.
+ *
+ * @param call call to terminate
+ * @param reason if the call was active (ringing or ready) this will be the
+ *        reason given to the other user for why we hung up
+ */
+void
+GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call,
+                              const char *reason)
+{
+  if (NULL != reason)
+  {
+    // FIXME: transmit reason to service... (not implemented!)
+    GNUNET_break (0);
+    // return;
+  }
+  if (NULL != call->speaker)
+  {
+    if (CS_ACTIVE == call->state)
+      call->speaker->disable_speaker (call->speaker->cls);
+    call->speaker = NULL;
+  }
+  if (NULL != call->mic)
+  {
+    if (CS_ACTIVE == call->state)
+      call->mic->disable_microphone (call->mic->cls);
+    call->mic =NULL;
+  }
+  if (NULL != call->mq)
+  {
+    GNUNET_MQ_destroy (call->mq);
+    call->mq = NULL;
+  }
+  if (NULL != call->client)
+  {
+    GNUNET_CLIENT_disconnect (call->client);
+    call->client = NULL;
+  }
+  if (NULL != call->gns_lookup)
+  {
+    GNUNET_GNS_lookup_cancel (call->gns_lookup);
+    call->gns_lookup = NULL;
+  }
+  if (NULL != call->gns)
+  {
+    GNUNET_GNS_disconnect (call->gns);
+    call->gns = NULL;
+  }
+
+  GNUNET_free (call);
+}
+
+
+/* end of conversation_api.c */

Deleted: gnunet/src/conversation/conversation_api2.c
===================================================================
--- gnunet/src/conversation/conversation_api2.c 2013-10-05 13:08:47 UTC (rev 
29860)
+++ gnunet/src/conversation/conversation_api2.c 2013-10-05 13:10:53 UTC (rev 
29861)
@@ -1,1132 +0,0 @@
-/*
-  This file is part of GNUnet
-  (C) 2013 Christian Grothoff (and other contributing authors)
-  
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-  
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file conversation/conversation_api2.c
- * @brief API to the conversation service
- * @author Simon Dieterle
- * @author Andreas Fuchs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_conversation_service.h"
-#include "gnunet_gns_service.h"
-#include "conversation.h"
-
-
-/**
- * A phone record specifies which peer is hosting a given user and
- * may also specify the phone line that is used (typically zero).
- * The version is also right now always zero.
- */
-struct PhoneRecord
-{
-
-  /**
-   * Version of the phone record, for now always zero.  We may
-   * use other versions for anonymously hosted phone lines in
-   * the future.
-   */
-  uint32_t version GNUNET_PACKED;
-
-  /**
-   * Phone line to use at the peer.
-   */
-  uint32_t line GNUNET_PACKED;
-
-  /**
-   * Identity of the peer hosting the phone service.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-};
-
-
-/**
- * Possible states of the phone.
- */
-enum PhoneState
-{
-  /**
-   * We still need to register the phone.
-   */
-  PS_REGISTER = 0,
-
-  /**
-   * We are waiting for a call.
-   */
-  PS_WAITING,
-
-  /**
-   * The phone is ringing.
-   */
-  PS_RINGING,
-
-  /**
-   * The phone is in an active conversation.
-   */
-  PS_ACTIVE
-};
-
-
-/**
- * A phone is a device that can ring to signal an incoming call and
- * that you can pick up to answer the call and hang up to terminate
- * the call.  You can also hang up a ringing phone immediately
- * (without picking it up) to stop it from ringing.  Phones have
- * caller ID.  You can ask the phone for its record and make that
- * record available (via GNS) to enable others to call you.
- * Multiple phones maybe connected to the same line (the line is
- * something rather internal to a phone and not obvious from it).
- * You can only have one conversation per phone at any time.
- */
-struct GNUNET_CONVERSATION_Phone
-{
-  /**
-   * Our configuration.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
-  /**
-   * Handle to talk with CONVERSATION service.
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * Function to call for phone events.
-   */
-  GNUNET_CONVERSATION_EventHandler event_handler;
-
-  /**
-   * Closure for @e event_handler
-   */
-  void *event_handler_cls;
-
-  /**
-   * Speaker, or NULL if none is attached.
-   */
-  struct GNUNET_SPEAKER_Handle *speaker;
-
-  /**
-   * Microphone, or NULL if none is attached.
-   */
-  struct GNUNET_MICROPHONE_Handle *mic;
-
-  /**
-   * Connection to NAMESTORE (for reverse lookup).
-   */ 
-  struct GNUNET_NAMESTORE_Handle *ns;
-
-  /**
-   * Active NAMESTORE lookup (or NULL).
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *qe;
-
-  /**
-   * Handle for transmitting to the CONVERSATION service.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * This phone's record.
-   */
-  struct PhoneRecord my_record;  
-
-  /**
-   * My GNS zone.
-   */
-  struct GNUNET_CRYPTO_EccPrivateKey my_zone;
-
-  /**
-   * Identity of the person calling us (valid while in state #PS_RINGING).
-   */
-  struct GNUNET_CRYPTO_EccPublicSignKey caller_id;
-
-  /**
-   * State machine for the phone.
-   */
-  enum PhoneState state;
-
-};
-
-
-/**
- * The phone got disconnected, reconnect to the service.
- *
- * @param phone phone to reconnect
- */
-static void
-reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone);
-
-
-/**
- * We have resolved the caller ID using our name service.
- *
- * @param cls the `struct GNUNET_CONVERSATION_Phone`
- * @param zone our zone used for resolution
- * @param label name of the caller
- * @param rd_count number of records we have in @a rd
- * @param rd records we have for the caller's label
- */
-static void
-handle_caller_name (void *cls,
-                    const struct GNUNET_CRYPTO_EccPrivateKey *zone,
-                    const char *label,
-                    unsigned int rd_count,
-                    const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-  char *name;
-
-  phone->qe = NULL;
-  if (NULL == label)
-    name = GNUNET_strdup (GNUNET_NAMESTORE_pkey_to_zkey (&phone->caller_id));
-  else
-    GNUNET_asprintf (&name, "%.gnu", label);
-  phone->event_handler (phone->event_handler_cls,
-                        GNUNET_CONVERSATION_EC_RING,
-                        name);
-  GNUNET_free (name);
-}
-
-
-/**
- * We received a `struct ClientPhoneRingMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Phone`
- * @param msg the message
- */
-static void
-handle_phone_ring (void *cls,
-                   const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-  const struct ClientPhoneRingMessage *ring;
-
-  ring = (const struct ClientPhoneRingMessage *) msg;
-  switch (phone->state)
-  {
-  case PS_REGISTER:
-    GNUNET_assert (0);
-    break;
-  case PS_WAITING:
-    phone->state = PS_RINGING;
-    phone->caller_id = ring->caller_id;
-    phone->qe = GNUNET_NAMESTORE_zone_to_name (phone->ns,
-                                               &phone->my_zone,
-                                               &ring->caller_id,
-                                               &handle_caller_name,
-                                               phone);
-    break;
-  case PS_RINGING:
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    break;
-  case PS_ACTIVE:
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    break;
-  }
-}
-
-
-/**
- * We received a `struct ClientPhoneHangupMessage`.
- *
- * @param cls the `struct GNUNET_CONVERSATION_Phone`
- * @param msg the message
- */
-static void
-handle_phone_hangup (void *cls,
-                     const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-  const struct ClientPhoneHangupMessage *hang;
-  size_t len;
-  const char *reason;
-
-  hang = (const struct ClientPhoneHangupMessage *) msg;
-  reason = (const char *) &hang[1];
-  len = htons (hang->header.size) - sizeof (struct ClientPhoneHangupMessage);
-  if ( (0 == len) ||
-       ('\0' != reason[len-1]) )
-  {
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    return;
-  }
-  switch (phone->state)
-  {
-  case PS_REGISTER:
-    GNUNET_assert (0);
-    break;
-  case PS_WAITING:
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    break;
-  case PS_RINGING:
-    if (NULL != phone->qe)
-    {
-      GNUNET_NAMESTORE_cancel (phone->qe);
-      phone->qe = NULL;
-      phone->state = PS_WAITING;
-      break;
-    }
-    phone->state = PS_WAITING;
-    phone->event_handler (phone->event_handler_cls,
-                          GNUNET_CONVERSATION_EC_TERMINATED,
-                          reason);
-    break;
-  case PS_ACTIVE:
-    GNUNET_break (NULL == phone->qe);
-    phone->state = PS_WAITING;
-    phone->event_handler (phone->event_handler_cls,
-                          GNUNET_CONVERSATION_EC_TERMINATED,
-                          reason);
-    break;
-  }
-}
-
-
-/**
- * We received a `struct ClientAudioMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Phone`
- * @param msg the message
- */
-static void
-handle_phone_audio_message (void *cls,
-                            const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-  const struct ClientAudioMessage *am;
-
-  am = (const struct ClientAudioMessage *) msg;
-  switch (phone->state)
-  {
-  case PS_REGISTER:
-    GNUNET_assert (0);
-    break;
-  case PS_WAITING:
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    break;
-  case PS_RINGING:
-    GNUNET_break (0);
-    reconnect_phone (phone);
-    break;
-  case PS_ACTIVE:
-    phone->speaker->play (phone->speaker->cls,
-                          ntohs (msg->size) - sizeof (struct 
ClientAudioMessage),
-                          &am[1]);
-    break;
-  }
-}
-
-
-/**
- * We encountered an error talking with the conversation service. 
- *
- * @param cls the `struct GNUNET_CONVERSATION_Phone`
- * @param error details about the error
- */
-static void
-phone_error_handler (void *cls,
-                     enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-
-  GNUNET_break (0);
-  reconnect_phone (phone);
-}
-
-
-/**
- * The phone got disconnected, reconnect to the service.
- *
- * @param phone phone to reconnect
- */
-static void
-reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
-{
-  static struct GNUNET_MQ_MessageHandler handlers[] =
-  {
-    { &handle_phone_ring,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING, 
-      sizeof (struct ClientPhoneRingMessage) },
-    { &handle_phone_hangup,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
-      0 },
-    { &handle_phone_audio_message,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
-      0 },    
-    { NULL, 0, 0 }    
-  };
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientPhoneRegisterMessage *reg;
-
-  if (NULL != phone->mq)
-  {
-    GNUNET_MQ_destroy (phone->mq);
-    phone->mq = NULL;
-  }
-  if (NULL != phone->client)
-  {
-    GNUNET_CLIENT_disconnect (phone->client);
-    phone->client = NULL;
-  }
-  phone->state = PS_REGISTER;
-  phone->client = GNUNET_CLIENT_connect ("conversation", phone->cfg);
-  if (NULL == phone->client)
-    return;
-  phone->mq = GNUNET_MQ_queue_for_connection_client (phone->client,
-                                                     handlers,
-                                                     &phone_error_handler,
-                                                     phone);
-  e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
-  reg->line = phone->my_record.line;
-  GNUNET_MQ_send (phone->mq, e);
-  phone->state = PS_WAITING;
-}
-
-
-/**
- * Create a new phone.
- *
- * @param cfg configuration for the phone; specifies the phone service and
- *        which line the phone is to be connected to
- * @param ego ego to use for name resolution (when determining caller ID)
- * @param event_handler how to notify the owner of the phone about events
- * @param event_handler_cls closure for @a event_handler
- */
-struct GNUNET_CONVERSATION_Phone *
-GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
-                                  const struct GNUNET_IDENTITY_Ego *ego,
-                                  GNUNET_CONVERSATION_EventHandler 
event_handler,
-                                 void *event_handler_cls)
-{
-  struct GNUNET_CONVERSATION_Phone *phone;
-  unsigned long long line;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, 
-                                             "CONVERSATION",
-                                             "LINE",
-                                             &line))
-    return NULL;
-  phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
-  if (GNUNET_OK !=
-      GNUNET_CRYPTO_get_host_identity (cfg,
-                                       &phone->my_record.peer))
-  {
-    GNUNET_break (0);
-    GNUNET_free (phone);
-    return NULL;
-  }
-  phone->cfg = cfg;
-  phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
-  phone->event_handler = event_handler;
-  phone->event_handler_cls = event_handler_cls;
-  phone->ns = GNUNET_NAMESTORE_connect (cfg);
-  phone->my_record.line = htonl ((uint32_t) line);
-  phone->my_record.version = htonl (0);
-  reconnect_phone (phone);
-  if ( (NULL == phone->client) ||
-       (NULL == phone->ns) )
-  {
-    GNUNET_break (0);
-    GNUNET_CONVERSATION_phone_destroy (phone);
-    return NULL;
-  }
-  return phone;
-}
-
-
-/**
- * Fill in a namestore record with the contact information
- * for this phone.  Note that the filled in "data" value
- * is only valid until the phone is destroyed.
- *
- * @param phone phone to create a record for
- * @param rd namestore record to fill in
- */
-void
-GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone,
-                                     struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  rd->data = &phone->my_record;
-  rd->expiration_time = 0;
-  rd->data_size = sizeof (struct PhoneRecord);
-  rd->record_type = GNUNET_NAMESTORE_TYPE_PHONE;
-  rd->flags = GNUNET_NAMESTORE_RF_NONE;
-}
-
-
-/**
- * Process recorded audio data.
- *
- * @param cls closure with the `struct GNUNET_CONVERSATION_Phone`
- * @param data_size number of bytes in @a data
- * @param data audio data to play
- */
-static void
-transmit_phone_audio (void *cls,
-                      size_t data_size,
-                      const void *data)
-{
-  struct GNUNET_CONVERSATION_Phone *phone = cls;
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientAudioMessage *am;
-
-  GNUNET_assert (PS_ACTIVE == phone->state);
-  e = GNUNET_MQ_msg_extra (am, 
-                           data_size,
-                           GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
-  memcpy (&am[1], data, data_size);
-  GNUNET_MQ_send (phone->mq, e);
-}
-
-
-/**
- * Picks up a (ringing) phone.  This will connect the speaker 
- * to the microphone of the other party, and vice versa.
- *
- * @param phone phone to pick up
- * @param metadata meta data to give to the other user about the pick up event
- * @param speaker speaker to use
- * @param mic microphone to use
- */
-void
-GNUNET_CONVERSATION_phone_pick_up (struct GNUNET_CONVERSATION_Phone *phone,
-                                   const char *metadata,
-                                   struct GNUNET_SPEAKER_Handle *speaker,
-                                   struct GNUNET_MICROPHONE_Handle *mic)
-{
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientPhonePickupMessage *pick;
-  size_t slen;
-
-  GNUNET_assert (PS_RINGING == phone->state);
-  phone->speaker = speaker;
-  phone->mic = mic;
-  slen = strlen (metadata) + 1;
-  e = GNUNET_MQ_msg_extra (pick, slen, 
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
-  memcpy (&pick[1], metadata, slen);
-  GNUNET_MQ_send (phone->mq, e);
-  phone->state = PS_ACTIVE;
-  phone->speaker->enable_speaker (phone->speaker->cls);
-  phone->mic->enable_microphone (phone->mic->cls,
-                                 &transmit_phone_audio,
-                                 phone);
-}
-
-
-/**
- * Hang up up a (possibly ringing) phone.  This will notify the other
- * party that we are no longer interested in talking with them.
- *
- * @param phone phone to pick up
- * @param reason text we give to the other party about why we terminated the 
conversation
- */
-void
-GNUNET_CONVERSATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone,
-                                   const char *reason)
-{
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientPhoneHangupMessage *hang;
-  size_t slen;
-
-  GNUNET_assert ( (PS_RINGING == phone->state) ||
-                  (PS_ACTIVE == phone->state) );
-  phone->speaker->disable_speaker (phone->speaker->cls);
-  phone->mic->disable_microphone (phone->mic->cls);
-  phone->speaker = NULL;
-  phone->mic = NULL;
-  slen = strlen (reason) + 1;
-  e = GNUNET_MQ_msg_extra (hang, slen, 
GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
-  memcpy (&hang[1], reason, slen);
-  GNUNET_MQ_send (phone->mq, e);
-  phone->state = PS_WAITING;
-}
-
-
-/**
- * Destroys a phone.
- *
- * @param phone phone to destroy
- */
-void
-GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone)
-{
-  if (NULL != phone->speaker)
-  {
-    phone->speaker->disable_speaker (phone->speaker->cls);
-    phone->speaker = NULL;
-  }
-  if (NULL != phone->mic)
-  {
-    phone->mic->disable_microphone (phone->mic->cls);
-    phone->mic = NULL;
-  }
-  if (NULL != phone->qe)
-  {
-    GNUNET_NAMESTORE_cancel (phone->qe);
-    phone->qe = NULL;
-  }
-  if (NULL != phone->ns)
-  {
-    GNUNET_NAMESTORE_disconnect (phone->ns);
-    phone->ns = NULL;
-  }
-  if (NULL != phone->mq)
-  {
-    GNUNET_MQ_destroy (phone->mq);
-    phone->mq = NULL;
-  }
-  if (NULL != phone->client)
-  {
-    GNUNET_CLIENT_disconnect (phone->client);
-    phone->client = NULL;
-  }
-  GNUNET_free (phone);
-}
-
-
-/* ******************************* Call API *************************** */
-
-/**
- * Possible states of the phone.
- */
-enum CallState
-{
-  /**
-   * We still need to lookup the callee.
-   */
-  CS_LOOKUP = 0,
-
-  /**
-   * The call is ringing.
-   */
-  CS_RINGING,
-
-  /**
-   * The call is in an active conversation.
-   */
-  CS_ACTIVE,
-
-  /**
-   * The call is in termination.
-   */
-  CS_SHUTDOWN
-};
-
-
-/**
- * Handle for an outgoing call.
- */
-struct GNUNET_CONVERSATION_Call
-{
-
-  /**
-   * Our configuration.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
-  /**
-   * Handle to talk with CONVERSATION service.
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * Our caller identity.
-   */
-  struct GNUNET_IDENTITY_Ego *caller_id;
-
-  /**
-   * Target callee as a GNS address/name.
-   */
-  char *callee;
-
-  /**
-   * Our speaker.
-   */
-  struct GNUNET_SPEAKER_Handle *speaker;
-
-  /**
-   * Our microphone.
-   */
-  struct GNUNET_MICROPHONE_Handle *mic;
-  
-  /**
-   * Function to call with events.
-   */
-  GNUNET_CONVERSATION_EventHandler event_handler;
-
-  /**
-   * Closure for @e event_handler
-   */
-  void *event_handler_cls;
-
-  /**
-   * Handle for transmitting to the CONVERSATION service.
-   */
-  struct GNUNET_MQ_Handle *mq;
-
-  /**
-   * Connection to GNS (can be NULL).
-   */ 
-  struct GNUNET_GNS_Handle *gns;
-
-  /**
-   * Active GNS lookup (or NULL).
-   */
-  struct GNUNET_GNS_LookupRequest *gns_lookup;
-
-  /**
-   * Target phone record, only valid after the lookup is done.
-   */
-  struct PhoneRecord phone_record;
-
-  /**
-   * State machine for the call.
-   */
-  enum CallState state;
-
-};
-
-
-/**
- * The call got disconnected, reconnect to the service.
- *
- * @param call call to reconnect
- */
-static void
-reconnect_call (struct GNUNET_CONVERSATION_Call *call);
-
-
-/**
- * We received a `struct ClientPhoneBusyMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call`
- * @param msg the message
- */
-static void
-handle_call_busy (void *cls,
-                  const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-
-  switch (call->state)
-  {
-  case CS_LOOKUP:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_RINGING:
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_BUSY);
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    break;
-  case CS_ACTIVE:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_SHUTDOWN:
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    break;
-  }
-}
-
-
-/**
- * Process recorded audio data.
- *
- * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
- * @param data_size number of bytes in @a data
- * @param data audio data to play
- */
-static void
-transmit_call_audio (void *cls,
-                     size_t data_size,
-                     const void *data)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientAudioMessage *am;
-
-  GNUNET_assert (CS_ACTIVE == call->state);
-  e = GNUNET_MQ_msg_extra (am, 
-                           data_size,
-                           GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
-  memcpy (&am[1], data, data_size);
-  GNUNET_MQ_send (call->mq, e);
-}
-
-
-/**
- * We received a `struct ClientPhonePickedupMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call`
- * @param msg the message
- */
-static void
-handle_call_picked_up (void *cls,
-                       const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-  const struct ClientPhonePickedupMessage *am;
-  const char *metadata;
-  size_t size;
-
-  am = (const struct ClientPhonePickedupMessage *) msg;
-  size = ntohs (am->header.size) - sizeof (struct ClientPhonePickedupMessage);
-  metadata = (const char *) &am[1];
-  if ( (0 == size) ||
-       ('\0' != metadata[size - 1]) )
-    metadata = NULL;  
-  switch (call->state)
-  {
-  case CS_LOOKUP:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_RINGING:
-    call->state = CS_ACTIVE;
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_READY,
-                         metadata);
-    call->speaker->enable_speaker (call->speaker->cls);
-    call->mic->enable_microphone (call->mic->cls,
-                                  &transmit_call_audio,
-                                  call);
-    break;
-  case CS_ACTIVE:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_SHUTDOWN:
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    break;
-  }
-}
-
-
-/**
- * We received a `struct ClientPhoneHangupMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call`
- * @param msg the message
- */
-static void
-handle_call_hangup (void *cls,
-                    const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-  const struct ClientPhoneHangupMessage *am;
-  const char *reason;
-  size_t size;
-
-  am = (const struct ClientPhoneHangupMessage *) msg;
-  size = ntohs (am->header.size) - sizeof (struct ClientPhoneHangupMessage);
-  reason = (const char *) &am[1];
-  if ( (0 == size) ||
-       ('\0' != reason[size - 1]) )
-    reason = NULL;  
-  switch (call->state)
-  {
-  case CS_LOOKUP:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_RINGING:
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_TERMINATED,
-                         reason);
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    return;
-  case CS_ACTIVE:
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_TERMINATED,
-                         reason);
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    return;
-  case CS_SHUTDOWN:
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    break;
-  }
-}
-
-
-/**
- * We received a `struct ClientAudioMessage`
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call`
- * @param msg the message
- */
-static void
-handle_call_audio_message (void *cls,
-                           const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-  const struct ClientAudioMessage *am;
-
-  am = (const struct ClientAudioMessage *) msg;
-  switch (call->state)
-  {
-  case CS_LOOKUP:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_RINGING:
-    GNUNET_break (0);
-    reconnect_call (call);
-    break;
-  case CS_ACTIVE:
-    call->speaker->play (call->speaker->cls,
-                         ntohs (msg->size) - sizeof (struct 
ClientAudioMessage),
-                         &am[1]);
-    break;
-  case CS_SHUTDOWN:
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    break;
-
-  }
-}
-
-
-/**
- * Iterator called on obtained result for a GNS lookup.
- *
- * @param cls closure with the `struct GNUNET_CONVERSATION_Call`
- * @param rd_count number of records in @a rd
- * @param rd the records in reply
- */
-static void 
-handle_gns_response (void *cls,
-                     uint32_t rd_count,
-                     const struct GNUNET_NAMESTORE_RecordData *rd)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-  uint32_t i;
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientCallMessage *ccm;
-
-  for (i=0;i<rd_count;i++)
-  {
-    if (GNUNET_NAMESTORE_TYPE_PHONE == rd[i].record_type)
-    {
-      if (rd[i].data_size != sizeof (struct PhoneRecord))
-      {
-        GNUNET_break_op (0);
-        continue;
-      }      
-      memcpy (&call->phone_record,
-              rd[i].data,
-              rd[i].data_size);
-      e = GNUNET_MQ_msg (ccm, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL);
-      ccm->line = call->phone_record.line;
-      ccm->target = call->phone_record.peer;
-      ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id);
-      GNUNET_MQ_send (call->mq, e);
-      call->state = CS_RINGING;
-      call->event_handler (call->event_handler_cls,
-                           GNUNET_CONVERSATION_EC_RINGING);
-      return;
-    }
-  }
-  /* not found */
-  call->event_handler (call->event_handler_cls,
-                       GNUNET_CONVERSATION_EC_GNS_FAIL);
-  GNUNET_CONVERSATION_call_stop (call, NULL);
-}
-
-
-/**
- * We encountered an error talking with the conversation service. 
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call`
- * @param error details about the error
- */
-static void
-call_error_handler (void *cls,
-                    enum GNUNET_MQ_Error error)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-
-  GNUNET_break (0);
-  reconnect_call (call);
-}
-
-
-/**
- * The call got disconnected, reconnect to the service.
- *
- * @param call call to reconnect
- */
-static void
-reconnect_call (struct GNUNET_CONVERSATION_Call *call)
-{
-  static struct GNUNET_MQ_MessageHandler handlers[] =
-  {
-    { &handle_call_busy,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY, 
-      sizeof (struct ClientPhoneBusyMessage) },
-    { &handle_call_picked_up,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP, 
-      0 },
-    { &handle_call_hangup,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
-      0 },
-    { &handle_call_audio_message,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
-      0 },    
-    { NULL, 0, 0 }    
-  };
- if (NULL != call->mq)
-  {
-    GNUNET_MQ_destroy (call->mq);
-    call->mq = NULL;
-  }
-  if (NULL != call->client)
-  {
-    GNUNET_CLIENT_disconnect (call->client);
-    call->client = NULL;
-  }
-  call->client = GNUNET_CLIENT_connect ("conversation", call->cfg);
-  if (NULL == call->client)
-    return;
-  call->mq = GNUNET_MQ_queue_for_connection_client (call->client,
-                                                    handlers,
-                                                    &call_error_handler,
-                                                    call);
-}
-
-
-/**
- * Call the phone of another user.
- *
- * @param cfg configuration to use, specifies our phone service
- * @param caller_id identity of the caller
- * @param callee GNS name of the callee (used to locate the callee's record)
- * @param speaker speaker to use (will be used automatically immediately once 
the
- *        #GNUNET_CONVERSATION_EC_READY event is generated); we will NOT 
generate
- *        a ring tone on the speaker
- * @param mic microphone to use (will be used automatically immediately once 
the
- *        #GNUNET_CONVERSATION_EC_READY event is generated)
- * @param event_handler how to notify the owner of the phone about events
- * @param event_handler_cls closure for @a event_handler
- */
-struct GNUNET_CONVERSATION_Call *
-GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                               struct GNUNET_IDENTITY_Ego *caller_id,
-                               const char *callee,
-                               struct GNUNET_SPEAKER_Handle *speaker,
-                               struct GNUNET_MICROPHONE_Handle *mic,
-                               GNUNET_CONVERSATION_EventHandler event_handler,
-                               void *event_handler_cls)
-{
-  struct GNUNET_CONVERSATION_Call *call;
-  struct GNUNET_CRYPTO_EccPublicSignKey my_zone;
-
-  GNUNET_IDENTITY_ego_get_public_key (caller_id,
-                                      &my_zone);
-  call = GNUNET_new (struct GNUNET_CONVERSATION_Call);
-  call->cfg = cfg;
-  call->caller_id = caller_id;
-  call->callee = GNUNET_strdup (callee);
-  call->speaker = speaker;
-  call->mic = mic;
-  call->event_handler = event_handler;
-  call->event_handler_cls = event_handler_cls;
-  call->gns = GNUNET_GNS_connect (cfg);
-  reconnect_call (call);
-
-  if ( (NULL == call->client) ||
-       (NULL == call->gns) )
-  {
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    return NULL;
-  }
-  call->gns_lookup = GNUNET_GNS_lookup (call->gns, callee,
-                                        &my_zone,
-                                        GNUNET_NAMESTORE_TYPE_PHONE,
-                                        GNUNET_NO,
-                                        NULL /* FIXME: add shortening support 
*/,
-                                        &handle_gns_response, call);
-  GNUNET_assert (NULL != call->gns_lookup);
-  return call;
-}
-
-
-/**
- * Terminate a call.  The call may be ringing or ready at this time.
- *
- * @param call call to terminate
- * @param reason if the call was active (ringing or ready) this will be the
- *        reason given to the other user for why we hung up
- */
-void
-GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call,
-                              const char *reason)
-{
-  if (NULL != reason)
-  {
-    // FIXME: transmit reason to service... (not implemented!)
-    GNUNET_break (0);
-    // return;
-  }
-  if (NULL != call->speaker)
-  {
-    if (CS_ACTIVE == call->state)
-      call->speaker->disable_speaker (call->speaker->cls);
-    call->speaker = NULL;
-  }
-  if (NULL != call->mic)
-  {
-    if (CS_ACTIVE == call->state)
-      call->mic->disable_microphone (call->mic->cls);
-    call->mic =NULL;
-  }
-  if (NULL != call->mq)
-  {
-    GNUNET_MQ_destroy (call->mq);
-    call->mq = NULL;
-  }
-  if (NULL != call->client)
-  {
-    GNUNET_CLIENT_disconnect (call->client);
-    call->client = NULL;
-  }
-  if (NULL != call->gns_lookup)
-  {
-    GNUNET_GNS_lookup_cancel (call->gns_lookup);
-    call->gns_lookup = NULL;
-  }
-  if (NULL != call->gns)
-  {
-    GNUNET_GNS_disconnect (call->gns);
-    call->gns = NULL;
-  }
-
-  GNUNET_free (call);
-}
-
-
-/* end of conversation_api.c */

Deleted: gnunet/src/conversation/gnunet-conversation-new.c
===================================================================
--- gnunet/src/conversation/gnunet-conversation-new.c   2013-10-05 13:08:47 UTC 
(rev 29860)
+++ gnunet/src/conversation/gnunet-conversation-new.c   2013-10-05 13:10:53 UTC 
(rev 29861)
@@ -1,855 +0,0 @@
-/*
-  This file is part of GNUnet.
-  (C) 2013 Christian Grothoff (and other contributing authors)
-  
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-  
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
-*/
-/**
- * @file conversation/gnunet-conversation.c
- * @brief conversation implementation
- * @author Simon Dieterle
- * @author Andreas Fuchs
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_conversation_service.h"
-
-
-/**
- * Maximum length allowed for the command line input.
- */
-#define MAX_MESSAGE_LENGTH 1024
-
-
-/**
- * Possible states of the program.
- */
-enum ConversationState
-{
-  /**
-   * We're waiting for our own idenitty.
-   */
-  CS_LOOKUP_EGO,
-
-  /**
-   * We're listening for calls
-   */
-  CS_LISTEN,
-
-  /**
-   * Our phone is ringing.
-   */
-  CS_RING,
-
-  /**
-   * We accepted an incoming phone call.
-   */
-  CS_ACCEPTED,
-
-  /**
-   * We are looking up some other participant.
-   */
-  CS_RESOLVING,
-
-  /**
-   * We are now ringing the other participant.
-   */
-  CS_RINGING,
-
-  /**
-   * The other party accepted our call and we are now connected.
-   */
-  CS_CONNECTED,
-
-  /**
-   * Internal error
-   */
-  CS_ERROR
-
-};
-
-
-/**
- * Phone handle
- */
-static struct GNUNET_CONVERSATION_Phone *phone;
-
-/**
- * Call handle
- */
-static struct GNUNET_CONVERSATION_Call *call;
-
-/**
- * Desired phone line.
- */
-static unsigned int line;
-
-/**
- * Task which handles the commands
- */
-static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
-
-/**
- * Our speaker.
- */
-static struct GNUNET_SPEAKER_Handle *speaker;
-
-/**
- * Our microphone.
- */
-static struct GNUNET_MICROPHONE_Handle *mic;
-
-/**
- * Our configuration.
- */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Our ego.
- */
-static struct GNUNET_IDENTITY_Ego *caller_id;
-
-/**
- * Handle to identity service.
- */
-static struct GNUNET_IDENTITY_Handle *id;
-
-/**
- * Name of our ego.
- */
-static char *ego_name;
-
-/**
- * Name of conversation partner (if any).
- */
-static char *peer_name;
-
-/**
- * File handle for stdin.
- */
-static struct GNUNET_DISK_FileHandle *stdin_fh;
-
-/**
- * Our current state.
- */
-static enum ConversationState state;
-
-/**
- * Be verbose.
- */
-static int verbose;
-
-
-/**
- * Function called with an event emitted by a phone.
- *
- * @param cls closure
- * @param code type of the event on the phone
- * @param ... additional information, depends on @a code
- */
-static void
-phone_event_handler (void *cls,
-                     enum GNUNET_CONVERSATION_EventCode code,
-                     ...)
-{
-  va_list va;
-  
-  va_start (va, code);
-  switch (code)
-  {
-  case GNUNET_CONVERSATION_EC_RING:
-    GNUNET_break (CS_LISTEN == state);
-    GNUNET_free_non_null (peer_name);
-    peer_name = GNUNET_strdup (va_arg (va, const char *));
-    FPRINTF (stdout,
-             _("Incoming call from `%s'.\nPlease /accept or /cancel the 
call.\n"),
-             peer_name);
-    state = CS_RING;
-    break;
-  case GNUNET_CONVERSATION_EC_RINGING:
-    GNUNET_break (0);
-    break;
-  case GNUNET_CONVERSATION_EC_READY:
-    GNUNET_break (0);
-    break;
-  case GNUNET_CONVERSATION_EC_GNS_FAIL:
-    GNUNET_break (0);
-    break;
-  case GNUNET_CONVERSATION_EC_BUSY:
-    GNUNET_break (0);
-    break;
-  case GNUNET_CONVERSATION_EC_TERMINATED:
-    GNUNET_break ( (CS_RING == state) ||
-                   (CS_ACCEPTED == state) );
-    FPRINTF (stdout,
-             _("Call terminated: %s\n"),
-             va_arg (va, const char *));
-    state = CS_LISTEN;
-    break;
-  }
-  va_end (va);
-}
-
-
-/**
- * Start our phone.
- */
-static void
-start_phone ()
-{
-  if (NULL == caller_id)
-  {
-    FPRINTF (stderr,
-             _("Ego `%s' no longer available, phone is now down.\n"),
-             ego_name);
-    state = CS_LOOKUP_EGO;
-    return;
-  }
-  phone = GNUNET_CONVERSATION_phone_create (cfg,
-                                            caller_id,
-                                            &phone_event_handler, NULL);
-  /* FIXME: get record and print full GNS record info later here... */
-  if (NULL == phone)
-  {
-    FPRINTF (stderr,
-             "%s",
-             _("Failed to setup phone (internal error)\n"));
-    state = CS_ERROR;
-  }
-  else
-  {
-    if (verbose)
-      FPRINTF (stdout,
-               _("Phone active on line %u\n"),
-               (unsigned int) line);
-    state = CS_LISTEN;
-  }
-}
-
-
-/**
- * Function called with an event emitted by a phone.
- *
- * @param cls closure
- * @param code type of the event on the phone
- * @param ... additional information, depends on @a code
- */
-static void
-call_event_handler (void *cls,
-                    enum GNUNET_CONVERSATION_EventCode code,
-                    ...)
-{
-  va_list va;
-  
-  va_start (va, code);
-  switch (code)
-  {
-  case GNUNET_CONVERSATION_EC_RING:
-    GNUNET_break (0);
-    break;
-  case GNUNET_CONVERSATION_EC_RINGING:
-    GNUNET_break (CS_RESOLVING == state);
-    if (verbose)
-      FPRINTF (stdout,
-               "%s",
-               _("Resolved address. Now ringing other party.\n"));
-    state = CS_RINGING;
-    break;
-  case GNUNET_CONVERSATION_EC_READY:
-    GNUNET_break (CS_RINGING == state);
-    FPRINTF (stdout,
-             _("Connection established: %s\n"),
-             va_arg (va, const char *));
-    state = CS_CONNECTED;
-    break;
-  case GNUNET_CONVERSATION_EC_GNS_FAIL:
-    GNUNET_break (CS_RESOLVING == state);
-    FPRINTF (stdout,
-             "%s",
-             _("Failed to resolve name\n"));
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    call = NULL;
-    start_phone ();
-    break;
-  case GNUNET_CONVERSATION_EC_BUSY:
-    GNUNET_break (CS_RINGING == state);
-    FPRINTF (stdout,
-             "%s",
-             _("Line busy\n"));
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    call = NULL;
-    start_phone ();
-    break;
-  case GNUNET_CONVERSATION_EC_TERMINATED:
-    GNUNET_break ( (CS_RINGING == state) ||
-                   (CS_CONNECTED == state) );
-    FPRINTF (stdout,
-             _("Call terminated: %s\n"),
-             va_arg (va, const char *));
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    call = NULL;
-    start_phone ();
-    break;
-  }
-  va_end (va);
-}
-
-
-/**
- * Function declareation for executing a action
- *
- * @param arguments arguments given to the function
- */
-typedef void (*ActionFunction) (const char *arguments);
-
-
-/**
- * Structure which defines a command
- */
-struct VoipCommand
-{
-  /**
-   * Command the user needs to enter.
-   */
-  const char *command;
-  
-  /**
-   * Function to call on command.
-   */
-  ActionFunction Action;
-
-  /**
-   * Help text for the command.
-   */
-  const char *helptext;
-};
-
-
-/**
- * Action function to print help for the command shell.
- *
- * @param arguments arguments given to the command
- */
-static void
-do_help (const char *args);
-
-
-/**
- * Terminate the client
- *
- * @param args arguments given to the command
- */
-static void
-do_quit (const char *args)
-{
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Handler for unknown command.
- *
- * @param args arguments given to the command
- */
-static void
-do_unknown (const char *msg)
-{
-  FPRINTF (stderr, 
-          _("Unknown command `%s'\n"), 
-          msg);
-}
-
-
-/**
- * Initiating a new call
- *
- * @param args arguments given to the command
- */
-static void
-do_call (const char *arg)
-{
-  if (NULL == caller_id)
-  {
-    FPRINTF (stderr,
-             _("Ego `%s' not available\n"),
-             ego_name);
-    return;
-  }
-  switch (state)
-  {
-  case CS_LOOKUP_EGO: 
-    FPRINTF (stderr,
-             _("Ego `%s' not available\n"),
-             ego_name);
-    return;
-  case CS_LISTEN:
-    /* ok to call! */
-    break;
-  case CS_RING:
-    FPRINTF (stdout,
-             _("Hanging up on incoming phone call from `%s' to call `%s'.\n"),
-             peer_name,
-             arg);
-    GNUNET_CONVERSATION_phone_hang_up (phone, NULL);
-    break;
-  case CS_ACCEPTED:
-    FPRINTF (stderr,
-             _("You are already in a conversation with `%s', refusing to call 
`%s'.\n"),
-             peer_name,
-             arg);
-    return;
-  case CS_RESOLVING:
-  case CS_RINGING:
-    FPRINTF (stderr,
-             _("Aborting call to `%s'\n"),
-             peer_name);
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    call = NULL;
-    break;
-  case CS_CONNECTED:
-    FPRINTF (stderr,
-             _("You are already in a conversation with `%s', refusing to call 
`%s'.\n"),
-             peer_name,
-             arg);
-    return;
-  case CS_ERROR:
-    /* ok to call */
-    break;
-  }
-  GNUNET_assert (NULL == call);
-  if (NULL != phone)
-  {
-    GNUNET_CONVERSATION_phone_destroy (phone);
-    phone = NULL;
-  }
-  GNUNET_free_non_null (peer_name);
-  peer_name = GNUNET_strdup (arg);
-  call = GNUNET_CONVERSATION_call_start (cfg,
-                                         caller_id,
-                                         arg,
-                                         speaker,
-                                         mic,
-                                         &call_event_handler, NULL);
-  state = CS_RESOLVING;
-}
-
-
-/**
- * Accepting an incoming call
- *
- * @param args arguments given to the command
- */
-static void
-do_accept (const char *args)
-{
-  switch (state)
-  {
-  case CS_LOOKUP_EGO:     
-  case CS_LISTEN:
-  case CS_ERROR:
-    FPRINTF (stderr,
-             _("There is no incoming call to be accepted!\n"));
-    return;
-  case CS_RING:
-    /* this is the expected state */
-    break;
-  case CS_ACCEPTED:
-    FPRINTF (stderr,
-             _("You are already in a conversation with `%s'.\n"),
-             peer_name);
-    return;
-  case CS_RESOLVING:
-  case CS_RINGING:
-    FPRINTF (stderr,
-             _("You are trying to call `%s', cannot accept incoming calls 
right now.\n"),
-             peer_name);
-    return;
-  case CS_CONNECTED:
-    FPRINTF (stderr,
-             _("You are already in a conversation with `%s'.\n"),
-             peer_name);
-    return;
-  }
-  GNUNET_assert (NULL != phone);
-  GNUNET_CONVERSATION_phone_pick_up (phone, 
-                                     args,
-                                     speaker,
-                                     mic);
-  state = CS_ACCEPTED;
-}
-
-
-/**
- * Accepting an incoming call
- *
- * @param args arguments given to the command
- */
-static void
-do_status (const char *args)
-{
-  switch (state)
-  {
-  case CS_LOOKUP_EGO: 
-    FPRINTF (stdout,
-             _("We are currently trying to locate the private key for the ego 
`%s'.\n"),
-             ego_name);
-    break;
-  case CS_LISTEN:
-    FPRINTF (stdout,
-             _("We are listening for incoming calls for ego `%s' on line 
%u.\n"),
-             ego_name,
-             line);
-    break;
-  case CS_RING:
-    FPRINTF (stdout,
-             _("The phone is rining. `%s' is trying to call us.\n"),
-             peer_name);
-    break;
-  case CS_ACCEPTED:
-  case CS_CONNECTED:
-    FPRINTF (stdout,
-             _("You are having a conversation with `%s'.\n"),
-             peer_name);
-    break;
-  case CS_RESOLVING:
-    FPRINTF (stdout,
-             _("We are trying to find the network address to call `%s'.\n"),
-             peer_name);
-    break;
-  case CS_RINGING:
-    FPRINTF (stdout,
-             _("We are calling `%s', his phone should be ringing.\n"),
-             peer_name);
-    break;
-  case CS_ERROR:
-    FPRINTF (stdout,
-             _("We had an internal error setting up our phone line. You can 
still make calls.\n"));
-    break;
-  }
-}
-
-
-/**
- * Rejecting a call
- *
- * @param args arguments given to the command
- */
-static void
-do_reject (const char *args)
-{
-  switch (state)
-  {
-  case CS_LOOKUP_EGO: 
-  case CS_LISTEN:
-  case CS_ERROR:
-    FPRINTF (stderr,
-             "%s",
-             _("There is no call that could be cancelled right now.\n"));
-    return;
-  case CS_RING:
-  case CS_ACCEPTED:
-  case CS_RESOLVING:
-  case CS_RINGING:
-  case CS_CONNECTED:
-    /* expected state, do rejection logic */
-    break;
-  }
-  if (NULL == call)
-  {
-    GNUNET_assert (NULL != phone);
-    GNUNET_CONVERSATION_phone_hang_up (phone, 
-                                       args);
-    state = CS_LISTEN;
-  }
-  else
-  {
-    GNUNET_CONVERSATION_call_stop (call, args);
-    call = NULL;
-    start_phone ();
-  }
-}
-
-
-/**
- * List of supported commands.
- */
-static struct VoipCommand commands[] = {
-  {"/call", &do_call, 
-   gettext_noop ("Use `/call USER.gnu'")},
-  {"/accept", &do_accept,
-   gettext_noop ("Use `/accept MESSAGE' to accept an incoming call")},
-  {"/cancel", &do_reject,
-   gettext_noop ("Use `/cancel MESSAGE' to reject or terminate a call")},
-  {"/status", &do_status,
-   gettext_noop ("Use `/status to print status information")},
-  {"/quit", &do_quit, 
-   gettext_noop ("Use `/quit' to terminate gnunet-conversation")},
-  {"/help", &do_help,
-   gettext_noop ("Use `/help command' to get help for a specific command")},
-  {"", &do_unknown, 
-   NULL},
-  {NULL, NULL, NULL},
-};
-
-
-/**
- * Action function to print help for the command shell.
- *
- * @param arguments arguments given to the command
- */
-static void
-do_help (const char *args)
-{
-  unsigned int i;
-  
-  i = 0; 
-  while ( (NULL != args) &&
-          (0 != strlen (args)) &&
-          (commands[i].Action != &do_help))
-  {
-    if (0 ==
-       strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
-    {
-      FPRINTF (stdout, 
-              "%s\n",
-              gettext (commands[i].helptext));
-      return;
-    }
-    i++;
-  }
-  i = 0;
-  FPRINTF (stdout, 
-          "%s", 
-          "Available commands:\n");
-  while (commands[i].Action != &do_help)
-  {
-    FPRINTF (stdout, 
-            "%s\n", 
-            gettext (commands[i].command));
-    i++;
-  }
-  FPRINTF (stdout,
-          "%s",
-          "\n");
-  FPRINTF (stdout,
-          "%s\n",
-          gettext (commands[i].helptext));
-}
-
-
-/**
- * Task run during shutdown.
- *
- * @param cls NULL
- * @param tc unused
- */
-static void
-do_stop_task (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (NULL != call)
-  {
-    GNUNET_CONVERSATION_call_stop (call, NULL);
-    call = NULL;
-  }
-  if (NULL != phone)
-  {
-    GNUNET_CONVERSATION_phone_destroy (phone);
-    phone = NULL;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != handle_cmd_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle_cmd_task);
-    handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
-  } 
-  if (NULL != id)
-  {
-    GNUNET_IDENTITY_disconnect (id);
-    id = NULL;
-  }
-  GNUNET_SPEAKER_destroy (speaker);
-  speaker = NULL;
-  GNUNET_MICROPHONE_destroy (mic);
-  mic = NULL;
-  GNUNET_free (ego_name);
-  ego_name = NULL;
-  GNUNET_CONFIGURATION_destroy (cfg);
-  cfg = NULL;
-  GNUNET_free_non_null (peer_name);
-  state = CS_ERROR;
-}
-
-
-/**
- * Task to handle commands from the terminal.
- *
- * @param cls NULL
- * @param tc scheduler context
- */
-static void
-handle_command (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char message[MAX_MESSAGE_LENGTH + 1];
-  const char *ptr;
-  size_t i;
-
-  handle_cmd_task =
-    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                    stdin_fh,
-                                    &handle_command, NULL);
-  /* read message from command line and handle it */
-  memset (message, 0, MAX_MESSAGE_LENGTH + 1);
-  if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
-    return;
-  if (0 == strlen (message))
-    return;
-  if (message[strlen (message) - 1] == '\n')
-    message[strlen (message) - 1] = '\0';
-  if (0 == strlen (message))
-    return;
-  i = 0;
-  while ((NULL != commands[i].command) &&
-        (0 != strncasecmp (commands[i].command, message,
-                            strlen (commands[i].command))))
-    i++;
-  ptr = &message[strlen (commands[i].command)];
-  while (isspace ((int) *ptr))
-    ptr++;
-  commands[i].Action (ptr);
-}
-
-
-/**
- * Function called by identity service with information about egos.
- *
- * @param cls NULL
- * @param ego ego handle
- * @param ctx unused
- * @param name name of the ego
- */
-static void
-identity_cb (void *cls,
-             struct GNUNET_IDENTITY_Ego *ego,
-             void **ctx,
-             const char *name)
-{
-  if (NULL == name)
-    return;
-  if (ego == caller_id)
-  {
-    if (verbose)
-      FPRINTF (stdout,
-               _("Name of our ego changed to `%s'\n"),
-               name);
-    GNUNET_free (ego_name);
-    ego_name = GNUNET_strdup (name);
-    return;
-  }
-  if (0 != strcmp (name,
-                   ego_name))
-    return;
-  if (NULL == ego)
-  {    
-    if (verbose)
-      FPRINTF (stdout,
-               _("Our ego `%s' was deleted!\n"),
-               ego_name);
-    caller_id = NULL;
-    return;
-  }
-  caller_id = ego;
-  GNUNET_CONFIGURATION_set_value_number (cfg,
-                                         "CONVERSATION",
-                                         "LINE",
-                                         line);
-  start_phone ();
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param c configuration
- */
-static void
-run (void *cls,
-     char *const *args, 
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  cfg = GNUNET_CONFIGURATION_dup (c);
-  speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
-  mic = GNUNET_MICROPHONE_create_from_hardware (cfg);
-  if (NULL == ego_name)
-  {
-    FPRINTF (stderr,
-             "%s",
-             _("You must specify the NAME of an ego to use\n"));
-    return;
-  }
-  id = GNUNET_IDENTITY_connect (cfg,
-                                &identity_cb,
-                                NULL);
-  handle_cmd_task =
-    GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
-                                       &handle_command, NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
-                               NULL);
-}
-
-
-/** 
- * The main function to conversation.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'e', "ego", "NAME",
-     gettext_noop ("sets the NAME of the ego to use for the phone (and name 
resolution)"),
-     1, &GNUNET_GETOPT_set_string, &ego_name},
-    {'p', "phone", "LINE",
-      gettext_noop ("sets the LINE to use for the phone"),
-     1, &GNUNET_GETOPT_set_uint, &line},
-    GNUNET_GETOPT_OPTION_END
-  };
-  int flags;
-  int ret;
-
-  flags = fcntl (0, F_GETFL, 0);
-  flags |= O_NONBLOCK;
-  fcntl (0, F_SETFL, flags);
-  stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
-    return 2;
-  ret = GNUNET_PROGRAM_run (argc, argv,
-                            "gnunet-conversation",
-                           gettext_noop ("Enables having a conversation with 
other GNUnet users."),
-                           options, &run, NULL);
-  GNUNET_free ((void *) argv);
-  return (GNUNET_OK == ret) ? 0 : 1;
-}
-
-/* end of gnunet-conversation.c */

Deleted: gnunet/src/conversation/gnunet-conversation.c
===================================================================
--- gnunet/src/conversation/gnunet-conversation.c       2013-10-05 13:08:47 UTC 
(rev 29860)
+++ gnunet/src/conversation/gnunet-conversation.c       2013-10-05 13:10:53 UTC 
(rev 29861)
@@ -1,473 +0,0 @@
-/*
-  This file is part of GNUnet.
-  (C) 2013 Christian Grothoff (and other contributing authors)
-  
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-  
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, InGNUNET_SERVERc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
-*/
-/**
- * @file conversation/gnunet-conversation.c
- * @brief conversation implementation
- * @author Simon Dieterle
- * @author Andreas Fuchs
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_constants.h"
-#include "gnunet_conversation_service.h"
-#include <fcntl.h>
-
-#define MAX_MESSAGE_LENGTH   (32 * 1024)
-
-/**
- * CONVERSATION handle
- */
-static struct GNUNET_CONVERSATION_Handle *conversation;
-
-/**
- * Task which handles the commands
- */
-static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
-
-/**
- * Function declareation for executing a action
- */
-typedef int (*ActionFunction) (const char *argumetns, 
-                              const void *xtra);
-
-/**
-* Structure which defines a command
-*/
-struct VoipCommand
-{
-  const char *command;
-  ActionFunction Action;
-  const char *helptext;
-};
-
-
-static int
-do_help (const char *args, 
-        const void *xtra);
-
-
-/**
- * Method called whenever a call is incoming
- *
- * @param cls closure
- * @param handle to the conversation session
- * @param caller peer that calls you
- */
-static void
-call_handler (void *cls,
-             struct GNUNET_CONVERSATION_Handle *handle,
-             const struct GNUNET_PeerIdentity *caller)
-{
-  FPRINTF (stdout, 
-          _("Incoming call from peer: %s\n"),
-          GNUNET_i2s_full (caller));
-}
-
-
-/**
- * Method called whenever a call is rejected
- *
- * @param cls closure
- * @param handle to the conversation session
- * @param reason given reason why the call was rejected
- * @param peer peer that rejected your call
- */
-static void
-reject_handler (void *cls, 
-               struct GNUNET_CONVERSATION_Handle *handle, 
-               enum GNUNET_CONVERSATION_RejectReason reason,
-               const struct GNUNET_PeerIdentity *peer)
-{
-  FPRINTF (stdout, 
-          _("Peer %s rejected your call. Reason: %d\n"),
-          GNUNET_i2s_full (peer), reason);
-}
-
-
-/**
- * Method called whenever a notification is there
- *
- * @param cls closure
- * @param handle to the conversation session
- * @param type the type of the notification
- * @param peer peer that the notification is about
- */
-static void
-notification_handler (void *cls, 
-                     struct GNUNET_CONVERSATION_Handle *handle, 
-                     enum GNUNET_CONVERSATION_NotificationType type,
-                     const struct GNUNET_PeerIdentity *peer)
-{
-  switch (type)
-  {
-  case GNUNET_CONVERSATION_NT_SERVICE_BLOCKED:
-    FPRINTF (stdout,
-            _("The service is already in use. Try again later."));    
-    break;    
-  case GNUNET_CONVERSATION_NT_NO_PEER:
-    FPRINTF (stdout, 
-            _("The Peer you were calling is no correct peer.\n"));    
-    break;    
-  case GNUNET_CONVERSATION_NT_NO_ANSWER:
-    FPRINTF (stdout, 
-            _("Peer %s did not answer your call.\n"),
-            GNUNET_i2s_full (peer));    
-    break;    
-  case GNUNET_CONVERSATION_NT_AVAILABLE_AGAIN:
-    FPRINTF (stdout,
-            _("Peer %s is now available.\n"),
-            GNUNET_i2s_full (peer));    
-    break;    
-  case GNUNET_CONVERSATION_NT_CALL_ACCEPTED:
-    FPRINTF (stdout, 
-            _("Peer %s has accepted your call.\n"),
-            GNUNET_i2s_full (peer));    
-    break;    
-  case GNUNET_CONVERSATION_NT_CALL_TERMINATED:
-    FPRINTF (stdout,
-            _("Peer %s has terminated the call.\n"),
-            GNUNET_i2s_full (peer));
-    break;
-  default:
-    GNUNET_break (0);
-  }  
-}
-
-
-/**
- * Method called whenever a notification for missed calls is there
- *
- * @param cls closure
- * @param handle to the conversation session
- * @param missed_calls a list of missed calls
- */
-static void
-missed_call_handler (void *cls,
-                    struct GNUNET_CONVERSATION_Handle *handle,
-                    struct GNUNET_CONVERSATION_MissedCallNotification 
*missed_calls)
-{
-  FPRINTF (stdout, 
-          _("You have missed calls.\n"));
-}
-
-
-/**
- * Terminating the client
- */
-static int
-do_quit (const char *args, 
-        const void *xtra)
-{
-  return GNUNET_SYSERR;
-}
-
-
-/**
- *
- */
-static int
-do_unknown (const char *msg, 
-           const void *xtra)
-{
-  FPRINTF (stderr, 
-          _("Unknown command `%s'\n"), 
-          msg);
-  return GNUNET_OK;
-}
-
-
-/**
- * Initiating a new call
- */
-static int
-do_call (const char *arg, 
-        const void *xtra)
-{
-  FPRINTF (stdout, 
-          _("Initiating call to: %s\n"), 
-          arg);
-  GNUNET_CONVERSATION_call (conversation, 
-                           arg, 
-                           GNUNET_YES);
-  return GNUNET_OK;
-}
-
-
-/**
- * Initiating a new call
- */
-static int
-do_call_peer (const char *arg, 
-             const void *xtra)
-{
-  FPRINTF (stdout, 
-          _("Initiating call to: %s\n"), 
-          arg);
-  GNUNET_CONVERSATION_call (conversation, 
-                           arg,
-                           GNUNET_NO);
-  return GNUNET_OK;
-}
-
-
-/**
- * Accepting an incoming call
- */
-static int
-do_accept (const char *args, 
-          const void *xtra)
-{
-  FPRINTF (stdout,
-          _("Accepting the call\n"));
-  GNUNET_CONVERSATION_accept (conversation);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Rejecting a call
- */
-static int
-do_reject (const char *args, 
-          const void *xtra)
-{
-  FPRINTF (stdout,
-          _("Rejecting the call\n"));
-  GNUNET_CONVERSATION_reject (conversation);
-  return GNUNET_OK;
-}
-
-
-/**
- * Terminating a call
- */
-static int
-do_hang_up (const char *args, 
-           const void *xtra)
-{
-  FPRINTF (stdout, 
-          _("Terminating the call\n"));
-  GNUNET_CONVERSATION_hangup (conversation);  
-  return GNUNET_OK;
-}
-
-
-/**
- * List of supported commands.
- */
-static struct VoipCommand commands[] = {
-  {"/call ", &do_call, gettext_noop ("Use `/call gns_name'")},
-  {"/callpeer ", &do_call_peer,
-   gettext_noop ("Use `/call private_key' to call a person")},
-  {"/accept", &do_accept,
-   gettext_noop ("Use `/accept' to accept an incoming call")},
-  {"/terminate", &do_hang_up,
-   gettext_noop ("Use `/terminate' to end a call")},
-  {"/reject", &do_reject,
-   gettext_noop ("Use `/rejet' to reject an incoming call")},
-  {"/quit", &do_quit, gettext_noop ("Use `/quit' to terminate 
gnunet-conversation")},
-  {"/help", &do_help,
-   gettext_noop ("Use `/help command' to get help for a specific command")},
-  {"/", &do_unknown, NULL},
-  {"", &do_unknown, NULL},
-  {NULL, NULL, NULL},
-};
-
-
-/**
- *
- */
-static int
-do_help (const char *args, 
-        const void *xtra)
-{
-  int i;
-
-  i = 0;
-  while ((NULL != args) && (0 != strlen (args)) &&
-        (commands[i].Action != &do_help))
-  {
-    if (0 ==
-       strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
-    {
-      FPRINTF (stdout, 
-              "%s\n",
-              gettext (commands[i].helptext));
-      return GNUNET_OK;
-    }
-    i++;
-  }
-  i = 0;
-  FPRINTF (stdout, 
-          "%s", 
-          "Available commands:");
-  while (commands[i].Action != &do_help)
-  {
-    FPRINTF (stdout, 
-            " %s", 
-            gettext (commands[i].command));
-    i++;
-  }
-  FPRINTF (stdout,
-          "%s",
-          "\n");
-  FPRINTF (stdout,
-          "%s\n",
-          gettext (commands[i].helptext));
-  return GNUNET_OK;
-}
-
-
-/**
- *
- */
-static void
-do_stop_task (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             "Running shutdown task\n");
-  GNUNET_CONVERSATION_disconnect (conversation);
-  
-  if (handle_cmd_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (handle_cmd_task);
-    handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
-  } 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             "Running shutdown task finished\n");
-}
-
-
-/**
- *
- */
-static void
-handle_command (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char message[MAX_MESSAGE_LENGTH + 1];
-  int i;
-
-  /* read message from command line and handle it */
-  memset (message, 0, MAX_MESSAGE_LENGTH + 1);
-  if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
-    goto next;
-  if (strlen (message) == 0)
-    goto next;
-  if (message[strlen (message) - 1] == '\n')
-    message[strlen (message) - 1] = '\0';
-  if (strlen (message) == 0)
-    goto next;
-  i = 0;
-  while ((NULL != commands[i].command) &&
-        (0 !=
-         strncasecmp (commands[i].command, message,
-                      strlen (commands[i].command))))
-    i++;
-  if (GNUNET_OK !=
-      commands[i].Action (&message[strlen (commands[i].command)], NULL))
-    goto out;
-
-next:
-  handle_cmd_task =
-    GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_multiply
-                                               (GNUNET_TIME_UNIT_MILLISECONDS,
-                                                100),
-                                               GNUNET_SCHEDULER_PRIORITY_UI,
-                                               &handle_command, NULL);
-  return;
-
-out:
-  handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param c configuration
- */
-static void
-run (void *cls,
-     char *const *args, 
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  if (NULL ==
-      (conversation =
-       GNUNET_CONVERSATION_connect (c, NULL, 
-                                   &call_handler,
-                                   &reject_handler,
-                                   &notification_handler,
-                                   &missed_call_handler)))
-  {
-    FPRINTF (stderr,
-            "%s",
-            _("Could not access CONVERSATION service.  Exiting.\n"));
-    return;
-  }
-
-  handle_cmd_task =
-    GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
-                                       &handle_command, NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
-                               NULL);
-}
-
-
-/** 
- * The main function to conversation.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-
-  int flags;
-  int ret;
-
-  flags = fcntl (0, F_GETFL, 0);
-  flags |= O_NONBLOCK;
-  fcntl (0, F_SETFL, flags);
-
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
-    return 2;
-
-  ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-conversation",
-                           gettext_noop ("Print information about 
conversation."),
-                           options, &run, NULL);
-  GNUNET_free ((void *) argv);
-
-  return ret;
-}
-
-/* end of gnunet-conversation.c */

Copied: gnunet/src/conversation/gnunet-conversation.c (from rev 29858, 
gnunet/src/conversation/gnunet-conversation-new.c)
===================================================================
--- gnunet/src/conversation/gnunet-conversation.c                               
(rev 0)
+++ gnunet/src/conversation/gnunet-conversation.c       2013-10-05 13:10:53 UTC 
(rev 29861)
@@ -0,0 +1,855 @@
+/*
+  This file is part of GNUnet.
+  (C) 2013 Christian Grothoff (and other contributing authors)
+  
+  GNUnet is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+  
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+  Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file conversation/gnunet-conversation.c
+ * @brief conversation implementation
+ * @author Simon Dieterle
+ * @author Andreas Fuchs
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_conversation_service.h"
+
+
+/**
+ * Maximum length allowed for the command line input.
+ */
+#define MAX_MESSAGE_LENGTH 1024
+
+
+/**
+ * Possible states of the program.
+ */
+enum ConversationState
+{
+  /**
+   * We're waiting for our own idenitty.
+   */
+  CS_LOOKUP_EGO,
+
+  /**
+   * We're listening for calls
+   */
+  CS_LISTEN,
+
+  /**
+   * Our phone is ringing.
+   */
+  CS_RING,
+
+  /**
+   * We accepted an incoming phone call.
+   */
+  CS_ACCEPTED,
+
+  /**
+   * We are looking up some other participant.
+   */
+  CS_RESOLVING,
+
+  /**
+   * We are now ringing the other participant.
+   */
+  CS_RINGING,
+
+  /**
+   * The other party accepted our call and we are now connected.
+   */
+  CS_CONNECTED,
+
+  /**
+   * Internal error
+   */
+  CS_ERROR
+
+};
+
+
+/**
+ * Phone handle
+ */
+static struct GNUNET_CONVERSATION_Phone *phone;
+
+/**
+ * Call handle
+ */
+static struct GNUNET_CONVERSATION_Call *call;
+
+/**
+ * Desired phone line.
+ */
+static unsigned int line;
+
+/**
+ * Task which handles the commands
+ */
+static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task;
+
+/**
+ * Our speaker.
+ */
+static struct GNUNET_SPEAKER_Handle *speaker;
+
+/**
+ * Our microphone.
+ */
+static struct GNUNET_MICROPHONE_Handle *mic;
+
+/**
+ * Our configuration.
+ */
+static struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Our ego.
+ */
+static struct GNUNET_IDENTITY_Ego *caller_id;
+
+/**
+ * Handle to identity service.
+ */
+static struct GNUNET_IDENTITY_Handle *id;
+
+/**
+ * Name of our ego.
+ */
+static char *ego_name;
+
+/**
+ * Name of conversation partner (if any).
+ */
+static char *peer_name;
+
+/**
+ * File handle for stdin.
+ */
+static struct GNUNET_DISK_FileHandle *stdin_fh;
+
+/**
+ * Our current state.
+ */
+static enum ConversationState state;
+
+/**
+ * Be verbose.
+ */
+static int verbose;
+
+
+/**
+ * Function called with an event emitted by a phone.
+ *
+ * @param cls closure
+ * @param code type of the event on the phone
+ * @param ... additional information, depends on @a code
+ */
+static void
+phone_event_handler (void *cls,
+                     enum GNUNET_CONVERSATION_EventCode code,
+                     ...)
+{
+  va_list va;
+  
+  va_start (va, code);
+  switch (code)
+  {
+  case GNUNET_CONVERSATION_EC_RING:
+    GNUNET_break (CS_LISTEN == state);
+    GNUNET_free_non_null (peer_name);
+    peer_name = GNUNET_strdup (va_arg (va, const char *));
+    FPRINTF (stdout,
+             _("Incoming call from `%s'.\nPlease /accept or /cancel the 
call.\n"),
+             peer_name);
+    state = CS_RING;
+    break;
+  case GNUNET_CONVERSATION_EC_RINGING:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CONVERSATION_EC_READY:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CONVERSATION_EC_GNS_FAIL:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CONVERSATION_EC_BUSY:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CONVERSATION_EC_TERMINATED:
+    GNUNET_break ( (CS_RING == state) ||
+                   (CS_ACCEPTED == state) );
+    FPRINTF (stdout,
+             _("Call terminated: %s\n"),
+             va_arg (va, const char *));
+    state = CS_LISTEN;
+    break;
+  }
+  va_end (va);
+}
+
+
+/**
+ * Start our phone.
+ */
+static void
+start_phone ()
+{
+  if (NULL == caller_id)
+  {
+    FPRINTF (stderr,
+             _("Ego `%s' no longer available, phone is now down.\n"),
+             ego_name);
+    state = CS_LOOKUP_EGO;
+    return;
+  }
+  phone = GNUNET_CONVERSATION_phone_create (cfg,
+                                            caller_id,
+                                            &phone_event_handler, NULL);
+  /* FIXME: get record and print full GNS record info later here... */
+  if (NULL == phone)
+  {
+    FPRINTF (stderr,
+             "%s",
+             _("Failed to setup phone (internal error)\n"));
+    state = CS_ERROR;
+  }
+  else
+  {
+    if (verbose)
+      FPRINTF (stdout,
+               _("Phone active on line %u\n"),
+               (unsigned int) line);
+    state = CS_LISTEN;
+  }
+}
+
+
+/**
+ * Function called with an event emitted by a phone.
+ *
+ * @param cls closure
+ * @param code type of the event on the phone
+ * @param ... additional information, depends on @a code
+ */
+static void
+call_event_handler (void *cls,
+                    enum GNUNET_CONVERSATION_EventCode code,
+                    ...)
+{
+  va_list va;
+  
+  va_start (va, code);
+  switch (code)
+  {
+  case GNUNET_CONVERSATION_EC_RING:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CONVERSATION_EC_RINGING:
+    GNUNET_break (CS_RESOLVING == state);
+    if (verbose)
+      FPRINTF (stdout,
+               "%s",
+               _("Resolved address. Now ringing other party.\n"));
+    state = CS_RINGING;
+    break;
+  case GNUNET_CONVERSATION_EC_READY:
+    GNUNET_break (CS_RINGING == state);
+    FPRINTF (stdout,
+             _("Connection established: %s\n"),
+             va_arg (va, const char *));
+    state = CS_CONNECTED;
+    break;
+  case GNUNET_CONVERSATION_EC_GNS_FAIL:
+    GNUNET_break (CS_RESOLVING == state);
+    FPRINTF (stdout,
+             "%s",
+             _("Failed to resolve name\n"));
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    call = NULL;
+    start_phone ();
+    break;
+  case GNUNET_CONVERSATION_EC_BUSY:
+    GNUNET_break (CS_RINGING == state);
+    FPRINTF (stdout,
+             "%s",
+             _("Line busy\n"));
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    call = NULL;
+    start_phone ();
+    break;
+  case GNUNET_CONVERSATION_EC_TERMINATED:
+    GNUNET_break ( (CS_RINGING == state) ||
+                   (CS_CONNECTED == state) );
+    FPRINTF (stdout,
+             _("Call terminated: %s\n"),
+             va_arg (va, const char *));
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    call = NULL;
+    start_phone ();
+    break;
+  }
+  va_end (va);
+}
+
+
+/**
+ * Function declareation for executing a action
+ *
+ * @param arguments arguments given to the function
+ */
+typedef void (*ActionFunction) (const char *arguments);
+
+
+/**
+ * Structure which defines a command
+ */
+struct VoipCommand
+{
+  /**
+   * Command the user needs to enter.
+   */
+  const char *command;
+  
+  /**
+   * Function to call on command.
+   */
+  ActionFunction Action;
+
+  /**
+   * Help text for the command.
+   */
+  const char *helptext;
+};
+
+
+/**
+ * Action function to print help for the command shell.
+ *
+ * @param arguments arguments given to the command
+ */
+static void
+do_help (const char *args);
+
+
+/**
+ * Terminate the client
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_quit (const char *args)
+{
+  GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Handler for unknown command.
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_unknown (const char *msg)
+{
+  FPRINTF (stderr, 
+          _("Unknown command `%s'\n"), 
+          msg);
+}
+
+
+/**
+ * Initiating a new call
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_call (const char *arg)
+{
+  if (NULL == caller_id)
+  {
+    FPRINTF (stderr,
+             _("Ego `%s' not available\n"),
+             ego_name);
+    return;
+  }
+  switch (state)
+  {
+  case CS_LOOKUP_EGO: 
+    FPRINTF (stderr,
+             _("Ego `%s' not available\n"),
+             ego_name);
+    return;
+  case CS_LISTEN:
+    /* ok to call! */
+    break;
+  case CS_RING:
+    FPRINTF (stdout,
+             _("Hanging up on incoming phone call from `%s' to call `%s'.\n"),
+             peer_name,
+             arg);
+    GNUNET_CONVERSATION_phone_hang_up (phone, NULL);
+    break;
+  case CS_ACCEPTED:
+    FPRINTF (stderr,
+             _("You are already in a conversation with `%s', refusing to call 
`%s'.\n"),
+             peer_name,
+             arg);
+    return;
+  case CS_RESOLVING:
+  case CS_RINGING:
+    FPRINTF (stderr,
+             _("Aborting call to `%s'\n"),
+             peer_name);
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    call = NULL;
+    break;
+  case CS_CONNECTED:
+    FPRINTF (stderr,
+             _("You are already in a conversation with `%s', refusing to call 
`%s'.\n"),
+             peer_name,
+             arg);
+    return;
+  case CS_ERROR:
+    /* ok to call */
+    break;
+  }
+  GNUNET_assert (NULL == call);
+  if (NULL != phone)
+  {
+    GNUNET_CONVERSATION_phone_destroy (phone);
+    phone = NULL;
+  }
+  GNUNET_free_non_null (peer_name);
+  peer_name = GNUNET_strdup (arg);
+  call = GNUNET_CONVERSATION_call_start (cfg,
+                                         caller_id,
+                                         arg,
+                                         speaker,
+                                         mic,
+                                         &call_event_handler, NULL);
+  state = CS_RESOLVING;
+}
+
+
+/**
+ * Accepting an incoming call
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_accept (const char *args)
+{
+  switch (state)
+  {
+  case CS_LOOKUP_EGO:     
+  case CS_LISTEN:
+  case CS_ERROR:
+    FPRINTF (stderr,
+             _("There is no incoming call to be accepted!\n"));
+    return;
+  case CS_RING:
+    /* this is the expected state */
+    break;
+  case CS_ACCEPTED:
+    FPRINTF (stderr,
+             _("You are already in a conversation with `%s'.\n"),
+             peer_name);
+    return;
+  case CS_RESOLVING:
+  case CS_RINGING:
+    FPRINTF (stderr,
+             _("You are trying to call `%s', cannot accept incoming calls 
right now.\n"),
+             peer_name);
+    return;
+  case CS_CONNECTED:
+    FPRINTF (stderr,
+             _("You are already in a conversation with `%s'.\n"),
+             peer_name);
+    return;
+  }
+  GNUNET_assert (NULL != phone);
+  GNUNET_CONVERSATION_phone_pick_up (phone, 
+                                     args,
+                                     speaker,
+                                     mic);
+  state = CS_ACCEPTED;
+}
+
+
+/**
+ * Accepting an incoming call
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_status (const char *args)
+{
+  switch (state)
+  {
+  case CS_LOOKUP_EGO: 
+    FPRINTF (stdout,
+             _("We are currently trying to locate the private key for the ego 
`%s'.\n"),
+             ego_name);
+    break;
+  case CS_LISTEN:
+    FPRINTF (stdout,
+             _("We are listening for incoming calls for ego `%s' on line 
%u.\n"),
+             ego_name,
+             line);
+    break;
+  case CS_RING:
+    FPRINTF (stdout,
+             _("The phone is rining. `%s' is trying to call us.\n"),
+             peer_name);
+    break;
+  case CS_ACCEPTED:
+  case CS_CONNECTED:
+    FPRINTF (stdout,
+             _("You are having a conversation with `%s'.\n"),
+             peer_name);
+    break;
+  case CS_RESOLVING:
+    FPRINTF (stdout,
+             _("We are trying to find the network address to call `%s'.\n"),
+             peer_name);
+    break;
+  case CS_RINGING:
+    FPRINTF (stdout,
+             _("We are calling `%s', his phone should be ringing.\n"),
+             peer_name);
+    break;
+  case CS_ERROR:
+    FPRINTF (stdout,
+             _("We had an internal error setting up our phone line. You can 
still make calls.\n"));
+    break;
+  }
+}
+
+
+/**
+ * Rejecting a call
+ *
+ * @param args arguments given to the command
+ */
+static void
+do_reject (const char *args)
+{
+  switch (state)
+  {
+  case CS_LOOKUP_EGO: 
+  case CS_LISTEN:
+  case CS_ERROR:
+    FPRINTF (stderr,
+             "%s",
+             _("There is no call that could be cancelled right now.\n"));
+    return;
+  case CS_RING:
+  case CS_ACCEPTED:
+  case CS_RESOLVING:
+  case CS_RINGING:
+  case CS_CONNECTED:
+    /* expected state, do rejection logic */
+    break;
+  }
+  if (NULL == call)
+  {
+    GNUNET_assert (NULL != phone);
+    GNUNET_CONVERSATION_phone_hang_up (phone, 
+                                       args);
+    state = CS_LISTEN;
+  }
+  else
+  {
+    GNUNET_CONVERSATION_call_stop (call, args);
+    call = NULL;
+    start_phone ();
+  }
+}
+
+
+/**
+ * List of supported commands.
+ */
+static struct VoipCommand commands[] = {
+  {"/call", &do_call, 
+   gettext_noop ("Use `/call USER.gnu'")},
+  {"/accept", &do_accept,
+   gettext_noop ("Use `/accept MESSAGE' to accept an incoming call")},
+  {"/cancel", &do_reject,
+   gettext_noop ("Use `/cancel MESSAGE' to reject or terminate a call")},
+  {"/status", &do_status,
+   gettext_noop ("Use `/status to print status information")},
+  {"/quit", &do_quit, 
+   gettext_noop ("Use `/quit' to terminate gnunet-conversation")},
+  {"/help", &do_help,
+   gettext_noop ("Use `/help command' to get help for a specific command")},
+  {"", &do_unknown, 
+   NULL},
+  {NULL, NULL, NULL},
+};
+
+
+/**
+ * Action function to print help for the command shell.
+ *
+ * @param arguments arguments given to the command
+ */
+static void
+do_help (const char *args)
+{
+  unsigned int i;
+  
+  i = 0; 
+  while ( (NULL != args) &&
+          (0 != strlen (args)) &&
+          (commands[i].Action != &do_help))
+  {
+    if (0 ==
+       strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1))
+    {
+      FPRINTF (stdout, 
+              "%s\n",
+              gettext (commands[i].helptext));
+      return;
+    }
+    i++;
+  }
+  i = 0;
+  FPRINTF (stdout, 
+          "%s", 
+          "Available commands:\n");
+  while (commands[i].Action != &do_help)
+  {
+    FPRINTF (stdout, 
+            "%s\n", 
+            gettext (commands[i].command));
+    i++;
+  }
+  FPRINTF (stdout,
+          "%s",
+          "\n");
+  FPRINTF (stdout,
+          "%s\n",
+          gettext (commands[i].helptext));
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls NULL
+ * @param tc unused
+ */
+static void
+do_stop_task (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (NULL != call)
+  {
+    GNUNET_CONVERSATION_call_stop (call, NULL);
+    call = NULL;
+  }
+  if (NULL != phone)
+  {
+    GNUNET_CONVERSATION_phone_destroy (phone);
+    phone = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != handle_cmd_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle_cmd_task);
+    handle_cmd_task = GNUNET_SCHEDULER_NO_TASK;
+  } 
+  if (NULL != id)
+  {
+    GNUNET_IDENTITY_disconnect (id);
+    id = NULL;
+  }
+  GNUNET_SPEAKER_destroy (speaker);
+  speaker = NULL;
+  GNUNET_MICROPHONE_destroy (mic);
+  mic = NULL;
+  GNUNET_free (ego_name);
+  ego_name = NULL;
+  GNUNET_CONFIGURATION_destroy (cfg);
+  cfg = NULL;
+  GNUNET_free_non_null (peer_name);
+  state = CS_ERROR;
+}
+
+
+/**
+ * Task to handle commands from the terminal.
+ *
+ * @param cls NULL
+ * @param tc scheduler context
+ */
+static void
+handle_command (void *cls,
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char message[MAX_MESSAGE_LENGTH + 1];
+  const char *ptr;
+  size_t i;
+
+  handle_cmd_task =
+    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                    stdin_fh,
+                                    &handle_command, NULL);
+  /* read message from command line and handle it */
+  memset (message, 0, MAX_MESSAGE_LENGTH + 1);
+  if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
+    return;
+  if (0 == strlen (message))
+    return;
+  if (message[strlen (message) - 1] == '\n')
+    message[strlen (message) - 1] = '\0';
+  if (0 == strlen (message))
+    return;
+  i = 0;
+  while ((NULL != commands[i].command) &&
+        (0 != strncasecmp (commands[i].command, message,
+                            strlen (commands[i].command))))
+    i++;
+  ptr = &message[strlen (commands[i].command)];
+  while (isspace ((int) *ptr))
+    ptr++;
+  commands[i].Action (ptr);
+}
+
+
+/**
+ * Function called by identity service with information about egos.
+ *
+ * @param cls NULL
+ * @param ego ego handle
+ * @param ctx unused
+ * @param name name of the ego
+ */
+static void
+identity_cb (void *cls,
+             struct GNUNET_IDENTITY_Ego *ego,
+             void **ctx,
+             const char *name)
+{
+  if (NULL == name)
+    return;
+  if (ego == caller_id)
+  {
+    if (verbose)
+      FPRINTF (stdout,
+               _("Name of our ego changed to `%s'\n"),
+               name);
+    GNUNET_free (ego_name);
+    ego_name = GNUNET_strdup (name);
+    return;
+  }
+  if (0 != strcmp (name,
+                   ego_name))
+    return;
+  if (NULL == ego)
+  {    
+    if (verbose)
+      FPRINTF (stdout,
+               _("Our ego `%s' was deleted!\n"),
+               ego_name);
+    caller_id = NULL;
+    return;
+  }
+  caller_id = ego;
+  GNUNET_CONFIGURATION_set_value_number (cfg,
+                                         "CONVERSATION",
+                                         "LINE",
+                                         line);
+  start_phone ();
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args, 
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  cfg = GNUNET_CONFIGURATION_dup (c);
+  speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
+  mic = GNUNET_MICROPHONE_create_from_hardware (cfg);
+  if (NULL == ego_name)
+  {
+    FPRINTF (stderr,
+             "%s",
+             _("You must specify the NAME of an ego to use\n"));
+    return;
+  }
+  id = GNUNET_IDENTITY_connect (cfg,
+                                &identity_cb,
+                                NULL);
+  handle_cmd_task =
+    GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
+                                       &handle_command, NULL);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
+                               NULL);
+}
+
+
+/** 
+ * The main function to conversation.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    {'e', "ego", "NAME",
+     gettext_noop ("sets the NAME of the ego to use for the phone (and name 
resolution)"),
+     1, &GNUNET_GETOPT_set_string, &ego_name},
+    {'p', "phone", "LINE",
+      gettext_noop ("sets the LINE to use for the phone"),
+     1, &GNUNET_GETOPT_set_uint, &line},
+    GNUNET_GETOPT_OPTION_END
+  };
+  int flags;
+  int ret;
+
+  flags = fcntl (0, F_GETFL, 0);
+  flags |= O_NONBLOCK;
+  fcntl (0, F_SETFL, flags);
+  stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+  ret = GNUNET_PROGRAM_run (argc, argv,
+                            "gnunet-conversation",
+                           gettext_noop ("Enables having a conversation with 
other GNUnet users."),
+                           options, &run, NULL);
+  GNUNET_free ((void *) argv);
+  return (GNUNET_OK == ret) ? 0 : 1;
+}
+
+/* end of gnunet-conversation.c */

Deleted: gnunet/src/conversation/gnunet-service-conversation-new.c
===================================================================
--- gnunet/src/conversation/gnunet-service-conversation-new.c   2013-10-05 
13:08:47 UTC (rev 29860)
+++ gnunet/src/conversation/gnunet-service-conversation-new.c   2013-10-05 
13:10:53 UTC (rev 29861)
@@ -1,1227 +0,0 @@
-/*
-  This file is part of GNUnet.
-  (C) 2013 Christian Grothoff (and other contributing authors)
-  
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-  
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
-*/
-/**
- * @file conversation/gnunet-service-conversation.c
- * @brief conversation service implementation
- * @author Simon Dieterle
- * @author Andreas Fuchs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_protocols.h"
-#include "gnunet_applications.h"
-#include "gnunet_constants.h"
-#include "gnunet_signatures.h"
-#include "gnunet_mesh_service.h"
-#include "gnunet_conversation_service.h"
-#include "conversation.h"
-
-
-/**
- * How long is our signature on a call valid?  Needs to be long enough for 
time zone
- * differences and network latency to not matter.  No strong need for it to be 
short,
- * but we simply like all signatures to eventually expire.
- */
-#define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
-
-
-/**
- * The possible connection status
- */
-enum LineStatus
-{
-  /**
-   * We are waiting for incoming calls.
-   */
-  LS_CALLEE_LISTEN,
-
-  /**
-   * Our phone is ringing, waiting for the client to pick up.
-   */
-  LS_CALLEE_RINGING,
-
-  /**
-   * We are talking!
-   */
-  LS_CALLEE_CONNECTED,
-
-  /**
-   * We're in shutdown, sending hangup messages before cleaning up.
-   */
-  LS_CALLEE_SHUTDOWN,
-
-  /**
-   * We are waiting for the phone to be picked up.
-   */
-  LS_CALLER_CALLING,
-
-  /**
-   * We are talking!
-   */
-  LS_CALLER_CONNECTED,
-
-  /**
-   * We're in shutdown, sending hangup messages before cleaning up.
-   */
-  LS_CALLER_SHUTDOWN
-};
-
-
-/**
- * A line connects a local client with a mesh tunnel (or, if it is an
- * open line, is waiting for a mesh tunnel).
- */
-struct Line
-{
-  /**
-   * Kept in a DLL.
-   */
-  struct Line *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct Line *prev;
-
-  /**
-   * Handle for the reliable tunnel (contol data)
-   */
-  struct GNUNET_MESH_Tunnel *tunnel_reliable;
-  
-  /**
-   * Handle for unreliable tunnel (audio data)
-   */
-  struct GNUNET_MESH_Tunnel *tunnel_unreliable;
-
-  /**
-   * Transmit handle for pending audio messages
-   */
-  struct GNUNET_MESH_TransmitHandle *unreliable_mth;
-
-  /**
-   * Message queue for control messages
-   */
-  struct GNUNET_MQ_Handle *reliable_mq;
-
-  /**
-   * Handle to the line client.
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Target of the line, if we are the caller.
-   */
-  struct GNUNET_PeerIdentity target;
-
-  /**
-   * Temporary buffer for audio data.
-   */
-  void *audio_data;
-
-  /**
-   * Number of bytes in @e audio_data.
-   */
-  size_t audio_size;
-
-  /**
-   * Our line number.
-   */
-  uint32_t local_line;
-
-  /**
-   * Remote line number.
-   */
-  uint32_t remote_line;
-
-  /**
-   * Current status of this line.
-   */ 
-  enum LineStatus status;
-
-};
-
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Notification context containing all connected clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
-/**
- * Handle for mesh
- */
-static struct GNUNET_MESH_Handle *mesh;
-
-/**
- * Identity of this peer.
- */
-static struct GNUNET_PeerIdentity my_identity;
-
-/**
- * Head of DLL of active lines.
- */
-static struct Line *lines_head;
-
-/**
- * Tail of DLL of active lines.
- */
-static struct Line *lines_tail;
-
-/**
- * Counter for generating local line numbers.
- * FIXME: randomize generation in the future
- * to eliminate information leakage.
- */
-static uint32_t local_line_cnt;
-
-
-/**
- * Function to register a phone.
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
- */
-static void
-handle_client_register_message (void *cls,
-                                struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
-{
-  const struct ClientPhoneRegisterMessage *msg;
-  struct Line *line;
-
-  msg = (struct ClientPhoneRegisterMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL != line)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  line = GNUNET_new (struct Line);
-  line->client = client;
-  GNUNET_SERVER_notification_context_add (nc, client);
-  GNUNET_CONTAINER_DLL_insert (lines_head,
-                               lines_tail,
-                               line);
-  line->local_line = ntohl (msg->line);
-  GNUNET_SERVER_client_set_user_context (client, line);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Function to handle a pickup request message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
- */
-static void
-handle_client_pickup_message (void *cls,
-                              struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
-{
-  const struct ClientPhonePickupMessage *msg;
-  struct GNUNET_MQ_Envelope *e;
-  struct MeshPhonePickupMessage *mppm;
-  const char *meta;
-  struct Line *line;
-  size_t len;
-
-  msg = (struct ClientPhonePickupMessage *) message;
-  meta = (const char *) &msg[1];
-  len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
-  if ( (0 == len) ||
-       ('\0' != meta[len - 1]) )
-  {
-    meta = NULL;
-    len = 0;
-  }
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL == line)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Ignoring client's PICKUP message, caller has HUNG UP 
already\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    break;
-  case LS_CALLEE_RINGING:
-    line->status = LS_CALLEE_CONNECTED;
-    break;
-  case LS_CALLEE_CONNECTED:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  case LS_CALLEE_SHUTDOWN:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    break;
-  case LS_CALLER_CALLING:
-  case LS_CALLER_CONNECTED:
-  case LS_CALLER_SHUTDOWN:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  line->status = LS_CALLEE_CONNECTED;
-  e = GNUNET_MQ_msg_extra (mppm,
-                           len,
-                           
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP);
-  memcpy (&mppm[1], meta, len);
-  GNUNET_MQ_send (line->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Destroy the mesh tunnels of a line.
- *
- * @param line line to shutdown tunnels of
- */
-static void
-destroy_line_mesh_tunnels (struct Line *line)
-{
-  if (NULL != line->reliable_mq)
-  {
-    GNUNET_MQ_destroy (line->reliable_mq);
-    line->reliable_mq = NULL;
-  }
-  if (NULL != line->unreliable_mth)
-  {
-    GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
-    line->unreliable_mth = NULL;
-  }
-  if (NULL != line->tunnel_unreliable)
-  {
-    GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable);
-    line->tunnel_unreliable = NULL;
-  }
-  if (NULL != line->tunnel_reliable)
-  {
-    GNUNET_MESH_tunnel_destroy (line->tunnel_reliable);
-    line->tunnel_reliable = NULL;
-  }
-}
-
-
-/**
- * We are done signalling shutdown to the other peer.  Close down
- * (or reset) the line.
- *
- * @param cls the `struct Line` to reset/terminate
- */
-static void
-mq_done_finish_caller_shutdown (void *cls)
-{
-  struct Line *line = cls;
-
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    break;
-  case LS_CALLEE_RINGING:
-    GNUNET_break (0);
-    break;
-  case LS_CALLEE_CONNECTED:
-    GNUNET_break (0);
-    break;
-  case LS_CALLEE_SHUTDOWN:
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    return;
-  case LS_CALLER_CALLING:
-    line->status = LS_CALLER_SHUTDOWN;
-    break;
-  case LS_CALLER_CONNECTED:
-    line->status = LS_CALLER_SHUTDOWN;
-    break;
-  case LS_CALLER_SHUTDOWN:
-    destroy_line_mesh_tunnels (line);
-    GNUNET_CONTAINER_DLL_remove (lines_head,
-                                 lines_tail,
-                                 line);
-    GNUNET_free_non_null (line->audio_data);
-    GNUNET_free (line);
-    break;
-  }  
-}
-
-
-/**
- * Function to handle a hangup request message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
- */
-static void
-handle_client_hangup_message (void *cls,
-                              struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
-{
-  const struct ClientPhoneHangupMessage *msg;
-  struct GNUNET_MQ_Envelope *e;
-  struct MeshPhoneHangupMessage *mhum;
-  const char *meta;
-  struct Line *line;
-  size_t len;
-
-  msg = (struct ClientPhoneHangupMessage *) message;
-  meta = (const char *) &msg[1];
-  len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
-  if ( (0 == len) ||
-       ('\0' != meta[len - 1]) )
-  {
-    meta = NULL;
-    len = 0;
-  }
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL == line)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  case LS_CALLEE_RINGING:
-    line->status = LS_CALLEE_SHUTDOWN;
-    break;
-  case LS_CALLEE_CONNECTED:
-    line->status = LS_CALLEE_SHUTDOWN;
-    break;
-  case LS_CALLEE_SHUTDOWN:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  case LS_CALLER_CALLING:
-    line->status = LS_CALLER_SHUTDOWN;
-    break;
-  case LS_CALLER_CONNECTED:
-    line->status = LS_CALLER_SHUTDOWN;
-    break;
-  case LS_CALLER_SHUTDOWN:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  e = GNUNET_MQ_msg_extra (mhum,
-                           len,
-                           
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
-  memcpy (&mhum[1], meta, len);
-  GNUNET_MQ_notify_sent (e,
-                         &mq_done_finish_caller_shutdown,
-                         line);
-  GNUNET_MQ_send (line->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Function to handle call request the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
- */
-static void
-handle_client_call_message (void *cls,
-                            struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  const struct ClientCallMessage *msg;
-  struct Line *line;
-  struct GNUNET_MQ_Envelope *e;
-  struct MeshPhoneRingMessage *ring;
-
-  msg = (struct ClientCallMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL != line)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  line = GNUNET_new (struct Line);
-  line->target = msg->target;
-  GNUNET_CONTAINER_DLL_insert (lines_head,
-                               lines_tail,
-                               line);
-  line->remote_line = ntohl (msg->line);
-  line->status = LS_CALLER_CALLING;
-  line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
-                                                     line,
-                                                     &msg->target,
-                                                     
GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
-                                                     GNUNET_NO,
-                                                     GNUNET_YES);
-  line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
-  line->local_line = local_line_cnt++;
-  e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
-  ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
-  ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
-                              sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-                              sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) +
-                              sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
-  GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
-                                                  &ring->caller_id);
-  ring->remote_line = msg->line;
-  ring->source_line = line->local_line;
-  ring->target = msg->target;
-  ring->source = my_identity;
-  ring->expiration_time = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
-  GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
-                          &ring->purpose,
-                          &ring->signature);
-  GNUNET_MQ_send (line->reliable_mq, e);
-  GNUNET_SERVER_client_set_user_context (client, line);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Transmit audio data via unreliable mesh channel.
- *
- * @param cls the `struct Line` we are transmitting for
- * @param size number of bytes available in @a buf
- * @param buf where to copy the data
- * @return number of bytes copied to @buf
- */
-static size_t
-transmit_line_audio (void *cls,
-                     size_t size,
-                     void *buf)
-{
-  struct Line *line = cls;
-  struct MeshAudioMessage *mam = buf;
-  
-  line->unreliable_mth = NULL;
-  if ( (NULL == buf) ||
-       (size < sizeof (struct MeshAudioMessage) + line->audio_size) )
-    {
-    /* eh, other error handling? */
-    return 0;
-  }
-  mam->header.size = htons (sizeof (struct MeshAudioMessage) + 
line->audio_size);
-  mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO);
-  mam->remote_line = htonl (line->remote_line);
-  memcpy (&mam[1], line->audio_data, line->audio_size);
-  GNUNET_free (line->audio_data);
-  line->audio_data = NULL;
-  return sizeof (struct MeshAudioMessage) + line->audio_size;  
-}
-
-
-/**
- * Function to handle audio data from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
- */
-static void
-handle_client_audio_message (void *cls,
-                             struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message)
-{
-  const struct ClientAudioMessage *msg;
-  struct Line *line;
-  size_t size;
-
-  size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
-  msg = (struct ClientAudioMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL == line)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-  case LS_CALLEE_RINGING:
-  case LS_CALLER_CALLING:
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  case LS_CALLEE_CONNECTED:
-  case LS_CALLER_CONNECTED:
-    /* common case, handled below */
-    break;
-  case LS_CALLEE_SHUTDOWN:
-  case LS_CALLER_SHUTDOWN:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Mesh audio channel in shutdown; audio data dropped\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  if (NULL == line->tunnel_unreliable)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Mesh audio channel not ready; audio data dropped\n"));
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);    
-    return;
-  }
-  if (NULL != line->unreliable_mth)
-  {
-    /* NOTE: we may want to not do this and instead combine the data */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Dropping previous audio data segment with %u bytes\n",
-                line->audio_size);
-    GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
-    GNUNET_free (line->audio_data);
-  }
-  line->audio_size = size;
-  line->audio_data = GNUNET_malloc (line->audio_size);
-  memcpy (line->audio_data,
-          &msg[1],
-          size);
-  line->unreliable_mth = GNUNET_MESH_notify_transmit_ready 
(line->tunnel_unreliable,
-                                                            GNUNET_NO,
-                                                            
GNUNET_TIME_UNIT_FOREVER_REL,
-                                                            sizeof (struct 
MeshAudioMessage) 
-                                                            + line->audio_size,
-                                                            
&transmit_line_audio,
-                                                            line);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * We are done signalling shutdown to the other peer.  
- * Destroy the tunnel.
- *
- * @param cls the `struct GNUNET_MESH_tunnel` to destroy
- */
-static void
-mq_done_destroy_tunnel (void *cls)
-{
-  struct GNUNET_MESH_Tunnel *tunnel = cls;
-  
-  GNUNET_MESH_tunnel_destroy (tunnel);
-}
-
-
-/**
- * Function to handle a ring message incoming over mesh
- *
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * @return #GNUNET_OK
- */
-static int
-handle_mesh_ring_message (void *cls,
-                          struct GNUNET_MESH_Tunnel *tunnel,
-                          void **tunnel_ctx,
-                          const struct GNUNET_MessageHeader *message)
-{
-  const struct MeshPhoneRingMessage *msg;
-  struct Line *line;
-  struct GNUNET_MQ_Envelope *e;
-  struct MeshPhoneBusyMessage *busy;
-  struct ClientPhoneRingMessage cring;
-  
-  msg = (const struct MeshPhoneRingMessage *) message;
-  if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
-                                    sizeof (struct GNUNET_TIME_AbsoluteNBO) +
-                                    sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) +
-                                    sizeof (struct 
GNUNET_CRYPTO_EccPublicSignKey))) ||
-       (GNUNET_OK !=
-        GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
-                                  &msg->purpose,
-                                  &msg->signature,
-                                  &msg->caller_id)) )
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  for (line = lines_head; NULL != line; line = line->next)  
-    if ( (line->local_line == ntohl (msg->remote_line)) &&
-         (LS_CALLEE_LISTEN == line->status) )
-      break;
-  if (NULL == line) 
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("No available phone for incoming call on line %u, sending 
BUSY signal\n"),
-                ntohl (msg->remote_line));
-    e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
-    GNUNET_MQ_notify_sent (e,
-                           &mq_done_destroy_tunnel,
-                           tunnel);
-    GNUNET_MQ_send (line->reliable_mq, e);
-    GNUNET_MESH_receive_done (tunnel); /* needed? */
-    return GNUNET_OK;
-  }
-  line->status = LS_CALLEE_RINGING;
-  line->remote_line = ntohl (msg->source_line);
-  line->tunnel_reliable = tunnel;
-  line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
-  *tunnel_ctx = line;
-  cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
-  cring.header.size = htons (sizeof (cring));
-  cring.reserved = htonl (0);
-  cring.caller_id = msg->caller_id;
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              line->client,
-                                              &cring.header,
-                                              GNUNET_NO);
-  GNUNET_MESH_receive_done (tunnel);
-  return GNUNET_OK;
-}
-
-
-/**
- * Function to handle a hangup message incoming over mesh
- *
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * @return #GNUNET_OK
- */
-static int
-handle_mesh_hangup_message (void *cls,
-                            struct GNUNET_MESH_Tunnel *tunnel,
-                            void **tunnel_ctx,
-                            const struct GNUNET_MessageHeader *message)
-{
-  struct Line *line = *tunnel_ctx;
-  const struct MeshPhoneHangupMessage *msg;
-  const char *reason;
-  size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage);
-  char buf[len + sizeof (struct ClientPhoneHangupMessage)];
-  struct ClientPhoneHangupMessage *hup;
-  
-  msg = (const struct MeshPhoneHangupMessage *) message;
-  len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage);
-  reason = (const char *) &msg[1];
-  if ( (0 == len) ||
-       ('\0' != reason[len - 1]) )
-  {
-    reason = NULL;
-    len = 0;
-  }
-  if (NULL == line)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "HANGUP message received for non-existing line, dropping 
tunnel.\n");
-    return GNUNET_SYSERR;
-  }
-  *tunnel_ctx = NULL;
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  case LS_CALLEE_RINGING:
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    break;
-  case LS_CALLEE_CONNECTED:
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    break;
-  case LS_CALLEE_SHUTDOWN:
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    return GNUNET_OK;
-  case LS_CALLER_CALLING:
-    line->status = LS_CALLER_SHUTDOWN;
-    mq_done_finish_caller_shutdown (line);
-    break;
-  case LS_CALLER_CONNECTED:
-    line->status = LS_CALLER_SHUTDOWN;
-    mq_done_finish_caller_shutdown (line);
-    break;
-  case LS_CALLER_SHUTDOWN:
-    mq_done_finish_caller_shutdown (line);
-    return GNUNET_OK;
-  }
-  hup = (struct ClientPhoneHangupMessage *) buf;
-  hup->header.size = sizeof (buf);
-  hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
-  memcpy (&hup[1], reason, len);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              line->client,
-                                              &hup->header,
-                                              GNUNET_NO);
-  GNUNET_MESH_receive_done (tunnel);
-  return GNUNET_OK;
-}
-
-
-/**
- * Function to handle a pickup message incoming over mesh
- *
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * @return #GNUNET_OK
- */
-static int
-handle_mesh_pickup_message (void *cls,
-                            struct GNUNET_MESH_Tunnel *tunnel,
-                            void **tunnel_ctx,
-                            const struct GNUNET_MessageHeader *message)
-{
-  const struct MeshPhonePickupMessage *msg;
-  struct Line *line = *tunnel_ctx;
-  const char *metadata;
-  size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage);
-  char buf[len + sizeof (struct ClientPhonePickupMessage)];
-  struct ClientPhonePickupMessage *pick;
-  
-  msg = (const struct MeshPhonePickupMessage *) message;
-  len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage);
-  metadata = (const char *) &msg[1];
-  if ( (0 == len) ||
-       ('\0' != metadata[len - 1]) )
-  {
-    metadata = NULL;
-    len = 0;
-  }
-  if (NULL == line)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "PICKUP message received for non-existing line, dropping 
tunnel.\n");
-    return GNUNET_SYSERR;
-  }
-  GNUNET_MESH_receive_done (tunnel);
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  case LS_CALLEE_RINGING:
-  case LS_CALLEE_CONNECTED:
-    GNUNET_break_op (0);
-    destroy_line_mesh_tunnels (line);
-    line->status = LS_CALLEE_LISTEN;
-    return GNUNET_SYSERR;
-  case LS_CALLEE_SHUTDOWN:
-    GNUNET_break_op (0);
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    break;
-  case LS_CALLER_CALLING:
-    line->status = LS_CALLER_CONNECTED;
-    break;
-  case LS_CALLER_CONNECTED:
-    GNUNET_break_op (0);
-    return GNUNET_OK;
-  case LS_CALLER_SHUTDOWN:
-    GNUNET_break_op (0);
-    mq_done_finish_caller_shutdown (line);
-    return GNUNET_SYSERR;
-  }
-  pick = (struct ClientPhonePickupMessage *) buf;
-  pick->header.size = sizeof (buf);
-  pick->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
-  memcpy (&pick[1], metadata, len);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              line->client,
-                                              &pick->header,
-                                              GNUNET_NO);
-  line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
-                                                       line,
-                                                       &line->target,
-                                                       
GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
-                                                       GNUNET_YES,
-                                                       GNUNET_NO);
-  return GNUNET_OK;
-}
-
-
-/**
- * Function to handle a busy message incoming over mesh
- *
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * @return #GNUNET_OK
- */
-static int
-handle_mesh_busy_message (void *cls,
-                          struct GNUNET_MESH_Tunnel *tunnel,
-                          void **tunnel_ctx,
-                          const struct GNUNET_MessageHeader *message)
-{
-  struct Line *line = *tunnel_ctx;
-  struct ClientPhoneBusyMessage busy;
-
-  if (NULL == line)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "HANGUP message received for non-existing line, dropping 
tunnel.\n");
-    return GNUNET_SYSERR;
-  }
-  busy.header.size = sizeof (busy);
-  busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              line->client,
-                                              &busy.header,
-                                              GNUNET_NO);
-  GNUNET_MESH_receive_done (tunnel);
-  *tunnel_ctx = NULL;
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  case LS_CALLEE_RINGING:
-    GNUNET_break_op (0);
-    break;
-  case LS_CALLEE_CONNECTED:
-    GNUNET_break_op (0);
-    break;
-  case LS_CALLEE_SHUTDOWN:
-    GNUNET_break_op (0);
-    break;
-  case LS_CALLER_CALLING:
-    line->status = LS_CALLER_SHUTDOWN;
-    mq_done_finish_caller_shutdown (line);
-    break;
-  case LS_CALLER_CONNECTED:
-    line->status = LS_CALLER_SHUTDOWN;
-    mq_done_finish_caller_shutdown (line);
-    break;
-  case LS_CALLER_SHUTDOWN:
-    mq_done_finish_caller_shutdown (line);
-    break;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Function to handle an audio message incoming over mesh
- *
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * @return #GNUNET_OK
- */
-static int
-handle_mesh_audio_message (void *cls,
-                           struct GNUNET_MESH_Tunnel *tunnel,
-                           void **tunnel_ctx,
-                           const struct GNUNET_MessageHeader *message)
-{
-  const struct MeshAudioMessage *msg;
-  struct Line *line = *tunnel_ctx;
-  struct GNUNET_PeerIdentity sender;
-  size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
-  char buf[msize + sizeof (struct ClientAudioMessage)];
-  struct ClientAudioMessage *cam;
-  
-  msg = (const struct MeshAudioMessage *) message;
-  if (NULL == line)
-  {
-    sender = *GNUNET_MESH_tunnel_get_info (tunnel,
-                                           GNUNET_MESH_OPTION_PEER)->peer;
-    for (line = lines_head; NULL != line; line = line->next)
-      if ( (line->local_line == ntohl (msg->remote_line)) &&
-           (LS_CALLEE_CONNECTED == line->status) &&
-           (0 == memcmp (&line->target,
-                         &sender,
-                         sizeof (struct GNUNET_PeerIdentity))) &&
-           (NULL == line->tunnel_unreliable) )
-        break;
-    if (NULL == line)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received AUDIO data for non-existing line %u, dropping.\n",
-                  ntohl (msg->remote_line));
-      return GNUNET_SYSERR;
-    }
-    line->tunnel_unreliable = tunnel;
-    *tunnel_ctx = line;
-  }
-  cam = (struct ClientAudioMessage *) buf;
-  cam->header.size = htons (sizeof (buf));
-  cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
-  memcpy (&cam[1], &msg[1], msize);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              line->client,
-                                              &cam->header,
-                                              GNUNET_YES);
-  GNUNET_MESH_receive_done (tunnel);
-  return GNUNET_OK;
-}
-
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param port port
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls,
-                struct GNUNET_MESH_Tunnel *tunnel,
-               const struct GNUNET_PeerIdentity *initiator, 
-                uint32_t port)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Received incoming tunnel on port %d\n"), 
-              port);
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from #GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls,
-             const struct GNUNET_MESH_Tunnel *tunnel,
-            void *tunnel_ctx)
-{
-  struct Line *line = tunnel_ctx;
-  struct ClientPhoneHangupMessage hup;
-
-  if (NULL == line)
-    return;
-  if (line->tunnel_unreliable == tunnel)
-  {
-    line->tunnel_unreliable = NULL;
-    return;
-  }
-  hup.header.size = sizeof (hup);
-  hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
-  switch (line->status)
-  {
-  case LS_CALLEE_LISTEN:
-    GNUNET_break (0);
-    return;
-  case LS_CALLEE_RINGING:
-  case LS_CALLEE_CONNECTED:
-    GNUNET_SERVER_notification_context_unicast (nc,
-                                                line->client,
-                                                &hup.header,
-                                                GNUNET_NO);
-    line->status = LS_CALLEE_LISTEN;
-    break;
-  case LS_CALLEE_SHUTDOWN:
-    line->status = LS_CALLEE_LISTEN;
-    destroy_line_mesh_tunnels (line);
-    break;
-  case LS_CALLER_CALLING:
-  case LS_CALLER_CONNECTED:
-    GNUNET_SERVER_notification_context_unicast (nc,
-                                                line->client,
-                                                &hup.header,
-                                                GNUNET_NO);
-    destroy_line_mesh_tunnels (line);
-    GNUNET_CONTAINER_DLL_remove (lines_head,
-                                 lines_tail,
-                                 line);
-    GNUNET_free_non_null (line->audio_data);
-    GNUNET_free (line);
-    break;
-  case LS_CALLER_SHUTDOWN:
-    destroy_line_mesh_tunnels (line);
-    GNUNET_CONTAINER_DLL_remove (lines_head,
-                                 lines_tail,
-                                 line);
-    GNUNET_free (line);
-    break;
-  }
-}
-
-
-/**
- * A client disconnected.  Remove all of its data structure entries.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- */
-static void
-handle_client_disconnect (void *cls, 
-                          struct GNUNET_SERVER_Client *client)
-{
-  struct Line *line;
-
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
-  if (NULL == line)
-    return;
-  GNUNET_CONTAINER_DLL_remove (lines_head,
-                               lines_tail,
-                               line);
-  GNUNET_free (line);
-  GNUNET_SERVER_client_set_user_context (client, NULL);
-}
-
-
-/**
- * Shutdown nicely
- * 
- * @param cls closure, NULL
- * @param tc the task context
- */
-static void
-do_shutdown (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  if (NULL != mesh)
-  {
-    GNUNET_MESH_disconnect (mesh);
-    mesh = NULL;
-  }
-  if (NULL != nc)
-  {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
-  }
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param server server handle
- * @param c configuration
- */
-static void
-run (void *cls, 
-     struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-  static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
-    {&handle_client_register_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
-     sizeof (struct ClientPhoneRegisterMessage)},
-    {&handle_client_pickup_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
-     0},
-    {&handle_client_hangup_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
-     0},
-    {&handle_client_call_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
-     0},
-    {&handle_client_audio_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
-     0},
-    {NULL, NULL, 0, 0}
-  };
-  static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
-    {&handle_mesh_ring_message,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
-     sizeof (struct MeshPhoneRingMessage)},
-    {&handle_mesh_hangup_message, 
-     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
-     0},
-    {&handle_mesh_pickup_message, 
-     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
-     0},
-    {&handle_mesh_busy_message, 
-     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
-     sizeof (struct MeshPhoneBusyMessage)},
-    {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
-     0},
-    {NULL, 0, 0}
-  };
-  static uint32_t ports[] = { 
-    GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
-    GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
-    0 
-  };
-
-  cfg = c;
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_get_host_identity (cfg,
-                                                  &my_identity));
-  mesh = GNUNET_MESH_connect (cfg,
-                             NULL,
-                             &inbound_tunnel,
-                             &inbound_end, 
-                              mesh_handlers, 
-                              ports);
-
-  if (NULL == mesh)
-  {
-    GNUNET_break (0);
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  nc = GNUNET_SERVER_notification_context_create (server, 16);
-  GNUNET_SERVER_add_handlers (server, server_handlers);
-  GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
-                                &do_shutdown,
-                               NULL);
-}
-
-
-/**
- * The main function for the conversation service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, 
-      char *const *argv)
-{
-  return (GNUNET_OK ==
-         GNUNET_SERVICE_run (argc, argv,
-                              "conversation", 
-                              GNUNET_SERVICE_OPTION_NONE,
-                             &run, NULL)) ? 0 : 1;
-}
-
-/* end of gnunet-service-conversation.c */

Deleted: gnunet/src/conversation/gnunet-service-conversation.c
===================================================================
--- gnunet/src/conversation/gnunet-service-conversation.c       2013-10-05 
13:08:47 UTC (rev 29860)
+++ gnunet/src/conversation/gnunet-service-conversation.c       2013-10-05 
13:10:53 UTC (rev 29861)
@@ -1,1832 +0,0 @@
-/*
-  This file is part of GNUnet.
-  (C) 2013 Christian Grothoff (and other contributing authors)
-  
-  GNUnet is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-  
-  GNUnet is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
-*/
-/**
- * @file conversation/gnunet-service-conversation.c
- * @brief conversation service implementation
- * @author Simon Dieterle
- * @author Andreas Fuchs
- * STRUCTURE:
- * - Variables
- * - AUXILIARY FUNCTIONS
- * - SENDING FUNCTIONS CL -> SERVER
- * - RECEIVE FUNCTIONS CL -> SERVER
- * - SENDING FUNCTIONS MESH
- * - RECEIVE FUNCTIONS MESH
- * - HELPER
- * - TUNNEL HANDLING
- * - CLIENT HANDLING
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_protocols.h"
-#include "gnunet_constants.h"
-#include "gnunet_mesh_service.h"
-#include "gnunet_conversation_service.h"
-#include "conversation.h"
-
-
-
-/*
-* The possible connection status
-*/
-enum connection_status
-{
-  LISTEN,
-  CALLER,
-  CALLEE,
-  CONNECTED
-};
-
-
-/******************************************************** 
- * Ugly hack because of not working MESH API
-*/
-typedef uint32_t MESH_TunnelNumber;
-struct GNUNET_MESH_Tunnel
-{
-  struct GNUNET_MESH_Tunnel *next;
-  struct GNUNET_MESH_Tunnel *prev;
-  struct GNUNET_MESH_Handle *mesh;
-  MESH_TunnelNumber tid;
-  uint32_t port;
-  GNUNET_PEER_Id peer;
-  void *ctx;
-  unsigned int packet_size;
-  int buffering;
-  int reliable;
-  int allow_send;
-};
-
-
-/**
- * Our configuration.
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Head of the list of current clients.
- */
-static struct GNUNET_CONTAINER_SList *clients;
-
-/**
- * Notification context containing all connected clients.
- */
-struct GNUNET_SERVER_NotificationContext *nc = NULL;
-
-/**
-* The connection status
-*/
-static struct ConnectionStatus connection;
-
-/**
-* Handle for the record helper
-*/
-static struct GNUNET_HELPER_Handle *record_helper;
-
-/** Handle for the playback handler
-*
-*/
-static struct GNUNET_HELPER_Handle *playback_helper;
-
-/**
-* Handle for mesh
-*/
-static struct GNUNET_MESH_Handle *mesh;
-
-/**
-* Transmit handle for audio messages
-*/
-static struct GNUNET_MESH_TransmitHandle *mth = NULL;
-
-/**
-* Handle for the reliable tunnel (contol data)
-*/
-static struct GNUNET_MESH_Tunnel *tunnel_reliable;
-
-/**
-* Handle for unreliable tunnel (audio data)
-*/
-static struct GNUNET_MESH_Tunnel *tunnel_unreliable;
-
-/**
-* List for missed calls
-*/
-static struct GNUNET_CONTAINER_SList *missed_calls;
-
-/**
-* List for peers to notify that we are available again
-*/
-static struct GNUNET_CONTAINER_SList *peers_to_notify;
-
-/**
-* Audio buffer (outgoing)
-*/
-static struct GNUNET_CONTAINER_SList *audio_buffer;
-
-/**
-* The pointer to the task for sending audio
-*/
-static GNUNET_SCHEDULER_TaskIdentifier audio_task;
-
-/**
-* The pointer to the task for checking timeouts an calling a peer
-*/
-static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-/**
- * Timestamp for call statistics
- */
-static struct GNUNET_TIME_Absolute start_time;
-
-/**
- * Number of payload packes sent
- */
-static int data_sent;
-static int data_sent_size;
-
-/**
- * Number of payload packets received
- */
-static int data_received;
-static int data_received_size;
-
-
-/**
-* Transmit a mesh message
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the error message
- * @return number of bytes written to buf
- */
-static size_t transmit_mesh_message (void *cls, size_t size, void *buf);
-
-/**
- * Function called to send a peer no answer message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the peer no answer message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_no_answer_message (void *cls, size_t size, void *buf);
-
-/**
- * Task to schedule a audio transmission.
- * 
- * @param cls Closure.
- * @param tc Task Context.
- */
-static void
-transmit_audio_task (void *cls,
-                    const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
-* Start the audio helpers
-*/
-int start_helpers (void);
-
-/**
-* Stop the audio helpers
-*/
-void stop_helpers (void);
-
-
-
-/******************************************************************************/
-/***********************     AUXILIARY FUNCTIONS      
*************************/
-/******************************************************************************/
-
-/**
-* Function which displays some call stats
-*/
-static void
-show_end_data (void)
-{
-  static struct GNUNET_TIME_Absolute end_time;
-  static struct GNUNET_TIME_Relative total_time;
-
-  end_time = GNUNET_TIME_absolute_get ();
-  total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time);
-  FPRINTF (stderr, "\nResults of send\n");
-  FPRINTF (stderr, "Test time %s\n",
-          GNUNET_STRINGS_relative_time_to_string (total_time,
-                                                  GNUNET_NO));
-  FPRINTF (stderr, "Test total packets: %d\n", 
-          data_sent);
-  FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 
-          data_sent_size * 1000.0 / (total_time.rel_value_us + 1));    // 
4bytes * us
-  FPRINTF (stderr, "Test throughput: %f packets/s\n\n",
-          data_sent * 1000000.0 / (total_time.rel_value_us + 1));      // 
packets * us
-
-  FPRINTF (stderr, "\nResults of recv\n");
-  FPRINTF (stderr, "Test time %s\n",
-          GNUNET_STRINGS_relative_time_to_string (total_time,
-                                                  GNUNET_NO));
-  FPRINTF (stderr, "Test total packets: %d\n", 
-          data_received);
-  FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 
-          data_received_size * 1000.0 / (total_time.rel_value_us + 1));        
// 4bytes * us
-  FPRINTF (stderr, "Test throughput: %f packets/s\n\n", 
-          data_received * 1000000.0 / (total_time.rel_value_us + 1));  // 
packets * us
-}
-
-/**
-* Function which sets the connection state to LISTEN
-*/
-static void
-status_to_listen (void)
-{
-
-  if (CONNECTED == connection.status)
-    {
-      show_end_data ();
-    }
-
-  if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (timeout_task);
-      timeout_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-
-  stop_helpers ();
-
-  connection.status = LISTEN;
-  connection.client = NULL;
-
-  data_sent = 0;
-  data_sent_size = 0;
-  data_received = 0;
-  data_received_size = 0;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %s\n"),
-             "LISTEN");
-}
-
-/**
-* Function to terminate the active call
-*/
-static void
-terminate_call ()
-{
-  size_t msg_size;
-  msg_size = sizeof (struct MeshSessionTerminateMessage);
-  struct MeshSessionTerminateMessage *message_mesh_terminate =
-    (struct MeshSessionTerminateMessage *) GNUNET_malloc (msg_size);
-
-  if (NULL == message_mesh_terminate)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not create MeshSessionTerminateMessage\n"));
-      status_to_listen ();
-
-      return;
-    }
-
-  message_mesh_terminate->header.size = htons (msg_size);
-  message_mesh_terminate->header.type =
-    htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE);
-
-  if (NULL ==
-      GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
-                                        MAX_TRANSMIT_DELAY, msg_size,
-                                        &transmit_mesh_message,
-                                        (void *) message_mesh_terminate))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not queue MeshSessionTerminateMessage\n"));
-      GNUNET_free (message_mesh_terminate);
-      status_to_listen ();
-    }
-}
-
-/**
-* Function to reject a call
-*
-* @param tunnel the tunnel where to reject the incoming call
-* @param reason te reson why the call is rejected
-*/
-static void
-reject_call (struct GNUNET_MESH_Tunnel *tunnel, int reason)
-{
-  size_t msg_size;
-  msg_size = sizeof (struct MeshSessionRejectMessage);
-  struct MeshSessionRejectMessage *message_mesh_reject =
-    (struct MeshSessionRejectMessage *) GNUNET_malloc (msg_size);
-
-  if (NULL == message_mesh_reject)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not create MeshSessionRejectMessage\n"));
-      status_to_listen ();
-
-      return;
-    }
-
-  message_mesh_reject->header.size = htons (msg_size);
-  message_mesh_reject->header.type =
-    htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT);
-  message_mesh_reject->reason = htons (reason);
-
-  if (NULL ==
-      GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
-                                        MAX_TRANSMIT_DELAY, msg_size,
-                                        &transmit_mesh_message,
-                                        (void *) message_mesh_reject))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not queue MeshSessionRejectMessage\n"));
-      GNUNET_free (message_mesh_reject);
-      status_to_listen ();
-    }
-}
-
-/**
- * Check for timeout when calling a peer
- *
- * @param cls closure, NULL
- * @param tc the task context (can be NULL)
- */
-static void
-check_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Call timeout\n");
-
-  if (NULL ==
-      GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                          sizeof (struct
-                                                  ServerClientNoAnswerMessage),
-                                          MAX_TRANSMIT_DELAY,
-                                          &transmit_server_no_answer_message,
-                                          NULL))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not queue ServerClientNoAnswerMessage\n"));
-    }
-
-  terminate_call ();
-}
-
-/******************************************************************************/
-/***********************  SENDING FUNCTIONS CL -> SERVER    
*******************/
-/******************************************************************************/
-
-/**
- * Function called to send a session initiate message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the initiate message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_initiate_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientSessionInitiateMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientSessionInitiateMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientSessionInitiateMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE);
-  memcpy (&(msg->peer), (struct GNUNET_PeerIdentity *) cls,
-         sizeof (struct GNUNET_PeerIdentity));
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session accept message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the accept message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_accept_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientSessionAcceptMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientSessionAcceptMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientSessionAcceptMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT);
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session reject message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the reject message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_reject_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientSessionRejectMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientSessionRejectMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientSessionRejectMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT);
-
-  if (NULL == cls)
-    {
-      msg->reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NOT_AVAILABLE);
-    }
-  else
-    {
-      msg->reason = ((struct MeshSessionRejectMessage *) cls)->reason;
-    }
-
-  return msg_size;
-}
-
-/**
- * Function called to send a session terminate message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the terminate message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_terminate_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientSessionTerminateMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientSessionTerminateMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientSessionTerminateMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE);
-
-  return msg_size;
-}
-
-/**
- * Function called to send a missed call message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the missed call message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_missed_call_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientMissedCallMessage *msg;
-  msg = (struct ServerClientMissedCallMessage *) cls;
-
-  memcpy (buf, msg, size);
-  GNUNET_free (msg);
-
-  return size;
-}
-
-/**
- * Function called to send a service blocked message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the service blocked message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_service_blocked_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientServiceBlockedMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientServiceBlockedMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientServiceBlockedMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED);
-
-  return msg_size;
-}
-
-/**
- * Function called to send a peer not connected message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the peer not connected message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_peer_not_connected_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientPeerNotConnectedMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientPeerNotConnectedMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientPeerNotConnectedMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED);
-
-  return msg_size;
-}
-
-/**
- * Function called to send a peer no answer message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the peer no answer message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_no_answer_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientNoAnswerMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientNoAnswerMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientNoAnswerMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER);
-
-  return msg_size;
-}
-
-/**
- * Function called to send a error message to the client.
- * "buf" will be NULL and "size" zero if the socket was closed for writing in
- * the meantime.
- *
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the error message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_server_error_message (void *cls, size_t size, void *buf)
-{
-  struct ServerClientErrorMessage *msg;
-  size_t msg_size;
-
-  msg_size = sizeof (struct ServerClientErrorMessage);
-
-  GNUNET_assert (size >= msg_size);
-
-  msg = (struct ServerClientErrorMessage *) buf;
-  msg->header.size = htons (msg_size);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR);
-
-  return msg_size;
-}
-
-/******************************************************************************/
-/***********************  RECEIVE FUNCTIONS CL -> SERVER   
********************/
-/******************************************************************************/
-
-/**
- * Function to handle a session initiate message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
-*/
-static void
-handle_session_initiate_message (void *cls,
-                                struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
-{
-  static uint32_t port = 50002;
-  size_t msg_size;
-  struct ClientServerSessionInitiateMessage *msg =
-    (struct ClientServerSessionInitiateMessage *) message;
-  struct GNUNET_PeerIdentity *peer = &(msg->peer);
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  if (NULL != connection.client)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("There is already a peer in interaction\n"));
-      GNUNET_SERVER_notify_transmit_ready (client,
-                                          sizeof (struct
-                                                  
ServerClientServiceBlockedMessage),
-                                          MAX_TRANSMIT_DELAY,
-                                          
&transmit_server_service_blocked_message,
-                                          NULL);
-
-      return;
-    }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Creating tunnel to: %s\n"),
-             GNUNET_i2s_full (peer));
-  tunnel_reliable =
-    GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO, GNUNET_NO);
-  if (NULL == tunnel_reliable)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not create reliable tunnel\n"));
-      GNUNET_SERVER_notify_transmit_ready (client,
-                                          sizeof (struct
-                                                  
ServerClientPeerNotConnectedMessage),
-                                          MAX_TRANSMIT_DELAY,
-                                          
&transmit_server_peer_not_connected_message,
-                                          NULL);
-
-      return;
-    }
-
-  msg_size = sizeof (struct MeshSessionInitiateMessage);
-  struct MeshSessionInitiateMessage *message_mesh_initiate =
-    (struct MeshSessionInitiateMessage *) GNUNET_malloc (msg_size);
-
-  if (NULL == message_mesh_initiate)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not create MeshSessionInitiateMessage\n"));
-      GNUNET_MESH_tunnel_destroy (tunnel_reliable);
-      tunnel_reliable = NULL;
-      GNUNET_SERVER_notify_transmit_ready (client,
-                                          sizeof (struct
-                                                  ServerClientErrorMessage),
-                                          MAX_TRANSMIT_DELAY,
-                                          &transmit_server_error_message,
-                                          NULL);
-
-      return;
-    }
-
-  message_mesh_initiate->header.size = htons (msg_size);
-  message_mesh_initiate->header.type =
-    htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE);
-
-  if (NULL ==
-      GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
-                                        MAX_TRANSMIT_DELAY, msg_size,
-                                        &transmit_mesh_message,
-                                        (void *) message_mesh_initiate))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not queue MeshSessionInitiateMessage\n"));
-      GNUNET_MESH_tunnel_destroy (tunnel_reliable);
-      tunnel_reliable = NULL;
-      GNUNET_free (message_mesh_initiate);
-      GNUNET_SERVER_notify_transmit_ready (client,
-                                          sizeof (struct
-                                                  ServerClientErrorMessage),
-                                          MAX_TRANSMIT_DELAY,
-                                          &transmit_server_error_message,
-                                          NULL);
-
-      return;
-    }
-
-  connection.status = CALLER;
-  connection.client = client;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
-             connection.status);
-  memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
-
-  return;
-}
-
-/**
- * Function to handle a session accept message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
-*/
-static void
-handle_session_accept_message (void *cls, struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
-{
-  size_t msg_size;
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  if (connection.status != CALLEE)
-    {
-      // TODO send illegal command
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _
-                 ("handle_session_accept_message called when not allowed\n"));
-      return;
-    }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Accepting the call of: %s\n"),
-             GNUNET_i2s_full (&(connection.peer)));
-
-  msg_size = sizeof (struct MeshSessionAcceptMessage);
-  struct MeshSessionAcceptMessage *message_mesh_accept =
-    (struct MeshSessionAcceptMessage *) GNUNET_malloc (msg_size);
-
-  if (NULL == message_mesh_accept)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not create MeshSessionAcceptMessage\n"));
-      return;
-    }
-
-  message_mesh_accept->header.size = htons (msg_size);
-  message_mesh_accept->header.type =
-    htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT);
-
-  if (NULL ==
-      GNUNET_MESH_notify_transmit_ready (tunnel_reliable, 0,
-                                        MAX_TRANSMIT_DELAY, msg_size,
-                                        &transmit_mesh_message,
-                                        (void *) message_mesh_accept))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not queue MeshSessionAcceptMessage\n"));
-      GNUNET_free (message_mesh_accept);
-      return;
-    }
-
-  connection.status = CONNECTED;
-  connection.client = client;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
-             connection.status);
-
-  return;
-}
-
-/**
- * Function to handle a session reject message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
-*/
-static void
-handle_session_reject_message (void *cls, struct GNUNET_SERVER_Client *client,
-                              const struct GNUNET_MessageHeader *message)
-{
-  struct ClientServerSessionRejectMessage *message_received;
-
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  if (connection.status != CALLEE)
-    {
-      // TODO send illegal command
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _
-                 ("handle_session_reject_message called when not allowed\n"));
-      return;
-    }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rejecting the call of: %s\n"),
-             GNUNET_i2s_full (&(connection.peer)));
-  message_received = (struct ClientServerSessionRejectMessage *) message;
-  reject_call (tunnel_reliable, ntohs (message_received->reason));
-
-  return;
-}
-
-/**
- * Function to handle a session terminate message from the client
- *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
-*/
-static void
-handle_session_terminate_message (void *cls,
-                                 struct GNUNET_SERVER_Client *client,
-                                 const struct GNUNET_MessageHeader *message)
-{
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
-  if (connection.client == NULL || connection.status == CALLEE)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _
-                 ("handle_session_terminate_message called when not 
allowed\n"));
-      return;
-    }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Terminating the call with: %s\n"),
-             GNUNET_i2s_full (&(connection.peer)));
-  terminate_call ();
-}
-
-/******************************************************************************/
-/***********************       SENDING FUNCTIONS MESH       
*******************/
-/******************************************************************************/
-
-/**
-* Transmit a mesh message
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_mesh_message (void *cls, size_t size, void *buf)
-{
-  struct VoIPMeshMessageHeader *msg_header =
-    (struct VoIPMeshMessageHeader *) cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting message over mesh\n"));
-
-  memcpy (buf, cls, size);
-  // Check if this is correct
-
-
-  if ((GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE ==
-       ntohs (msg_header->header.type))
-      || (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT ==
-         ntohs (msg_header->header.type)))
-    {
-      status_to_listen ();
-    }
-  else if (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE ==
-          ntohs (msg_header->header.type))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting timeout task.\n"));
-      timeout_task =
-       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                     (GNUNET_TIME_UNIT_SECONDS, 30),
-                                     &check_timeout, NULL);
-    }
-
-  GNUNET_free (cls);
-
-  return size;
-}
-
-/**
-* Transmit a audo message over mesh
- * @param cls closure, NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_mesh_audio_message (void *cls, size_t size, void *buf)
-{
-  struct AudioMessage *message = (struct AudioMessage *) cls;
-
-  if (size < sizeof (struct AudioMessage) || NULL == buf)
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 "size %u, buf %p, data_sent %u, data_received %u\n",
-                 size, buf, data_sent, data_received);
-      return 0;
-    }
-
-  memcpy (buf, message, size);
-
-  data_sent++;
-  data_sent_size += size;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " Sent packet %d\n", data_sent);
-
-  audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
-
-  return size;
-}
-
-/**
- * Task to schedule a audio transmission.
- * 
- * @param cls Closure.
- * @param tc Task Context.
- */
-static void
-transmit_audio_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CONTAINER_SList_Iterator iterator;
-  struct AudioMessage *msg;
-  int ab_length = GNUNET_CONTAINER_slist_count (audio_buffer);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "We have %d packets.\n", ab_length);
-
-  if (NULL == cls)
-    {
-      if (0 == ab_length && CONNECTED == connection.status)
-       {
-         audio_task =
-           GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                         (GNUNET_TIME_UNIT_MILLISECONDS, 10),
-                                         &transmit_audio_task, NULL);
-         return;
-       }
-
-      iterator = GNUNET_CONTAINER_slist_begin (audio_buffer);
-      msg =
-       (struct AudioMessage *) GNUNET_CONTAINER_slist_get (&iterator, NULL);
-      GNUNET_CONTAINER_slist_erase (&iterator);
-      GNUNET_CONTAINER_slist_iter_destroy (&iterator);
-    }
-  else
-    {
-      msg = (struct AudioMessage *) cls;
-    }
-
-  if (NULL == tunnel_unreliable)
-    {
-      GNUNET_CONTAINER_slist_clear (audio_buffer);
-      return;
-    }
-
-  mth = GNUNET_MESH_notify_transmit_ready (tunnel_unreliable, GNUNET_NO,
-                                          MAX_TRANSMIT_DELAY,
-                                          sizeof (struct AudioMessage),
-                                          &transmit_mesh_audio_message,
-                                          (void *) msg);
-
-  if (NULL == mth)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 "Need to retransmit audio packet\n");
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "  in 1 ms\n");
-      audio_task =
-       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
-                                     &transmit_audio_task, (void *) msg);
-    }
-}
-
-/******************************************************************************/
-/***********************       RECEIVE FUNCTIONS MESH      
********************/
-/******************************************************************************/
-
-/**
-* Function to handle a initiation messaage incoming over mesh
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * 
- * @return GNUNET_OK
-*/
-int
-handle_mesh_initiate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                             void **tunnel_ctx,
-                             const struct GNUNET_MessageHeader *message)
-{
-  int reject_reason;
-  //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, 
GNUNET_MESH_OPTION_PEER))->peer;
-  const struct GNUNET_PeerIdentity *peer =
-    GNUNET_PEER_resolve2 (tunnel->peer);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Handling MeshSessionInitiateMessage from peer: %s\n"),
-             GNUNET_i2s_full (peer));
-  GNUNET_MESH_receive_done (tunnel);
-
-  if (LISTEN != connection.status
-      || 1 > GNUNET_CONTAINER_slist_count (clients))
-    {
-
-      if (CONNECTED == connection.status)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _
-                     ("Rejected call from %s because there is an active call"),
-                     GNUNET_i2s_full (peer));
-         reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_ACTIVE_CALL);
-
-         // Notifying client about missed call
-         size_t msg_size =
-           sizeof (struct ServerClientMissedCallMessage) +
-           sizeof (struct MissedCall);
-         struct ServerClientMissedCallMessage *message =
-           GNUNET_malloc (msg_size);
-
-         message->header.size = htons (msg_size);
-         message->header.type =
-           htons (GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
-         message->number = 1;
-
-         memcpy (&(message->missed_call->peer), peer,
-                 sizeof (struct GNUNET_PeerIdentity));
-         message->missed_call->time = GNUNET_TIME_absolute_get ();
-
-         if (NULL ==
-             GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                                  sizeof (struct
-                                                          
ServerClientMissedCallMessage),
-                                                  MAX_TRANSMIT_DELAY,
-                                                  
&transmit_server_missed_call_message,
-                                                  (void *) message))
-           {
-             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                         _
-                         ("Could not queue ServerClientMissedCallMessage\n"));
-             GNUNET_free (message);
-           }
-       }
-
-      if (1 > GNUNET_CONTAINER_slist_count (clients))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("Got a call from %s while no client connected.\n"),
-                     GNUNET_i2s_full (peer));
-         reject_reason = htons (GNUNET_CONVERSATION_REJECT_REASON_NO_CLIENT);
-         // Store missed calls
-         struct MissedCall call;
-         memcpy (&(call.peer), peer, sizeof (struct GNUNET_PeerIdentity));
-         call.time = GNUNET_TIME_absolute_get ();
-         GNUNET_CONTAINER_slist_add_end (missed_calls,
-                                         
GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                         &call, sizeof (struct MissedCall));
-
-       }
-
-      reject_call (tunnel, reject_reason);
-    }
-  else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiated call from: %s\n"),
-                 GNUNET_i2s_full (peer));
-      tunnel_reliable = tunnel;
-      connection.status = CALLEE;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _("Changed connection status to %d\n"), connection.status);
-      memcpy (&(connection.peer), peer, sizeof (struct GNUNET_PeerIdentity));
-
-      struct GNUNET_CONTAINER_SList_Iterator iterator =
-       GNUNET_CONTAINER_slist_begin (clients);
-      do
-       {
-         struct VoipClient *conversation_client =
-           (struct VoipClient *) GNUNET_CONTAINER_slist_get (&iterator,
-                                                             NULL);
-         struct GNUNET_SERVER_Client *client = conversation_client->client;
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client found: %p\n"),
-                     client);
-
-         if (NULL ==
-             GNUNET_SERVER_notify_transmit_ready (client,
-                                                  sizeof (struct
-                                                          
ServerClientSessionInitiateMessage),
-                                                  MAX_TRANSMIT_DELAY,
-                                                  
&transmit_server_initiate_message,
-                                                  (void *) peer))
-           {
-             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                         _
-                         ("Could not queue 
ServerClientSessionInitiateMessage\n"));
-           }
-
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client notified.\n"));
-       }
-      while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
-
-      GNUNET_CONTAINER_slist_iter_destroy (&iterator);
-
-    }
-
-  return GNUNET_OK;
-}
-
-/**
-* Function to handle an accept messaage incoming over mesh
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * 
- * @return GNUNET_OK
-*/
-int
-handle_mesh_accept_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                           void **tunnel_ctx,
-                           const struct GNUNET_MessageHeader *message)
-{
-  static uint32_t port = 50003;
-  //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, 
GNUNET_MESH_OPTION_PEER))->peer;
-  const struct GNUNET_PeerIdentity *peer =
-    GNUNET_PEER_resolve2 (tunnel->peer);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Handling MeshSessionAccpetMessage from peer: %s 
(connection.peer: %s)\n"),
-             GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
-  GNUNET_MESH_receive_done (tunnel);
-
-  if (0 ==
-      memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
-      && connection.status == CALLER)
-    {
-      tunnel_unreliable =
-       GNUNET_MESH_tunnel_create (mesh, NULL, peer, port, GNUNET_NO,
-                                  GNUNET_NO);
-      if (NULL == tunnel_unreliable)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _("Could not create unreliable tunnel\n"));
-
-         status_to_listen ();
-
-         GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                              sizeof (struct
-                                                      
ServerClientSessionRejectMessage),
-                                              MAX_TRANSMIT_DELAY,
-                                              &transmit_server_reject_message,
-                                              NULL);
-         return GNUNET_SYSERR;
-       }
-
-      if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
-       {
-         GNUNET_SCHEDULER_cancel (timeout_task);
-         timeout_task = GNUNET_SCHEDULER_NO_TASK;
-       }
-
-      connection.status = CONNECTED;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _("Changed connection status to %d\n"), connection.status);
-
-      if (NULL ==
-         GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                              sizeof (struct
-                                                      
ServerClientSessionAcceptMessage),
-                                              MAX_TRANSMIT_DELAY,
-                                              &transmit_server_accept_message,
-                                              (void *) message))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _
-                     ("Could not queue ServerClientSessionAcceptMessage\n"));
-         return GNUNET_SYSERR;
-       }
-
-      start_time = GNUNET_TIME_absolute_get ();
-      start_helpers ();
-      audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
-    }
-
-  return GNUNET_OK;
-}
-
-/**
-* Function to handle a reject messaage incoming over mesh
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * 
- * @return GNUNET_OK
-*/
-int
-handle_mesh_reject_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                           void **tunnel_ctx,
-                           const struct GNUNET_MessageHeader *message)
-{
-  //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, 
GNUNET_MESH_OPTION_PEER))->peer;
-  const struct GNUNET_PeerIdentity *peer =
-    GNUNET_PEER_resolve2 (tunnel->peer);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Handling MeshSessionRejectMessage from peer: %s 
(connection.peer: %s)\n"),
-             GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
-  GNUNET_MESH_receive_done (tunnel);
-
-  if (0 ==
-      memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
-      && connection.status == CALLER)
-    {
-      if (NULL ==
-         GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                              sizeof (struct
-                                                      
ServerClientSessionRejectMessage),
-                                              MAX_TRANSMIT_DELAY,
-                                              &transmit_server_reject_message,
-                                              (void *) message))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _
-                     ("Could not queue ServerClientSessionRejectMessage\n"));
-       }
-
-      status_to_listen ();
-
-      if (NULL != tunnel_reliable)
-       {
-         GNUNET_MESH_tunnel_destroy (tunnel_reliable);
-         tunnel_reliable = NULL;
-       }
-    }
-
-  return GNUNET_OK;
-}
-
-/**
-* Function to handle a terminate messaage incoming over mesh
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * 
- * @return GNUNET_OK
-*/
-int
-handle_mesh_terminate_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                              void **tunnel_ctx,
-                              const struct GNUNET_MessageHeader *message)
-{
-  //struct GNUNET_PeerIdentity *peer =  (GNUNET_MESH_tunnel_get_info(tunnel, 
GNUNET_MESH_OPTION_PEER))->peer;
-  const struct GNUNET_PeerIdentity *peer =
-    GNUNET_PEER_resolve2 (tunnel->peer);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _
-             ("Handling MeshSessionTerminateMessage from peer: %s 
(connection.peer: %s)\n"),
-             GNUNET_i2s_full (peer), GNUNET_i2s_full (&(connection.peer)));
-  GNUNET_MESH_receive_done (tunnel);
-
-  if (!memcmp (peer, &(connection.peer), sizeof (struct GNUNET_PeerIdentity))
-      && (connection.status == CONNECTED || connection.status == CALLEE))
-    {
-      status_to_listen ();
-
-      if (NULL != tunnel_unreliable)
-       {
-         GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
-         tunnel_unreliable = NULL;
-       }
-
-      if (NULL != tunnel_reliable)
-       {
-         GNUNET_MESH_tunnel_destroy (tunnel_reliable);
-         tunnel_reliable = NULL;
-       }
-    }
-
-  return GNUNET_OK;
-}
-
-/**
-* Function to handle a audio messaage incoming over mesh
- * @param cls closure, NULL
- * @param tunnel the tunnel over which the message arrived
- * @param tunnel_ctx the tunnel context, can be NULL
- * @param message the incoming message
- * 
- * @return GNUNET_OK
-*/
-int
-handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-                          void **tunnel_ctx,
-                          const struct GNUNET_MessageHeader *message)
-{
-  const struct AudioMessage *audio;
-  audio = (const struct AudioMessage *) message;
-
-  GNUNET_MESH_receive_done (tunnel);
-  if (CONNECTED != connection.status)
-    return GNUNET_OK;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             "[RECV] %dbytes\n", 
-             ntohs (audio->header.size));
-  if (NULL == playback_helper)
-    return GNUNET_OK;
-  (void) GNUNET_HELPER_send (playback_helper,
-                            message, GNUNET_YES, NULL, NULL);
-  return GNUNET_OK;
-}
-
-/******************************************************************************/
-/***********************                     HELPER                
*******************/
-/******************************************************************************/
-
-/**
-* Function to process the audio from the record helper
- * @param cls closure, NULL
- * @param client NULL
- * @param msg the message from the helper
- * 
- * @return GNUNET_OK
-*/
-static int
-process_record_messages (void *cls GNUNET_UNUSED, void *client,
-                        const struct GNUNET_MessageHeader *msg)
-{
-  const struct AudioMessage *message = (const struct AudioMessage *) msg;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             " [REC] %dbyte\n", 
-             ntohs (message->header.size));
-  GNUNET_CONTAINER_slist_add_end (audio_buffer,
-                                 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                 message, ntohs (message->header.size));
-
-  return GNUNET_OK;
-}
-
-/**
-* Function to to start the playback helper
- * 
- * @return 0 ok, 1 on error
-*/
-int
-start_playback_helper (void)
-{
-  static char *playback_helper_argv[1];
-  int success = 1;
-
-  playback_helper_argv[0] = "gnunet-helper-audio-playback";
-  playback_helper = GNUNET_HELPER_start (GNUNET_NO,
-                                        "gnunet-helper-audio-playback",
-                                        playback_helper_argv,
-                                        NULL, NULL, NULL);
-
-  if (NULL == playback_helper)
-    {
-      success = 0;
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not start playback audio helper.\n"));
-    }
-
-  return success;
-}
-
-/**
-* Function to to start the record helper
- * 
- * @return 0 ok, 1 on error
-*/
-int
-start_record_helper (void)
-{
-  static char *record_helper_argv[1];
-  int success = 1;
-
-  record_helper_argv[0] = "gnunet-helper-audio-record";
-  record_helper = GNUNET_HELPER_start (GNUNET_NO,
-                                      "gnunet-helper-audio-record",
-                                      record_helper_argv,
-                                      &process_record_messages, NULL, NULL);
-
-  if (NULL == record_helper)
-    {
-      success = 0;
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not start record audio helper\n"));
-    }
-
-  return success;
-}
-
-
-/**
-* Function to to start both helpers
- * 
- * @return 0 ok, 1 on error
-*/
-int
-start_helpers (void)
-{
-
-  if (0 == start_playback_helper () || 0 == start_record_helper ())
-    {
-      stop_helpers ();
-      return 0;
-    }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Started helpers\n"));
-
-  return 1;
-}
-
-/**
-* Function to to stop the playback helper
-*/
-void
-stop_playback_helper (void)
-{
-  if (NULL != playback_helper)
-    {
-      GNUNET_HELPER_stop (playback_helper, GNUNET_NO);
-      playback_helper = NULL;
-
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped playback helper\n"));
-    }
-}
-
-/**
-* Function to to stop the record helper
-*/
-void
-stop_record_helper (void)
-{
-  if (NULL != record_helper)
-    {
-      GNUNET_HELPER_stop (record_helper, GNUNET_NO);
-      record_helper = NULL;
-
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopped record helper\n"));
-    }
-}
-
-/**
-* Function to stop both audio helpers
-*/
-void
-stop_helpers (void)
-{
-  stop_playback_helper ();
-  stop_record_helper ();
-}
-
-/******************************************************************************/
-/***********************                TUNNEL HANDLING            
*******************/
-/******************************************************************************/
-
-/**
- * Method called whenever another peer has added us to a tunnel
- * the other peer initiated.
- *
- * @param cls closure
- * @param tunnel new handle to the tunnel
- * @param initiator peer that started the tunnel
- * @param port port
- * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
- */
-static void *
-inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
-               const struct GNUNET_PeerIdentity *initiator, uint32_t port)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Received incoming tunnel on port %d\n"), port);
-  if (50003 == port)
-    {
-      tunnel_unreliable = tunnel;
-
-      start_time = GNUNET_TIME_absolute_get ();
-
-      start_helpers ();
-      audio_task = GNUNET_SCHEDULER_add_now (&transmit_audio_task, NULL);
-    }
-
-  return NULL;
-}
-
-
-/**
- * Function called whenever an inbound tunnel is destroyed.  Should clean up
- * any associated state.
- *
- * @param cls closure (set from GNUNET_MESH_connect)
- * @param tunnel connection to the other end (henceforth invalid)
- * @param tunnel_ctx place where local state associated
- *                   with the tunnel is stored
- */
-static void
-inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel,
-            void *tunnel_ctx)
-{
-  if (tunnel == tunnel_unreliable)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: audio\n");
-
-      stop_helpers ();
-      tunnel_unreliable = NULL;
-    }
-
-  if (tunnel == tunnel_reliable)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel closed: control\n");
-
-      if (LISTEN != connection.status && NULL != connection.client)
-       {
-         if (NULL ==
-             GNUNET_SERVER_notify_transmit_ready (connection.client,
-                                                  sizeof (struct
-                                                          
ServerClientSessionTerminateMessage),
-                                                  MAX_TRANSMIT_DELAY,
-                                                  
&transmit_server_terminate_message,
-                                                  NULL))
-           {
-             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                         _
-                         ("Could not queue 
ServerClientSessionTerminateMessage\n"));
-           }
-       }
-
-      status_to_listen ();
-    }
-}
-
-/******************************************************************************/
-/***********************          CLIENT HANDLING           
*******************/
-/******************************************************************************/
-
-/**
- * A client connected.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- */
-
-static void
-handle_client_connect (void *cls, struct GNUNET_SERVER_Client *cl)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client connected\n");
-  struct ServerClientMissedCallMessage *message;
-  size_t msg_size;
-  struct VoipClient c;
-  c.client = cl;
-
-  GNUNET_CONTAINER_slist_add_end (clients,
-                                 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
-                                 &c, sizeof (struct VoipClient));
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Client added: %p\n"), cl);
-
-  if (0 < GNUNET_CONTAINER_slist_count (missed_calls))
-    {
-      int i = 0;
-      msg_size =
-       sizeof (struct ServerClientMissedCallMessage) +
-       GNUNET_CONTAINER_slist_count (missed_calls) *
-       sizeof (struct MissedCall);
-      message =
-       (struct ServerClientMissedCallMessage *) GNUNET_malloc (msg_size);
-
-      message->header.size = htons (msg_size);
-      message->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL);
-      message->number = GNUNET_CONTAINER_slist_count (missed_calls);
-
-      struct GNUNET_CONTAINER_SList_Iterator iterator =
-       GNUNET_CONTAINER_slist_begin (missed_calls);
-      do
-       {
-         memcpy (&(message->missed_call[i]),
-                 GNUNET_CONTAINER_slist_get (&iterator, NULL),
-                 sizeof (struct MissedCall));
-         i++;
-       }
-      while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
-
-      GNUNET_CONTAINER_slist_iter_destroy (&iterator);
-      GNUNET_CONTAINER_slist_clear (missed_calls);
-
-
-      if (NULL ==
-         GNUNET_SERVER_notify_transmit_ready (cl, msg_size,
-                                              MAX_TRANSMIT_DELAY,
-                                              
&transmit_server_missed_call_message,
-                                              (void *) message))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _("Could not queue ServerClientMissedCallMessage\n"));
-         GNUNET_free (message);
-       }
-    }
-
-  return;
-}
-
-/**
- * A client disconnected.  Remove all of its data structure entries.
- *
- * @param cls closure, NULL
- * @param client identification of the client
- */
-static void
-handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *cl)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client disconnected\n");
-
-  if (connection.client == cl)
-    {
-      if (CONNECTED == connection.status)
-       {
-         terminate_call ();
-       }
-      else
-       {
-         status_to_listen ();
-       }
-    }
-
-  struct GNUNET_CONTAINER_SList_Iterator iterator =
-    GNUNET_CONTAINER_slist_begin (clients);
-  do
-    {
-      if (((struct VoipClient *)
-          GNUNET_CONTAINER_slist_get (&iterator, NULL))->client == cl)
-       {
-         GNUNET_CONTAINER_slist_erase (&iterator);
-       }
-    }
-  while (GNUNET_OK == GNUNET_CONTAINER_slist_next (&iterator));
-
-  GNUNET_CONTAINER_slist_iter_destroy (&iterator);
-
-  return;
-}
-
-/******************************************************************************/
-/***********************                     SERVICE               
*******************/
-/******************************************************************************/
-
-/**
- * Shutdown nicely
- * 
- * @param cls closure, NULL
- * @param tc the task context
- */
-static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown\n");
-
-  stop_helpers ();
-
-  if (NULL != tunnel_reliable)
-    {
-      GNUNET_MESH_tunnel_destroy (tunnel_reliable);
-    }
-
-  if (NULL != tunnel_unreliable)
-    {
-      GNUNET_MESH_tunnel_destroy (tunnel_unreliable);
-    }
-
-  if (NULL != mesh)
-    {
-      GNUNET_MESH_disconnect (mesh);
-    }
-
-  if (NULL != nc)
-    {
-      GNUNET_SERVER_notification_context_destroy (nc);
-      nc = NULL;
-    }
-
-  GNUNET_CONTAINER_slist_destroy (audio_buffer);
-  GNUNET_CONTAINER_slist_destroy (clients);
-  GNUNET_CONTAINER_slist_destroy (missed_calls);
-  GNUNET_CONTAINER_slist_destroy (peers_to_notify);
-}
-
-
-/**
- * Handler array for traffic received
- */
-static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
-  {&handle_mesh_initiate_message,
-   GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_INITIATE,
-   sizeof (struct MeshSessionInitiateMessage)},
-  {&handle_mesh_accept_message, 
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_ACCEPT,
-   sizeof (struct MeshSessionAcceptMessage)},
-  {&handle_mesh_reject_message, 
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_REJECT,
-   sizeof (struct MeshSessionRejectMessage)},
-  {&handle_mesh_terminate_message,
-   GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_SESSION_TERMINATE,
-   sizeof (struct MeshSessionTerminateMessage)},
-  {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO,
-   sizeof (struct AudioMessage)},
-  {NULL, 0, 0}
-};
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param server server handle
- * @param c configuration
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
-{
-
-  static uint32_t ports[] = { 50002, 50003, 0 };
-  cfg = c;
-
-  mesh = GNUNET_MESH_connect (cfg,
-                             NULL,
-                             &inbound_tunnel,
-                             &inbound_end, mesh_handlers, ports);
-
-  if (NULL == mesh)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n");
-      return;
-    }
-  else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to mesh\n");
-    }
-
-  static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
-    {&handle_session_initiate_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE,
-     sizeof (struct ClientServerSessionInitiateMessage)},
-    {&handle_session_accept_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT,
-     sizeof (struct ClientServerSessionAcceptMessage)},
-    {&handle_session_reject_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT,
-     sizeof (struct ClientServerSessionRejectMessage)},
-    {&handle_session_terminate_message, NULL,
-     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE,
-     sizeof (struct ClientServerSessionTerminateMessage)},
-    {NULL, NULL, 0, 0}
-  };
-
-  connection.status = LISTEN;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Changed connection status to %d\n"),
-             connection.status);
-
-  nc = GNUNET_SERVER_notification_context_create (server, 16);
-
-  GNUNET_SERVER_add_handlers (server, server_handlers);
-  GNUNET_SERVER_connect_notify (server, &handle_client_connect, NULL);
-  GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown,
-                               NULL);
-
-  clients = GNUNET_CONTAINER_slist_create ();
-
-  // Missed calls
-  missed_calls = GNUNET_CONTAINER_slist_create ();
-  peers_to_notify = GNUNET_CONTAINER_slist_create ();
-  audio_buffer = GNUNET_CONTAINER_slist_create ();
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Voip service running\n"));
-}
-
-/**
- * The main function for the conversation service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  return (GNUNET_OK ==
-         GNUNET_SERVICE_run (argc, argv, "conversation", 
GNUNET_SERVICE_OPTION_NONE,
-                             &run, NULL)) ? 0 : 1;
-}
-
-/* end of gnunet-service-conversation.c */

Copied: gnunet/src/conversation/gnunet-service-conversation.c (from rev 29856, 
gnunet/src/conversation/gnunet-service-conversation-new.c)
===================================================================
--- gnunet/src/conversation/gnunet-service-conversation.c                       
        (rev 0)
+++ gnunet/src/conversation/gnunet-service-conversation.c       2013-10-05 
13:10:53 UTC (rev 29861)
@@ -0,0 +1,1227 @@
+/*
+  This file is part of GNUnet.
+  (C) 2013 Christian Grothoff (and other contributing authors)
+  
+  GNUnet is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+  
+  GNUnet is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with GNUnet; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+  Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file conversation/gnunet-service-conversation.c
+ * @brief conversation service implementation
+ * @author Simon Dieterle
+ * @author Andreas Fuchs
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_applications.h"
+#include "gnunet_constants.h"
+#include "gnunet_signatures.h"
+#include "gnunet_mesh_service.h"
+#include "gnunet_conversation_service.h"
+#include "conversation.h"
+
+
+/**
+ * How long is our signature on a call valid?  Needs to be long enough for 
time zone
+ * differences and network latency to not matter.  No strong need for it to be 
short,
+ * but we simply like all signatures to eventually expire.
+ */
+#define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
+
+
+/**
+ * The possible connection status
+ */
+enum LineStatus
+{
+  /**
+   * We are waiting for incoming calls.
+   */
+  LS_CALLEE_LISTEN,
+
+  /**
+   * Our phone is ringing, waiting for the client to pick up.
+   */
+  LS_CALLEE_RINGING,
+
+  /**
+   * We are talking!
+   */
+  LS_CALLEE_CONNECTED,
+
+  /**
+   * We're in shutdown, sending hangup messages before cleaning up.
+   */
+  LS_CALLEE_SHUTDOWN,
+
+  /**
+   * We are waiting for the phone to be picked up.
+   */
+  LS_CALLER_CALLING,
+
+  /**
+   * We are talking!
+   */
+  LS_CALLER_CONNECTED,
+
+  /**
+   * We're in shutdown, sending hangup messages before cleaning up.
+   */
+  LS_CALLER_SHUTDOWN
+};
+
+
+/**
+ * A line connects a local client with a mesh tunnel (or, if it is an
+ * open line, is waiting for a mesh tunnel).
+ */
+struct Line
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct Line *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct Line *prev;
+
+  /**
+   * Handle for the reliable tunnel (contol data)
+   */
+  struct GNUNET_MESH_Tunnel *tunnel_reliable;
+  
+  /**
+   * Handle for unreliable tunnel (audio data)
+   */
+  struct GNUNET_MESH_Tunnel *tunnel_unreliable;
+
+  /**
+   * Transmit handle for pending audio messages
+   */
+  struct GNUNET_MESH_TransmitHandle *unreliable_mth;
+
+  /**
+   * Message queue for control messages
+   */
+  struct GNUNET_MQ_Handle *reliable_mq;
+
+  /**
+   * Handle to the line client.
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Target of the line, if we are the caller.
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * Temporary buffer for audio data.
+   */
+  void *audio_data;
+
+  /**
+   * Number of bytes in @e audio_data.
+   */
+  size_t audio_size;
+
+  /**
+   * Our line number.
+   */
+  uint32_t local_line;
+
+  /**
+   * Remote line number.
+   */
+  uint32_t remote_line;
+
+  /**
+   * Current status of this line.
+   */ 
+  enum LineStatus status;
+
+};
+
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Notification context containing all connected clients.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+/**
+ * Handle for mesh
+ */
+static struct GNUNET_MESH_Handle *mesh;
+
+/**
+ * Identity of this peer.
+ */
+static struct GNUNET_PeerIdentity my_identity;
+
+/**
+ * Head of DLL of active lines.
+ */
+static struct Line *lines_head;
+
+/**
+ * Tail of DLL of active lines.
+ */
+static struct Line *lines_tail;
+
+/**
+ * Counter for generating local line numbers.
+ * FIXME: randomize generation in the future
+ * to eliminate information leakage.
+ */
+static uint32_t local_line_cnt;
+
+
+/**
+ * Function to register a phone.
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_register_message (void *cls,
+                                struct GNUNET_SERVER_Client *client,
+                                const struct GNUNET_MessageHeader *message)
+{
+  const struct ClientPhoneRegisterMessage *msg;
+  struct Line *line;
+
+  msg = (struct ClientPhoneRegisterMessage *) message;
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL != line)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  line = GNUNET_new (struct Line);
+  line->client = client;
+  GNUNET_SERVER_notification_context_add (nc, client);
+  GNUNET_CONTAINER_DLL_insert (lines_head,
+                               lines_tail,
+                               line);
+  line->local_line = ntohl (msg->line);
+  GNUNET_SERVER_client_set_user_context (client, line);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Function to handle a pickup request message from the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_pickup_message (void *cls,
+                              struct GNUNET_SERVER_Client *client,
+                              const struct GNUNET_MessageHeader *message)
+{
+  const struct ClientPhonePickupMessage *msg;
+  struct GNUNET_MQ_Envelope *e;
+  struct MeshPhonePickupMessage *mppm;
+  const char *meta;
+  struct Line *line;
+  size_t len;
+
+  msg = (struct ClientPhonePickupMessage *) message;
+  meta = (const char *) &msg[1];
+  len = ntohs (msg->header.size) - sizeof (struct ClientPhonePickupMessage);
+  if ( (0 == len) ||
+       ('\0' != meta[len - 1]) )
+  {
+    meta = NULL;
+    len = 0;
+  }
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL == line)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring client's PICKUP message, caller has HUNG UP 
already\n");
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    break;
+  case LS_CALLEE_RINGING:
+    line->status = LS_CALLEE_CONNECTED;
+    break;
+  case LS_CALLEE_CONNECTED:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  case LS_CALLEE_SHUTDOWN:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    break;
+  case LS_CALLER_CALLING:
+  case LS_CALLER_CONNECTED:
+  case LS_CALLER_SHUTDOWN:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  line->status = LS_CALLEE_CONNECTED;
+  e = GNUNET_MQ_msg_extra (mppm,
+                           len,
+                           
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP);
+  memcpy (&mppm[1], meta, len);
+  GNUNET_MQ_send (line->reliable_mq, e);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Destroy the mesh tunnels of a line.
+ *
+ * @param line line to shutdown tunnels of
+ */
+static void
+destroy_line_mesh_tunnels (struct Line *line)
+{
+  if (NULL != line->reliable_mq)
+  {
+    GNUNET_MQ_destroy (line->reliable_mq);
+    line->reliable_mq = NULL;
+  }
+  if (NULL != line->unreliable_mth)
+  {
+    GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
+    line->unreliable_mth = NULL;
+  }
+  if (NULL != line->tunnel_unreliable)
+  {
+    GNUNET_MESH_tunnel_destroy (line->tunnel_unreliable);
+    line->tunnel_unreliable = NULL;
+  }
+  if (NULL != line->tunnel_reliable)
+  {
+    GNUNET_MESH_tunnel_destroy (line->tunnel_reliable);
+    line->tunnel_reliable = NULL;
+  }
+}
+
+
+/**
+ * We are done signalling shutdown to the other peer.  Close down
+ * (or reset) the line.
+ *
+ * @param cls the `struct Line` to reset/terminate
+ */
+static void
+mq_done_finish_caller_shutdown (void *cls)
+{
+  struct Line *line = cls;
+
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    break;
+  case LS_CALLEE_RINGING:
+    GNUNET_break (0);
+    break;
+  case LS_CALLEE_CONNECTED:
+    GNUNET_break (0);
+    break;
+  case LS_CALLEE_SHUTDOWN:
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    return;
+  case LS_CALLER_CALLING:
+    line->status = LS_CALLER_SHUTDOWN;
+    break;
+  case LS_CALLER_CONNECTED:
+    line->status = LS_CALLER_SHUTDOWN;
+    break;
+  case LS_CALLER_SHUTDOWN:
+    destroy_line_mesh_tunnels (line);
+    GNUNET_CONTAINER_DLL_remove (lines_head,
+                                 lines_tail,
+                                 line);
+    GNUNET_free_non_null (line->audio_data);
+    GNUNET_free (line);
+    break;
+  }  
+}
+
+
+/**
+ * Function to handle a hangup request message from the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_hangup_message (void *cls,
+                              struct GNUNET_SERVER_Client *client,
+                              const struct GNUNET_MessageHeader *message)
+{
+  const struct ClientPhoneHangupMessage *msg;
+  struct GNUNET_MQ_Envelope *e;
+  struct MeshPhoneHangupMessage *mhum;
+  const char *meta;
+  struct Line *line;
+  size_t len;
+
+  msg = (struct ClientPhoneHangupMessage *) message;
+  meta = (const char *) &msg[1];
+  len = ntohs (msg->header.size) - sizeof (struct ClientPhoneHangupMessage);
+  if ( (0 == len) ||
+       ('\0' != meta[len - 1]) )
+  {
+    meta = NULL;
+    len = 0;
+  }
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL == line)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  case LS_CALLEE_RINGING:
+    line->status = LS_CALLEE_SHUTDOWN;
+    break;
+  case LS_CALLEE_CONNECTED:
+    line->status = LS_CALLEE_SHUTDOWN;
+    break;
+  case LS_CALLEE_SHUTDOWN:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  case LS_CALLER_CALLING:
+    line->status = LS_CALLER_SHUTDOWN;
+    break;
+  case LS_CALLER_CONNECTED:
+    line->status = LS_CALLER_SHUTDOWN;
+    break;
+  case LS_CALLER_SHUTDOWN:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+  e = GNUNET_MQ_msg_extra (mhum,
+                           len,
+                           
GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP);
+  memcpy (&mhum[1], meta, len);
+  GNUNET_MQ_notify_sent (e,
+                         &mq_done_finish_caller_shutdown,
+                         line);
+  GNUNET_MQ_send (line->reliable_mq, e);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Function to handle call request the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_call_message (void *cls,
+                            struct GNUNET_SERVER_Client *client,
+                            const struct GNUNET_MessageHeader *message)
+{
+  const struct ClientCallMessage *msg;
+  struct Line *line;
+  struct GNUNET_MQ_Envelope *e;
+  struct MeshPhoneRingMessage *ring;
+
+  msg = (struct ClientCallMessage *) message;
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL != line)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  line = GNUNET_new (struct Line);
+  line->target = msg->target;
+  GNUNET_CONTAINER_DLL_insert (lines_head,
+                               lines_tail,
+                               line);
+  line->remote_line = ntohl (msg->line);
+  line->status = LS_CALLER_CALLING;
+  line->tunnel_reliable = GNUNET_MESH_tunnel_create (mesh,
+                                                     line,
+                                                     &msg->target,
+                                                     
GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
+                                                     GNUNET_NO,
+                                                     GNUNET_YES);
+  line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
+  line->local_line = local_line_cnt++;
+  e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING);
+  ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
+  ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
+                              sizeof (struct GNUNET_TIME_AbsoluteNBO) +
+                              sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) +
+                              sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
+  GNUNET_CRYPTO_ecc_key_get_public_for_signature (&msg->caller_id,
+                                                  &ring->caller_id);
+  ring->remote_line = msg->line;
+  ring->source_line = line->local_line;
+  ring->target = msg->target;
+  ring->source = my_identity;
+  ring->expiration_time = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
+  GNUNET_CRYPTO_ecc_sign (&msg->caller_id,
+                          &ring->purpose,
+                          &ring->signature);
+  GNUNET_MQ_send (line->reliable_mq, e);
+  GNUNET_SERVER_client_set_user_context (client, line);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Transmit audio data via unreliable mesh channel.
+ *
+ * @param cls the `struct Line` we are transmitting for
+ * @param size number of bytes available in @a buf
+ * @param buf where to copy the data
+ * @return number of bytes copied to @buf
+ */
+static size_t
+transmit_line_audio (void *cls,
+                     size_t size,
+                     void *buf)
+{
+  struct Line *line = cls;
+  struct MeshAudioMessage *mam = buf;
+  
+  line->unreliable_mth = NULL;
+  if ( (NULL == buf) ||
+       (size < sizeof (struct MeshAudioMessage) + line->audio_size) )
+    {
+    /* eh, other error handling? */
+    return 0;
+  }
+  mam->header.size = htons (sizeof (struct MeshAudioMessage) + 
line->audio_size);
+  mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO);
+  mam->remote_line = htonl (line->remote_line);
+  memcpy (&mam[1], line->audio_data, line->audio_size);
+  GNUNET_free (line->audio_data);
+  line->audio_data = NULL;
+  return sizeof (struct MeshAudioMessage) + line->audio_size;  
+}
+
+
+/**
+ * Function to handle audio data from the client
+ *
+ * @param cls closure, NULL
+ * @param client the client from which the message is
+ * @param message the message from the client
+ */
+static void
+handle_client_audio_message (void *cls,
+                             struct GNUNET_SERVER_Client *client,
+                             const struct GNUNET_MessageHeader *message)
+{
+  const struct ClientAudioMessage *msg;
+  struct Line *line;
+  size_t size;
+
+  size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
+  msg = (struct ClientAudioMessage *) message;
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL == line)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+  case LS_CALLEE_RINGING:
+  case LS_CALLER_CALLING:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  case LS_CALLEE_CONNECTED:
+  case LS_CALLER_CONNECTED:
+    /* common case, handled below */
+    break;
+  case LS_CALLEE_SHUTDOWN:
+  case LS_CALLER_SHUTDOWN:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Mesh audio channel in shutdown; audio data dropped\n");
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+  if (NULL == line->tunnel_unreliable)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Mesh audio channel not ready; audio data dropped\n"));
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);    
+    return;
+  }
+  if (NULL != line->unreliable_mth)
+  {
+    /* NOTE: we may want to not do this and instead combine the data */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Dropping previous audio data segment with %u bytes\n",
+                line->audio_size);
+    GNUNET_MESH_notify_transmit_ready_cancel (line->unreliable_mth);
+    GNUNET_free (line->audio_data);
+  }
+  line->audio_size = size;
+  line->audio_data = GNUNET_malloc (line->audio_size);
+  memcpy (line->audio_data,
+          &msg[1],
+          size);
+  line->unreliable_mth = GNUNET_MESH_notify_transmit_ready 
(line->tunnel_unreliable,
+                                                            GNUNET_NO,
+                                                            
GNUNET_TIME_UNIT_FOREVER_REL,
+                                                            sizeof (struct 
MeshAudioMessage) 
+                                                            + line->audio_size,
+                                                            
&transmit_line_audio,
+                                                            line);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * We are done signalling shutdown to the other peer.  
+ * Destroy the tunnel.
+ *
+ * @param cls the `struct GNUNET_MESH_tunnel` to destroy
+ */
+static void
+mq_done_destroy_tunnel (void *cls)
+{
+  struct GNUNET_MESH_Tunnel *tunnel = cls;
+  
+  GNUNET_MESH_tunnel_destroy (tunnel);
+}
+
+
+/**
+ * Function to handle a ring message incoming over mesh
+ *
+ * @param cls closure, NULL
+ * @param tunnel the tunnel over which the message arrived
+ * @param tunnel_ctx the tunnel context, can be NULL
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_mesh_ring_message (void *cls,
+                          struct GNUNET_MESH_Tunnel *tunnel,
+                          void **tunnel_ctx,
+                          const struct GNUNET_MessageHeader *message)
+{
+  const struct MeshPhoneRingMessage *msg;
+  struct Line *line;
+  struct GNUNET_MQ_Envelope *e;
+  struct MeshPhoneBusyMessage *busy;
+  struct ClientPhoneRingMessage cring;
+  
+  msg = (const struct MeshPhoneRingMessage *) message;
+  if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
+                                    sizeof (struct GNUNET_TIME_AbsoluteNBO) +
+                                    sizeof (struct 
GNUNET_CRYPTO_EccSignaturePurpose) +
+                                    sizeof (struct 
GNUNET_CRYPTO_EccPublicSignKey))) ||
+       (GNUNET_OK !=
+        GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
+                                  &msg->purpose,
+                                  &msg->signature,
+                                  &msg->caller_id)) )
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  for (line = lines_head; NULL != line; line = line->next)  
+    if ( (line->local_line == ntohl (msg->remote_line)) &&
+         (LS_CALLEE_LISTEN == line->status) )
+      break;
+  if (NULL == line) 
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("No available phone for incoming call on line %u, sending 
BUSY signal\n"),
+                ntohl (msg->remote_line));
+    e = GNUNET_MQ_msg (busy, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY);
+    GNUNET_MQ_notify_sent (e,
+                           &mq_done_destroy_tunnel,
+                           tunnel);
+    GNUNET_MQ_send (line->reliable_mq, e);
+    GNUNET_MESH_receive_done (tunnel); /* needed? */
+    return GNUNET_OK;
+  }
+  line->status = LS_CALLEE_RINGING;
+  line->remote_line = ntohl (msg->source_line);
+  line->tunnel_reliable = tunnel;
+  line->reliable_mq = GNUNET_MESH_mq_create (line->tunnel_reliable);
+  *tunnel_ctx = line;
+  cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
+  cring.header.size = htons (sizeof (cring));
+  cring.reserved = htonl (0);
+  cring.caller_id = msg->caller_id;
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              line->client,
+                                              &cring.header,
+                                              GNUNET_NO);
+  GNUNET_MESH_receive_done (tunnel);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function to handle a hangup message incoming over mesh
+ *
+ * @param cls closure, NULL
+ * @param tunnel the tunnel over which the message arrived
+ * @param tunnel_ctx the tunnel context, can be NULL
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_mesh_hangup_message (void *cls,
+                            struct GNUNET_MESH_Tunnel *tunnel,
+                            void **tunnel_ctx,
+                            const struct GNUNET_MessageHeader *message)
+{
+  struct Line *line = *tunnel_ctx;
+  const struct MeshPhoneHangupMessage *msg;
+  const char *reason;
+  size_t len = ntohs (message->size) - sizeof (struct MeshPhoneHangupMessage);
+  char buf[len + sizeof (struct ClientPhoneHangupMessage)];
+  struct ClientPhoneHangupMessage *hup;
+  
+  msg = (const struct MeshPhoneHangupMessage *) message;
+  len = ntohs (msg->header.size) - sizeof (struct MeshPhoneHangupMessage);
+  reason = (const char *) &msg[1];
+  if ( (0 == len) ||
+       ('\0' != reason[len - 1]) )
+  {
+    reason = NULL;
+    len = 0;
+  }
+  if (NULL == line)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "HANGUP message received for non-existing line, dropping 
tunnel.\n");
+    return GNUNET_SYSERR;
+  }
+  *tunnel_ctx = NULL;
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case LS_CALLEE_RINGING:
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    break;
+  case LS_CALLEE_CONNECTED:
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    break;
+  case LS_CALLEE_SHUTDOWN:
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    return GNUNET_OK;
+  case LS_CALLER_CALLING:
+    line->status = LS_CALLER_SHUTDOWN;
+    mq_done_finish_caller_shutdown (line);
+    break;
+  case LS_CALLER_CONNECTED:
+    line->status = LS_CALLER_SHUTDOWN;
+    mq_done_finish_caller_shutdown (line);
+    break;
+  case LS_CALLER_SHUTDOWN:
+    mq_done_finish_caller_shutdown (line);
+    return GNUNET_OK;
+  }
+  hup = (struct ClientPhoneHangupMessage *) buf;
+  hup->header.size = sizeof (buf);
+  hup->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
+  memcpy (&hup[1], reason, len);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              line->client,
+                                              &hup->header,
+                                              GNUNET_NO);
+  GNUNET_MESH_receive_done (tunnel);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function to handle a pickup message incoming over mesh
+ *
+ * @param cls closure, NULL
+ * @param tunnel the tunnel over which the message arrived
+ * @param tunnel_ctx the tunnel context, can be NULL
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_mesh_pickup_message (void *cls,
+                            struct GNUNET_MESH_Tunnel *tunnel,
+                            void **tunnel_ctx,
+                            const struct GNUNET_MessageHeader *message)
+{
+  const struct MeshPhonePickupMessage *msg;
+  struct Line *line = *tunnel_ctx;
+  const char *metadata;
+  size_t len = ntohs (message->size) - sizeof (struct MeshPhonePickupMessage);
+  char buf[len + sizeof (struct ClientPhonePickupMessage)];
+  struct ClientPhonePickupMessage *pick;
+  
+  msg = (const struct MeshPhonePickupMessage *) message;
+  len = ntohs (msg->header.size) - sizeof (struct MeshPhonePickupMessage);
+  metadata = (const char *) &msg[1];
+  if ( (0 == len) ||
+       ('\0' != metadata[len - 1]) )
+  {
+    metadata = NULL;
+    len = 0;
+  }
+  if (NULL == line)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "PICKUP message received for non-existing line, dropping 
tunnel.\n");
+    return GNUNET_SYSERR;
+  }
+  GNUNET_MESH_receive_done (tunnel);
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case LS_CALLEE_RINGING:
+  case LS_CALLEE_CONNECTED:
+    GNUNET_break_op (0);
+    destroy_line_mesh_tunnels (line);
+    line->status = LS_CALLEE_LISTEN;
+    return GNUNET_SYSERR;
+  case LS_CALLEE_SHUTDOWN:
+    GNUNET_break_op (0);
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    break;
+  case LS_CALLER_CALLING:
+    line->status = LS_CALLER_CONNECTED;
+    break;
+  case LS_CALLER_CONNECTED:
+    GNUNET_break_op (0);
+    return GNUNET_OK;
+  case LS_CALLER_SHUTDOWN:
+    GNUNET_break_op (0);
+    mq_done_finish_caller_shutdown (line);
+    return GNUNET_SYSERR;
+  }
+  pick = (struct ClientPhonePickupMessage *) buf;
+  pick->header.size = sizeof (buf);
+  pick->header.type = htons 
(GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
+  memcpy (&pick[1], metadata, len);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              line->client,
+                                              &pick->header,
+                                              GNUNET_NO);
+  line->tunnel_unreliable = GNUNET_MESH_tunnel_create (mesh,
+                                                       line,
+                                                       &line->target,
+                                                       
GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
+                                                       GNUNET_YES,
+                                                       GNUNET_NO);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function to handle a busy message incoming over mesh
+ *
+ * @param cls closure, NULL
+ * @param tunnel the tunnel over which the message arrived
+ * @param tunnel_ctx the tunnel context, can be NULL
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_mesh_busy_message (void *cls,
+                          struct GNUNET_MESH_Tunnel *tunnel,
+                          void **tunnel_ctx,
+                          const struct GNUNET_MessageHeader *message)
+{
+  struct Line *line = *tunnel_ctx;
+  struct ClientPhoneBusyMessage busy;
+
+  if (NULL == line)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "HANGUP message received for non-existing line, dropping 
tunnel.\n");
+    return GNUNET_SYSERR;
+  }
+  busy.header.size = sizeof (busy);
+  busy.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              line->client,
+                                              &busy.header,
+                                              GNUNET_NO);
+  GNUNET_MESH_receive_done (tunnel);
+  *tunnel_ctx = NULL;
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case LS_CALLEE_RINGING:
+    GNUNET_break_op (0);
+    break;
+  case LS_CALLEE_CONNECTED:
+    GNUNET_break_op (0);
+    break;
+  case LS_CALLEE_SHUTDOWN:
+    GNUNET_break_op (0);
+    break;
+  case LS_CALLER_CALLING:
+    line->status = LS_CALLER_SHUTDOWN;
+    mq_done_finish_caller_shutdown (line);
+    break;
+  case LS_CALLER_CONNECTED:
+    line->status = LS_CALLER_SHUTDOWN;
+    mq_done_finish_caller_shutdown (line);
+    break;
+  case LS_CALLER_SHUTDOWN:
+    mq_done_finish_caller_shutdown (line);
+    break;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function to handle an audio message incoming over mesh
+ *
+ * @param cls closure, NULL
+ * @param tunnel the tunnel over which the message arrived
+ * @param tunnel_ctx the tunnel context, can be NULL
+ * @param message the incoming message
+ * @return #GNUNET_OK
+ */
+static int
+handle_mesh_audio_message (void *cls,
+                           struct GNUNET_MESH_Tunnel *tunnel,
+                           void **tunnel_ctx,
+                           const struct GNUNET_MessageHeader *message)
+{
+  const struct MeshAudioMessage *msg;
+  struct Line *line = *tunnel_ctx;
+  struct GNUNET_PeerIdentity sender;
+  size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage);
+  char buf[msize + sizeof (struct ClientAudioMessage)];
+  struct ClientAudioMessage *cam;
+  
+  msg = (const struct MeshAudioMessage *) message;
+  if (NULL == line)
+  {
+    sender = *GNUNET_MESH_tunnel_get_info (tunnel,
+                                           GNUNET_MESH_OPTION_PEER)->peer;
+    for (line = lines_head; NULL != line; line = line->next)
+      if ( (line->local_line == ntohl (msg->remote_line)) &&
+           (LS_CALLEE_CONNECTED == line->status) &&
+           (0 == memcmp (&line->target,
+                         &sender,
+                         sizeof (struct GNUNET_PeerIdentity))) &&
+           (NULL == line->tunnel_unreliable) )
+        break;
+    if (NULL == line)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Received AUDIO data for non-existing line %u, dropping.\n",
+                  ntohl (msg->remote_line));
+      return GNUNET_SYSERR;
+    }
+    line->tunnel_unreliable = tunnel;
+    *tunnel_ctx = line;
+  }
+  cam = (struct ClientAudioMessage *) buf;
+  cam->header.size = htons (sizeof (buf));
+  cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
+  memcpy (&cam[1], &msg[1], msize);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                              line->client,
+                                              &cam->header,
+                                              GNUNET_YES);
+  GNUNET_MESH_receive_done (tunnel);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Method called whenever another peer has added us to a tunnel
+ * the other peer initiated.
+ *
+ * @param cls closure
+ * @param tunnel new handle to the tunnel
+ * @param initiator peer that started the tunnel
+ * @param port port
+ * @return initial tunnel context for the tunnel (can be NULL -- that's not an 
error)
+ */
+static void *
+inbound_tunnel (void *cls,
+                struct GNUNET_MESH_Tunnel *tunnel,
+               const struct GNUNET_PeerIdentity *initiator, 
+                uint32_t port)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             _("Received incoming tunnel on port %d\n"), 
+              port);
+  return NULL;
+}
+
+
+/**
+ * Function called whenever an inbound tunnel is destroyed.  Should clean up
+ * any associated state.
+ *
+ * @param cls closure (set from #GNUNET_MESH_connect)
+ * @param tunnel connection to the other end (henceforth invalid)
+ * @param tunnel_ctx place where local state associated
+ *                   with the tunnel is stored
+ */
+static void
+inbound_end (void *cls,
+             const struct GNUNET_MESH_Tunnel *tunnel,
+            void *tunnel_ctx)
+{
+  struct Line *line = tunnel_ctx;
+  struct ClientPhoneHangupMessage hup;
+
+  if (NULL == line)
+    return;
+  if (line->tunnel_unreliable == tunnel)
+  {
+    line->tunnel_unreliable = NULL;
+    return;
+  }
+  hup.header.size = sizeof (hup);
+  hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
+  switch (line->status)
+  {
+  case LS_CALLEE_LISTEN:
+    GNUNET_break (0);
+    return;
+  case LS_CALLEE_RINGING:
+  case LS_CALLEE_CONNECTED:
+    GNUNET_SERVER_notification_context_unicast (nc,
+                                                line->client,
+                                                &hup.header,
+                                                GNUNET_NO);
+    line->status = LS_CALLEE_LISTEN;
+    break;
+  case LS_CALLEE_SHUTDOWN:
+    line->status = LS_CALLEE_LISTEN;
+    destroy_line_mesh_tunnels (line);
+    break;
+  case LS_CALLER_CALLING:
+  case LS_CALLER_CONNECTED:
+    GNUNET_SERVER_notification_context_unicast (nc,
+                                                line->client,
+                                                &hup.header,
+                                                GNUNET_NO);
+    destroy_line_mesh_tunnels (line);
+    GNUNET_CONTAINER_DLL_remove (lines_head,
+                                 lines_tail,
+                                 line);
+    GNUNET_free_non_null (line->audio_data);
+    GNUNET_free (line);
+    break;
+  case LS_CALLER_SHUTDOWN:
+    destroy_line_mesh_tunnels (line);
+    GNUNET_CONTAINER_DLL_remove (lines_head,
+                                 lines_tail,
+                                 line);
+    GNUNET_free (line);
+    break;
+  }
+}
+
+
+/**
+ * A client disconnected.  Remove all of its data structure entries.
+ *
+ * @param cls closure, NULL
+ * @param client identification of the client
+ */
+static void
+handle_client_disconnect (void *cls, 
+                          struct GNUNET_SERVER_Client *client)
+{
+  struct Line *line;
+
+  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  if (NULL == line)
+    return;
+  GNUNET_CONTAINER_DLL_remove (lines_head,
+                               lines_tail,
+                               line);
+  GNUNET_free (line);
+  GNUNET_SERVER_client_set_user_context (client, NULL);
+}
+
+
+/**
+ * Shutdown nicely
+ * 
+ * @param cls closure, NULL
+ * @param tc the task context
+ */
+static void
+do_shutdown (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (NULL != mesh)
+  {
+    GNUNET_MESH_disconnect (mesh);
+    mesh = NULL;
+  }
+  if (NULL != nc)
+  {
+    GNUNET_SERVER_notification_context_destroy (nc);
+    nc = NULL;
+  }
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param server server handle
+ * @param c configuration
+ */
+static void
+run (void *cls, 
+     struct GNUNET_SERVER_Handle *server,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
+    {&handle_client_register_message, NULL,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
+     sizeof (struct ClientPhoneRegisterMessage)},
+    {&handle_client_pickup_message, NULL,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
+     0},
+    {&handle_client_hangup_message, NULL,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
+     0},
+    {&handle_client_call_message, NULL,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
+     0},
+    {&handle_client_audio_message, NULL,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
+     0},
+    {NULL, NULL, 0, 0}
+  };
+  static struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
+    {&handle_mesh_ring_message,
+     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING,
+     sizeof (struct MeshPhoneRingMessage)},
+    {&handle_mesh_hangup_message, 
+     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP,
+     0},
+    {&handle_mesh_pickup_message, 
+     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP,
+     0},
+    {&handle_mesh_busy_message, 
+     GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY,
+     sizeof (struct MeshPhoneBusyMessage)},
+    {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO,
+     0},
+    {NULL, 0, 0}
+  };
+  static uint32_t ports[] = { 
+    GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
+    GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
+    0 
+  };
+
+  cfg = c;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_get_host_identity (cfg,
+                                                  &my_identity));
+  mesh = GNUNET_MESH_connect (cfg,
+                             NULL,
+                             &inbound_tunnel,
+                             &inbound_end, 
+                              mesh_handlers, 
+                              ports);
+
+  if (NULL == mesh)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  nc = GNUNET_SERVER_notification_context_create (server, 16);
+  GNUNET_SERVER_add_handlers (server, server_handlers);
+  GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, 
+                                &do_shutdown,
+                               NULL);
+}
+
+
+/**
+ * The main function for the conversation service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, 
+      char *const *argv)
+{
+  return (GNUNET_OK ==
+         GNUNET_SERVICE_run (argc, argv,
+                              "conversation", 
+                              GNUNET_SERVICE_OPTION_NONE,
+                             &run, NULL)) ? 0 : 1;
+}
+
+/* end of gnunet-service-conversation.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]