mirror of
https://github.com/RangeNetworks/openbts.git
synced 2025-11-09 16:15:54 +00:00
Fixed Bug #172, OpenBTS now sends CANCEL messages when there is no active call (instead of BYE)
git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3006 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
@@ -119,11 +119,16 @@ void forceSIPClearing(TransactionEntry *transaction)
|
|||||||
SIP::SIPState state = transaction->SIPState();
|
SIP::SIPState state = transaction->SIPState();
|
||||||
LOG(INFO) << "SIP state " << state;
|
LOG(INFO) << "SIP state " << state;
|
||||||
if (state==SIP::Cleared) return;
|
if (state==SIP::Cleared) return;
|
||||||
if (state!=SIP::MODClearing) {
|
if (state==SIP::Active){
|
||||||
// This also changes the SIP state to "clearing".
|
//Changes state to clearing
|
||||||
transaction->MODSendBYE();
|
transaction->MODSendBYE();
|
||||||
} else {
|
} else if (state==SIP::MODCanceling){
|
||||||
|
transaction->MODResendCANCEL();
|
||||||
|
} else if (state==SIP::MODClearing) {
|
||||||
transaction->MODResendBYE();
|
transaction->MODResendBYE();
|
||||||
|
} else {
|
||||||
|
//Changes state to canceling
|
||||||
|
transaction->MODSendCANCEL();
|
||||||
}
|
}
|
||||||
transaction->MODWaitForOK();
|
transaction->MODWaitForOK();
|
||||||
}
|
}
|
||||||
@@ -300,8 +305,16 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne
|
|||||||
LCH->send(GSM::L3Release(transaction->L3TI()));
|
LCH->send(GSM::L3Release(transaction->L3TI()));
|
||||||
transaction->setTimer("308");
|
transaction->setTimer("308");
|
||||||
transaction->GSMState(GSM::ReleaseRequest);
|
transaction->GSMState(GSM::ReleaseRequest);
|
||||||
// FIXME -- Maybe we need to send CANCEL. See ticket #172.
|
//bug #172 fixed
|
||||||
|
if (transaction->SIPState()==SIP::Active){
|
||||||
transaction->MODSendBYE();
|
transaction->MODSendBYE();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
transaction->MODSendCANCEL();
|
||||||
|
//if we disconnect, we don't get another
|
||||||
|
//of these, wait here? -kurtis
|
||||||
|
transaction->MODWaitForOK();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -420,6 +420,14 @@ SIP::SIPState TransactionEntry::MODSendBYE()
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIP::SIPState TransactionEntry::MODSendCANCEL()
|
||||||
|
{
|
||||||
|
ScopedLock lock(mLock);
|
||||||
|
SIP::SIPState state = mSIP.MODSendCANCEL();
|
||||||
|
echoSIPState(state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
SIP::SIPState TransactionEntry::MODResendBYE()
|
SIP::SIPState TransactionEntry::MODResendBYE()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
@@ -428,6 +436,14 @@ SIP::SIPState TransactionEntry::MODResendBYE()
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIP::SIPState TransactionEntry::MODResendCANCEL()
|
||||||
|
{
|
||||||
|
ScopedLock lock(mLock);
|
||||||
|
SIP::SIPState state = mSIP.MODResendCANCEL();
|
||||||
|
echoSIPState(state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
SIP::SIPState TransactionEntry::MODWaitForOK()
|
SIP::SIPState TransactionEntry::MODWaitForOK()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
|
|||||||
@@ -198,7 +198,9 @@ class TransactionEntry {
|
|||||||
void MTCInitRTP() { ScopedLock lock(mLock); mSIP.MTCInitRTP(); }
|
void MTCInitRTP() { ScopedLock lock(mLock); mSIP.MTCInitRTP(); }
|
||||||
|
|
||||||
SIP::SIPState MODSendBYE();
|
SIP::SIPState MODSendBYE();
|
||||||
|
SIP::SIPState MODSendCANCEL();
|
||||||
SIP::SIPState MODResendBYE();
|
SIP::SIPState MODResendBYE();
|
||||||
|
SIP::SIPState MODResendCANCEL();
|
||||||
SIP::SIPState MODWaitForOK();
|
SIP::SIPState MODWaitForOK();
|
||||||
|
|
||||||
SIP::SIPState MTDCheckBYE();
|
SIP::SIPState MTDCheckBYE();
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const char* SIP::SIPStateString(SIPState s)
|
|||||||
case Fail: return "Fail";
|
case Fail: return "Fail";
|
||||||
case Busy: return "Busy";
|
case Busy: return "Busy";
|
||||||
case MODClearing: return "MODClearing";
|
case MODClearing: return "MODClearing";
|
||||||
|
case MODCanceling: return "MODCanceling";
|
||||||
case MTDClearing: return "MTDClearing";
|
case MTDClearing: return "MTDClearing";
|
||||||
case Cleared: return "Cleared";
|
case Cleared: return "Cleared";
|
||||||
case MessageSubmit: return "SMS-Submit";
|
case MessageSubmit: return "SMS-Submit";
|
||||||
@@ -93,7 +94,7 @@ SIPEngine::SIPEngine(const char* proxy, const char* IMSI)
|
|||||||
mSIPPort(gConfig.getNum("SIP.Local.Port")),
|
mSIPPort(gConfig.getNum("SIP.Local.Port")),
|
||||||
mSIPIP(gConfig.getStr("SIP.Local.IP")),
|
mSIPIP(gConfig.getStr("SIP.Local.IP")),
|
||||||
mINVITE(NULL), mLastResponse(NULL), mBYE(NULL),
|
mINVITE(NULL), mLastResponse(NULL), mBYE(NULL),
|
||||||
mSession(NULL),mTxTime(0), mRxTime(0),
|
mCANCEL(NULL), mSession(NULL), mTxTime(0), mRxTime(0),
|
||||||
mState(NullState),
|
mState(NullState),
|
||||||
mDTMF('\0'),mDTMFDuration(0)
|
mDTMF('\0'),mDTMFDuration(0)
|
||||||
{
|
{
|
||||||
@@ -126,6 +127,7 @@ SIPEngine::~SIPEngine()
|
|||||||
if (mINVITE!=NULL) osip_message_free(mINVITE);
|
if (mINVITE!=NULL) osip_message_free(mINVITE);
|
||||||
if (mLastResponse!=NULL) osip_message_free(mLastResponse);
|
if (mLastResponse!=NULL) osip_message_free(mLastResponse);
|
||||||
if (mBYE!=NULL) osip_message_free(mBYE);
|
if (mBYE!=NULL) osip_message_free(mBYE);
|
||||||
|
if (mCANCEL!=NULL) osip_message_free(mCANCEL);
|
||||||
// FIXME -- Do we need to dispose of the RtpSesion *mSesison?
|
// FIXME -- Do we need to dispose of the RtpSesion *mSesison?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +186,15 @@ void SIPEngine::saveBYE(const osip_message_t *BYE, bool mine)
|
|||||||
osip_message_clone(BYE,&mBYE);
|
osip_message_clone(BYE,&mBYE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SIPEngine::saveCANCEL(const osip_message_t *CANCEL, bool mine)
|
||||||
|
{
|
||||||
|
// Instead of cloning, why not just keep the old one?
|
||||||
|
// Because that doesn't work in all calling contexts.
|
||||||
|
// This simplifies the call-handling logic.
|
||||||
|
if (mCANCEL!=NULL) osip_message_free(mCANCEL);
|
||||||
|
osip_message_clone(CANCEL,&mCANCEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SIPEngine::user( const char * IMSI )
|
void SIPEngine::user( const char * IMSI )
|
||||||
@@ -548,6 +559,20 @@ SIPState SIPEngine::MODSendBYE()
|
|||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIPState SIPEngine::MODSendCANCEL()
|
||||||
|
{
|
||||||
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
|
assert(mINVITE);
|
||||||
|
|
||||||
|
osip_message_t * cancel = sip_cancel(mINVITE);
|
||||||
|
gSIPInterface.write(&mProxyAddr,cancel);
|
||||||
|
saveCANCEL(cancel, true);
|
||||||
|
osip_message_free(cancel);
|
||||||
|
mState = MODCanceling;
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIPState SIPEngine::MODResendBYE()
|
SIPState SIPEngine::MODResendBYE()
|
||||||
{
|
{
|
||||||
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
@@ -557,12 +582,21 @@ SIPState SIPEngine::MODResendBYE()
|
|||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIPState SIPEngine::MODResendCANCEL()
|
||||||
|
{
|
||||||
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
|
assert(mState==MODCanceling);
|
||||||
|
assert(mCANCEL);
|
||||||
|
gSIPInterface.write(&mProxyAddr,mCANCEL);
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
SIPState SIPEngine::MODWaitForOK()
|
SIPState SIPEngine::MODWaitForOK()
|
||||||
{
|
{
|
||||||
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
bool responded = false;
|
bool responded = false;
|
||||||
Timeval byeTimeout(gConfig.getNum("SIP.Timer.F"));
|
Timeval timeout(gConfig.getNum("SIP.Timer.F"));
|
||||||
while (!byeTimeout.passed()) {
|
while (!timeout.passed()) {
|
||||||
try {
|
try {
|
||||||
osip_message_t * ok = gSIPInterface.read(mCallID, gConfig.getNum("SIP.Timer.E"));
|
osip_message_t * ok = gSIPInterface.read(mCallID, gConfig.getNum("SIP.Timer.E"));
|
||||||
responded = true;
|
responded = true;
|
||||||
@@ -575,10 +609,16 @@ SIPState SIPEngine::MODWaitForOK()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (SIPTimeout& e) {
|
catch (SIPTimeout& e) {
|
||||||
|
//this is sketchy -kurtis
|
||||||
|
if (mState==MODCanceling){
|
||||||
|
LOG(NOTICE) << "response timeout, resending CANCEL";
|
||||||
|
MODResendCANCEL();
|
||||||
|
} else {
|
||||||
LOG(NOTICE) << "response timeout, resending BYE";
|
LOG(NOTICE) << "response timeout, resending BYE";
|
||||||
MODResendBYE();
|
MODResendBYE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!responded) { LOG(ALERT) << "lost contact with proxy " << mProxyIP << ":" << mProxyPort; }
|
if (!responded) { LOG(ALERT) << "lost contact with proxy " << mProxyIP << ":" << mProxyPort; }
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ enum SIPState {
|
|||||||
Connecting,
|
Connecting,
|
||||||
Active,
|
Active,
|
||||||
MODClearing,
|
MODClearing,
|
||||||
|
MODCanceling,
|
||||||
MTDClearing,
|
MTDClearing,
|
||||||
Cleared,
|
Cleared,
|
||||||
Fail,
|
Fail,
|
||||||
@@ -108,6 +109,7 @@ private:
|
|||||||
osip_message_t * mINVITE; ///< the INVITE message for this transaction
|
osip_message_t * mINVITE; ///< the INVITE message for this transaction
|
||||||
osip_message_t * mLastResponse; ///< the last response received for this transaction
|
osip_message_t * mLastResponse; ///< the last response received for this transaction
|
||||||
osip_message_t * mBYE; ///< the BYE message for this transaction
|
osip_message_t * mBYE; ///< the BYE message for this transaction
|
||||||
|
osip_message_t * mCANCEL; ///< the CANCEL message for this transaction
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/**@name RTP state and parameters. */
|
/**@name RTP state and parameters. */
|
||||||
@@ -263,8 +265,12 @@ public:
|
|||||||
//@{
|
//@{
|
||||||
SIPState MODSendBYE();
|
SIPState MODSendBYE();
|
||||||
|
|
||||||
|
SIPState MODSendCANCEL();
|
||||||
|
|
||||||
SIPState MODResendBYE();
|
SIPState MODResendBYE();
|
||||||
|
|
||||||
|
SIPState MODResendCANCEL();
|
||||||
|
|
||||||
SIPState MODWaitForOK();
|
SIPState MODWaitForOK();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
@@ -320,6 +326,9 @@ public:
|
|||||||
/** Save a copy of a BYE message in the engine. */
|
/** Save a copy of a BYE message in the engine. */
|
||||||
void saveBYE(const osip_message_t *BYE, bool mine);
|
void saveBYE(const osip_message_t *BYE, bool mine);
|
||||||
|
|
||||||
|
/** Save a copy of a CANCEL message in the engine. */
|
||||||
|
void saveCANCEL(const osip_message_t *CANCEL, bool mine);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -592,6 +592,22 @@ osip_message_t * SIP::sip_bye(const char * req_uri, const char * dialed_number,
|
|||||||
return bye;
|
return bye;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cancel a previous invite */
|
||||||
|
osip_message_t * SIP::sip_cancel( osip_message_t * invite)
|
||||||
|
{
|
||||||
|
|
||||||
|
osip_message_t * cancel;
|
||||||
|
osip_message_init(&cancel);
|
||||||
|
osip_message_clone(invite, &cancel);
|
||||||
|
// FIXME -- Should use the "force_update" function.
|
||||||
|
cancel->message_property = 2;
|
||||||
|
cancel->sip_method = strdup("CANCEL");
|
||||||
|
|
||||||
|
//update message type
|
||||||
|
osip_cseq_set_method(cancel->cseq, strdup("CANCEL"));
|
||||||
|
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
osip_message_t * SIP::sip_okay_sdp( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port, short rtp_port, unsigned audio_codec)
|
osip_message_t * SIP::sip_okay_sdp( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port, short rtp_port, unsigned audio_codec)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ osip_message_t * sip_ack( const char * req_uri, const char * dialed_number, cons
|
|||||||
|
|
||||||
osip_message_t * sip_bye( const char * req_uri, const char * dialed_number, const char * sip_username, short local_port, const char * local_ip, const char * proxy_ip, short proxy_port, const osip_from_t *from_header, const osip_to_t * to_header, const char * via_branch, const osip_call_id_t* call_id_header, int cseq);
|
osip_message_t * sip_bye( const char * req_uri, const char * dialed_number, const char * sip_username, short local_port, const char * local_ip, const char * proxy_ip, short proxy_port, const osip_from_t *from_header, const osip_to_t * to_header, const char * via_branch, const osip_call_id_t* call_id_header, int cseq);
|
||||||
|
|
||||||
|
osip_message_t * sip_cancel( osip_message_t * invite);
|
||||||
|
|
||||||
osip_message_t * sip_okay_sdp( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port, short rtp_port, unsigned audio_codecs );
|
osip_message_t * sip_okay_sdp( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port, short rtp_port, unsigned audio_codecs );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user