From dfda5df8fd0544e8a47e3d2aeb486a5ade8aeda1 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Date: Thu, 19 Jul 2012 10:11:17 -0400
Subject: [PATCH] #13678: Fix Zrtp thread may hang when hanging up a call

---
 .../src/audio/audiortp/audio_zrtp_session.cpp | 76 +++++++++----------
 .../src/audio/audiortp/audio_zrtp_session.h   | 29 ++++++-
 2 files changed, 61 insertions(+), 44 deletions(-)

diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp
index 5b41a5c4d2..4d50bf1466 100644
--- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp
+++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp
@@ -47,25 +47,27 @@
 namespace sfl {
 
 AudioZrtpSession::AudioZrtpSession(SIPCall &call, const std::string &zidFilename) :
-    AudioRtpSession(call, *this, *this),
-    ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue>(ost::InetHostAddress(call_.getLocalIp().c_str()),
-    call_.getLocalAudioPort(),
-    0,
-    ost::MembershipBookkeeping::defaultMembersHashSize,
-    ost::defaultApplication()),
-    zidFilename_(zidFilename)
+    ost::TimerPort()
+    , ost::SymmetricZRTPSession(ost::InetHostAddress(call.getLocalIp().c_str()), call.getLocalAudioPort())
+    , AudioRtpSession(call, *this, *this)
+    , zidFilename_(zidFilename)
+    , rtpThread_(*this)
 {
     initializeZid();
     DEBUG("Setting new RTP session with destination %s:%d",
           call_.getLocalIp().c_str(), call_.getLocalAudioPort());
+    audioRtpRecord_.callId_ = call_.getCallId();
 }
 
 AudioZrtpSession::~AudioZrtpSession()
 {
-    ost::Thread::terminate();
-    Manager::instance().getMainBuffer()->unBindAll(call_.getCallId());
+    if (rtpThread_.running_) {
+        rtpThread_.running_ = false;
+        rtpThread_.join();
+    }
 }
 
+
 void AudioZrtpSession::initializeZid()
 {
     if (zidFilename_.empty())
@@ -120,46 +122,31 @@ void AudioZrtpSession::sendMicData()
     queue_.sendImmediate(timestamp_, getMicDataEncoded(), compSize);
 }
 
-void AudioZrtpSession::run()
+AudioZrtpSession::AudioZrtpThread::AudioZrtpThread(AudioZrtpSession &session) : running_(true), zrtpSession_(session)
+{}
+
+void AudioZrtpSession::AudioZrtpThread::run()
 {
     // Set recording sampling rate
-    call_.setRecordingSmplRate(getCodecSampleRate());
-    DEBUG("Entering mainloop for call %s", call_.getCallId().c_str());
+    int threadSleep = 20;
 
-    uint32 timeout = 0;
+    DEBUG("Entering Audio zrtp thread main loop %s", running_ ? "running" : "not running");
 
-    while (isActive()) {
-        if (timeout < 1000)
-            timeout = getSchedulingTimeout();
+    TimerPort::setTimer(threadSleep);
 
+    while (running_) {
         // Send session
-        if (hasDTMFPending())
-            sendDtmfEvent();
+        if (zrtpSession_.hasDTMFPending())
+            zrtpSession_.sendDtmfEvent();
         else
-            sendMicData();
-
-        controlReceptionService();
-        controlTransmissionService();
-        uint32 maxWait = timeval2microtimeout(getRTCPCheckInterval());
-        // make sure the scheduling timeout is
-        // <= the check interval for RTCP
-        // packets
-        timeout = (timeout > maxWait) ? maxWait : timeout;
-
-        if (timeout < 1000) {   // !(timeout/1000)
-            // dispatchDataPacket();
-            timerTick();
-        } else {
-            if (isPendingData(timeout / 1000)) {
-
-                if (isActive())
-                    takeInDataPacket();
-            }
-            timeout = 0;
-        }
+            zrtpSession_.sendMicData();
+
+        Thread::sleep(TimerPort::getTimer());
+
+        TimerPort::incTimer(threadSleep);
     }
 
-    DEBUG("Left main loop for call %s", call_.getCallId().c_str());
+    DEBUG("Leaving audio rtp thread loop");
 }
 
 int AudioZrtpSession::getIncrementForDTMF() const
@@ -172,4 +159,13 @@ void AudioZrtpSession::setSessionMedia(AudioCodec &audioCodec)
     AudioRtpSession::setSessionMedia(audioCodec);
 }
 
+int AudioZrtpSession::startRtpThread(AudioCodec &audiocodec)
+{
+    if(isStarted_)
+        return 0;
+
+    AudioRtpSession::startRtpThread(audiocodec);
+    return startZrtpThread();
+}
+
 }
diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h
index d056d021ca..b3bc670b44 100644
--- a/daemon/src/audio/audiortp/audio_zrtp_session.h
+++ b/daemon/src/audio/audiortp/audio_zrtp_session.h
@@ -54,25 +54,46 @@ class ZrtpZidException : public std::runtime_error {
 };
 
 class AudioZrtpSession :
-    public AudioRtpSession, protected ost::Thread,
-    public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> {
+     public ost::TimerPort,
+    // public ost::TRTPSessionBase<ost::SymmetricRTPChannel, ost::SymmetricRTPChannel, ost::ZrtpQueue> {
+    public ost::SymmetricZRTPSession,
+    public AudioRtpSession {
     public:
         AudioZrtpSession(SIPCall &call, const std::string& zidFilename);
         ~AudioZrtpSession();
 
-        // Thread associated method
-        virtual void run();
+        int startZrtpThread() {
+            rtpThread_.start();
+            return 0;
+        }
 
         virtual bool onRTPPacketRecv(ost::IncomingRTPPkt &pkt) {
             return AudioRtpSession::onRTPPacketRecv(pkt);
         }
 
     private:
+        NON_COPYABLE(AudioZrtpSession);
+
+        class AudioZrtpThread : public ost::Thread, public ost::TimerPort {
+            public:
+                AudioZrtpThread(AudioZrtpSession &session);
+
+                virtual void run();
+
+                bool running_;
+
+            private:
+                NON_COPYABLE(AudioZrtpThread);
+                AudioZrtpSession &zrtpSession_;
+        };
         void sendMicData();
         void initializeZid();
         std::string zidFilename_;
         void setSessionMedia(AudioCodec &codec);
+        int startRtpThread(AudioCodec &audiocodec);
         virtual int getIncrementForDTMF() const;
+
+        AudioZrtpThread rtpThread_;
 };
 
 }
-- 
GitLab