-converting API to use new CADET ports
authorChristian Grothoff <christian@grothoff.org>
Thu, 11 Aug 2016 18:04:19 +0000 (18:04 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 11 Aug 2016 18:04:19 +0000 (18:04 +0000)
src/conversation/conversation.h
src/conversation/conversation_api.c
src/conversation/conversation_api_call.c
src/conversation/gnunet-conversation.c
src/conversation/gnunet-service-conversation.c
src/conversation/plugin_gnsrecord_conversation.c
src/conversation/test_conversation.conf
src/conversation/test_conversation_api.c
src/conversation/test_conversation_api_reject.c

index bbe587b50ddbc0c38c3406f16b1d4fd1a9a18774..1ca816f0e825cc28e07b4950b0d717c4150d0afb 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2013 GNUnet e.V.
+     Copyright (C) 2013-2016 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -75,9 +75,14 @@ struct ClientPhoneRegisterMessage
   struct GNUNET_MessageHeader header;
 
   /**
-   * Phone line to register.
+   * Always zero.
    */
-  uint32_t line GNUNET_PACKED;
+  uint32_t reserved GNUNET_PACKED;
+
+  /**
+   * Phone line / CADET port to register.
+   */
+  struct GNUNET_HashCode line_port;
 };
 
 
@@ -92,8 +97,8 @@ struct ClientPhoneRingMessage
   struct GNUNET_MessageHeader header;
 
   /**
-   * CID, internal caller ID to identify which active call we are
-   * talking about.
+   * CID, internal caller ID number used in the future to identify
+   * which active call we are talking about.
    */
   uint32_t cid GNUNET_PACKED;
 
@@ -183,7 +188,7 @@ struct ClientPhoneHangupMessage
 
 
 /**
- * Message Client <->Service to transmit the audio.
+ * Message Client <-> Service to transmit the audio.
  */
 struct ClientAudioMessage
 {
@@ -214,15 +219,20 @@ struct ClientCallMessage
   struct GNUNET_MessageHeader header;
 
   /**
-   * Which phone line to call at the peer?
+   * Always zero.
    */
-  uint32_t line GNUNET_PACKED;
+  uint32_t reserved GNUNET_PACKED;
 
   /**
    * Which peer is hosting the line?
    */
   struct GNUNET_PeerIdentity target;
 
+  /**
+   * Which phone line to call at the peer?
+   */
+  struct GNUNET_HashCode line_port;
+
   /**
    * Identity of the caller.
    */
@@ -241,58 +251,74 @@ struct ClientPhonePickedupMessage
    */
   struct GNUNET_MessageHeader header;
 
+  /**
+   * Call ID of the corresponding
+   * #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL
+   */
+  uint32_t cid GNUNET_PACKED;
+
 };
 
 
 /**
- * Cadet message for phone is ringing.
+ * Information signed in a `struct CadetPhoneRingMessage`
+ * whereby the caller self-identifies to the receiver.
  */
-struct CadetPhoneRingMessage
+struct CadetPhoneRingInfoPS
 {
   /**
-   * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING
+   * Purpose for the signature, must be
+   * #GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING.
    */
-  struct GNUNET_MessageHeader header;
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
 
   /**
-   * Desired target line.
+   * Which port did the call go to?
    */
-  uint32_t remote_line GNUNET_PACKED;
+  struct GNUNET_HashCode line_port;
 
   /**
-   * Purpose for the signature.
+   * Which peer is the call for?
    */
-  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+  struct GNUNET_PeerIdentity target_peer;
 
   /**
-   * Who is calling us? (also who is signing).
+   * When does the signature expire?
    */
-  struct GNUNET_CRYPTO_EcdsaPublicKey caller_id;
+  struct GNUNET_TIME_AbsoluteNBO expiration_time;
+};
+
 
+/**
+ * Cadet message to make a phone ring.  Sent to the port
+ * of the respective phone.
+ */
+struct CadetPhoneRingMessage
+{
   /**
-   * Who are we calling?
+   * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING
    */
-  struct GNUNET_PeerIdentity target;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * From where are we calling?
+   * Always zero.
    */
-  struct GNUNET_PeerIdentity source;
+  uint32_t reserved GNUNET_PACKED;
 
   /**
-   * When does the signature expire?
+   * Who is calling us? (also who is signing).
    */
-  struct GNUNET_TIME_AbsoluteNBO expiration_time;
+  struct GNUNET_CRYPTO_EcdsaPublicKey caller_id;
 
   /**
-   * Signature on the above.
+   * When does the signature expire?
    */
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  struct GNUNET_TIME_AbsoluteNBO expiration_time;
 
   /**
-   * Source line for audio data in the other direction.
+   * Signature over a `struct CadetPhoneRingInfoPS`
    */
-  uint32_t source_line GNUNET_PACKED;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
 
 };
 
@@ -359,16 +385,6 @@ struct CadetAudioMessage
    */
   struct GNUNET_MessageHeader header;
 
-  /**
-   * Target line on the receiving end.
-   */
-  uint32_t remote_line GNUNET_PACKED;
-
-  /**
-   * The source line sending this data
-   */
-  uint32_t source_line GNUNET_PACKED;
-
   /* followed by audio data */
 
 };
index 3c0a68f4f40edfd661def98d103addc29995c01f..5dd9cf79e6a0dd45448a1e40e6dff02eefa67f11 100644 (file)
@@ -238,8 +238,11 @@ transmit_phone_audio (void *cls,
                            data_size,
                            GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
   am->cid = caller->cid;
-  GNUNET_memcpy (&am[1], data, data_size);
-  GNUNET_MQ_send (phone->mq, e);
+  GNUNET_memcpy (&am[1],
+                 data,
+                 data_size);
+  GNUNET_MQ_send (phone->mq,
+                  e);
 }
 
 
@@ -279,6 +282,26 @@ handle_phone_ring (void *cls,
 }
 
 
+/**
+ * Find the record of the caller matching the @a cid
+ *
+ * @param phone phone to search
+ * @param cid caller ID to search for (in NBO)
+ * @return NULL if @a cid was not found
+ */
+static struct GNUNET_CONVERSATION_Caller *
+find_caller (struct GNUNET_CONVERSATION_Phone *phone,
+             uint32_t cid)
+{
+  struct GNUNET_CONVERSATION_Caller *caller;
+
+  for (caller = phone->caller_head;NULL != caller;caller = caller->next)
+    if (cid == caller->cid)
+      return caller;
+  return NULL;
+}
+
+
 /**
  * We received a `struct ClientPhoneHangupMessage`.
  *
@@ -292,9 +315,8 @@ handle_phone_hangup (void *cls,
   struct GNUNET_CONVERSATION_Phone *phone = cls;
   struct GNUNET_CONVERSATION_Caller *caller;
 
-  for (caller = phone->caller_head; NULL != caller; caller = caller->next)
-    if (hang->cid == caller->cid)
-      break;
+  caller = find_caller (phone,
+                        hang->cid);
   if (NULL == caller)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -351,9 +373,8 @@ handle_phone_suspend (void *cls,
   struct GNUNET_CONVERSATION_Phone *phone = cls;
   struct GNUNET_CONVERSATION_Caller *caller;
 
-  for (caller = phone->caller_head; NULL != caller; caller = caller->next)
-    if (suspend->cid == caller->cid)
-      break;
+  caller = find_caller (phone,
+                        suspend->cid);
   if (NULL == caller)
     return;
   switch (caller->state)
@@ -394,9 +415,8 @@ handle_phone_resume (void *cls,
   struct GNUNET_CONVERSATION_Phone *phone = cls;
   struct GNUNET_CONVERSATION_Caller *caller;
 
-  for (caller = phone->caller_head; NULL != caller; caller = caller->next)
-    if (resume->cid == caller->cid)
-      break;
+  caller = find_caller (phone,
+                        resume->cid);
   if (NULL == caller)
     return;
   switch (caller->state)
@@ -455,9 +475,8 @@ handle_phone_audio (void *cls,
   struct GNUNET_CONVERSATION_Phone *phone = cls;
   struct GNUNET_CONVERSATION_Caller *caller;
 
-  for (caller = phone->caller_head; NULL != caller; caller = caller->next)
-    if (am->cid == caller->cid)
-      break;
+  caller = find_caller (phone,
+                        am->cid);
   if (NULL == caller)
     return;
   switch (caller->state)
@@ -572,9 +591,11 @@ reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
                                      phone);
   if (NULL == phone->mq)
     return;
-  e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
-  reg->line = phone->my_record.line;
-  GNUNET_MQ_send (phone->mq, e);
+  e = GNUNET_MQ_msg (reg,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
+  reg->line_port = phone->my_record.line_port;
+  GNUNET_MQ_send (phone->mq,
+                  e);
   phone->state = PS_READY;
 }
 
@@ -596,10 +617,11 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                  void *event_handler_cls)
 {
   struct GNUNET_CONVERSATION_Phone *phone;
-  unsigned long long line;
+  char *line;
+  struct GNUNET_HashCode line_port;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg,
+      GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "CONVERSATION",
                                              "LINE",
                                              &line))
@@ -609,14 +631,9 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                "LINE");
     return NULL;
   }
-  if (line >= HIGH_BIT)
-  {
-    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
-                               "CONVERSATION",
-                               "LINE",
-                               _("number too large"));
-    return NULL;
-  }
+  GNUNET_CRYPTO_hash (line,
+                      strlen (line),
+                      &line_port);
   phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
   if (GNUNET_OK !=
       GNUNET_CRYPTO_get_peer_identity (cfg,
@@ -631,8 +648,9 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
   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);
+  phone->my_record.version = htonl (1);
+  phone->my_record.reserved = htonl (0);
+  phone->my_record.line_port = line_port;
   reconnect_phone (phone);
   if ( (NULL == phone->mq) ||
        (NULL == phone->ns) )
@@ -689,9 +707,11 @@ GNUNET_CONVERSATION_caller_pick_up (struct GNUNET_CONVERSATION_Caller *caller,
   GNUNET_assert (CS_RINGING == caller->state);
   caller->speaker = speaker;
   caller->mic = mic;
-  e = GNUNET_MQ_msg (pick, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
+  e = GNUNET_MQ_msg (pick,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
   pick->cid = caller->cid;
-  GNUNET_MQ_send (phone->mq, e);
+  GNUNET_MQ_send (phone->mq,
+                  e);
   caller->state = CS_ACTIVE;
   caller->event_handler = event_handler;
   caller->event_handler_cls = event_handler_cls;
@@ -730,7 +750,8 @@ GNUNET_CONVERSATION_caller_hang_up (struct GNUNET_CONVERSATION_Caller *caller)
   e = GNUNET_MQ_msg (hang,
                      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
   hang->cid = caller->cid;
-  GNUNET_MQ_send (phone->mq, e);
+  GNUNET_MQ_send (phone->mq,
+                  e);
   GNUNET_free (caller);
 }
 
@@ -781,9 +802,11 @@ GNUNET_CONVERSATION_caller_suspend (struct GNUNET_CONVERSATION_Caller *caller)
   }
   caller->speaker = NULL;
   caller->mic = NULL;
-  e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
+  e = GNUNET_MQ_msg (suspend,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
   suspend->cid = caller->cid;
-  GNUNET_MQ_send (phone->mq, e);
+  GNUNET_MQ_send (phone->mq,
+                  e);
   if (CS_ACTIVE == caller->state)
     caller->state = CS_CALLEE_SUSPENDED;
   else
@@ -811,9 +834,11 @@ GNUNET_CONVERSATION_caller_resume (struct GNUNET_CONVERSATION_Caller *caller,
                   (CS_BOTH_SUSPENDED == caller->state) );
   caller->speaker = speaker;
   caller->mic = mic;
-  e = GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
+  e = GNUNET_MQ_msg (resume,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
   resume->cid = caller->cid;
-  GNUNET_MQ_send (phone->mq, e);
+  GNUNET_MQ_send (phone->mq,
+                  e);
   if (CS_CALLEE_SUSPENDED == caller->state)
   {
     caller->state = CS_ACTIVE;
index cd1bf8f86751837c6714dcd48e97664a7b3aff9d..af05f3ea678762671b8f4769ea6ab86bd36cc93d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   This file is part of GNUnet
-  Copyright (C) 2013 GNUnet e.V.
+  Copyright (C) 2013, 2016 GNUnet e.V.
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
@@ -177,8 +177,11 @@ transmit_call_audio (void *cls,
   e = GNUNET_MQ_msg_extra (am,
                            data_size,
                            GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
-  GNUNET_memcpy (&am[1], data, data_size);
-  GNUNET_MQ_send (call->mq, e);
+  GNUNET_memcpy (&am[1],
+                 data,
+                 data_size);
+  GNUNET_MQ_send (call->mq,
+                  e);
 }
 
 
@@ -345,7 +348,8 @@ handle_call_hangup (void *cls,
     eh = call->event_handler;
     eh_cls = call->event_handler_cls;
     GNUNET_CONVERSATION_call_stop (call);
-    eh (eh_cls, GNUNET_CONVERSATION_EC_CALL_HUNG_UP);
+    eh (eh_cls,
+        GNUNET_CONVERSATION_EC_CALL_HUNG_UP);
     return;
   case CS_SHUTDOWN:
     GNUNET_CONVERSATION_call_stop (call);
@@ -443,13 +447,15 @@ handle_gns_response (void *cls,
         continue;
       }
       GNUNET_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;
+                     rd[i].data,
+                     rd[i].data_size);
+      e = GNUNET_MQ_msg (ccm,
+                         GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL);
+      ccm->line_port = call->phone_record.line_port;
       ccm->target = call->phone_record.peer;
       ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id);
-      GNUNET_MQ_send (call->mq, e);
+      GNUNET_MQ_send (call->mq,
+                      e);
       call->state = CS_RINGING;
       call->event_handler (call->event_handler_cls,
                            GNUNET_CONVERSATION_EC_CALL_RINGING);
@@ -663,8 +669,10 @@ GNUNET_CONVERSATION_call_suspend (struct GNUNET_CONVERSATION_Call *call)
   }
   call->speaker = NULL;
   call->mic = NULL;
-  e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
-  GNUNET_MQ_send (call->mq, e);
+  e = GNUNET_MQ_msg (suspend,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
+  GNUNET_MQ_send (call->mq,
+                  e);
   if (CS_SUSPENDED_CALLER == call->state)
     call->state = CS_SUSPENDED_BOTH;
   else
index d899ee5ca920bea41c068d01c304cea194e9cc7f..925db4665694bde3a33794fd838b1bc4011947f9 100644 (file)
@@ -166,9 +166,9 @@ static struct CallList *cl_head;
 static struct CallList *cl_tail;
 
 /**
- * Desired phone line.
+ * Desired phone line (string to be converted to a hash).
  */
-static unsigned int line;
+static char *line;
 
 /**
  * Task which handles the commands
@@ -357,7 +357,8 @@ start_phone ()
   GNUNET_assert (NULL == phone);
   phone = GNUNET_CONVERSATION_phone_create (cfg,
                                             my_caller_id,
-                                            &phone_event_handler, NULL);
+                                            &phone_event_handler,
+                                            NULL);
   /* FIXME: get record and print full GNS record info later here... */
   if (NULL == phone)
   {
@@ -375,8 +376,8 @@ start_phone ()
                                                 rd.data,
                                                 rd.data_size);
     FPRINTF (stdout,
-             _("Phone active on line %u.  Type `/help' for a list of available commands\n"),
-             (unsigned int) line);
+             _("Phone active at `%s'.  Type `/help' for a list of available commands\n"),
+             address);
     phone_state = PS_LISTEN;
   }
 }
@@ -687,7 +688,7 @@ do_status (const char *args)
     break;
   case PS_LISTEN:
     FPRINTF (stdout,
-             _("We are listening for incoming calls for ego `%s' on line %u.\n"),
+             _("We are listening for incoming calls for ego `%s' on line `%s'.\n"),
              ego_name,
              line);
     break;
@@ -1187,7 +1188,7 @@ identity_cb (void *cls,
     return;
   }
   my_caller_id = ego;
-  GNUNET_CONFIGURATION_set_value_number (cfg,
+  GNUNET_CONFIGURATION_set_value_string (cfg,
                                          "CONVERSATION",
                                          "LINE",
                                          line);
@@ -1270,7 +1271,7 @@ main (int argc, char *const *argv)
      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},
+     1, &GNUNET_GETOPT_set_string, &line},
     GNUNET_GETOPT_OPTION_END
   };
   int ret;
index b547d814c3b908b6e60d3dd7491b2951973fa464..baf35c9a287514fe78ecd3f6d7e930c6a37111fe 100644 (file)
@@ -1,6 +1,6 @@
 /*
   This file is part of GNUnet.
-  Copyright (C) 2013 GNUnet e.V.
+  Copyright (C) 2013, 2016 GNUnet e.V.
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
@@ -54,6 +54,11 @@ struct Line;
  */
 enum ChannelStatus
 {
+  /**
+   * We just got the connection, but no introduction yet.
+   */
+  CS_CALLEE_INIT,
+
   /**
    * Our phone is ringing, waiting for the client to pick up.
    */
@@ -112,50 +117,25 @@ struct Channel
   struct Line *line;
 
   /**
-   * Handle for the reliable channel (contol data)
-   */
-  struct GNUNET_CADET_Channel *channel_reliable;
-
-  /**
-   * Handle for unreliable channel (audio data)
-   */
-  struct GNUNET_CADET_Channel *channel_unreliable;
-
-  /**
-   * Transmit handle for pending audio messages
+   * Handle for the channel.
    */
-  struct GNUNET_CADET_TransmitHandle *unreliable_mth;
+  struct GNUNET_CADET_Channel *channel;
 
   /**
    * Message queue for control messages
    */
-  struct GNUNET_MQ_Handle *reliable_mq;
+  struct GNUNET_MQ_Handle *mq;
 
   /**
-   * Target of the line, if we are the caller.
+   * Temporary buffer for audio data in the @e mq.
    */
-  struct GNUNET_PeerIdentity target;
+  struct GNUNET_MQ_Envelope *env;
 
   /**
-   * Temporary buffer for audio data.
-   */
-  void *audio_data;
-
-  /**
-   * Number of bytes in @e audio_data.
-   */
-  size_t audio_size;
-
-  /**
-   * Channel identifier.
+   * Channel identifier we use for this call with the client.
    */
   uint32_t cid;
 
-  /**
-   * Remote line number.
-   */
-  uint32_t remote_line;
-
   /**
    * Current status of this line.
    */
@@ -179,16 +159,6 @@ struct Channel
  */
 struct Line
 {
-  /**
-   * Kept in a DLL.
-   */
-  struct Line *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct Line *prev;
-
   /**
    * This is a DLL.
    */
@@ -205,14 +175,20 @@ struct Line
   struct GNUNET_SERVER_Client *client;
 
   /**
-   * Generator for channel IDs.
+   * Our open port.
    */
-  uint32_t cid_gen;
+  struct GNUNET_CADET_Port *port;
 
   /**
-   * Our line number.
+   * Port number we are listening on (to verify signatures).
+   * Only valid if @e port is non-NULL.
    */
-  uint32_t local_line;
+  struct GNUNET_HashCode line_port;
+
+  /**
+   * Generator for channel IDs.
+   */
+  uint32_t cid_gen;
 
 };
 
@@ -237,56 +213,25 @@ static struct GNUNET_CADET_Handle *cadet;
  */
 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.
+ * Given a @a cid, find the corresponding channel given
+ * a @a line.
  *
- * @param cls closure, NULL
- * @param client the client from which the message is
- * @param message the message from the client
+ * @param line a line to search
+ * @param cid what to search for
+ * @return NULL for not found
  */
-static void
-handle_client_register_message (void *cls,
-                                struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
+static struct Channel *
+find_channel_by_line (struct Line *line,
+                      uint32_t cid)
 {
-  const struct ClientPhoneRegisterMessage *msg;
-  struct Line *line;
+  struct Channel *ch;
 
-  msg = (const 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_SERVER_client_set_user_context (client, line);
-  GNUNET_CONTAINER_DLL_insert (lines_head,
-                               lines_tail,
-                               line);
-  line->local_line = ntohl (msg->line) & (~ HIGH_BIT);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  for (ch = line->channel_head; NULL != ch; ch = ch->next)
+    if (cid == ch->cid)
+      return ch;
+  return NULL;
 }
 
 
@@ -309,7 +254,8 @@ handle_client_pickup_message (void *cls,
   struct Channel *ch;
 
   msg = (const struct ClientPhonePickupMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
   {
     GNUNET_break (0);
@@ -325,17 +271,24 @@ handle_client_pickup_message (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
-    GNUNET_SERVER_receive_done (client, GNUNET_YES);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_YES);
     return;
   }
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
+    return;
   case CS_CALLEE_RINGING:
     ch->status = CS_CALLEE_CONNECTED;
     break;
   case CS_CALLEE_CONNECTED:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLEE_SHUTDOWN:
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -353,8 +306,9 @@ handle_client_pickup_message (void *cls,
               "Sending PICK_UP message to cadet\n");
   e = GNUNET_MQ_msg (mppm,
                      GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP);
-  GNUNET_MQ_send (ch->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (ch->mq, e);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -366,36 +320,15 @@ handle_client_pickup_message (void *cls,
 static void
 destroy_line_cadet_channels (struct Channel *ch)
 {
-  struct Line *line = ch->line;
-  struct GNUNET_CADET_Channel *t;
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Destroying cadet channels\n");
-  if (NULL != ch->reliable_mq)
-  {
-    GNUNET_MQ_destroy (ch->reliable_mq);
-    ch->reliable_mq = NULL;
-  }
-  if (NULL != ch->unreliable_mth)
-  {
-    GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
-    ch->unreliable_mth = NULL;
-  }
-  if (NULL != (t = ch->channel_unreliable))
-  {
-    ch->channel_unreliable = NULL;
-    GNUNET_CADET_channel_destroy (t);
-  }
-  if (NULL != (t = ch->channel_reliable))
+  if (NULL != ch->mq)
   {
-    ch->channel_reliable = NULL;
-    GNUNET_CADET_channel_destroy (t);
+    GNUNET_MQ_destroy (ch->mq);
+    ch->mq = NULL;
   }
-  GNUNET_CONTAINER_DLL_remove (line->channel_head,
-                               line->channel_tail,
-                               ch);
-  GNUNET_free_non_null (ch->audio_data);
-  GNUNET_free (ch);
+  if (NULL != ch->channel)
+    GNUNET_CADET_channel_destroy (ch->channel);
 }
 
 
@@ -412,6 +345,9 @@ mq_done_finish_caller_shutdown (void *cls)
 
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    break;
   case CS_CALLEE_RINGING:
     GNUNET_break (0);
     break;
@@ -453,11 +389,13 @@ handle_client_hangup_message (void *cls,
   struct Channel *ch;
 
   msg = (const struct ClientPhoneHangupMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   for (ch = line->channel_head; NULL != ch; ch = ch->next)
@@ -469,7 +407,8 @@ handle_client_hangup_message (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -478,6 +417,11 @@ handle_client_hangup_message (void *cls,
               ch->status);
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
+    return;
   case CS_CALLEE_RINGING:
     ch->status = CS_CALLEE_SHUTDOWN;
     break;
@@ -486,7 +430,8 @@ handle_client_hangup_message (void *cls,
     break;
   case CS_CALLEE_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   case CS_CALLER_CALLING:
     ch->status = CS_CALLER_SHUTDOWN;
@@ -506,8 +451,10 @@ handle_client_hangup_message (void *cls,
   GNUNET_MQ_notify_sent (e,
                          &mq_done_finish_caller_shutdown,
                          ch);
-  GNUNET_MQ_send (ch->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (ch->mq,
+                  e);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -530,11 +477,13 @@ handle_client_suspend_message (void *cls,
   struct Channel *ch;
 
   msg = (const struct ClientPhoneSuspendMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   for (ch = line->channel_head; NULL != ch; ch = ch->next)
@@ -546,13 +495,15 @@ handle_client_suspend_message (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   if (GNUNET_YES == ch->suspended_local)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -561,35 +512,46 @@ handle_client_suspend_message (void *cls,
               ch->status);
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
+    return;
   case CS_CALLEE_RINGING:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLEE_CONNECTED:
     ch->suspended_local = GNUNET_YES;
     break;
   case CS_CALLEE_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   case CS_CALLER_CALLING:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLER_CONNECTED:
     ch->suspended_local = GNUNET_YES;
     break;
   case CS_CALLER_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Sending SUSPEND message via cadet\n");
   e = GNUNET_MQ_msg (mhum,
                      GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND);
-  GNUNET_MQ_send (ch->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (ch->mq,
+                  e);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -612,11 +574,13 @@ handle_client_resume_message (void *cls,
   struct Channel *ch;
 
   msg = (const struct ClientPhoneResumeMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   for (ch = line->channel_head; NULL != ch; ch = ch->next)
@@ -628,7 +592,8 @@ handle_client_resume_message (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   if (GNUNET_YES != ch->suspended_local)
@@ -643,35 +608,46 @@ handle_client_resume_message (void *cls,
               ch->status);
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
+    return;
   case CS_CALLEE_RINGING:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLEE_CONNECTED:
     ch->suspended_local = GNUNET_NO;
     break;
   case CS_CALLEE_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   case CS_CALLER_CALLING:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLER_CONNECTED:
     ch->suspended_local = GNUNET_NO;
     break;
   case CS_CALLER_SHUTDOWN:
     /* maybe the other peer closed asynchronously... */
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Sending RESUME message via cadet\n");
   e = GNUNET_MQ_msg (mhum,
                      GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME);
-  GNUNET_MQ_send (ch->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (ch->mq,
+                  e);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -692,9 +668,11 @@ handle_client_call_message (void *cls,
   struct Channel *ch;
   struct GNUNET_MQ_Envelope *e;
   struct CadetPhoneRingMessage *ring;
+  struct CadetPhoneRingInfoPS rs;
 
   msg = (const struct ClientCallMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL != line)
   {
     GNUNET_break (0);
@@ -703,86 +681,59 @@ handle_client_call_message (void *cls,
   }
   line = GNUNET_new (struct Line);
   line->client = client;
-  line->local_line = (local_line_cnt++) | HIGH_BIT;
-  GNUNET_SERVER_client_set_user_context (client, line);
-  GNUNET_SERVER_notification_context_add (nc, client);
-  GNUNET_CONTAINER_DLL_insert (lines_head,
-                               lines_tail,
-                               line);
+  line->line_port = msg->line_port;
+  GNUNET_SERVER_client_set_user_context (client,
+                                         line);
+  GNUNET_SERVER_notification_context_add (nc,
+                                          client);
+  rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
+  rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
+  rs.line_port = line->line_port;
+  rs.target_peer = msg->target;
+  rs.expiration_time
+    = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
+
   ch = GNUNET_new (struct Channel);
   ch->line = line;
   GNUNET_CONTAINER_DLL_insert (line->channel_head,
                                line->channel_tail,
                                ch);
-  ch->target = msg->target;
-  ch->remote_line = ntohl (msg->line);
   ch->status = CS_CALLER_CALLING;
-  ch->channel_reliable = GNUNET_CADET_channel_create (cadet,
-                                                     ch,
-                                                     &msg->target,
-                                                     GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL),
-                                                     GNUNET_CADET_OPTION_RELIABLE);
-  ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable);
-  e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_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_EcdsaPublicKey));
+  ch->channel = GNUNET_CADET_channel_create (cadet,
+                                             ch,
+                                             &msg->target,
+                                             &msg->line_port,
+                                             GNUNET_CADET_OPTION_RELIABLE);
+  ch->mq = GNUNET_CADET_mq_create (ch->channel);
+  e = GNUNET_MQ_msg (ring,
+                     GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING);
   GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id,
                                       &ring->caller_id);
-  ring->remote_line = msg->line;
-  ring->source_line = htonl (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));
+  ring->expiration_time = rs.expiration_time;
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id,
-                                           &ring->purpose,
+                                           &rs.purpose,
                                            &ring->signature));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending RING message via cadet\n");
-  GNUNET_MQ_send (ch->reliable_mq, e);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+              "Sending RING message via CADET\n");
+  GNUNET_MQ_send (ch->mq,
+                  e);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
 /**
- * Transmit audio data via unreliable cadet channel.
+ * Transmission of audio data via cadet channel finished.
  *
  * @param cls the `struct Channel` 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 @a buf
  */
-static size_t
-transmit_line_audio (void *cls,
-                     size_t size,
-                     void *buf)
+static void
+channel_audio_sent_notify (void *cls)
 {
   struct Channel *ch = cls;
-  struct CadetAudioMessage *mam = buf;
-
-  ch->unreliable_mth = NULL;
-  if ( (NULL == buf) ||
-       (size < sizeof (struct CadetAudioMessage) + ch->audio_size) )
-    {
-    /* eh, other error handling? */
-    return 0;
-  }
-  mam->header.size = htons (sizeof (struct CadetAudioMessage) + ch->audio_size);
-  mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO);
-  mam->remote_line = htonl (ch->remote_line);
-  mam->source_line = htonl (ch->line->local_line);
-  GNUNET_memcpy (&mam[1], ch->audio_data, ch->audio_size);
-  GNUNET_free (ch->audio_data);
-  ch->audio_data = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending %u bytes of audio data from line %u to remote line %u via cadet\n",
-              (unsigned int) ch->audio_size,
-              ch->line->local_line,
-              ch->remote_line);
-  return sizeof (struct CadetAudioMessage) + ch->audio_size;
+
+  ch->env = NULL;
 }
 
 
@@ -799,38 +750,43 @@ handle_client_audio_message (void *cls,
                              const struct GNUNET_MessageHeader *message)
 {
   const struct ClientAudioMessage *msg;
+  struct ClientAudioMessage *mam;
   struct Line *line;
   struct Channel *ch;
   size_t size;
 
   size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
   msg = (const struct ClientAudioMessage *) message;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
-  for (ch = line->channel_head; NULL != ch; ch = ch->next)
-    if (msg->cid == ch->cid)
-      break;
+  ch = find_channel_by_line (line,
+                             msg->cid);
   if (NULL == ch)
   {
     /* could have been destroyed asynchronously, ignore message */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Channel %u not found\n",
                 msg->cid);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
 
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
   case CS_CALLEE_RINGING:
   case CS_CALLER_CALLING:
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   case CS_CALLEE_CONNECTED:
   case CS_CALLER_CONNECTED:
@@ -840,61 +796,41 @@ handle_client_audio_message (void *cls,
   case CS_CALLER_SHUTDOWN:
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                 "Cadet audio channel in shutdown; audio data dropped\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   if (GNUNET_YES == ch->suspended_local)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "This channel is suspended locally\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (NULL == ch->channel_unreliable)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
-                _("Cadet audio channel not ready; audio data dropped\n"));
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "This channel is suspended locally\n");
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
-  if (NULL != ch->unreliable_mth)
+  if (NULL != ch->env)
   {
     /* NOTE: we may want to not do this and instead combine the data */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Bandwidth insufficient; dropping previous audio data segment with %u bytes\n",
-                (unsigned int) ch->audio_size);
-    GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
-    ch->unreliable_mth = NULL;
-    GNUNET_free (ch->audio_data);
-    ch->audio_data = NULL;
+                "Bandwidth insufficient; dropping previous audio data segment\n");
+    GNUNET_MQ_send_cancel (ch->env);
+    ch->env = NULL;
   }
-  ch->audio_size = size;
-  ch->audio_data = GNUNET_malloc (ch->audio_size);
-  GNUNET_memcpy (ch->audio_data,
-          &msg[1],
-          size);
-  ch->unreliable_mth = GNUNET_CADET_notify_transmit_ready (ch->channel_unreliable,
-                                                          GNUNET_NO,
-                                                          GNUNET_TIME_UNIT_FOREVER_REL,
-                                                          sizeof (struct CadetAudioMessage)
-                                                          + ch->audio_size,
-                                                          &transmit_line_audio,
-                                                          ch);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
 
-/**
- * We are done signalling shutdown to the other peer.
- * Destroy the channel.
- *
- * @param cls the `struct GNUNET_CADET_channel` to destroy
- */
-static void
-mq_done_destroy_channel (void *cls)
-{
-  struct GNUNET_CADET_Channel *channel = cls;
-
-  GNUNET_CADET_channel_destroy (channel);
+  ch->env = GNUNET_MQ_msg_extra (mam,
+                                 size,
+                                 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO);
+  GNUNET_memcpy (&mam[1],
+                 &msg[1],
+                 size);
+  /* FIXME: set options for unreliable transmission */
+  GNUNET_MQ_notify_sent (ch->env,
+                         &channel_audio_sent_notify,
+                         ch);
+  GNUNET_MQ_send (ch->mq,
+                  ch->env);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -910,70 +846,55 @@ mq_done_destroy_channel (void *cls)
  */
 static int
 handle_cadet_ring_message (void *cls,
-                          struct GNUNET_CADET_Channel *channel,
-                          void **channel_ctx,
-                          const struct GNUNET_MessageHeader *message)
+                           struct GNUNET_CADET_Channel *channel,
+                           void **channel_ctx,
+                           const struct GNUNET_MessageHeader *message)
 {
+  struct Channel *ch = *channel_ctx;
+  struct Line *line = ch->line;
   const struct CadetPhoneRingMessage *msg;
-  struct Line *line;
-  struct Channel *ch;
-  struct GNUNET_MQ_Envelope *e;
-  struct CadetPhoneHangupMessage *hang_up;
   struct ClientPhoneRingMessage cring;
-  struct GNUNET_MQ_Handle *reliable_mq;
+  struct CadetPhoneRingInfoPS rs;
 
   msg = (const struct CadetPhoneRingMessage *) 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_EcdsaPublicKey))) ||
-       (GNUNET_OK !=
-        GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
-                                  &msg->purpose,
+  rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
+  rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
+  rs.line_port = line->line_port;
+  rs.target_peer = my_identity;
+  rs.expiration_time = msg->expiration_time;
+
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
+                                  &rs.purpose,
                                   &msg->signature,
-                                  &msg->caller_id)) )
+                                  &msg->caller_id))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  GNUNET_CADET_receive_done (channel); /* needed? */
-  for (line = lines_head; NULL != line; line = line->next)
-    if (line->local_line == ntohl (msg->remote_line))
-      break;
-  if (NULL == line)
+  if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (msg->expiration_time)).rel_value_us)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("No available phone for incoming call on line %u, sending HANG_UP signal\n"),
-                ntohl (msg->remote_line));
-    e = GNUNET_MQ_msg (hang_up,
-                       GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
-    GNUNET_MQ_notify_sent (e,
-                           &mq_done_destroy_channel,
-                           channel);
-    reliable_mq = GNUNET_CADET_mq_create (channel);
-    GNUNET_MQ_send (reliable_mq, e);
-    /* FIXME: do we need to clean up reliable_mq somehow/somewhere? */
-    return GNUNET_OK;
+    /* ancient call, replay? */
+    GNUNET_break_op (0);
+    /* Note that our reliance on time here is awkward; better would be
+       to use a more complex challenge-response protocol against
+       replay attacks.  Left for future work ;-). */
+    return GNUNET_SYSERR;
   }
-  ch = GNUNET_new (struct Channel);
-  ch->line = line;
-  GNUNET_CONTAINER_DLL_insert (line->channel_head,
-                               line->channel_tail,
-                               ch);
+  if (CS_CALLEE_INIT != ch->status)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_CADET_receive_done (channel);
   ch->status = CS_CALLEE_RINGING;
-  ch->remote_line = ntohl (msg->source_line);
-  ch->channel_reliable = channel;
-  ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable);
-  ch->cid = line->cid_gen++;
-  ch->target = msg->source;
-  *channel_ctx = ch;
   cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
   cring.header.size = htons (sizeof (cring));
   cring.cid = ch->cid;
   cring.caller_id = msg->caller_id;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending RING message to client. CID %u:(%u, %u)\n",
-              ch->cid, ch->remote_line, line->local_line);
+              "Sending RING message to client. CID is %u\n",
+              (unsigned int) ch->cid);
   GNUNET_SERVER_notification_context_unicast (nc,
                                               line->client,
                                               &cring.header,
@@ -994,31 +915,26 @@ handle_cadet_ring_message (void *cls,
  */
 static int
 handle_cadet_hangup_message (void *cls,
-                            struct GNUNET_CADET_Channel *channel,
-                            void **channel_ctx,
-                            const struct GNUNET_MessageHeader *message)
+                             struct GNUNET_CADET_Channel *channel,
+                             void **channel_ctx,
+                             const struct GNUNET_MessageHeader *message)
 {
   struct Channel *ch = *channel_ctx;
-  struct Line *line;
+  struct Line *line = ch->line;
   struct ClientPhoneHangupMessage hup;
   enum ChannelStatus status;
 
-  if (NULL == ch)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "HANGUP message received for non-existing line, dropping channel.\n");
-    return GNUNET_SYSERR;
-  }
-  line = ch->line;
-  *channel_ctx = NULL;
+  GNUNET_CADET_receive_done (channel);
   hup.header.size = htons (sizeof (hup));
   hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
   hup.cid = ch->cid;
   status = ch->status;
-  GNUNET_CADET_receive_done (channel);
   destroy_line_cadet_channels (ch);
   switch (status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break_op (0);
+    return GNUNET_OK;
   case CS_CALLEE_RINGING:
   case CS_CALLEE_CONNECTED:
     break;
@@ -1053,24 +969,18 @@ handle_cadet_hangup_message (void *cls,
  */
 static int
 handle_cadet_pickup_message (void *cls,
-                            struct GNUNET_CADET_Channel *channel,
-                            void **channel_ctx,
-                            const struct GNUNET_MessageHeader *message)
+                             struct GNUNET_CADET_Channel *channel,
+                             void **channel_ctx,
+                             const struct GNUNET_MessageHeader *message)
 {
   struct Channel *ch = *channel_ctx;
-  struct Line *line;
+  struct Line *line = ch->line;
   struct ClientPhonePickedupMessage pick;
 
-  if (NULL == ch)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "PICKUP message received for non-existing channel, dropping channel.\n");
-    return GNUNET_SYSERR;
-  }
-  line = ch->line;
   GNUNET_CADET_receive_done (channel);
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
   case CS_CALLEE_RINGING:
   case CS_CALLEE_CONNECTED:
     GNUNET_break_op (0);
@@ -1093,21 +1003,13 @@ handle_cadet_pickup_message (void *cls,
   }
   pick.header.size = htons (sizeof (pick));
   pick.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP);
+  pick.cid = ch->cid;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Sending PICKED UP message to client\n");
   GNUNET_SERVER_notification_context_unicast (nc,
                                               line->client,
                                               &pick.header,
                                               GNUNET_NO);
-  ch->channel_unreliable = GNUNET_CADET_channel_create (cadet,
-                                                       ch,
-                                                       &ch->target,
-                                                       GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO),
-                                                       GNUNET_CADET_OPTION_DEFAULT);
-  if (NULL == ch->channel_unreliable)
-  {
-    GNUNET_break (0);
-  }
   return GNUNET_OK;
 }
 
@@ -1124,30 +1026,26 @@ handle_cadet_pickup_message (void *cls,
  */
 static int
 handle_cadet_suspend_message (void *cls,
-                             struct GNUNET_CADET_Channel *channel,
-                             void **channel_ctx,
-                             const struct GNUNET_MessageHeader *message)
+                              struct GNUNET_CADET_Channel *channel,
+                              void **channel_ctx,
+                              const struct GNUNET_MessageHeader *message)
 {
   struct Channel *ch = *channel_ctx;
-  struct Line *line;
+  struct Line *line = ch->line;
   struct ClientPhoneSuspendMessage suspend;
 
-  if (NULL == ch)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "SUSPEND message received for non-existing line, dropping channel.\n");
-    return GNUNET_SYSERR;
-  }
-  line = ch->line;
+  GNUNET_CADET_receive_done (channel);
   suspend.header.size = htons (sizeof (suspend));
   suspend.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
   suspend.cid = ch->cid;
-  GNUNET_CADET_receive_done (channel);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Suspending channel CID: %u(%u:%u)\n",
-              ch->cid, ch->remote_line, line->local_line);
+              "Suspending channel CID: %u\n",
+              ch->cid);
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break_op (0);
+    break;
   case CS_CALLEE_RINGING:
     GNUNET_break_op (0);
     break;
@@ -1212,6 +1110,9 @@ handle_cadet_resume_message (void *cls,
   }
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    GNUNET_break (0);
+    break;
   case CS_CALLEE_RINGING:
     GNUNET_break (0);
     break;
@@ -1249,86 +1150,38 @@ handle_cadet_resume_message (void *cls,
  */
 static int
 handle_cadet_audio_message (void *cls,
-                           struct GNUNET_CADET_Channel *channel,
-                           void **channel_ctx,
-                           const struct GNUNET_MessageHeader *message)
+                            struct GNUNET_CADET_Channel *channel,
+                            void **channel_ctx,
+                            const struct GNUNET_MessageHeader *message)
 {
-  const struct CadetAudioMessage *msg;
   struct Channel *ch = *channel_ctx;
-  struct Line *line;
-  struct GNUNET_PeerIdentity sender;
+  const struct CadetAudioMessage *msg;
   size_t msize = ntohs (message->size) - sizeof (struct CadetAudioMessage);
-  char buf[msize + sizeof (struct ClientAudioMessage)];
+  char buf[msize + sizeof (struct ClientAudioMessage)] GNUNET_ALIGN;
   struct ClientAudioMessage *cam;
-  const union GNUNET_CADET_ChannelInfo *info;
 
   msg = (const struct CadetAudioMessage *) message;
-  if (NULL == ch)
+  GNUNET_CADET_receive_done (channel);
+  if ( (GNUNET_YES == ch->suspended_local) ||
+       (GNUNET_YES == ch->suspended_remote) )
   {
-    info = GNUNET_CADET_channel_get_info (channel,
-                                         GNUNET_CADET_OPTION_PEER);
-    if (NULL == info)
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    sender = info->peer;
-    for (line = lines_head; NULL != line; line = line->next)
-      if (line->local_line == ntohl (msg->remote_line))
-      {
-        for (ch = line->channel_head; NULL != ch; ch = ch->next)
-        {
-          if ( (CS_CALLEE_CONNECTED == ch->status) &&
-               (0 == memcmp (&ch->target,
-                             &sender,
-                             sizeof (struct GNUNET_PeerIdentity))) &&
-               (NULL == ch->channel_unreliable) &&
-               (ch->remote_line == ntohl (msg->source_line)) )
-            break;
-        }
-        break;
-      }
-    if (NULL == line)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received %u bytes of AUDIO data for non-existing line %u, dropping.\n",
-                  (unsigned int) msize,
-                  ntohl (msg->remote_line));
-      return GNUNET_SYSERR;
-    }
-    if (NULL == ch)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received %u bytes of AUDIO data for unknown sender.\n",
-                  (unsigned int) msize);
-      return GNUNET_SYSERR;
-    }
-    if ((GNUNET_YES == ch->suspended_local) || (GNUNET_YES == ch->suspended_remote))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received %u bytes of AUDIO data on suspended channel CID %u:(%u:%u); dropping\n",
-                  (unsigned int) msize,
-                  ch->cid,
-                  ch->remote_line,
-                  line->local_line);
-      GNUNET_CADET_receive_done (channel);
-      return GNUNET_OK;
-    }
-    ch->channel_unreliable = channel;
-    *channel_ctx = ch;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n",
+                (unsigned int) msize,
+                ch->cid);
+    return GNUNET_OK;
   }
-  GNUNET_CADET_receive_done (channel);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Forwarding %u bytes of AUDIO data to client CID %u:(%u:%u)\n",
+              "Forwarding %u bytes of AUDIO data to client CID %u\n",
               (unsigned int) msize,
-              ch->cid,
-              ch->remote_line,
-              ch->line->local_line);
+              ch->cid);
   cam = (struct ClientAudioMessage *) buf;
   cam->header.size = htons (sizeof (buf));
   cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
   cam->cid = ch->cid;
-  GNUNET_memcpy (&cam[1], &msg[1], msize);
+  GNUNET_memcpy (&cam[1],
+                 &msg[1],
+                 msize);
   GNUNET_SERVER_notification_context_unicast (nc,
                                               ch->line->client,
                                               &cam->header,
@@ -1341,13 +1194,12 @@ handle_cadet_audio_message (void *cls,
  * Method called whenever another peer has added us to a channel
  * the other peer initiated.
  *
- * @param cls closure
+ * @param cls the `struct Line` receiving a connection
  * @param channel new handle to the channel
  * @param initiator peer that started the channel
  * @param port port
  * @param options channel option flags
- * @return initial channel context for the channel;
- *         (can be NULL -- that's not an error)
+ * @return initial channel context for the channel
  */
 static void *
 inbound_channel (void *cls,
@@ -1356,10 +1208,22 @@ inbound_channel (void *cls,
                  const struct GNUNET_HashCode *port,
                  enum GNUNET_CADET_ChannelOption options)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              _("Received incoming Cadet channel on port %s\n"),
-              GNUNET_h2s (port));
-  return NULL;
+  struct Line *line = cls;
+  struct Channel *ch;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received incoming cadet channel on line %p\n",
+              line);
+  ch = GNUNET_new (struct Channel);
+  ch->status = CS_CALLEE_INIT;
+  ch->line = line;
+  ch->channel = channel;
+  ch->mq = GNUNET_CADET_mq_create (ch->channel);
+  ch->cid = line->cid_gen++;
+  GNUNET_CONTAINER_DLL_insert (line->channel_head,
+                               line->channel_tail,
+                               ch);
+  return ch;
 }
 
 
@@ -1379,63 +1243,53 @@ inbound_end (void *cls,
             void *channel_ctx)
 {
   struct Channel *ch = channel_ctx;
-  struct Line *line;
+  struct Line *line = ch->line;
   struct ClientPhoneHangupMessage hup;
 
   if (NULL == ch)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Cadet channel destroyed, but channel is unknown to us\n");
-    return;
-  }
-  line = ch->line;
-  if (ch->channel_unreliable == channel)
-  {
-    if (NULL != ch->unreliable_mth)
-    {
-      GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
-      ch->unreliable_mth = NULL;
-    }
-    ch->channel_unreliable = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Unreliable channel destroyed\n");
-    return;
-  }
-  if (ch->channel_reliable != channel)
-  {
-    /* recursive call, I'm the one destroying 'ch' right now */
+    GNUNET_break (0);
     return;
   }
-  ch->channel_reliable = NULL;
-
+  GNUNET_assert (channel == ch->channel);
+  ch->channel = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Cadet channel destroyed by Cadet in state %d\n",
+             "Channel destroyed by CADET in state %d\n",
               ch->status);
   hup.header.size = htons (sizeof (hup));
   hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
   hup.cid = ch->cid;
   switch (ch->status)
   {
+  case CS_CALLEE_INIT:
+    break;
   case CS_CALLEE_RINGING:
   case CS_CALLEE_CONNECTED:
-    GNUNET_SERVER_notification_context_unicast (nc,
-                                                line->client,
-                                                &hup.header,
-                                                GNUNET_NO);
+    if (NULL != line)
+      GNUNET_SERVER_notification_context_unicast (nc,
+                                                  line->client,
+                                                  &hup.header,
+                                                  GNUNET_NO);
     break;
   case CS_CALLEE_SHUTDOWN:
     break;
   case CS_CALLER_CALLING:
   case CS_CALLER_CONNECTED:
-    GNUNET_SERVER_notification_context_unicast (nc,
-                                                line->client,
-                                                &hup.header,
-                                                GNUNET_NO);
+    if (NULL != line)
+      GNUNET_SERVER_notification_context_unicast (nc,
+                                                  line->client,
+                                                  &hup.header,
+                                                  GNUNET_NO);
     break;
   case CS_CALLER_SHUTDOWN:
     break;
   }
   destroy_line_cadet_channels (ch);
+  if (NULL != line)
+    GNUNET_CONTAINER_DLL_remove (line->channel_head,
+                                 line->channel_tail,
+                                 ch);
+  GNUNET_free (ch);
 }
 
 
@@ -1450,45 +1304,83 @@ handle_client_disconnect (void *cls,
                           struct GNUNET_SERVER_Client *client)
 {
   struct Line *line;
+  struct Channel *ch;
+  struct Channel *chn;
 
   if (NULL == client)
     return;
-  line = GNUNET_SERVER_client_get_user_context (client, struct Line);
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
   if (NULL == line)
     return;
-  GNUNET_SERVER_client_set_user_context (client, NULL);
+  GNUNET_SERVER_client_set_user_context (client,
+                                         NULL);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client disconnected, closing line\n");
-  GNUNET_CONTAINER_DLL_remove (lines_head,
-                               lines_tail,
-                               line);
-  while (NULL != line->channel_head)
-    destroy_line_cadet_channels (line->channel_head);
+  if (NULL != line->port)
+  {
+    GNUNET_CADET_close_port (line->port);
+    line->port = NULL;
+  }
+  for (ch = line->channel_head; NULL != ch; ch = chn)
+  {
+    chn = ch->next;
+    ch->line = NULL;
+    destroy_line_cadet_channels (ch);
+  }
   GNUNET_free (line);
 }
 
 
 /**
- * Shutdown nicely
+ * 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
-do_shutdown (void *cls)
+handle_client_register_message (void *cls,
+                                struct GNUNET_SERVER_Client *client,
+                                const struct GNUNET_MessageHeader *message)
 {
+  const struct ClientPhoneRegisterMessage *msg;
   struct Line *line;
-  struct Channel *ch;
 
-  while (NULL != (line = lines_head))
+  msg = (const struct ClientPhoneRegisterMessage *) message;
+  line = GNUNET_SERVER_client_get_user_context (client,
+                                                struct Line);
+  if (NULL != line)
   {
-    while (NULL != (ch = line->channel_head))
-      destroy_line_cadet_channels (ch);
-    GNUNET_CONTAINER_DLL_remove (lines_head,
-                                 lines_tail,
-                                 line);
-    GNUNET_SERVER_client_set_user_context (line->client, NULL);
-    GNUNET_free (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_SERVER_client_set_user_context (client,
+                                         line);
+  line->line_port = msg->line_port;
+  line->port = GNUNET_CADET_open_port (cadet,
+                                       &msg->line_port,
+                                       &inbound_channel,
+                                       line);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
+}
+
+
+/**
+ * Shutdown nicely
+ *
+ * @param cls closure, NULL
+ */
+static void
+do_shutdown (void *cls)
+{
   if (NULL != cadet)
   {
     GNUNET_CADET_disconnect (cadet);
@@ -1564,26 +1456,19 @@ run (void *cls,
                  GNUNET_CRYPTO_get_peer_identity (cfg,
                                                   &my_identity));
   cadet = GNUNET_CADET_connect (cfg,
-                             NULL,
-                             &inbound_end,
-                              cadet_handlers);
-
+                                NULL,
+                                &inbound_end,
+                                cadet_handlers);
   if (NULL == cadet)
   {
     GNUNET_break (0);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-
-  GNUNET_CADET_open_port (cadet,
-                          GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL),
-                          &inbound_channel, NULL);
-  GNUNET_CADET_open_port (cadet,
-                          GC_u2h (GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO),
-                          &inbound_channel, NULL);
-
-  nc = GNUNET_SERVER_notification_context_create (server, 16);
-  GNUNET_SERVER_add_handlers (server, server_handlers);
+  nc = GNUNET_SERVER_notification_context_create (server,
+                                                  16);
+  GNUNET_SERVER_add_handlers (server,
+                              server_handlers);
   GNUNET_SERVER_disconnect_notify (server,
                                   &handle_client_disconnect,
                                   NULL);
index f68377a64179c8c4bb718b6ba05d06257f7c4549..ecdcb2057f8102f4db5ed7b7859f7b2dee79c757 100644 (file)
@@ -49,6 +49,8 @@ conversation_value_to_string (void *cls,
                               const void *data,
                               size_t data_size)
 {
+  char *s;
+
   switch (type)
   {
   case GNUNET_GNSRECORD_TYPE_PHONE:
@@ -63,10 +65,14 @@ conversation_value_to_string (void *cls,
       if (0 != ntohl (pr->version))
        return NULL;
       pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key);
+      s = GNUNET_STRINGS_data_to_string_alloc (&pr->line_port,
+                                               sizeof (struct GNUNET_HashCode));
+
       GNUNET_asprintf (&ret,
-                      "%u-%s",
-                      ntohl (pr->line),
+                      "%s-%s",
+                      s,
                       pkey);
+      GNUNET_free (s);
       GNUNET_free (pkey);
       return ret;
     }
@@ -89,10 +95,10 @@ conversation_value_to_string (void *cls,
  */
 static int
 conversation_string_to_value (void *cls,
-                     uint32_t type,
-                     const char *s,
-                     void **data,
-                     size_t *data_size)
+                              uint32_t type,
+                              const char *s,
+                              void **data,
+                              size_t *data_size)
 {
   if (NULL == s)
     return GNUNET_SYSERR;
@@ -101,16 +107,16 @@ conversation_string_to_value (void *cls,
   case GNUNET_GNSRECORD_TYPE_PHONE:
     {
       struct GNUNET_CONVERSATION_PhoneRecord *pr;
-      unsigned int line;
+      char line_port[128];
       const char *dash;
       struct GNUNET_PeerIdentity peer;
 
       if ( (NULL == (dash = strchr (s, '-'))) ||
-          (1 != sscanf (s, "%u-", &line)) ||
+          (1 != sscanf (s, "%128s-", line_port)) ||
           (GNUNET_OK !=
            GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
-                                                          strlen (dash + 1),
-                                                          &peer.public_key)) )
+                                                        strlen (dash + 1),
+                                                        &peer.public_key)) )
       {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     _("Unable to parse PHONE record `%s'\n"),
@@ -118,8 +124,20 @@ conversation_string_to_value (void *cls,
        return GNUNET_SYSERR;
       }
       pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord);
-      pr->version = htonl (0);
-      pr->line = htonl ((uint32_t) line);
+      pr->version = htonl (1);
+      pr->reserved = htonl (0);
+      if (GNUNET_OK !=
+          GNUNET_STRINGS_string_to_data (line_port,
+                                         strlen (line_port),
+                                         &pr->line_port,
+                                         sizeof (struct GNUNET_HashCode)))
+      {
+       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _("Unable to parse PHONE record `%s'\n"),
+                    s);
+        GNUNET_free (pr);
+        return GNUNET_SYSERR;
+      }
       pr->peer = peer;
       *data = pr;
       *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord);
@@ -153,7 +171,7 @@ static struct {
  */
 static uint32_t
 conversation_typename_to_number (void *cls,
-                        const char *gns_typename)
+                                 const char *gns_typename)
 {
   unsigned int i;
 
@@ -174,7 +192,7 @@ conversation_typename_to_number (void *cls,
  */
 static const char *
 conversation_number_to_typename (void *cls,
-                        uint32_t type)
+                                 uint32_t type)
 {
   unsigned int i;
 
index 421a62682a80016a6fcc8658247bcc0f614510d5..46ea95d52e54b62b6db0b0f5d23bc6524d069d22 100644 (file)
@@ -1,6 +1,7 @@
+@INLINE@ ../../contrib/no_forcestart.conf
+
 [conversation]
 LINE=1
 
 [nse]
 WORKBITS = 0
-
index fd9327805276c345b09045af17b0c1ab7fffe4e6..0bf173d2ba97d93d26d7d7374dc80e23afaf0742 100644 (file)
@@ -317,7 +317,9 @@ caller_event_handler (void *cls,
   {
   case GNUNET_CONVERSATION_EC_CALLER_SUSPEND:
   case GNUNET_CONVERSATION_EC_CALLER_RESUME:
-    fprintf (stderr, "Unexpected caller code: %d\n", code);
+    fprintf (stderr,
+             "Unexpected caller code: %d\n",
+             code);
     break;
   }
 }
index 5f1f836f703a74f1d242e6ca72f0f736ef5e4441..9257764cff5360d24f00ffb93f8f7ad7f24ffe36 100644 (file)
@@ -147,7 +147,8 @@ end_test (void *cls)
   }
   if (NULL != phone)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Disconnecting from PHONE service.\n");
     GNUNET_CONVERSATION_phone_destroy (phone);
     phone = NULL;
   }
@@ -214,8 +215,11 @@ call_event_handler (void *cls,
   case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL:
   case GNUNET_CONVERSATION_EC_CALL_SUSPENDED:
   case GNUNET_CONVERSATION_EC_CALL_RESUMED:
+    fprintf (stderr, "Unexpected call code: %d\n", code);
+    break;
   case GNUNET_CONVERSATION_EC_CALL_ERROR:
     fprintf (stderr, "Unexpected call code: %d\n", code);
+    call = NULL;
     break;
   }
 }