diff --git a/Control/CallControl.cpp b/Control/CallControl.cpp index 42a96f7..c9f6b2e 100644 --- a/Control/CallControl.cpp +++ b/Control/CallControl.cpp @@ -72,17 +72,20 @@ using namespace Control; */ unsigned allocateRTPPorts() { - // FIXME -- We need a real port allocator. const unsigned base = gConfig.getNum("RTP.Start"); const unsigned range = gConfig.getNum("RTP.Range"); const unsigned top = base+range; static Mutex lock; // Pick a random starting point. static unsigned port = base + 2*(random()%(range/2)); + unsigned retVal; lock.lock(); - unsigned retVal = port; - port += 2; - if (port>=top) port=base; + //This is a little hacky as RTPAvail is O(n) + do { + retVal = port; + port += 2; + if (port>=top) port=base; + } while (!gTransactionTable.RTPAvailable(retVal)); lock.unlock(); return retVal; } diff --git a/Control/TransactionTable.cpp b/Control/TransactionTable.cpp index 3c1bf05..4489dc7 100644 --- a/Control/TransactionTable.cpp +++ b/Control/TransactionTable.cpp @@ -805,5 +805,19 @@ TransactionEntry* TransactionTable::findLongestCall() +/* linear, we should move the actual search into this structure */ +bool TransactionTable::RTPAvailable(short rtpPort) +{ + ScopedLock lock(mLock); + clearDeadEntries(); + bool avail = true; + for (TransactionMap::iterator itr = mTable.begin(); itr!=mTable.end(); ++itr) { + if (itr->second->mSIP.RTPPort() == rtpPort){ + avail = false; + break; + } + } + return avail; +} // vim: ts=4 sw=4 diff --git a/Control/TransactionTable.h b/Control/TransactionTable.h index d997575..eb06b8d 100644 --- a/Control/TransactionTable.h +++ b/Control/TransactionTable.h @@ -337,6 +337,12 @@ class TransactionTable { */ TransactionEntry* findLongestCall(); + /** + Return the availability of this particular RTP port + @return True if Port is available, False otherwise + */ + bool RTPAvailable(short rtpPort); + /** Remove an entry from the table and from gSIPMessageMap. @param wID The transaction ID to search. diff --git a/SIP/SIPEngine.cpp b/SIP/SIPEngine.cpp index dccd0bd..e6f9690 100644 --- a/SIP/SIPEngine.cpp +++ b/SIP/SIPEngine.cpp @@ -121,6 +121,9 @@ SIPEngine::SIPEngine(const char* proxy, const char* IMSI) mMyTag=tmp; // set our CSeq in case we need one mCSeq = random()%600; + + //to make sure noise doesn't magically equal a valid RTP port + mRTPPort = 0; } diff --git a/SIP/SIPEngine.h b/SIP/SIPEngine.h index cecd61d..6b207ae 100644 --- a/SIP/SIPEngine.h +++ b/SIP/SIPEngine.h @@ -151,6 +151,9 @@ public: /** Return the current SIP call state. */ SIPState state() const { return mState; } + /** Return the RTP Port being used. */ + short RTPPort() const { return mRTPPort; } + /** Return if the call has successfully finished */ bool finished() const { return (mState==Cleared || mState==Canceled); }