mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-04 05:43:14 +00:00 
			
		
		
		
	r4259 in private:
More checking for defunct tranaactions. Send RELEASE on TCH if the call fails before EA Assignment step. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4915 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
		@@ -124,6 +124,11 @@ void forceGSMClearing(TransactionEntry *transaction, GSM::LogicalChannel *LCH, c
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
void forceSIPClearing(TransactionEntry *transaction)
 | 
					void forceSIPClearing(TransactionEntry *transaction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
							LOG(ERR) << "aborting transaction that is already removed or defunct";
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SIP::SIPState state = transaction->SIPState();
 | 
						SIP::SIPState state = transaction->SIPState();
 | 
				
			||||||
	LOG(INFO) << "SIP state " << state;
 | 
						LOG(INFO) << "SIP state " << state;
 | 
				
			||||||
	//why aren't we checking for failed here? -kurtis
 | 
						//why aren't we checking for failed here? -kurtis
 | 
				
			||||||
@@ -157,9 +162,22 @@ void forceSIPClearing(TransactionEntry *transaction)
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
void abortCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH, const GSM::L3Cause& cause)
 | 
					void abortCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH, const GSM::L3Cause& cause)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						LOG(DEBUG);
 | 
				
			||||||
 | 
						if (!transaction->deadOrRemoved()) {
 | 
				
			||||||
		LOG(INFO) << "cause: " << cause << ", transaction: " << *transaction;
 | 
							LOG(INFO) << "cause: " << cause << ", transaction: " << *transaction;
 | 
				
			||||||
		if (LCH) forceGSMClearing(transaction,LCH,cause);
 | 
							if (LCH) forceGSMClearing(transaction,LCH,cause);
 | 
				
			||||||
		forceSIPClearing(transaction);
 | 
							forceSIPClearing(transaction);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							if (LCH) {
 | 
				
			||||||
 | 
								LOG(ERR) << "aborting transaction that is already removed or defunct on " << *LCH;
 | 
				
			||||||
 | 
								forceGSMClearing(transaction,LCH,cause);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								LOG(ERR) << "aborting transaction that is already removed or defunct, no channel";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -171,6 +189,15 @@ void abortCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH, const GS
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
void abortAndRemoveCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH, const GSM::L3Cause& cause)
 | 
					void abortAndRemoveCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH, const GSM::L3Cause& cause)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
							if (LCH) {
 | 
				
			||||||
 | 
								LOG(ERR) << "aborting transaction that is already removed or defunct on " << *LCH;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								LOG(ERR) << "aborting transaction that is already removed or defunct, no channel";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	LOG(NOTICE) << "cause: " << cause << ", transaction: " << *transaction;
 | 
						LOG(NOTICE) << "cause: " << cause << ", transaction: " << *transaction;
 | 
				
			||||||
	abortCall(transaction,LCH,cause);
 | 
						abortCall(transaction,LCH,cause);
 | 
				
			||||||
	gTransactionTable.remove(transaction);
 | 
						gTransactionTable.remove(transaction);
 | 
				
			||||||
@@ -186,6 +213,7 @@ void abortAndRemoveCall(TransactionEntry *transaction, GSM::LogicalChannel *LCH,
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
GSM::TCHFACCHLogicalChannel *allocateTCH(GSM::LogicalChannel *DCCH)
 | 
					GSM::TCHFACCHLogicalChannel *allocateTCH(GSM::LogicalChannel *DCCH)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						// Get TCH will open the channel.
 | 
				
			||||||
	GSM::TCHFACCHLogicalChannel *TCH = gBTS.getTCH();
 | 
						GSM::TCHFACCHLogicalChannel *TCH = gBTS.getTCH();
 | 
				
			||||||
	if (!TCH) {
 | 
						if (!TCH) {
 | 
				
			||||||
		LOG(WARNING) << "congestion, no TCH available for assignment";
 | 
							LOG(WARNING) << "congestion, no TCH available for assignment";
 | 
				
			||||||
@@ -222,6 +250,7 @@ bool assignTCHF(TransactionEntry *transaction, GSM::LogicalChannel *DCCH, GSM::T
 | 
				
			|||||||
		transaction->channel(TCH);
 | 
							transaction->channel(TCH);
 | 
				
			||||||
		LOG(DEBUG) << "updated transaction " << *transaction;
 | 
							LOG(DEBUG) << "updated transaction " << *transaction;
 | 
				
			||||||
		LOG(INFO) << "sending AssignmentCommand for " << *TCH << " on " << *DCCH;
 | 
							LOG(INFO) << "sending AssignmentCommand for " << *TCH << " on " << *DCCH;
 | 
				
			||||||
 | 
							// FIXME - We should probably be setting the initial power here.
 | 
				
			||||||
		DCCH->send(GSM::L3AssignmentCommand(TCH->channelDescription(),GSM::L3ChannelMode(GSM::L3ChannelMode::SpeechV1)));
 | 
							DCCH->send(GSM::L3AssignmentCommand(TCH->channelDescription(),GSM::L3ChannelMode(GSM::L3ChannelMode::SpeechV1)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// This read is SUPPOSED to time out if the assignment was successful.
 | 
							// This read is SUPPOSED to time out if the assignment was successful.
 | 
				
			||||||
@@ -725,7 +754,24 @@ void callManagementLoop(TransactionEntry *transaction, GSM::TCHFACCHLogicalChann
 | 
				
			|||||||
	LOG(INFO) << " call connected " << *transaction;
 | 
						LOG(INFO) << " call connected " << *transaction;
 | 
				
			||||||
	gReports.incr("OpenBTS.GSM.CC.CallMinutes");
 | 
						gReports.incr("OpenBTS.GSM.CC.CallMinutes");
 | 
				
			||||||
	// poll everything until the call is finished
 | 
						// poll everything until the call is finished
 | 
				
			||||||
	while (!pollInCall(transaction,TCH)) { }
 | 
						// A rough count of frames.
 | 
				
			||||||
 | 
						size_t fCount = 0;
 | 
				
			||||||
 | 
						while (!pollInCall(transaction,TCH)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
								LOG(ERR) << "attempting to use a defunct transaction";
 | 
				
			||||||
 | 
								TCH->send(GSM::L3ChannelRelease());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fCount++;
 | 
				
			||||||
 | 
							// On average, pollInCall blocks for 20 ms.
 | 
				
			||||||
 | 
							// Every minute, reset the watchdog timer.
 | 
				
			||||||
 | 
							if ((fCount%(60*50))==0) {
 | 
				
			||||||
 | 
								LOG(DEBUG) << fCount << " cycles of call management loop; resetting watchdog";
 | 
				
			||||||
 | 
								gReports.incr("OpenBTS.GSM.CC.CallMinutes");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	gTransactionTable.remove(transaction);
 | 
						gTransactionTable.remove(transaction);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -902,18 +948,31 @@ void Control::MOCStarter(const GSM::L3CMServiceRequest* req, GSM::LogicalChannel
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel* TCH)
 | 
					void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel* TCH)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						assert(transaction);
 | 
				
			||||||
 | 
						assert(TCH);
 | 
				
			||||||
 | 
						if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
							LOG(ERR) << "dead or defunct transaciton on " << *TCH;
 | 
				
			||||||
 | 
							TCH->send(GSM::L3ChannelRelease());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	LOG(DEBUG) << "transaction: " << *transaction;
 | 
						LOG(DEBUG) << "transaction: " << *transaction;
 | 
				
			||||||
	unsigned L3TI = transaction->L3TI();
 | 
						unsigned L3TI = transaction->L3TI();
 | 
				
			||||||
	assert(L3TI>7);
 | 
						assert(L3TI>7);
 | 
				
			||||||
	assert(TCH);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Look for RINGING or OK from the SIP side.
 | 
						// Look for RINGING or OK from the SIP side.
 | 
				
			||||||
	// There's a T310 running on the phone now.
 | 
						// There's a T310 running on the phone now.
 | 
				
			||||||
	// The phone will initiate clearing if it expires.
 | 
						// The phone will initiate clearing if it expires.
 | 
				
			||||||
	// FIXME -- We should also have a SIP.Timer.B timeout on this end.
 | 
						// FIXME -- We should also have a SIP.Timer.B timeout on this end.
 | 
				
			||||||
 | 
						SIP::SIPState prevState = transaction->SIPState();
 | 
				
			||||||
	while (transaction->GSMState()!=GSM::CallReceived) {
 | 
						while (transaction->GSMState()!=GSM::CallReceived) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
								LOG(ERR) << "attempting to use a defunct transaction";
 | 
				
			||||||
 | 
								TCH->send(GSM::L3ChannelRelease());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (updateGSMSignalling(transaction,TCH)) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x15));
 | 
							if (updateGSMSignalling(transaction,TCH)) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x15));
 | 
				
			||||||
		if (transaction->clearingGSM()) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
 | 
							if (transaction->clearingGSM()) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -937,10 +996,13 @@ void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
 | 
				
			|||||||
				transaction->GSMState(GSM::CallReceived);
 | 
									transaction->GSMState(GSM::CallReceived);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case SIP::Proceeding:
 | 
								case SIP::Proceeding:
 | 
				
			||||||
				LOG(DEBUG) << "SIP:Proceeding, send progress";
 | 
									if (state != prevState) {
 | 
				
			||||||
 | 
										LOG(DEBUG) << "SIP::Proceeding, state change, sending L3 progress";
 | 
				
			||||||
					TCH->send(GSM::L3Progress(L3TI));
 | 
										TCH->send(GSM::L3Progress(L3TI));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case SIP::Timeout:
 | 
								case SIP::Timeout:
 | 
				
			||||||
 | 
									// This is CRIT instead of ALERT because it could also be due to packet loss.
 | 
				
			||||||
				LOG(CRIT) << "MOC INVITE Timed out. Is SIP.Proxy.Speech (" << gConfig.getStr("SIP.Proxy.Speech") << ") configured correctly?";
 | 
									LOG(CRIT) << "MOC INVITE Timed out. Is SIP.Proxy.Speech (" << gConfig.getStr("SIP.Proxy.Speech") << ") configured correctly?";
 | 
				
			||||||
				state = transaction->MOCResendINVITE();
 | 
									state = transaction->MOCResendINVITE();
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
@@ -948,6 +1010,7 @@ void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
 | 
				
			|||||||
				LOG(NOTICE) << "SIP unexpected state " << state;
 | 
									LOG(NOTICE) << "SIP unexpected state " << state;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							prevState = state;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// There's a question here of what entity is generating the "patterns"
 | 
						// There's a question here of what entity is generating the "patterns"
 | 
				
			||||||
@@ -961,6 +1024,12 @@ void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
 | 
				
			|||||||
	SIP::SIPState state = transaction->SIPState();
 | 
						SIP::SIPState state = transaction->SIPState();
 | 
				
			||||||
	while (state!=SIP::Active) {
 | 
						while (state!=SIP::Active) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
								LOG(ERR) << "attempting to use a defunct transaction";
 | 
				
			||||||
 | 
								TCH->send(GSM::L3ChannelRelease());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		LOG(DEBUG) << "wait for SIP session start";
 | 
							LOG(DEBUG) << "wait for SIP session start";
 | 
				
			||||||
		state = transaction->MOCCheckForOK();
 | 
							state = transaction->MOCCheckForOK();
 | 
				
			||||||
		LOG(DEBUG) << "SIP state "<< state;
 | 
							LOG(DEBUG) << "SIP state "<< state;
 | 
				
			||||||
@@ -1004,6 +1073,13 @@ void Control::MOCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Get the Connect Acknowledge message.
 | 
						// Get the Connect Acknowledge message.
 | 
				
			||||||
	while (transaction->GSMState()!=GSM::Active) {
 | 
						while (transaction->GSMState()!=GSM::Active) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (transaction->deadOrRemoved()) {
 | 
				
			||||||
 | 
								LOG(ERR) << "attempting to use a defunct transaction";
 | 
				
			||||||
 | 
								TCH->send(GSM::L3ChannelRelease());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		LOG(DEBUG) << "MOC Q.931 state=" << transaction->GSMState();
 | 
							LOG(DEBUG) << "MOC Q.931 state=" << transaction->GSMState();
 | 
				
			||||||
		if (updateGSMSignalling(transaction,TCH,T313ms)) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
 | 
							if (updateGSMSignalling(transaction,TCH,T313ms)) return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1063,7 +1139,7 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
 | 
				
			|||||||
	while (transaction->GSMState()!=GSM::MTCConfirmed) {
 | 
						while (transaction->GSMState()!=GSM::MTCConfirmed) {
 | 
				
			||||||
		if (transaction->MTCSendTrying()==SIP::Fail) {
 | 
							if (transaction->MTCSendTrying()==SIP::Fail) {
 | 
				
			||||||
			LOG(NOTICE) << "call failed on SIP side";
 | 
								LOG(NOTICE) << "call failed on SIP side";
 | 
				
			||||||
			LCH->send(GSM::RELEASE);
 | 
								if (TCH) TCH->send(GSM::HARDRELEASE);
 | 
				
			||||||
			// Cause 0x03 is "no route to destination"
 | 
								// Cause 0x03 is "no route to destination"
 | 
				
			||||||
			return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x03));
 | 
								return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x03));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -1071,12 +1147,14 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
 | 
				
			|||||||
		// It's the SIP TRYING timeout, whatever that is.
 | 
							// It's the SIP TRYING timeout, whatever that is.
 | 
				
			||||||
		if (updateGSMSignalling(transaction,LCH,1000)) {
 | 
							if (updateGSMSignalling(transaction,LCH,1000)) {
 | 
				
			||||||
			LOG(INFO) << "Release from GSM side";
 | 
								LOG(INFO) << "Release from GSM side";
 | 
				
			||||||
 | 
								if (TCH) TCH->send(GSM::HARDRELEASE);
 | 
				
			||||||
			LCH->send(GSM::RELEASE);
 | 
								LCH->send(GSM::RELEASE);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Check for SIP cancel, too.
 | 
							// Check for SIP cancel, too.
 | 
				
			||||||
		if (transaction->MTCCheckForCancel()==SIP::MTDCanceling) {
 | 
							if (transaction->MTCCheckForCancel()==SIP::MTDCanceling) {
 | 
				
			||||||
			LOG(INFO) << "call cancelled on SIP side";
 | 
								LOG(INFO) << "call cancelled on SIP side";
 | 
				
			||||||
 | 
								if (TCH) TCH->send(GSM::HARDRELEASE);
 | 
				
			||||||
			transaction->MTDSendCANCELOK();
 | 
								transaction->MTDSendCANCELOK();
 | 
				
			||||||
			//should probably send a 487 here
 | 
								//should probably send a 487 here
 | 
				
			||||||
			// Cause 0x15 is "rejected"
 | 
								// Cause 0x15 is "rejected"
 | 
				
			||||||
@@ -1085,6 +1163,7 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
 | 
				
			|||||||
		//lastly check if we're toast
 | 
							//lastly check if we're toast
 | 
				
			||||||
		if(transaction->SIPState()==SIP::Fail) {
 | 
							if(transaction->SIPState()==SIP::Fail) {
 | 
				
			||||||
			LOG(DEBUG) << "Call failed";
 | 
								LOG(DEBUG) << "Call failed";
 | 
				
			||||||
 | 
								if (TCH) TCH->send(GSM::HARDRELEASE);
 | 
				
			||||||
			return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x7F));
 | 
								return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x7F));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1096,6 +1175,7 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
 | 
				
			|||||||
		// For very early assignment, we need a mode change.
 | 
							// For very early assignment, we need a mode change.
 | 
				
			||||||
		static const GSM::L3ChannelMode mode(GSM::L3ChannelMode::SpeechV1);
 | 
							static const GSM::L3ChannelMode mode(GSM::L3ChannelMode::SpeechV1);
 | 
				
			||||||
		LCH->send(GSM::L3ChannelModeModify(LCH->channelDescription(),mode));
 | 
							LCH->send(GSM::L3ChannelModeModify(LCH->channelDescription(),mode));
 | 
				
			||||||
 | 
							// FIXME - We should call this in a loop in case there are stray messages in the channel.
 | 
				
			||||||
		GSM::L3Message* msg_ack = getMessage(LCH);
 | 
							GSM::L3Message* msg_ack = getMessage(LCH);
 | 
				
			||||||
		const GSM::L3ChannelModeModifyAcknowledge *ack =
 | 
							const GSM::L3ChannelModeModifyAcknowledge *ack =
 | 
				
			||||||
			dynamic_cast<GSM::L3ChannelModeModifyAcknowledge*>(msg_ack);
 | 
								dynamic_cast<GSM::L3ChannelModeModifyAcknowledge*>(msg_ack);
 | 
				
			||||||
@@ -1115,6 +1195,7 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
 | 
				
			|||||||
	else {
 | 
						else {
 | 
				
			||||||
		// For late assignment, send the TCH assignment now.
 | 
							// For late assignment, send the TCH assignment now.
 | 
				
			||||||
		// This dispatcher on the next channel will continue the transaction.
 | 
							// This dispatcher on the next channel will continue the transaction.
 | 
				
			||||||
 | 
							assert(TCH);
 | 
				
			||||||
		assignTCHF(transaction,LCH,TCH);
 | 
							assignTCHF(transaction,LCH,TCH);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user