-rps: merge duplicate functions
[oweals/gnunet.git] / src / conversation / conversation_api_call.c
index 20992c6b58ce6de08fad6348230aebaea0e32e60..0984290d3fe256efde027e4788e346c1617ccb09 100644 (file)
@@ -1,6 +1,6 @@
 /*
   This file is part of GNUnet
-  (C) 2013 Christian Grothoff (and other contributing authors)
+  Copyright (C) 2013 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
@@ -14,8 +14,8 @@
 
   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.
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
  */
 
 /**
@@ -95,6 +95,11 @@ struct GNUNET_CONVERSATION_Call
    */
   struct GNUNET_IDENTITY_Ego *caller_id;
 
+  /**
+   * GNS zone to use to resolve @e callee.
+   */
+  struct GNUNET_IDENTITY_Ego *zone_id;
+
   /**
    * Target callee as a GNS address/name.
    */
@@ -215,10 +220,10 @@ handle_call_suspend (void *cls,
     break;
   case CS_ACTIVE:
     call->state = CS_SUSPENDED_CALLEE;
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_CALL_SUSPENDED);
     call->speaker->disable_speaker (call->speaker->cls);
     call->mic->disable_microphone (call->mic->cls);
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_CALL_SUSPENDED);
     break;
   case CS_SHUTDOWN:
     GNUNET_CONVERSATION_call_stop (call);
@@ -254,12 +259,12 @@ handle_call_resume (void *cls,
     break;
   case CS_SUSPENDED_CALLEE:
     call->state = CS_ACTIVE;
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_CALL_RESUMED);
     call->speaker->enable_speaker (call->speaker->cls);
     call->mic->enable_microphone (call->mic->cls,
                                   &transmit_call_audio,
                                   call);
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_CALL_RESUMED);
     break;
   case CS_SUSPENDED_BOTH:
     call->state = CS_SUSPENDED_CALLER;
@@ -296,12 +301,12 @@ handle_call_picked_up (void *cls,
     break;
   case CS_RINGING:
     call->state = CS_ACTIVE;
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_CALL_PICKED_UP);
     call->speaker->enable_speaker (call->speaker->cls);
     call->mic->enable_microphone (call->mic->cls,
                                   &transmit_call_audio,
                                   call);
+    call->event_handler (call->event_handler_cls,
+                         GNUNET_CONVERSATION_EC_CALL_PICKED_UP);
     break;
   case CS_SUSPENDED_CALLER:
   case CS_SUSPENDED_CALLEE:
@@ -328,6 +333,8 @@ handle_call_hangup (void *cls,
                     const struct GNUNET_MessageHeader *msg)
 {
   struct GNUNET_CONVERSATION_Call *call = cls;
+  GNUNET_CONVERSATION_CallEventHandler eh;
+  void *eh_cls;
 
   switch (call->state)
   {
@@ -340,9 +347,10 @@ handle_call_hangup (void *cls,
   case CS_SUSPENDED_CALLEE:
   case CS_SUSPENDED_BOTH:
   case CS_ACTIVE:
-    call->event_handler (call->event_handler_cls,
-                         GNUNET_CONVERSATION_EC_CALL_HUNG_UP);
+    eh = call->event_handler;
+    eh_cls = call->event_handler_cls;
     GNUNET_CONVERSATION_call_stop (call);
+    eh (eh_cls, GNUNET_CONVERSATION_EC_CALL_HUNG_UP);
     return;
   case CS_SHUTDOWN:
     GNUNET_CONVERSATION_call_stop (call);
@@ -381,7 +389,7 @@ handle_call_audio_message (void *cls,
     break;
   case CS_SUSPENDED_CALLEE:
   case CS_SUSPENDED_BOTH:
-    /* can (rarely) also happen: other peer suspended, but mesh might
+    /* can (rarely) also happen: other peer suspended, but cadet might
        have had delayed data on the unreliable channel */
     break;
   case CS_ACTIVE:
@@ -413,6 +421,8 @@ handle_gns_response (void *cls,
   struct GNUNET_MQ_Envelope *e;
   struct ClientCallMessage *ccm;
 
+  GNUNET_break (NULL != call->gns_lookup);
+  GNUNET_break (CS_LOOKUP == call->state);
   call->gns_lookup = NULL;
   for (i=0;i<rd_count;i++)
   {
@@ -475,27 +485,6 @@ call_error_handler (void *cls,
 static void
 reconnect_call (struct GNUNET_CONVERSATION_Call *call)
 {
-  static struct GNUNET_MQ_MessageHandler handlers[] =
-  {
-    { &handle_call_suspend,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
-      sizeof (struct ClientPhoneSuspendMessage) },
-    { &handle_call_resume,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
-      sizeof (struct ClientPhoneResumeMessage) },
-    { &handle_call_picked_up,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP,
-      sizeof (struct ClientPhonePickedupMessage) },
-    { &handle_call_hangup,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
-      sizeof (struct ClientPhoneHangupMessage) },
-    { &handle_call_audio_message,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
-      0 },
-    { NULL, 0, 0 }
-  };
-  struct GNUNET_CRYPTO_EcdsaPublicKey my_zone;
-
   if (CS_ACTIVE == call->state)
   {
     call->speaker->disable_speaker (call->speaker->cls);
@@ -512,24 +501,9 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
     call->client = NULL;
   }
   call->state = CS_SHUTDOWN;
-  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->state = CS_LOOKUP;
-  GNUNET_IDENTITY_ego_get_public_key (call->caller_id,
-                                      &my_zone);
-  call->gns_lookup = GNUNET_GNS_lookup (call->gns,
-                                        call->callee,
-                                        &my_zone,
-                                        GNUNET_GNSRECORD_TYPE_PHONE,
-                                        GNUNET_NO,
-                                        NULL /* FIXME: add shortening support */,
-                                        &handle_gns_response, call);
-  GNUNET_assert (NULL != call->gns_lookup);
+  call->event_handler (call->event_handler_cls,
+                       GNUNET_CONVERSATION_EC_CALL_ERROR);
+  GNUNET_CONVERSATION_call_stop (call);
 }
 
 
@@ -538,6 +512,7 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
  *
  * @param cfg configuration to use, specifies our phone service
  * @param caller_id identity of the caller
+ * @param zone_id GNS zone to use to resolve @a callee
  * @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_CALL_PICKED_UP event is generated); we will NOT generate
@@ -546,54 +521,81 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
  *        #GNUNET_CONVERSATION_EC_CALL_PICKED_UP 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
+ * @return handle for the call, NULL on hard errors
  */
 struct GNUNET_CONVERSATION_Call *
 GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                struct GNUNET_IDENTITY_Ego *caller_id,
+                               struct GNUNET_IDENTITY_Ego *zone_id,
                                const char *callee,
                                struct GNUNET_SPEAKER_Handle *speaker,
                                struct GNUNET_MICROPHONE_Handle *mic,
                                GNUNET_CONVERSATION_CallEventHandler event_handler,
                                void *event_handler_cls)
 {
+  static struct GNUNET_MQ_MessageHandler handlers[] =
+  {
+    { &handle_call_suspend,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
+      sizeof (struct ClientPhoneSuspendMessage) },
+    { &handle_call_resume,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
+      sizeof (struct ClientPhoneResumeMessage) },
+    { &handle_call_picked_up,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP,
+      sizeof (struct ClientPhonePickedupMessage) },
+    { &handle_call_hangup,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
+      sizeof (struct ClientPhoneHangupMessage) },
+    { &handle_call_audio_message,
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
+      0 },
+    { NULL, 0, 0 }
+  };
+  struct GNUNET_CRYPTO_EcdsaPublicKey my_zone;
   struct GNUNET_CONVERSATION_Call *call;
 
   call = GNUNET_new (struct GNUNET_CONVERSATION_Call);
+  call->client = GNUNET_CLIENT_connect ("conversation", cfg);
+  if (NULL == call->client)
+  {
+    GNUNET_break (0);
+    GNUNET_free (call);
+    return NULL;
+  }
   call->cfg = cfg;
   call->caller_id = caller_id;
+  call->zone_id = zone_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) )
+  if (NULL == call->gns)
   {
     GNUNET_CONVERSATION_call_stop (call);
     return NULL;
   }
+  call->mq = GNUNET_MQ_queue_for_connection_client (call->client,
+                                                    handlers,
+                                                    &call_error_handler,
+                                                    call);
+  call->state = CS_LOOKUP;
+  GNUNET_IDENTITY_ego_get_public_key (call->zone_id,
+                                      &my_zone);
+  call->gns_lookup = GNUNET_GNS_lookup (call->gns,
+                                        call->callee,
+                                        &my_zone,
+                                        GNUNET_GNSRECORD_TYPE_PHONE,
+                                        GNUNET_NO,
+                                        NULL /* FIXME: add shortening support */,
+                                        &handle_gns_response, call);
+  GNUNET_assert (NULL != call->gns_lookup);
   return call;
 }
 
 
-/**
- * We've sent the hang up message, now finish terminating the call.
- *
- * @param cls the `struct GNUNET_CONVERSATION_Call` to terminate
- */
-static void
-finish_stop (void *cls)
-{
-  struct GNUNET_CONVERSATION_Call *call = cls;
-
-  GNUNET_assert (CS_SHUTDOWN == call->state);
-  GNUNET_CONVERSATION_call_stop (call);
-}
-
-
 /**
  * Terminate a call.  The call may be ringing or ready at this time.
  *
@@ -602,9 +604,6 @@ finish_stop (void *cls)
 void
 GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call)
 {
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientPhoneHangupMessage *hang;
-
   if ( (NULL != call->speaker) &&
        (CS_ACTIVE == call->state) )
     call->speaker->disable_speaker (call->speaker->cls);
@@ -614,10 +613,6 @@ GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call)
   if (CS_SHUTDOWN != call->state)
   {
     call->state = CS_SHUTDOWN;
-    e = GNUNET_MQ_msg (hang, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
-    GNUNET_MQ_notify_sent (e, &finish_stop, call);
-    GNUNET_MQ_send (call->mq, e);
-    return;
   }
   if (NULL != call->mq)
   {