mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-10-31 20:03: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