[Freeswitch-svn] [commit] r13014 - freeswitch/trunk/src/mod/endpoints/mod_opal

FreeSWITCH SVN robertj at freeswitch.org
Tue Apr 14 00:10:55 PDT 2009


Author: robertj
Date: Tue Apr 14 02:10:55 2009
New Revision: 13014

Log:
Applied patch to fix some race conditions on call termination, thanks Peter Olsson

Modified:
   freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.cpp
   freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.h

Modified: freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.cpp
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.cpp	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.cpp	Tue Apr 14 02:10:55 2009
@@ -72,12 +72,12 @@
     /*.on_hangup */ on_hangup,
     /*.on_exchange_media */ FSConnection::on_exchange_media,
     /*.on_soft_execute */ FSConnection::on_soft_execute,
-	/*.on_consume_media*/ NULL,
-	/*.on_hibernate*/ NULL,
-	/*.on_reset*/ NULL,
-	/*.on_park*/ NULL,
-	/*.on_reporting*/ NULL,
-	/*.on_destroy*/ on_destroy
+    /*.on_consume_media*/ NULL,
+    /*.on_hibernate*/ NULL,
+    /*.on_reset*/ NULL,
+    /*.on_park*/ NULL,
+    /*.on_reporting*/ NULL,
+    /*.on_destroy*/ on_destroy
 };
 
 
@@ -510,7 +510,20 @@
 
 OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userData)
 {
-    return new FSConnection(call, *this, (switch_caller_profile_t *)userData);
+    FSManager & mgr = (FSManager &) GetManager();
+    switch_core_session_t *fsSession = switch_core_session_request(mgr.GetSwitchInterface(), 
+                                       (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
+    if (fsSession == NULL)
+        return NULL;
+
+    switch_channel_t *fsChannel = switch_core_session_get_channel(fsSession);
+
+    if (fsChannel == NULL) {
+        switch_core_session_destroy(&fsSession);
+        return NULL;
+    }
+
+    return new FSConnection(call, *this, (switch_caller_profile_t *)userData, fsSession, fsChannel);
 }
 
 
@@ -543,15 +556,13 @@
 ///////////////////////////////////////////////////////////////////////
 
 
-FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile)
+FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile, switch_core_session_t *fsSession, switch_channel_t *fsChannel)
   : OpalLocalConnection(call, endpoint, NULL)
   , m_endpoint(endpoint)
+  , m_fsSession(fsSession)
+  , m_fsChannel(fsChannel)
 {
     opal_private_t *tech_pvt;
-    FSManager & mgr = (FSManager &) endpoint.GetManager();
-    m_fsSession = switch_core_session_request(mgr.GetSwitchInterface(), 
-                                              outbound_profile ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
-    m_fsChannel = switch_core_session_get_channel(m_fsSession);
 
     tech_pvt = (opal_private_t *) switch_core_session_alloc(m_fsSession, sizeof(*tech_pvt));
     tech_pvt->me = this;
@@ -679,8 +690,7 @@
 PBoolean FSConnection::SendUserInputTone(char tone, unsigned duration)
 {
     switch_dtmf_t dtmf = { tone, duration };
-
-    return (switch_channel_queue_dtmf(m_fsChannel, &dtmf) == SWITCH_STATUS_SUCCESS) ? true : false;
+    return switch_channel_queue_dtmf(m_fsChannel, &dtmf) == SWITCH_STATUS_SUCCESS;
 }
 
 OpalMediaFormatList FSConnection::GetMediaFormats() const
@@ -697,37 +707,37 @@
 {
     int numCodecs = 0;
     const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];    
-	const char *codec_string = NULL, *abs, *ocodec;
+    const char *codec_string = NULL, *abs, *ocodec;
     char *tmp_codec_string = NULL;
     char *codec_order[SWITCH_MAX_CODECS];
     int codec_order_last;
 
 
-	if ((abs = switch_channel_get_variable(m_fsChannel, "absolute_codec_string"))) {
-		codec_string = abs;
-	} else {
-		if ((abs = switch_channel_get_variable(m_fsChannel, "codec_string"))) {
+    if ((abs = switch_channel_get_variable(m_fsChannel, "absolute_codec_string"))) {
+        codec_string = abs;
+    } else {
+        if ((abs = switch_channel_get_variable(m_fsChannel, "codec_string"))) {
             codec_string = abs;
-		}
+        }
 
-		if ((ocodec = switch_channel_get_variable(m_fsChannel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
+        if ((ocodec = switch_channel_get_variable(m_fsChannel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
             codec_string = switch_core_session_sprintf(m_fsSession, "%s,%s", ocodec, codec_string);
-		}
-	}
+        }
+    }
     
     if (!codec_string) {
         codec_string = mod_opal_globals.codec_string;
     }
 
-	if (codec_string) {
-		if ((tmp_codec_string = strdup(codec_string))) {
-			codec_order_last = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
+    if (codec_string) {
+        if ((tmp_codec_string = strdup(codec_string))) {
+            codec_order_last = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
             numCodecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, codec_order, codec_order_last);
             
-		}
-	} else {
-		numCodecs = switch_loadable_module_get_codecs(codecs, sizeof(codecs) / sizeof(codecs[0]));
-	}
+        }
+    } else {
+        numCodecs = switch_loadable_module_get_codecs(codecs, sizeof(codecs) / sizeof(codecs[0]));
+    }
     
     for (int i = 0; i < numCodecs; i++) {
         const switch_codec_implementation_t *codec = codecs[i];
@@ -843,34 +853,34 @@
 {
     //switch_channel_t *channel = switch_core_session_get_channel(session);
     opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session);
-
+    
     if (tech_pvt) {
-        if (tech_pvt->read_codec.implementation) {
-            switch_core_codec_destroy(&tech_pvt->read_codec);
-        }
+    if (tech_pvt->read_codec.implementation) {
+        switch_core_codec_destroy(&tech_pvt->read_codec);
+    }
 
-        if (tech_pvt->write_codec.implementation) {
-            switch_core_codec_destroy(&tech_pvt->write_codec);
-        }
+    if (tech_pvt->write_codec.implementation) {
+        switch_core_codec_destroy(&tech_pvt->write_codec);
+    }
 
-        if (tech_pvt->vid_read_codec.implementation) {
-            switch_core_codec_destroy(&tech_pvt->vid_read_codec);
-        }
+    if (tech_pvt->vid_read_codec.implementation) {
+        switch_core_codec_destroy(&tech_pvt->vid_read_codec);
+    }
 
-        if (tech_pvt->vid_write_codec.implementation) {
-            switch_core_codec_destroy(&tech_pvt->vid_write_codec);
-        }
+    if (tech_pvt->vid_write_codec.implementation) {
+        switch_core_codec_destroy(&tech_pvt->vid_write_codec);
+    }
 
-        if (tech_pvt->read_timer.timer_interface) {
-            switch_core_timer_destroy(&tech_pvt->read_timer);
-        }
+    if (tech_pvt->read_timer.timer_interface) {
+        switch_core_timer_destroy(&tech_pvt->read_timer);
+    }
 
-        if (tech_pvt->vid_read_timer.timer_interface) {
-            switch_core_timer_destroy(&tech_pvt->vid_read_timer);
-        }
+    if (tech_pvt->vid_read_timer.timer_interface) {
+        switch_core_timer_destroy(&tech_pvt->vid_read_timer);
+    }
     }
 
-	return SWITCH_STATUS_SUCCESS;
+    return SWITCH_STATUS_SUCCESS;
 }
 
 /* this function has to be called with the original session beause the FSConnection might already be destroyed and we 
@@ -888,7 +898,7 @@
         tech_pvt->me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
         tech_pvt->me = NULL;
     }
-    
+
     return SWITCH_STATUS_SUCCESS;
 }
 
@@ -974,6 +984,14 @@
         OnAlerting();
         break;
 
+    case SWITCH_MESSAGE_INDICATE_DEFLECT:
+    {
+        char transfer_to[128] = "";
+        switch_set_string(transfer_to, msg->string_arg);
+        TransferConnection(transfer_to);
+        break;
+    }
+
     case SWITCH_MESSAGE_INDICATE_PROGRESS:
     case SWITCH_MESSAGE_INDICATE_ANSWER:
         {
@@ -1163,6 +1181,7 @@
                                        m_switchCodec->implementation->samples_per_packet,
                                        switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
                 switch_core_codec_destroy(m_switchCodec);
+                m_switchCodec = NULL;
                 return false;
             }
         } else {
@@ -1189,7 +1208,12 @@
 {
     if (!IsOpen())
         return false;
-    
+
+    /* forget these FS will properly destroy them for us */
+
+    m_switchTimer = NULL;
+    m_switchCodec = NULL;
+
     return OpalMediaStream::Close();
 }
 
@@ -1205,6 +1229,21 @@
     return false;
 }
 
+bool FSMediaStream::CheckPatchAndLock()
+{
+    if (GetConnection().GetPhase() >= GetConnection().ReleasingPhase || !IsOpen())
+        return false;
+
+    if (LockReadWrite()) {
+        if (!GetPatch() || !IsOpen()) {
+            UnlockReadWrite();
+            return false;
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
 
 switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag_t flags)
 {
@@ -1222,16 +1261,27 @@
         while(!GetPatch()) {
             switch_cond_next();
         }
-        GetPatch()->OnPatchStart();
-        m_callOnStart = false;
+        if (CheckPatchAndLock()) {
+            GetPatch()->OnPatchStart();
+            m_callOnStart = false;
+            UnlockReadWrite();
+        } else {
+            return SWITCH_STATUS_FALSE; 
+        }
     }
 
     m_readFrame.flags = 0;
 
     /*
     while (switch_channel_ready(m_fsChannel)) {
-        if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
-            return SWITCH_STATUS_FALSE;
+        if (CheckPatchAndLock()) {
+            if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
+                UnlockReadWrite();
+                return SWITCH_STATUS_FALSE;
+            }            
+            UnlockReadWrite();
+        } else {
+            return SWITCH_STATUS_FALSE; 
         }
         
         if ((m_readFrame.datalen = m_readRTP.GetPayloadSize()) || switch_core_timer_check(&m_switchTimer, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
@@ -1249,9 +1299,16 @@
     if (switch_channel_test_private_flag(m_fsChannel, CF_NEED_FLUSH)) {
         switch_channel_clear_private_flag(m_fsChannel, CF_NEED_FLUSH);
         for(;;) {
-            if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
-                return SWITCH_STATUS_FALSE;
+            if (CheckPatchAndLock()) {
+                if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
+                    UnlockReadWrite();
+                    return SWITCH_STATUS_FALSE;
+                }            
+                UnlockReadWrite();
+            } else {
+                return SWITCH_STATUS_FALSE; 
             }
+
             if (!m_readRTP.GetPayloadSize()) {
                 m_readFrame.flags = SFF_CNG;
                 break;
@@ -1259,8 +1316,14 @@
         }
     } else {
 
-        if (!m_switchTimer || !GetPatch()->GetSource().ReadPacket(m_readRTP)) {
-            return SWITCH_STATUS_FALSE;
+        if (CheckPatchAndLock()) {
+            if (!m_switchTimer || !GetPatch()->GetSource().ReadPacket(m_readRTP)) {
+                UnlockReadWrite();
+                return SWITCH_STATUS_FALSE;
+            }            
+            UnlockReadWrite();
+        } else {
+            return SWITCH_STATUS_FALSE; 
         }
     
         switch_core_timer_next(m_switchTimer);
@@ -1303,8 +1366,13 @@
     }
 
     if (m_callOnStart) {
-        GetPatch()->OnPatchStart();
-        m_callOnStart = false;
+        if (CheckPatchAndLock()) {
+            GetPatch()->OnPatchStart();
+            m_callOnStart = false;
+            UnlockReadWrite();
+        } else {
+            return SWITCH_STATUS_FALSE; 
+        }
     }
 
     if ((frame->flags & SFF_CNG)) {
@@ -1313,8 +1381,15 @@
 
     if ((frame->flags & SFF_RAW_RTP) != 0) {
         RTP_DataFrame rtp((const BYTE *) frame->packet, frame->packetlen, false);
-        if (GetPatch()->PushFrame(rtp)) {
-            return SWITCH_STATUS_SUCCESS;
+
+        if (CheckPatchAndLock()) {
+            if (GetPatch()->PushFrame(rtp)) {
+                UnlockReadWrite();
+                return SWITCH_STATUS_SUCCESS;
+            }
+            UnlockReadWrite();
+        } else {
+            return SWITCH_STATUS_FALSE; 
         }
     } 
     
@@ -1337,8 +1412,14 @@
 
     memcpy(rtp.GetPayloadPtr(), frame->data, frame->datalen);
 
-    if (GetPatch()->PushFrame(rtp)) {
-        return SWITCH_STATUS_SUCCESS;
+    if (CheckPatchAndLock()) {
+        if (GetPatch()->PushFrame(rtp)) {
+            UnlockReadWrite();
+            return SWITCH_STATUS_SUCCESS;
+        }
+        UnlockReadWrite();
+    } else {
+        return SWITCH_STATUS_FALSE; 
     }
 
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_opal/mod_opal.h	Tue Apr 14 02:10:55 2009
@@ -177,7 +177,11 @@
     PCLASSINFO(FSConnection, OpalLocalConnection)
 
   public:
-    FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile);
+    FSConnection(OpalCall & call,
+                 FSEndPoint & endpoint,
+                 switch_caller_profile_t *outbound_profile,
+                 switch_core_session_t *fsSession,
+                 switch_channel_t *fsChannel);
 
     virtual bool OnIncoming();
     virtual void OnReleased();
@@ -194,7 +198,6 @@
     DECLARE_CALLBACK0(on_init);
     DECLARE_CALLBACK0(on_routing);
     DECLARE_CALLBACK0(on_execute);
-    //DECLARE_CALLBACK0(on_hangup);
 
     DECLARE_CALLBACK0(on_exchange_media);
     DECLARE_CALLBACK0(on_soft_execute);
@@ -251,6 +254,8 @@
     RTP_DataFrame m_readRTP;
     bool m_callOnStart;
     uint32_t m_timeStamp;
+
+    bool CheckPatchAndLock();
 };
 
 



More information about the Freeswitch-svn mailing list