-fix crash observed on FreeBSD
[oweals/gnunet.git] / src / conversation / conversation_api_call.c
index a57bf1ddb6a6be2deba059fb0db7c8d6a8126bb2..f69a6518cfc2fd997e688605094d6ecfed3d1672 100644 (file)
@@ -215,10 +215,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 +254,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 +296,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 +328,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 +342,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 +384,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 +416,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++)
   {
@@ -456,10 +461,13 @@ call_error_handler (void *cls,
 {
   struct GNUNET_CONVERSATION_Call *call = cls;
 
-  GNUNET_break (0);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              _("Internal MQ error %d\n"),
-              error);
+  if (CS_SHUTDOWN == call->state)
+  {
+    GNUNET_CONVERSATION_call_stop (call);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              _("Connection to conversation service lost, trying to reconnect\n"));
   reconnect_call (call);
 }
 
@@ -511,7 +519,12 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
   call->state = CS_SHUTDOWN;
   call->client = GNUNET_CLIENT_connect ("conversation", call->cfg);
   if (NULL == call->client)
+  {
+    call->event_handler (call->event_handler_cls,
+                       GNUNET_CONVERSATION_EC_CALL_ERROR);
     return;
+  }
+
   call->mq = GNUNET_MQ_queue_for_connection_client (call->client,
                                                     handlers,
                                                     &call_error_handler,
@@ -537,10 +550,10 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
  * @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
+ *        #GNUNET_CONVERSATION_EC_CALL_PICKED_UP 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)
+ *        #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
  */
@@ -576,34 +589,14 @@ GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
 }
 
 
-/**
- * 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.
  *
  * @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)
 {
-  struct GNUNET_MQ_Envelope *e;
-  struct ClientPhoneHangupMessage *hang;
-
   if ( (NULL != call->speaker) &&
        (CS_ACTIVE == call->state) )
     call->speaker->disable_speaker (call->speaker->cls);
@@ -612,11 +605,7 @@ GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call)
     call->mic->disable_microphone (call->mic->cls);
   if (CS_SHUTDOWN != call->state)
   {
-    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);
     call->state = CS_SHUTDOWN;
-    return;
   }
   if (NULL != call->mq)
   {
@@ -652,26 +641,61 @@ GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call)
 void
 GNUNET_CONVERSATION_call_suspend (struct GNUNET_CONVERSATION_Call *call)
 {
-  GNUNET_break (0);
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhoneSuspendMessage *suspend;
+
+  GNUNET_assert ( (CS_SUSPENDED_CALLEE == call->state) ||
+                  (CS_ACTIVE == call->state) );
+  if (CS_ACTIVE == call->state)
+  {
+    call->speaker->disable_speaker (call->speaker->cls);
+    call->mic->disable_microphone (call->mic->cls);
+  }
+  call->speaker = NULL;
+  call->mic = NULL;
+  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
+    call->state = CS_SUSPENDED_CALLER;
 }
 
 
 /**
- * Resumes a call after #GNUNET_CONVERSATION_call_pause.
+ * Resumes a call after #GNUNET_CONVERSATION_call_suspend.
  *
  * @param call call to resume
- * @param speaker speaker to use (will be used automatically immediately once the
- *        #GNUNET_CONVERSATION_EC_READY event is generated); we will NOT generate
+ * @param speaker speaker to use
  *        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 mic microphone to use
  */
 void
 GNUNET_CONVERSATION_call_resume (struct GNUNET_CONVERSATION_Call *call,
                                  struct GNUNET_SPEAKER_Handle *speaker,
                                  struct GNUNET_MICROPHONE_Handle *mic)
 {
-  GNUNET_break (0);
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhoneResumeMessage *resume;
+
+  GNUNET_assert ( (CS_SUSPENDED_CALLER == call->state) ||
+                  (CS_SUSPENDED_BOTH == call->state) );
+  e = GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
+  GNUNET_MQ_send (call->mq, e);
+  call->speaker = speaker;
+  call->mic = mic;
+  if (CS_SUSPENDED_CALLER == call->state)
+  {
+    call->state = CS_ACTIVE;
+    call->speaker->enable_speaker (call->speaker->cls);
+    call->mic->enable_microphone (call->mic->cls,
+                                  &transmit_call_audio,
+                                  call);
+  }
+  else
+  {
+    call->state = CS_SUSPENDED_CALLEE;
+  }
 }