]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Applied patch to fix some race conditions on call termination, thanks Peter Olsson
authorRobert Joly <rjoly@nortel.com>
Tue, 14 Apr 2009 07:10:55 +0000 (07:10 +0000)
committerRobert Joly <rjoly@nortel.com>
Tue, 14 Apr 2009 07:10:55 +0000 (07:10 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13014 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_opal/mod_opal.cpp
src/mod/endpoints/mod_opal/mod_opal.h

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