fix more leaks
[oweals/gnunet.git] / src / conversation / conversation_api.c
index 1303586134a982a617830b5190ba075c1212706d..50ee0a23a2c080e2bdb8ae089fc52589c3ef8e08 100644 (file)
@@ -1,17 +1,17 @@
 /*
   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,
@@ -75,7 +75,7 @@ struct GNUNET_CONVERSATION_Phone
    * Our configuration.
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
+
   /**
    * Handle to talk with CONVERSATION service.
    */
@@ -103,7 +103,7 @@ struct GNUNET_CONVERSATION_Phone
 
   /**
    * Connection to NAMESTORE (for reverse lookup).
-   */ 
+   */
   struct GNUNET_NAMESTORE_Handle *ns;
 
   /**
@@ -119,7 +119,7 @@ struct GNUNET_CONVERSATION_Phone
   /**
    * This phone's record.
    */
-  struct GNUNET_CONVERSATION_PhoneRecord my_record;  
+  struct GNUNET_CONVERSATION_PhoneRecord my_record;
 
   /**
    * My GNS zone.
@@ -272,6 +272,8 @@ handle_phone_hangup (void *cls,
     phone->event_handler (phone->event_handler_cls,
                           GNUNET_CONVERSATION_EC_TERMINATED,
                           reason);
+    phone->speaker->disable_speaker (phone->speaker->cls);
+    phone->mic->disable_microphone (phone->mic->cls);
     break;
   }
 }
@@ -314,7 +316,7 @@ handle_phone_audio_message (void *cls,
 
 
 /**
- * We encountered an error talking with the conversation service. 
+ * We encountered an error talking with the conversation service.
  *
  * @param cls the `struct GNUNET_CONVERSATION_Phone`
  * @param error details about the error
@@ -326,6 +328,9 @@ phone_error_handler (void *cls,
   struct GNUNET_CONVERSATION_Phone *phone = cls;
 
   GNUNET_break (0);
+  FPRINTF (stderr,
+           _("Internal error %d\n"),
+           error);
   reconnect_phone (phone);
 }
 
@@ -341,19 +346,24 @@ reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
   static struct GNUNET_MQ_MessageHandler handlers[] =
   {
     { &handle_phone_ring,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_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 }    
+      0 },
+    { NULL, 0, 0 }
   };
   struct GNUNET_MQ_Envelope *e;
   struct ClientPhoneRegisterMessage *reg;
 
+  if (PS_ACTIVE == phone->state)
+  {
+    phone->speaker->disable_speaker (phone->speaker->cls);
+    phone->mic->disable_microphone (phone->mic->cls);
+  }
   if (NULL != phone->mq)
   {
     GNUNET_MQ_destroy (phone->mq);
@@ -398,14 +408,14 @@ GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
   unsigned long long line;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, 
+      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,
+      GNUNET_CRYPTO_get_peer_identity (cfg,
                                        &phone->my_record.peer))
   {
     GNUNET_break (0);
@@ -468,7 +478,7 @@ transmit_phone_audio (void *cls,
   struct ClientAudioMessage *am;
 
   GNUNET_assert (PS_ACTIVE == phone->state);
-  e = GNUNET_MQ_msg_extra (am, 
+  e = GNUNET_MQ_msg_extra (am,
                            data_size,
                            GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
   memcpy (&am[1], data, data_size);
@@ -477,7 +487,7 @@ transmit_phone_audio (void *cls,
 
 
 /**
- * Picks up a (ringing) phone.  This will connect the speaker 
+ * 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
@@ -620,7 +630,7 @@ struct GNUNET_CONVERSATION_Call
    * Our configuration.
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
+
   /**
    * Handle to talk with CONVERSATION service.
    */
@@ -645,7 +655,7 @@ struct GNUNET_CONVERSATION_Call
    * Our microphone.
    */
   struct GNUNET_MICROPHONE_Handle *mic;
-  
+
   /**
    * Function to call with events.
    */
@@ -663,7 +673,7 @@ struct GNUNET_CONVERSATION_Call
 
   /**
    * Connection to GNS (can be NULL).
-   */ 
+   */
   struct GNUNET_GNS_Handle *gns;
 
   /**
@@ -744,7 +754,7 @@ transmit_call_audio (void *cls,
   struct ClientAudioMessage *am;
 
   GNUNET_assert (CS_ACTIVE == call->state);
-  e = GNUNET_MQ_msg_extra (am, 
+  e = GNUNET_MQ_msg_extra (am,
                            data_size,
                            GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
   memcpy (&am[1], data, data_size);
@@ -772,7 +782,7 @@ handle_call_picked_up (void *cls,
   metadata = (const char *) &am[1];
   if ( (0 == size) ||
        ('\0' != metadata[size - 1]) )
-    metadata = NULL;  
+    metadata = NULL;
   switch (call->state)
   {
   case CS_LOOKUP:
@@ -820,7 +830,7 @@ handle_call_hangup (void *cls,
   reason = (const char *) &am[1];
   if ( (0 == size) ||
        ('\0' != reason[size - 1]) )
-    reason = NULL;  
+    reason = NULL;
   switch (call->state)
   {
   case CS_LOOKUP:
@@ -890,7 +900,7 @@ handle_call_audio_message (void *cls,
  * @param rd_count number of records in @a rd
  * @param rd the records in reply
  */
-static void 
+static void
 handle_gns_response (void *cls,
                      uint32_t rd_count,
                      const struct GNUNET_NAMESTORE_RecordData *rd)
@@ -900,6 +910,7 @@ handle_gns_response (void *cls,
   struct GNUNET_MQ_Envelope *e;
   struct ClientCallMessage *ccm;
 
+  call->gns_lookup = NULL;
   for (i=0;i<rd_count;i++)
   {
     if (GNUNET_NAMESTORE_TYPE_PHONE == rd[i].record_type)
@@ -908,7 +919,7 @@ handle_gns_response (void *cls,
       {
         GNUNET_break_op (0);
         continue;
-      }      
+      }
       memcpy (&call->phone_record,
               rd[i].data,
               rd[i].data_size);
@@ -931,7 +942,7 @@ handle_gns_response (void *cls,
 
 
 /**
- * We encountered an error talking with the conversation service. 
+ * We encountered an error talking with the conversation service.
  *
  * @param cls the `struct GNUNET_CONVERSATION_Call`
  * @param error details about the error
@@ -943,6 +954,9 @@ call_error_handler (void *cls,
   struct GNUNET_CONVERSATION_Call *call = cls;
 
   GNUNET_break (0);
+  FPRINTF (stderr,
+           _("Internal error %d\n"),
+           error);
   reconnect_call (call);
 }
 
@@ -958,20 +972,27 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
   static struct GNUNET_MQ_MessageHandler handlers[] =
   {
     { &handle_call_busy,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY, 
+      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY,
       sizeof (struct ClientPhoneBusyMessage) },
     { &handle_call_picked_up,
-      GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_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 }    
+      0 },
+    { NULL, 0, 0 }
   };
- if (NULL != call->mq)
+  struct GNUNET_CRYPTO_EccPublicSignKey my_zone;
+
+  if (CS_ACTIVE == call->state)
+  {
+    call->speaker->disable_speaker (call->speaker->cls);
+    call->mic->disable_microphone (call->mic->cls);
+  }
+  if (NULL != call->mq)
   {
     GNUNET_MQ_destroy (call->mq);
     call->mq = NULL;
@@ -981,6 +1002,7 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
     GNUNET_CLIENT_disconnect (call->client);
     call->client = NULL;
   }
+  call->state = CS_SHUTDOWN;
   call->client = GNUNET_CLIENT_connect ("conversation", call->cfg);
   if (NULL == call->client)
     return;
@@ -988,6 +1010,17 @@ reconnect_call (struct GNUNET_CONVERSATION_Call *call)
                                                     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_NAMESTORE_TYPE_PHONE,
+                                        GNUNET_NO,
+                                        NULL /* FIXME: add shortening support */,
+                                        &handle_gns_response, call);
+  GNUNET_assert (NULL != call->gns_lookup);
 }
 
 
@@ -1015,10 +1048,7 @@ GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
                                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;
@@ -1036,17 +1066,25 @@ GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
     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;
 }
 
 
+/**
+ * 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, NULL);
+}
+
+
 /**
  * Terminate a call.  The call may be ringing or ready at this time.
  *
@@ -1058,23 +1096,25 @@ void
 GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call,
                               const char *reason)
 {
+  struct GNUNET_MQ_Envelope *e;
+  struct ClientPhoneHangupMessage *hang;
+  size_t slen;
+
+  if ( (NULL != call->speaker) &&
+       (CS_ACTIVE == call->state) )
+    call->speaker->disable_speaker (call->speaker->cls);
+  if ( (NULL != call->mic) &&
+       (CS_ACTIVE == call->state) )
+    call->mic->disable_microphone (call->mic->cls);
   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;
+    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_notify_sent (e, &finish_stop, call);
+    GNUNET_MQ_send (call->mq, e);
+    call->state = CS_SHUTDOWN;
+    return;
   }
   if (NULL != call->mq)
   {
@@ -1096,7 +1136,7 @@ GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call,
     GNUNET_GNS_disconnect (call->gns);
     call->gns = NULL;
   }
-
+  GNUNET_free (call->callee);
   GNUNET_free (call);
 }