From fb2205a84eb2dcf619c1967d17c2a5b645942f13 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.net>
Date: Mon, 17 Aug 2009 08:59:49 -0400
Subject: [PATCH] [#1883] Fix mem leaks in audio rtp

---
 sflphone-common/src/audio/audiortp.cpp   | 37 +++++++++++++--------
 sflphone-common/src/audio/audiortp.h     |  5 ++-
 sflphone-common/src/audio/mainbuffer.cpp | 41 ++++++++++++++++++++----
 sflphone-common/src/audio/pulselayer.cpp |  4 +++
 sflphone-common/src/audio/ringbuffer.cpp | 18 +++++++----
 sflphone-common/src/conference.cpp       | 30 +++++++++++++++--
 sflphone-common/src/conference.h         |  2 ++
 sflphone-common/src/managerimpl.cpp      | 30 ++++++++++++++---
 sflphone-common/src/managerimpl.h        |  4 +++
 sflphone-common/src/sipcall.cpp          |  3 +-
 sflphone-common/src/sipvoiplink.cpp      |  2 +-
 11 files changed, 141 insertions(+), 35 deletions(-)

diff --git a/sflphone-common/src/audio/audiortp.cpp b/sflphone-common/src/audio/audiortp.cpp
index 4109f03efe..c744424f69 100644
--- a/sflphone-common/src/audio/audiortp.cpp
+++ b/sflphone-common/src/audio/audiortp.cpp
@@ -43,23 +43,26 @@
 ////////////////////////////////////////////////////////////////////////////////
 // AudioRtp
 ////////////////////////////////////////////////////////////////////////////////
-AudioRtp::AudioRtp() :_RTXThread (0), _symmetric(), _threadMutex()
+AudioRtp::AudioRtp() :_RTXThread (0), _symmetric(), _rtpMutex()
 {
 }
 
 AudioRtp::~AudioRtp (void)
 {
-    ost::MutexLock m (_threadMutex);
+    ost::MutexLock m (_rtpMutex);
 
-    delete _RTXThread;
-    _RTXThread = 0;
+    if (_RTXThread != _RTXThread)
+    {
+        delete _RTXThread;
+        _RTXThread = 0;
+    }
 }
 
 void
 AudioRtp::createNewSession (SIPCall *ca)
 {
 
-    ost::MutexLock m (_threadMutex);
+    ost::MutexLock m (_rtpMutex);
 
     _debug ("AudioRtp::Create new rtp session\n");
 
@@ -83,7 +86,7 @@ AudioRtp::createNewSession (SIPCall *ca)
 int
 AudioRtp::start (void)
 {
-    ost::MutexLock m (_threadMutex);
+    ost::MutexLock m (_rtpMutex);
 
     if (_RTXThread == 0) {
         _debug ("! ARTP Failure: Cannot start audiortp thread since not yet created\n");
@@ -109,7 +112,7 @@ bool
 AudioRtp::closeRtpSession ()
 {
 
-    ost::MutexLock m (_threadMutex);
+    ost::MutexLock m (_rtpMutex);
     // This will make RTP threads finish.
     _debug ("AudioRtp::Stopping rtp session\n");
 
@@ -174,9 +177,9 @@ AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym) : time (new ost::Time()),
 AudioRtpRTX::~AudioRtpRTX ()
 {
 
-    // ost::MutexLock m (_threadMutex);
+    ost::MutexLock m (_rtpRtxMutex);
 
-    _debug ("Delete AudioRtpRTX instance\n");
+    _debug ("Delete AudioRtpRTX instance in callid %s\n", _ca->getCallId().c_str());
 
     try {
         this->terminate();
@@ -188,8 +191,7 @@ AudioRtpRTX::~AudioRtpRTX ()
     _debug("Unbind call id %s from all participants\n", _ca->getCallId().c_str());
     _audiolayer->getMainBuffer()->unBindAll(_ca->getCallId());
 
-    _ca = 0;
-
+    _debug("DELETE print micData address %p\n", micData);
     delete [] micData;
     micData = NULL;
     delete [] micDataConverted;
@@ -208,6 +210,7 @@ AudioRtpRTX::~AudioRtpRTX ()
     delete converter;
     converter = NULL;
 
+    _ca = 0;
     // _session->terminate();
 
     delete _session;
@@ -221,17 +224,24 @@ AudioRtpRTX::~AudioRtpRTX ()
 void
 AudioRtpRTX::initBuffers()
 {
+    ost::MutexLock m (_rtpRtxMutex);
+    
+    _debug("AudioRtpRTX::initBuffers Init RTP buffers for %s\n", _ca->getCallId().c_str());
+    
     converter = new SamplerateConverter (_layerSampleRate , _layerFrameSize);
 
     int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
+    _debug("AudioRtpRTX::initBuffers NBSAMPLEMAX %i\n", nbSamplesMax);
 
     micData = new SFLDataFormat[nbSamplesMax];
+    _debug("CREATE print micData address %p\n", micData);
     micDataConverted = new SFLDataFormat[nbSamplesMax];
     micDataEncoded = new unsigned char[nbSamplesMax];
 
     spkrDataConverted = new SFLDataFormat[nbSamplesMax];
     spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
 
+    Manager::instance().addStream(_ca->getCallId());
     // _audiolayer->getMainBuffer()->bindCallID(_ca->getCallId());
 }
 
@@ -356,10 +366,10 @@ AudioRtpRTX::processDataEncode()
 
     // available bytes inside ringbuffer
     int availBytesFromMic = _audiolayer->getMainBuffer()->availForGet(_ca->getCallId());
-
+    
     // set available byte to maxByteToGet
     int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
-
+    // _debug("bytesAvail %i\n", bytesAvail);
     if (bytesAvail == 0)
         return 0;
 
@@ -573,6 +583,7 @@ AudioRtpRTX::run ()
 
     while (!testCancel()) {
 
+	// _debug("Main while loop for call: %s\n", _ca->getCallId().c_str());
         // Send session
         sessionWaiting = _session->isWaiting();
 
diff --git a/sflphone-common/src/audio/audiortp.h b/sflphone-common/src/audio/audiortp.h
index 49330c2fd8..8335ef9d0d 100644
--- a/sflphone-common/src/audio/audiortp.h
+++ b/sflphone-common/src/audio/audiortp.h
@@ -222,6 +222,9 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
     
     /** The audio codec used during the session */
     AudioCodec* _audiocodec;
+
+    /** Mutex */
+    ost::Mutex _rtpRtxMutex;
    
 };
 
@@ -281,7 +284,7 @@ class AudioRtp {
     bool _symmetric;
 
     /** Mutex */
-    ost::Mutex _threadMutex;
+    ost::Mutex _rtpMutex;
 };
 
 #endif // __AUDIO_RTP_H__
diff --git a/sflphone-common/src/audio/mainbuffer.cpp b/sflphone-common/src/audio/mainbuffer.cpp
index e2bbe9e132..244d323fd7 100644
--- a/sflphone-common/src/audio/mainbuffer.cpp
+++ b/sflphone-common/src/audio/mainbuffer.cpp
@@ -301,7 +301,12 @@ int MainBuffer::availForPut(CallID call_id)
 
     ost::MutexLock guard (_mutex);
 
-    return getRingBuffer(call_id)->AvailForPut();
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+
+    if (ringbuffer == NULL)
+	return 0;
+    else
+	return ringbuffer->AvailForPut();
     
 }
 
@@ -314,6 +319,9 @@ int MainBuffer::getData(void *buffer, int toCopy, unsigned short volume, CallID
 
     CallIDSet* callid_set = getCallIDSet(call_id);
 
+    if(callid_set == NULL)
+	return 0;
+
     if(callid_set->empty())
     {
 	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
@@ -391,15 +399,17 @@ int MainBuffer::getDataByID(void *buffer, int toCopy, unsigned short volume, Cal
 
 int MainBuffer::availForGet(CallID call_id)
 {
-    // _debug("MainBuffer::availForGet\n");
 
     ost::MutexLock guard (_mutex);
 
     CallIDSet* callid_set = getCallIDSet(call_id);
 
+    if (callid_set == NULL)
+	return 0;
+
     if (callid_set->empty())
     {
-	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
+	_debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
 	return 0;
     }
 
@@ -429,7 +439,12 @@ int MainBuffer::availForGet(CallID call_id)
 int MainBuffer::availForGetByID(CallID call_id, CallID reader_id)
 {
 
-    return getRingBuffer(call_id)->AvailForGet(reader_id);
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+    
+    if (ringbuffer == NULL)
+	return 0;
+    else
+	return ringbuffer->AvailForGet(reader_id);
 
 }
 
@@ -442,6 +457,9 @@ int MainBuffer::discard(int toDiscard, CallID call_id)
 
     CallIDSet* callid_set = getCallIDSet(call_id);
 
+    if (callid_set == NULL)
+	return 0;
+
     if(callid_set->empty())
     {
 	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
@@ -472,7 +490,12 @@ int MainBuffer::discard(int toDiscard, CallID call_id)
 int MainBuffer::discardByID(int toDiscard, CallID call_id, CallID reader_id)
 {
 
-    return getRingBuffer(call_id)->Discard(toDiscard, reader_id);
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+    
+    if(ringbuffer == NULL)
+	return 0;
+    else
+	return ringbuffer->Discard(toDiscard, reader_id);
 
 }
 
@@ -486,6 +509,9 @@ void MainBuffer::flush(CallID call_id)
 
     CallIDSet* callid_set = getCallIDSet(call_id);
 
+    if (callid_set == NULL)
+	return;
+
     if(callid_set->empty())
     {
 	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
@@ -520,5 +546,8 @@ void MainBuffer::flushDefault()
 void MainBuffer::flushByID(CallID call_id, CallID reader_id)
 {
 
-    getRingBuffer(call_id)->flush(reader_id);
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+
+    if(ringbuffer != NULL)
+	ringbuffer->flush(reader_id);
 }
diff --git a/sflphone-common/src/audio/pulselayer.cpp b/sflphone-common/src/audio/pulselayer.cpp
index c8c28c33ee..93f7dacb91 100644
--- a/sflphone-common/src/audio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulselayer.cpp
@@ -40,6 +40,8 @@ PulseLayer::PulseLayer (ManagerImpl* manager)
     _debug ("PulseLayer::Pulse audio constructor: Create context\n");
     out_buffer = new SFLDataFormat[STATIC_BUFSIZE];
 
+    _urgentRingBuffer.createReadPointer();
+
 }
 
 // Destructor
@@ -361,6 +363,7 @@ void PulseLayer::writeToSpeaker (void)
 	out_buffer[k] = 0;
 
     if (urgentAvail > 0) {
+
 	
         // Urgent data (dtmf, incoming call signal) come first.
         //_debug("Play urgent!: %i\e" , urgentAvail);
@@ -396,6 +399,7 @@ void PulseLayer::writeToSpeaker (void)
         } else {
             // out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
 	    // _debug("PulseLayer::writeToSpeaker _mainBuffer.getData() toGet %i\n", toGet);
+	    
 	    normalAvail = _mainBuffer.availForGet();
 	    
             toGet = (normalAvail < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof (SFLDataFormat);
diff --git a/sflphone-common/src/audio/ringbuffer.cpp b/sflphone-common/src/audio/ringbuffer.cpp
index c8198df9a2..c342669f64 100644
--- a/sflphone-common/src/audio/ringbuffer.cpp
+++ b/sflphone-common/src/audio/ringbuffer.cpp
@@ -98,11 +98,19 @@ RingBuffer::getReadPointer(CallID call_id)
     if(getNbReadPointer() == 0)
 	return 0;
 
+    // _debug("RingBuffer::getReadPointer() id %s\n", call_id.c_str());
+    
     ReadPointer::iterator iter = _readpointer.find(call_id);
     if (iter == _readpointer.end())
     {
-	_debug("RingBuffer::getReadPointer Error read pointer is null\n");
-	return NULL;
+	// _debug("                RingBuffer::getReadPointer Error read pointer size: %i\n", _readpointer.size());
+	// _debug("                RingBuffer::getReadPointer Error read pointer \"%s\" is null\n", call_id.c_str());
+	ReadPointer::iterator iter2;
+	for( iter2 = _readpointer.begin(); iter2 != _readpointer.end(); iter2++)
+	{
+	    // x_debug("                RingBuffer::getReadPointer list avail pointer \"%s\"\n", iter2->first.c_str());
+	}
+	return 0;
     }
     else
     {
@@ -137,7 +145,7 @@ RingBuffer::storeReadPointer(int pointer_value, CallID call_id)
     if(iter != _readpointer.end())
     {	
 	iter->second = pointer_value;
-	_debug("store read pointer call_id %s, size: %i \n",call_id.c_str(), _readpointer.size());
+	// _debug("store read pointer call_id %s, size: %i \n",call_id.c_str(), _readpointer.size());
     }
     else
     {
@@ -295,10 +303,8 @@ RingBuffer::Get (void *buffer, int toCopy, unsigned short volume, CallID call_id
     dest = (samplePtr) buffer;
 
     copied = 0;
-    
-    int mStart = getReadPointer(call_id);
-
 
+    int mStart = getReadPointer(call_id);
 
     //fprintf(stderr, "G");
     while (toCopy) {
diff --git a/sflphone-common/src/conference.cpp b/sflphone-common/src/conference.cpp
index 4bb252ea67..50b2ff4116 100644
--- a/sflphone-common/src/conference.cpp
+++ b/sflphone-common/src/conference.cpp
@@ -43,6 +43,7 @@ void Conference::add(CallID participant_id)
 
     _debug("---- Conference:: add participant %s\n", participant_id.c_str());
 
+    /*
     if(_nbParticipant >= 1)
     {
 	ParticipantSet::iterator iter;
@@ -54,8 +55,8 @@ void Conference::add(CallID participant_id)
 	}
     }
 
-    // Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id);
-
+    Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id);
+    */
     _participants.insert(participant_id);
 
     _nbParticipant++;
@@ -67,6 +68,7 @@ void Conference::remove(CallID participant_id)
 
     _debug("---- Conference:: remove participant %s\n", participant_id.c_str());
 
+    /*
     if(_nbParticipant >= 1)
     {
 	ParticipantSet::iterator iter = _participants.begin();
@@ -77,9 +79,33 @@ void Conference::remove(CallID participant_id)
 	    Manager::instance().getAudioDriver()->getMainBuffer()->unBindCallID(participant_id, *iter);
 	}
     }
+    */
 
     _participants.erase(participant_id);
 
     _nbParticipant--;
 
 }
+
+void Conference::bindParticipant(CallID participant_id)
+{
+
+    if(_nbParticipant >= 1)
+    {
+	ParticipantSet::iterator iter;
+	
+	for(iter = _participants.begin(); iter != _participants.end(); iter++)
+	{
+	    if (participant_id != (*iter))
+	    {
+	        _debug("---- Conference:: bind callid %s with %s in conference add\n", participant_id.c_str(), (*iter).c_str());
+	        Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id, *iter);
+	    }
+	}
+    }
+
+    _debug("---- Conference:: bind callid %s with default_id in conference add\n", participant_id.c_str());
+
+    Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id);
+
+}
diff --git a/sflphone-common/src/conference.h b/sflphone-common/src/conference.h
index 8340997470..b1e0cb2c0e 100644
--- a/sflphone-common/src/conference.h
+++ b/sflphone-common/src/conference.h
@@ -43,6 +43,8 @@ class Conference{
 
 	void remove(CallID participant_id);
 
+	void bindParticipant(CallID participant_id);
+
     private:  
 
         /** Unique ID of the call */
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index 486ef37fcf..b0f901cd86 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -369,9 +369,6 @@ ManagerImpl::hangupCall (const CallID& id)
     if (! (nbCalls > 1))
         audiolayer->stopStream();
 
-    if(participToConference(id))
-	removeParticipant(id);
-
     /* Direct IP to IP call */
     if (getConfigFromCall (id) == Call::IPtoIP) {
         returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id);
@@ -392,6 +389,9 @@ ManagerImpl::hangupCall (const CallID& id)
         removeCallAccount (id);
     }
 
+    if(participToConference(id))
+	removeParticipant(id);
+
     switchCall ("");
 
     if (_audiodriver->getLayerType() == PULSEAUDIO && getConfigInt (PREFERENCES , CONFIG_PA_VOLUME_CTRL)) {
@@ -650,8 +650,6 @@ ManagerImpl::createConference(const CallID& id)
     conf->add(getCurrentCallId());
     conf->add(id);
 
-    answerCall(id);
-    
 }
 
 void
@@ -705,6 +703,9 @@ ManagerImpl::addParticipant(const CallID& call_id)
     {
 	_debug("NO CONFERENCE YET, CREATE ONE\n");
 	createConference(call_id);
+
+	answerCall(call_id);
+
     }
     else
     {
@@ -747,6 +748,25 @@ ManagerImpl::removeParticipant(const CallID& call_id)
     }
 }
 
+void
+ManagerImpl::addStream(const CallID& call_id)
+{
+    _debug("ManagerImpl::addStream %s\n", call_id.c_str());
+
+    if(participToConference(call_id))
+    {
+	ConferenceMap::iterator iter = _conferencemap.find(default_conf);
+	
+	Conference* conf = iter->second;
+
+	conf->bindParticipant(call_id);
+    }
+    else
+    {
+	getAudioDriver()->getMainBuffer()->bindCallID(call_id);
+    }
+}
+
 //THREAD=Main
 bool
 ManagerImpl::saveConfig (void)
diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index a3ca34541a..f6b6d9184c 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -196,6 +196,8 @@ class ManagerImpl {
 
     void removeParticipant(const CallID& call_id);
 
+    void addStream(const CallID& call_id);
+
     /**
      * Save config to file
      * @return true on success
@@ -1162,8 +1164,10 @@ class ManagerImpl {
     int isStunEnabled (void);
     void enableStun (void);
 
+    // Map 
     ConferenceCallMap _conferencecall;
 
+    // 
     ConferenceMap _conferencemap;
 
 private:
diff --git a/sflphone-common/src/sipcall.cpp b/sflphone-common/src/sipcall.cpp
index fdfd2c3294..68d2eb47bc 100644
--- a/sflphone-common/src/sipcall.cpp
+++ b/sflphone-common/src/sipcall.cpp
@@ -39,7 +39,8 @@ SIPCall::SIPCall (const CallID& id, Call::CallType type, pj_pool_t *pool) : Call
 
 SIPCall::~SIPCall()
 {
-
+    delete _audiortp;
+    _audiortp = 0;
     delete _local_sdp;
     _local_sdp = 0;
     _debug ("SIPCALL::Destructor for this class is called \n");
diff --git a/sflphone-common/src/sipvoiplink.cpp b/sflphone-common/src/sipvoiplink.cpp
index fd9915f79e..2023c3b6c1 100644
--- a/sflphone-common/src/sipvoiplink.cpp
+++ b/sflphone-common/src/sipvoiplink.cpp
@@ -734,7 +734,7 @@ SIPVoIPLink::hangup (const CallID& id)
 
     // Release RTP thread
     if (Manager::instance().isCurrentCall (id)) {
-        _debug ("* SIP Info: Stopping AudioRTP for hangup\n");
+        _debug ("* SIP Info: Stopping AudioRTP for hangup %s\n", call->getCallId().c_str());
         call->getAudioRtp()->closeRtpSession();
     }
 
-- 
GitLab