]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
changes to put freeswitch in control of lifecycle of some critical objects, -sigh
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 12 Feb 2009 00:26:04 +0000 (00:26 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 12 Feb 2009 00:26:04 +0000 (00:26 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11899 d0543943-73ff-0310-b7d9-9358b9ac24b2

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

index 7e21b078916427c1a68fe7be229dd07b2c97954c..4526942535b3de239aad6c6451cd75d03158c593 100644 (file)
@@ -47,6 +47,9 @@ static FSProcess *opal_process = NULL;
 static const char ModuleName[] = "opal";\r
 \r
 \r
+static switch_status_t on_hangup(switch_core_session_t *session);\r
+\r
+\r
 static switch_io_routines_t opalfs_io_routines = {\r
     /*.outgoing_channel */ create_outgoing_channel,\r
     /*.read_frame */ FSConnection::read_audio_frame,\r
@@ -64,7 +67,7 @@ static switch_state_handler_table_t opalfs_event_handlers = {
     /*.on_init */ FSConnection::on_init,\r
     /*.on_routing */ FSConnection::on_routing,\r
     /*.on_execute */ FSConnection::on_execute,\r
-    /*.on_hangup */ FSConnection::on_hangup,\r
+    /*.on_hangup */ on_hangup,\r
     /*.on_loopback */ FSConnection::on_loopback,\r
     /*.on_transmit */ FSConnection::on_transmit\r
 };\r
@@ -486,14 +489,19 @@ OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userDat
 \r
 ///////////////////////////////////////////////////////////////////////\r
 \r
+\r
 FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint)\r
   : OpalLocalConnection(call, endpoint, NULL)\r
   , m_endpoint(endpoint)\r
 {\r
+    opal_private_t *tech_pvt;\r
     FSManager & mgr = (FSManager &) endpoint.GetManager();\r
     m_fsSession = switch_core_session_request(mgr.GetSwitchInterface(), NULL);\r
     m_fsChannel = switch_core_session_get_channel(m_fsSession);\r
-    switch_core_session_set_private(m_fsSession, this);\r
+\r
+    tech_pvt = (opal_private_t *) switch_core_session_alloc(m_fsSession, sizeof(*tech_pvt));\r
+    tech_pvt->me = this;\r
+    switch_core_session_set_private(m_fsSession, tech_pvt);\r
 }\r
 \r
 \r
@@ -568,11 +576,16 @@ bool FSConnection::OnIncoming()
 \r
 void FSConnection::OnReleased()\r
 {\r
+    opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(m_fsSession);\r
+    \r
+    /* so FS on_hangup will not try to deref a landmine */\r
+    tech_pvt->me = NULL;\r
+    \r
     m_rxAudioOpened.Signal();   // Just in case\r
     m_txAudioOpened.Signal();\r
     H225_ReleaseCompleteReason dummy;\r
     switch_channel_hangup(switch_core_session_get_channel(m_fsSession),\r
-                          (switch_call_cause_t)H323TranslateFromCallEndReason(GetCallEndReason(), dummy));\r
+                          (switch_call_cause_t)H323TranslateFromCallEndReason(GetCallEndReason(), dummy));    \r
     OpalLocalConnection::OnReleased();\r
 }\r
 \r
@@ -752,16 +765,49 @@ switch_status_t FSConnection::on_execute()
 }\r
 \r
 \r
-switch_status_t FSConnection::on_hangup()\r
+/* this function has to be called with the original session beause the FSConnection might already be destroyed and we \r
+   will can't have it be a method of a dead object\r
+ */\r
+static switch_status_t on_hangup(switch_core_session_t *session)\r
 {\r
-    switch_channel_t *channel = switch_core_session_get_channel(m_fsSession);\r
-    if (channel == NULL) {\r
-        return SWITCH_STATUS_FALSE;\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
+    /* if this is still here it was our idea to hangup not opal's */\r
+    if (tech_pvt->me) {\r
+        Q931::CauseValues cause = (Q931::CauseValues)switch_channel_get_cause_q850(channel);\r
+        tech_pvt->me->SetQ931Cause(cause);\r
+        tech_pvt->me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));\r
+        tech_pvt->me = NULL;\r
+    }\r
+    \r
+    if (tech_pvt->read_codec.implementation) {\r
+        switch_core_codec_destroy(&tech_pvt->read_codec);\r
     }\r
 \r
-    Q931::CauseValues cause = (Q931::CauseValues)switch_channel_get_cause_q850(channel);\r
-    SetQ931Cause(cause);\r
-    ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));\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
+\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
+\r
+    if (tech_pvt->vid_read_timer.timer_interface) {\r
+        switch_core_timer_destroy(&tech_pvt->vid_read_timer);\r
+    }\r
+\r
+    switch_core_session_unset_read_codec(session);\r
+    switch_core_session_unset_write_codec(session);\r
+\r
     return SWITCH_STATUS_SUCCESS;\r
 }\r
 \r
@@ -808,8 +854,7 @@ switch_status_t FSConnection::send_dtmf(const switch_dtmf_t *dtmf)
 \r
 switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg)\r
 {\r
-    switch_core_session_t *session = GetSession();\r
-    switch_channel_t *channel = switch_core_session_get_channel(session);\r
+    switch_channel_t *channel = switch_core_session_get_channel(m_fsSession);\r
 \r
 \r
     /*\r
@@ -969,13 +1014,15 @@ FSMediaStream::FSMediaStream(FSConnection & conn, const OpalMediaFormat & mediaF
     , m_callOnStart(true)\r
 {\r
     memset(&m_readFrame, 0, sizeof(m_readFrame));\r
-    m_readFrame.codec = &m_switchCodec;\r
+    m_readFrame.codec = m_switchCodec;\r
     m_readFrame.flags = SFF_RAW_RTP;\r
 }\r
 \r
 \r
 PBoolean FSMediaStream::Open()\r
 {\r
+    opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(m_fsSession);\r
+\r
     if (IsOpen()) {\r
         return true;\r
     }\r
@@ -993,13 +1040,21 @@ PBoolean FSMediaStream::Open()
     \r
     int ptime = mediaFormat.GetOptionInteger(OpalAudioFormat::TxFramesPerPacketOption()) * mediaFormat.GetFrameTime() / mediaFormat.GetTimeUnits();\r
 \r
+\r
+    if (IsSink()) {\r
+        m_switchCodec = isAudio ? &tech_pvt->read_codec : &tech_pvt->vid_read_codec;\r
+        m_switchTimer = isAudio ? &tech_pvt->read_timer : &tech_pvt->vid_read_timer;\r
+    } else {\r
+        m_switchCodec = isAudio ? &tech_pvt->write_codec : &tech_pvt->vid_write_codec;\r
+    }\r
+\r
     // The following is performed on two different instances of this object.\r
-    if (switch_core_codec_init(&m_switchCodec, mediaFormat.GetEncodingName(), NULL, // FMTP\r
+    if (switch_core_codec_init(m_switchCodec, mediaFormat.GetEncodingName(), NULL, // FMTP\r
                                mediaFormat.GetClockRate(), ptime, 1,  // Channels\r
                                SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,   // Settings\r
                                switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {\r
         // Could not select a codecs using negotiated frames/packet, so try using default.\r
-        if (switch_core_codec_init(&m_switchCodec, mediaFormat.GetEncodingName(), NULL, // FMTP\r
+        if (switch_core_codec_init(m_switchCodec, mediaFormat.GetEncodingName(), NULL, // FMTP\r
                                    mediaFormat.GetClockRate(), 0, 1,  // Channels\r
                                    SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,   // Settings\r
                                    switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {\r
@@ -1020,24 +1075,25 @@ PBoolean FSMediaStream::Open()
         m_readFrame.rate = mediaFormat.GetClockRate();\r
 \r
         if (isAudio) {\r
-            switch_core_session_set_read_codec(m_fsSession, &m_switchCodec);\r
-            if (switch_core_timer_init(&m_switchTimer,\r
+            switch_core_session_set_read_codec(m_fsSession, m_switchCodec);\r
+            if (switch_core_timer_init(m_switchTimer,\r
                                        "soft",\r
-                                       m_switchCodec.implementation->microseconds_per_packet / 1000,\r
-                                       m_switchCodec.implementation->samples_per_packet,\r
+                                       m_switchCodec->implementation->microseconds_per_packet / 1000,\r
+                                       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
+                switch_core_codec_destroy(m_switchCodec);\r
+                m_switchCodec = NULL;\r
                 return false;\r
             }\r
         } else {\r
-            switch_core_session_set_video_read_codec(m_fsSession, &m_switchCodec);\r
+            switch_core_session_set_video_read_codec(m_fsSession, m_switchCodec);\r
             switch_channel_set_flag(m_fsChannel, CF_VIDEO);\r
         }\r
     } else {\r
         if (isAudio) {\r
-            switch_core_session_set_write_codec(m_fsSession, &m_switchCodec);\r
+            switch_core_session_set_write_codec(m_fsSession, m_switchCodec);\r
         } else {\r
-            switch_core_session_set_video_write_codec(m_fsSession, &m_switchCodec);\r
+            switch_core_session_set_video_write_codec(m_fsSession, m_switchCodec);\r
             switch_channel_set_flag(m_fsChannel, CF_VIDEO);\r
         }\r
     }\r
@@ -1053,36 +1109,11 @@ PBoolean FSMediaStream::Close()
 {\r
     if (!IsOpen())\r
         return false;\r
+    \r
+    /* forget these FS will properly destroy them for us */\r
 \r
-    bool isAudio;\r
-\r
-    if (mediaFormat.GetMediaType() == OpalMediaType::Audio()) {\r
-        isAudio = true;\r
-    } else if (mediaFormat.GetMediaType() == OpalMediaType::Video()) {\r
-        isAudio = false;\r
-    } else {\r
-        return OpalMediaStream::Close();\r
-    }\r
-\r
-    if (IsSink()) {\r
-        if (isAudio) {\r
-            switch_core_session_unset_read_codec(m_fsSession);\r
-            switch_core_timer_destroy(&m_switchTimer);\r
-        } else {\r
-            switch_core_session_set_video_read_codec(m_fsSession, NULL);\r
-        }\r
-\r
-        switch_core_codec_destroy(&m_switchCodec);\r
-    } else {\r
-        if (isAudio)\r
-            switch_core_session_unset_write_codec(m_fsSession);\r
-        else\r
-            switch_core_session_set_video_write_codec(m_fsSession, NULL);\r
-        switch_core_codec_destroy(&m_switchCodec);\r
-    }\r
-\r
-    PTRACE(3, "mod_opal\tReset & destroyed " << (IsSink()? "read" : "write")\r
-           << ' ' << mediaFormat.GetMediaType() << " codec for connection " << *this);\r
+    m_switchTimer = NULL;\r
+    m_switchCodec = NULL;\r
 \r
     return OpalMediaStream::Close();\r
 }\r
@@ -1102,6 +1133,11 @@ PBoolean FSMediaStream::RequiresPatchThread(OpalMediaStream *) const
 \r
 switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag_t flags)\r
 {\r
+\r
+    if (!m_switchCodec) {\r
+        return SWITCH_STATUS_FALSE;\r
+    }\r
+\r
     if (m_callOnStart) {\r
         /*\r
           There is a race here... sometimes we make it here and GetPatch() is NULL\r
@@ -1148,11 +1184,11 @@ switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag
         }\r
     } else {\r
 \r
-        if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {\r
+        if (!m_switchTimer || !GetPatch()->GetSource().ReadPacket(m_readRTP)) {\r
             return SWITCH_STATUS_FALSE;\r
         }\r
     \r
-        switch_core_timer_next(&m_switchTimer);\r
+        switch_core_timer_next(m_switchTimer);\r
     \r
         if (!(m_readFrame.datalen = m_readRTP.GetPayloadSize())) {\r
             m_readFrame.flags = SFF_CNG;\r
@@ -1174,6 +1210,7 @@ switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag
     m_readFrame.m = (switch_bool_t) m_readRTP.GetMarker();\r
     m_readFrame.seq = m_readRTP.GetSequenceNumber();\r
     m_readFrame.ssrc = m_readRTP.GetSyncSource();\r
+    m_readFrame.codec = m_switchCodec;\r
     *frame = &m_readFrame;\r
 \r
     return SWITCH_STATUS_SUCCESS;\r
index fc9d91b7fb14bf7f1b7826f4468cbd75290cb259..24d7367d820196934e72badf3e5075bfa883b079 100644 (file)
@@ -106,6 +106,18 @@ class FSManager : public OpalManager {
     list < FSListener > m_listeners;
 };
 
+class FSConnection;
+typedef struct {
+    switch_timer_t read_timer;
+    switch_codec_t read_codec;
+    switch_codec_t write_codec;
+
+    switch_timer_t vid_read_timer;
+    switch_codec_t vid_read_codec;
+    switch_codec_t vid_write_codec;
+    FSConnection *me;
+} opal_private_t;
+
 
 class FSEndPoint:public OpalLocalEndPoint {
     PCLASSINFO(FSEndPoint, OpalLocalEndPoint);
@@ -117,23 +129,25 @@ class FSEndPoint:public OpalLocalEndPoint {
 };
 
 
-#define DECLARE_CALLBACK0(name)                                         \
+#define DECLARE_CALLBACK0(name)                           \
     static switch_status_t name(switch_core_session_t *session) {       \
-        FSConnection * conn = (FSConnection *)switch_core_session_get_private(session); \
-        return conn != NULL ? conn->name() : SWITCH_STATUS_FALSE; }     \
+        opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
+        return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name() : SWITCH_STATUS_FALSE; } \
 switch_status_t name()
 
 #define DECLARE_CALLBACK1(name, type1, name1)                           \
     static switch_status_t name(switch_core_session_t *session, type1 name1) { \
-        FSConnection * conn = (FSConnection *)switch_core_session_get_private(session); \
-        return conn != NULL ? conn->name(name1) : SWITCH_STATUS_FALSE; } \
-    switch_status_t name(type1 name1)
+        opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
+        return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name(name1) : SWITCH_STATUS_FALSE; } \
+switch_status_t name(type1 name1)
 
 #define DECLARE_CALLBACK3(name, type1, name1, type2, name2, type3, name3) \
     static switch_status_t name(switch_core_session_t *session, type1 name1, type2 name2, type3 name3) { \
-        FSConnection * conn = (FSConnection *)switch_core_session_get_private(session); \
-        return conn != NULL ? conn->name(name1, name2, name3) : SWITCH_STATUS_FALSE; } \
-    switch_status_t name(type1 name1, type2 name2, type3 name3)
+        opal_private_t *tech_pvt = (opal_private_t *) switch_core_session_get_private(session); \
+        return tech_pvt && tech_pvt->me != NULL ? tech_pvt->me->name(name1, name2, name3) : SWITCH_STATUS_FALSE; } \
+switch_status_t name(type1 name1, type2 name2, type3 name3)
+
+
 
 
 class FSConnection:public OpalLocalConnection {
@@ -156,7 +170,8 @@ class FSConnection:public OpalLocalConnection {
     DECLARE_CALLBACK0(on_init);
     DECLARE_CALLBACK0(on_routing);
     DECLARE_CALLBACK0(on_execute);
-    DECLARE_CALLBACK0(on_hangup);
+    //DECLARE_CALLBACK0(on_hangup);
+
     DECLARE_CALLBACK0(on_loopback);
     DECLARE_CALLBACK0(on_transmit);
 
@@ -206,8 +221,8 @@ class FSMediaStream:public OpalMediaStream {
  private:
     switch_core_session_t *m_fsSession;
     switch_channel_t *m_fsChannel;
-    switch_timer_t m_switchTimer;
-    switch_codec_t m_switchCodec;
+    switch_timer_t *m_switchTimer;
+    switch_codec_t *m_switchCodec;
     switch_frame_t m_readFrame;
     RTP_DataFrame m_readRTP;
     bool m_callOnStart;