mirror of
https://github.com/RangeNetworks/openbts.git
synced 2025-11-01 20:33:33 +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();
|
||||
LOG(INFO) << "SIP state " << state;
|
||||
if (state==SIP::Cleared) return;
|
||||
if (state!=SIP::MODClearing) {
|
||||
// This also changes the SIP state to "clearing".
|
||||
if (state==SIP::Active){
|
||||
//Changes state to clearing
|
||||
transaction->MODSendBYE();
|
||||
} else {
|
||||
} else if (state==SIP::MODCanceling){
|
||||
transaction->MODResendCANCEL();
|
||||
} else if (state==SIP::MODClearing) {
|
||||
transaction->MODResendBYE();
|
||||
} else {
|
||||
//Changes state to canceling
|
||||
transaction->MODSendCANCEL();
|
||||
}
|
||||
transaction->MODWaitForOK();
|
||||
}
|
||||
@@ -300,8 +305,16 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne
|
||||
LCH->send(GSM::L3Release(transaction->L3TI()));
|
||||
transaction->setTimer("308");
|
||||
transaction->GSMState(GSM::ReleaseRequest);
|
||||
// FIXME -- Maybe we need to send CANCEL. See ticket #172.
|
||||
transaction->MODSendBYE();
|
||||
//bug #172 fixed
|
||||
if (transaction->SIPState()==SIP::Active){
|
||||
transaction->MODSendBYE();
|
||||
}
|
||||
else{
|
||||
transaction->MODSendCANCEL();
|
||||
//if we disconnect, we don't get another
|
||||
//of these, wait here? -kurtis
|
||||
transaction->MODWaitForOK();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,6 +420,14 @@ SIP::SIPState TransactionEntry::MODSendBYE()
|
||||
return state;
|
||||
}
|
||||
|
||||
SIP::SIPState TransactionEntry::MODSendCANCEL()
|
||||
{
|
||||
ScopedLock lock(mLock);
|
||||
SIP::SIPState state = mSIP.MODSendCANCEL();
|
||||
echoSIPState(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
SIP::SIPState TransactionEntry::MODResendBYE()
|
||||
{
|
||||
ScopedLock lock(mLock);
|
||||
@@ -428,6 +436,14 @@ SIP::SIPState TransactionEntry::MODResendBYE()
|
||||
return state;
|
||||
}
|
||||
|
||||
SIP::SIPState TransactionEntry::MODResendCANCEL()
|
||||
{
|
||||
ScopedLock lock(mLock);
|
||||
SIP::SIPState state = mSIP.MODResendCANCEL();
|
||||
echoSIPState(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
SIP::SIPState TransactionEntry::MODWaitForOK()
|
||||
{
|
||||
ScopedLock lock(mLock);
|
||||
|
||||
@@ -198,7 +198,9 @@ class TransactionEntry {
|
||||
void MTCInitRTP() { ScopedLock lock(mLock); mSIP.MTCInitRTP(); }
|
||||
|
||||
SIP::SIPState MODSendBYE();
|
||||
SIP::SIPState MODSendCANCEL();
|
||||
SIP::SIPState MODResendBYE();
|
||||
SIP::SIPState MODResendCANCEL();
|
||||
SIP::SIPState MODWaitForOK();
|
||||
|
||||
SIP::SIPState MTDCheckBYE();
|
||||
|
||||
@@ -69,6 +69,7 @@ const char* SIP::SIPStateString(SIPState s)
|
||||
case Fail: return "Fail";
|
||||
case Busy: return "Busy";
|
||||
case MODClearing: return "MODClearing";
|
||||
case MODCanceling: return "MODCanceling";
|
||||
case MTDClearing: return "MTDClearing";
|
||||
case Cleared: return "Cleared";
|
||||
case MessageSubmit: return "SMS-Submit";
|
||||
@@ -93,7 +94,7 @@ SIPEngine::SIPEngine(const char* proxy, const char* IMSI)
|
||||
mSIPPort(gConfig.getNum("SIP.Local.Port")),
|
||||
mSIPIP(gConfig.getStr("SIP.Local.IP")),
|
||||
mINVITE(NULL), mLastResponse(NULL), mBYE(NULL),
|
||||
mSession(NULL),mTxTime(0), mRxTime(0),
|
||||
mCANCEL(NULL), mSession(NULL), mTxTime(0), mRxTime(0),
|
||||
mState(NullState),
|
||||
mDTMF('\0'),mDTMFDuration(0)
|
||||
{
|
||||
@@ -126,6 +127,7 @@ SIPEngine::~SIPEngine()
|
||||
if (mINVITE!=NULL) osip_message_free(mINVITE);
|
||||
if (mLastResponse!=NULL) osip_message_free(mLastResponse);
|
||||
if (mBYE!=NULL) osip_message_free(mBYE);
|
||||
if (mCANCEL!=NULL) osip_message_free(mCANCEL);
|
||||
// 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);
|
||||
}
|
||||
|
||||
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 )
|
||||
@@ -548,6 +559,20 @@ SIPState SIPEngine::MODSendBYE()
|
||||
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()
|
||||
{
|
||||
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||
@@ -557,12 +582,21 @@ SIPState SIPEngine::MODResendBYE()
|
||||
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()
|
||||
{
|
||||
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||
bool responded = false;
|
||||
Timeval byeTimeout(gConfig.getNum("SIP.Timer.F"));
|
||||
while (!byeTimeout.passed()) {
|
||||
Timeval timeout(gConfig.getNum("SIP.Timer.F"));
|
||||
while (!timeout.passed()) {
|
||||
try {
|
||||
osip_message_t * ok = gSIPInterface.read(mCallID, gConfig.getNum("SIP.Timer.E"));
|
||||
responded = true;
|
||||
@@ -575,8 +609,14 @@ SIPState SIPEngine::MODWaitForOK()
|
||||
break;
|
||||
}
|
||||
catch (SIPTimeout& e) {
|
||||
LOG(NOTICE) << "response timeout, resending BYE";
|
||||
MODResendBYE();
|
||||
//this is sketchy -kurtis
|
||||
if (mState==MODCanceling){
|
||||
LOG(NOTICE) << "response timeout, resending CANCEL";
|
||||
MODResendCANCEL();
|
||||
} else {
|
||||
LOG(NOTICE) << "response timeout, resending BYE";
|
||||
MODResendBYE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ enum SIPState {
|
||||
Connecting,
|
||||
Active,
|
||||
MODClearing,
|
||||
MODCanceling,
|
||||
MTDClearing,
|
||||
Cleared,
|
||||
Fail,
|
||||
@@ -108,6 +109,7 @@ private:
|
||||
osip_message_t * mINVITE; ///< the INVITE message 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 * mCANCEL; ///< the CANCEL message for this transaction
|
||||
//@}
|
||||
|
||||
/**@name RTP state and parameters. */
|
||||
@@ -263,8 +265,12 @@ public:
|
||||
//@{
|
||||
SIPState MODSendBYE();
|
||||
|
||||
SIPState MODSendCANCEL();
|
||||
|
||||
SIPState MODResendBYE();
|
||||
|
||||
SIPState MODResendCANCEL();
|
||||
|
||||
SIPState MODWaitForOK();
|
||||
//@}
|
||||
|
||||
@@ -320,6 +326,9 @@ public:
|
||||
/** Save a copy of a BYE message in the engine. */
|
||||
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:
|
||||
|
||||
@@ -592,6 +592,22 @@ osip_message_t * SIP::sip_bye(const char * req_uri, const char * dialed_number,
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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_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 );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user