Oh kay. Lots of patches trying to catch up to mainline:

r4232: Major change in hos entries are removed from a TransactionTable.

>From now on, the only place were entries are actually removed is in TransactionTable::innerRemove.
Anywhere else, the remove methods just set a flag to tag the entry for later removal be innerRemove.
This allows us to survive situations where we try to touch transactions that have been removed already.  We still log at the ERR level, but no more segfaults.

Updated all of the TransactionTable "find" methods to not return pointers to dead or removed tranactions.

Updated find-by-channel search to return the transaction entry with the highest transaction number, which fixes a bug that sometimes picked up the wrong transaction records during EA TCH assignment.

r4253: New exception class for when someone tries to use a "removed" transaction.

r4254: Updated copyright notice.

r4265: Unlock TransactionEntry::mLock while blocked on SIP message FIFOs in SIPEngine.  This does wonders to reduce lock contention and make everything more snappy.

Use Mutex::tryLock in TransactionEntry::dead and if lock is held, assume that it is not dead.  This also does a lot to reduce lock contention.

r4294: Change Um congestion response back to SIP 503.

r4295: When deleting an entry that has failed to respond to paging, send a SIP 480 response so the switch knows that transaction is dead.

r4412: Fixed bug that was causing SIPInterface to crash when the IMSI cannot be extracted from the To: header.

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4497 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
Kurtis Heimerl
2012-11-22 05:30:27 +00:00
parent 9536ac91dd
commit 768815e07f
11 changed files with 876 additions and 302 deletions

View File

@@ -1,22 +1,19 @@
/**@file Declarations for TransactionTable and related classes. */
/*
* Copyright 2008-2011 Free Software Foundation, Inc.
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011, 2012 Range Networks, Inc.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
@@ -32,6 +29,7 @@
#include <Logger.h>
#include <Interthread.h>
#include <Timeval.h>
#include <Sockets.h>
#include <GSML3CommonElements.h>
@@ -40,6 +38,11 @@
#include <GSML3RRElements.h>
#include <SIPEngine.h>
namespace GSM {
class LogicalChnanel;
class SACCHLogicalChannel;
}
struct sqlite3;
@@ -93,6 +96,8 @@ class TransactionEntry {
bool mTerminationRequested;
volatile bool mRemoved; ///< true if ready for removal
public:
/** This form is used for MTC or MT-SMS with TI generated by the network. */
@@ -137,11 +142,11 @@ class TransactionEntry {
/**@name Accessors. */
//@{
unsigned L3TI() const { return mL3TI; }
unsigned L3TI() const;
void L3TI(unsigned wL3TI);
const GSM::LogicalChannel* channel() const { return mChannel; }
GSM::LogicalChannel* channel() { return mChannel; }
const GSM::LogicalChannel* channel() const;
GSM::LogicalChannel* channel();
void channel(GSM::LogicalChannel* wChannel);
@@ -161,12 +166,9 @@ class TransactionEntry {
unsigned ID() const { return mID; }
GSM::CallState GSMState() const { ScopedLock lock(mLock); return mGSMState; }
GSM::CallState GSMState() const;
void GSMState(GSM::CallState wState);
//@}
/** Initiate the termination process. */
void terminate() { ScopedLock lock(mLock); mTerminationRequested=true; }
@@ -183,20 +185,20 @@ class TransactionEntry {
SIP::SIPState MOCSendINVITE(const char* calledUser, const char* calledDomain, short rtpPort, unsigned codec);
SIP::SIPState MOCResendINVITE();
SIP::SIPState MOCWaitForOK();
SIP::SIPState MOCCheckForOK();
SIP::SIPState MOCSendACK();
void MOCInitRTP() { ScopedLock lock(mLock); return mSIP.MOCInitRTP(); }
SIP::SIPState SOSSendINVITE(short rtpPort, unsigned codec);
SIP::SIPState SOSResendINVITE() { return MOCResendINVITE(); }
SIP::SIPState SOSWaitForOK() { return MOCWaitForOK(); }
SIP::SIPState SOSCheckForOK() { return MOCCheckForOK(); }
SIP::SIPState SOSSendACK() { return MOCSendACK(); }
void SOSInitRTP() { MOCInitRTP(); }
SIP::SIPState MTCSendTrying();
SIP::SIPState MTCSendRinging();
SIP::SIPState MTCWaitForACK();
SIP::SIPState MTCCheckForACK();
SIP::SIPState MTCCheckForCancel();
SIP::SIPState MTCSendOK(short rtpPort, unsigned codec);
void MTCInitRTP() { ScopedLock lock(mLock); mSIP.MTCInitRTP(); }
@@ -211,6 +213,7 @@ class TransactionEntry {
SIP::SIPState MODWaitForCANCELOK();
SIP::SIPState MODWaitForERRORACK(bool cancel);
SIP::SIPState MODWaitFor487();
SIP::SIPState MODWaitForResponse(vector<unsigned> *validResponses);
SIP::SIPState MTDCheckBYE();
SIP::SIPState MTDSendBYEOK();
@@ -224,12 +227,12 @@ class TransactionEntry {
bool sendINFOAndWaitForOK(unsigned info);
void txFrame(unsigned char* frame) { return mSIP.txFrame(frame); }
int rxFrame(unsigned char* frame) { return mSIP.rxFrame(frame); }
bool startDTMF(char key) { return mSIP.startDTMF(key); }
void stopDTMF() { mSIP.stopDTMF(); }
void txFrame(unsigned char* frame) { ScopedLock lock(mLock); return mSIP.txFrame(frame); }
int rxFrame(unsigned char* frame) { ScopedLock lock(mLock); return mSIP.rxFrame(frame); }
bool startDTMF(char key) { ScopedLock lock(mLock); return mSIP.startDTMF(key); }
void stopDTMF() { ScopedLock lock(mLock); mSIP.stopDTMF(); }
void SIPUser(const std::string& IMSI) { SIPUser(IMSI.c_str()); }
void SIPUser(const std::string& IMSI) { ScopedLock lock(mLock); SIPUser(IMSI.c_str()); }
void SIPUser(const char* IMSI);
void SIPUser(const char* callID, const char *IMSI , const char *origID, const char *origHost);
@@ -253,14 +256,11 @@ class TransactionEntry {
bool timerExpired(const char* name) const;
void setTimer(const char* name)
{ ScopedLock lock(mLock); return mTimers[name].set(); }
void setTimer(const char* name);
void setTimer(const char* name, long newLimit)
{ ScopedLock lock(mLock); return mTimers[name].set(newLimit); }
void setTimer(const char* name, long newLimit);
void resetTimer(const char* name)
{ ScopedLock lock(mLock); return mTimers[name].reset(); }
void resetTimer(const char* name);
/** Return true if any Q.931 timer is expired. */
bool anyTimerExpired() const;
@@ -271,12 +271,14 @@ class TransactionEntry {
//@}
/** Return true if clearing is in progress in the GSM side. */
bool clearingGSM() const
{ ScopedLock lock(mLock); return (mGSMState==GSM::ReleaseRequest) || (mGSMState==GSM::DisconnectIndication); }
bool clearingGSM() const;
/** Retrns true if the transaction is "dead". */
bool dead() const;
/** Returns true if dead, or if removal already requested. */
bool deadOrRemoved() const;
/** Dump information as text for debugging. */
void text(std::ostream&) const;
@@ -287,8 +289,20 @@ class TransactionEntry {
/** Create L3 timers from GSM and Q.931 (network side) */
void initTimers();
/** Set up a new entry in gTransactionTable's sqlite3 database. */
void insertIntoDatabase();
/** Run a database query. */
void runQuery(const char* query) const;
/** Echo latest SIPSTATE to the database. */
void echoSIPState(SIP::SIPState state) const;
SIP::SIPState echoSIPState(SIP::SIPState state) const;
/** Tag for removal. */
void remove() { mRemoved=true; mStateTimer.now(); }
/** Removal status. */
bool removed() { return mRemoved; }
};
@@ -314,9 +328,10 @@ class TransactionTable {
public:
/**
Initialize thetransaction table with a random mIDCounter value.
Initialize a transaction table.
@param path Path fto sqlite3 database file.
*/
void init();
void init(const char* path);
~TransactionTable();
@@ -371,12 +386,28 @@ class TransactionTable {
/**
Find an entry by its channel pointer.
Find an entry by its channel pointer; returns first entry found.
Also clears dead entries during search.
@param chan The channel pointer.
@return pointer to entry or NULL if no active match
*/
TransactionEntry* find(const GSM::LogicalChannel *chan);
/**
Find an entry by its SACCH channel pointer; returns first entry found.
Also clears dead entries during search.
@param chan The channel pointer.
@return pointer to entry or NULL if no active match
*/
TransactionEntry* findBySACCH(const GSM::SACCHLogicalChannel *chan);
/**
Find an entry by its channel type and offset.
Also clears dead entries during search.
@param chan The channel pointer to the first record found.
@return pointer to entry or NULL if no active match
*/
TransactionEntry* find(const GSM::LogicalChannel *chan);
TransactionEntry* find(GSM::TypeAndOffset chanDesc);
/**
Find an entry in the given state by its mobile ID.
@@ -386,14 +417,19 @@ class TransactionTable {
*/
TransactionEntry* find(const GSM::L3MobileIdentity& mobileID, GSM::CallState state);
#if 0
/** Return true if there is an ongoing call for this user. */
bool isBusy(const GSM::L3MobileIdentity& mobileID);
#endif
/** Find by subscriber and SIP call ID. */
TransactionEntry* find(const GSM::L3MobileIdentity& mobileID, const char* callID);
/** Find by subscriber and handover other BS transaction ID. */
TransactionEntry* find(const GSM::L3MobileIdentity& mobileID, unsigned transactionID);
/** Check for duplicated SMS delivery attempts. */
bool duplicateMessage(const GSM::L3MobileIdentity& mobileID, const std::string& wMessage);
/**
Find an entry in the Paging state by its mobile ID, change state to AnsweredPaging and reset T3113.
Also clears dead entries during search.
@@ -415,8 +451,7 @@ class TransactionTable {
size_t size() { ScopedLock lock(mLock); return mTable.size(); }
size_t dump(std::ostream& os) const;
size_t dump(std::ostream& os, bool showAll=false) const;
private:
@@ -437,6 +472,7 @@ class TransactionTable {
*/
void innerRemove(TransactionMap::iterator);
};
@@ -458,3 +494,5 @@ extern Control::TransactionTable gTransactionTable;
#endif
// vim: ts=4 sw=4