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

FreeSWITCH SVN anthm at freeswitch.org
Wed Feb 11 16:26:04 PST 2009


Author: anthm
Date: Wed Feb 11 18:26:04 2009
New Revision: 11899

Log:
changes to put freeswitch in control of lifecycle of some critical objects, -sigh

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

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	Wed Feb 11 18:26:04 2009
@@ -106,6 +106,18 @@
     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 @@
 };
 
 
-#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 @@
     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 @@
  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;



More information about the Freeswitch-svn mailing list