mirror of
https://github.com/fairwaves/openbts-2.8.git
synced 2025-11-09 08:25:52 +00:00
Fixes #34 in public release. We now have different states for the MTDCanceling and canceled calls now end in a canceled state. Also a few other hardening bug fixes.
git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3018 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
@@ -118,7 +118,8 @@ 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;
|
//why aren't we checking for failed here? -kurtis
|
||||||
|
if (transaction->SIPFinished()) return;
|
||||||
if (state==SIP::Active){
|
if (state==SIP::Active){
|
||||||
//Changes state to clearing
|
//Changes state to clearing
|
||||||
transaction->MODSendBYE();
|
transaction->MODSendBYE();
|
||||||
@@ -325,7 +326,7 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne
|
|||||||
LCH->send(GSM::L3ReleaseComplete(transaction->L3TI()));
|
LCH->send(GSM::L3ReleaseComplete(transaction->L3TI()));
|
||||||
LCH->send(GSM::L3ChannelRelease());
|
LCH->send(GSM::L3ChannelRelease());
|
||||||
transaction->GSMState(GSM::NullState);
|
transaction->GSMState(GSM::NullState);
|
||||||
transaction->MTDSendOK();
|
transaction->MTDSendBYEOK();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,10 +515,9 @@ bool updateSIPSignalling(TransactionEntry *transaction, GSM::LogicalChannel *LCH
|
|||||||
|
|
||||||
// The main purpose of this code is to initiate disconnects from the SIP side.
|
// The main purpose of this code is to initiate disconnects from the SIP side.
|
||||||
|
|
||||||
if (transaction->SIPState()==SIP::Cleared) return true;
|
if (transaction->SIPFinished()) return true;
|
||||||
|
|
||||||
bool GSMClearedOrClearing = GSMCleared || transaction->clearingGSM();
|
bool GSMClearedOrClearing = GSMCleared || transaction->clearingGSM();
|
||||||
|
|
||||||
if (transaction->MTDCheckBYE() == SIP::MTDClearing) {
|
if (transaction->MTDCheckBYE() == SIP::MTDClearing) {
|
||||||
LOG(DEBUG) << "got SIP BYE " << *transaction;
|
LOG(DEBUG) << "got SIP BYE " << *transaction;
|
||||||
if (!GSMClearedOrClearing) {
|
if (!GSMClearedOrClearing) {
|
||||||
@@ -528,11 +528,11 @@ bool updateSIPSignalling(TransactionEntry *transaction, GSM::LogicalChannel *LCH
|
|||||||
} else {
|
} else {
|
||||||
// GSM already cleared?
|
// GSM already cleared?
|
||||||
// Ack the BYE and end the call.
|
// Ack the BYE and end the call.
|
||||||
transaction->MTDSendOK();
|
transaction->MTDSendBYEOK();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return transaction->SIPState()==SIP::Cleared;
|
return (transaction->SIPFinished());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -548,8 +548,8 @@ bool updateSignalling(TransactionEntry *transaction, GSM::LogicalChannel *LCH, u
|
|||||||
{
|
{
|
||||||
|
|
||||||
bool GSMCleared = (updateGSMSignalling(transaction,LCH,timeout));
|
bool GSMCleared = (updateGSMSignalling(transaction,LCH,timeout));
|
||||||
bool SIPCleared = updateSIPSignalling(transaction,LCH,GSMCleared);
|
bool SIPFinished = updateSIPSignalling(transaction,LCH,GSMCleared);
|
||||||
return GSMCleared && SIPCleared;
|
return GSMCleared && SIPFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -628,7 +628,7 @@ bool waitInCall(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel *TCH,
|
|||||||
void callManagementLoop(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel* TCH)
|
void callManagementLoop(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel* TCH)
|
||||||
{
|
{
|
||||||
LOG(INFO) << " call connected " << *transaction;
|
LOG(INFO) << " call connected " << *transaction;
|
||||||
// poll everything until the call is cleared
|
// poll everything until the call is finished
|
||||||
while (!pollInCall(transaction,TCH)) { }
|
while (!pollInCall(transaction,TCH)) { }
|
||||||
gTransactionTable.remove(transaction);
|
gTransactionTable.remove(transaction);
|
||||||
}
|
}
|
||||||
@@ -948,11 +948,17 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check for SIP cancel, too.
|
// Check for SIP cancel, too.
|
||||||
if (transaction->MTCCheckForCancel()==SIP::Fail) {
|
if (transaction->MTCCheckForCancel()==SIP::MTDCanceling) {
|
||||||
LOG(NOTICE) << "call cancelled or failed on SIP side";
|
LOG(INFO) << "call cancelled on SIP side";
|
||||||
|
transaction->MTDSendCANCELOK();
|
||||||
// Cause 0x15 is "rejected"
|
// Cause 0x15 is "rejected"
|
||||||
return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x15));
|
return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x15));
|
||||||
}
|
}
|
||||||
|
//lastly check if we're toast
|
||||||
|
if(transaction->SIPState()==SIP::Fail) {
|
||||||
|
LOG(DEBUG) << "Call failed";
|
||||||
|
return abortAndRemoveCall(transaction,LCH,GSM::L3Cause(0x7F));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The transaction is moving to the MTCController.
|
// The transaction is moving to the MTCController.
|
||||||
@@ -1006,8 +1012,15 @@ void Control::MTCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
|
|||||||
transaction->MTCSendRinging();
|
transaction->MTCSendRinging();
|
||||||
}
|
}
|
||||||
// Check for SIP cancel, too.
|
// Check for SIP cancel, too.
|
||||||
if (transaction->MTCCheckForCancel()==SIP::Fail) {
|
if (transaction->MTCCheckForCancel()==SIP::MTDCanceling) {
|
||||||
LOG(DEBUG) << "MTCCheckForCancel return Fail";
|
LOG(INFO) << "MTCCheckForCancel return Canceling";
|
||||||
|
transaction->MTDSendCANCELOK();
|
||||||
|
// Cause 0x15 is "rejected"
|
||||||
|
return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x15));
|
||||||
|
}
|
||||||
|
//check if we're toast
|
||||||
|
if (transaction->SIPState()==SIP::Fail){
|
||||||
|
LOG(DEBUG) << "Call failed";
|
||||||
return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
|
return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x7F));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1031,6 +1044,10 @@ void Control::MTCController(TransactionEntry *transaction, GSM::TCHFACCHLogicalC
|
|||||||
break;
|
break;
|
||||||
case SIP::Connecting:
|
case SIP::Connecting:
|
||||||
break;
|
break;
|
||||||
|
case SIP::MTDCanceling:
|
||||||
|
state = transaction->MTDSendCANCELOK();
|
||||||
|
// Cause 0x15 is "rejected"
|
||||||
|
return abortAndRemoveCall(transaction,TCH,GSM::L3Cause(0x15));
|
||||||
default:
|
default:
|
||||||
LOG(NOTICE) << "SIP unexpected state " << state;
|
LOG(NOTICE) << "SIP unexpected state " << state;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -460,10 +460,18 @@ SIP::SIPState TransactionEntry::MTDCheckBYE()
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
SIP::SIPState TransactionEntry::MTDSendOK()
|
SIP::SIPState TransactionEntry::MTDSendBYEOK()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
SIP::SIPState state = mSIP.MTDSendOK();
|
SIP::SIPState state = mSIP.MTDSendBYEOK();
|
||||||
|
echoSIPState(state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIP::SIPState TransactionEntry::MTDSendCANCELOK()
|
||||||
|
{
|
||||||
|
ScopedLock lock(mLock);
|
||||||
|
SIP::SIPState state = mSIP.MTDSendCANCELOK();
|
||||||
echoSIPState(state);
|
echoSIPState(state);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,8 @@ class TransactionEntry {
|
|||||||
|
|
||||||
SIP::SIPState SIPState() { ScopedLock lock(mLock); return mSIP.state(); }
|
SIP::SIPState SIPState() { ScopedLock lock(mLock); return mSIP.state(); }
|
||||||
|
|
||||||
|
bool SIPFinished() { ScopedLock lock(mLock); return mSIP.finished(); }
|
||||||
|
|
||||||
SIP::SIPState MOCSendINVITE(const char* calledUser, const char* calledDomain, short rtpPort, unsigned codec);
|
SIP::SIPState MOCSendINVITE(const char* calledUser, const char* calledDomain, short rtpPort, unsigned codec);
|
||||||
SIP::SIPState MOCResendINVITE();
|
SIP::SIPState MOCResendINVITE();
|
||||||
SIP::SIPState MOCWaitForOK();
|
SIP::SIPState MOCWaitForOK();
|
||||||
@@ -204,7 +206,8 @@ class TransactionEntry {
|
|||||||
SIP::SIPState MODWaitForOK();
|
SIP::SIPState MODWaitForOK();
|
||||||
|
|
||||||
SIP::SIPState MTDCheckBYE();
|
SIP::SIPState MTDCheckBYE();
|
||||||
SIP::SIPState MTDSendOK();
|
SIP::SIPState MTDSendBYEOK();
|
||||||
|
SIP::SIPState MTDSendCANCELOK();
|
||||||
|
|
||||||
// TODO: Remove contentType from here and use the setter above.
|
// TODO: Remove contentType from here and use the setter above.
|
||||||
SIP::SIPState MOSMSSendMESSAGE(const char* calledUser, const char* calledDomain, const char* contentType);
|
SIP::SIPState MOSMSSendMESSAGE(const char* calledUser, const char* calledDomain, const char* contentType);
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ const char* SIP::SIPStateString(SIPState s)
|
|||||||
case MODClearing: return "MODClearing";
|
case MODClearing: return "MODClearing";
|
||||||
case MODCanceling: return "MODCanceling";
|
case MODCanceling: return "MODCanceling";
|
||||||
case MTDClearing: return "MTDClearing";
|
case MTDClearing: return "MTDClearing";
|
||||||
|
case MTDCanceling: return "MTDCanceling";
|
||||||
|
case Canceled: return "Canceled";
|
||||||
case Cleared: return "Cleared";
|
case Cleared: return "Cleared";
|
||||||
case MessageSubmit: return "SMS-Submit";
|
case MessageSubmit: return "SMS-Submit";
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
@@ -622,8 +624,12 @@ SIPState SIPEngine::MODWaitForOK()
|
|||||||
|
|
||||||
if (!responded) { LOG(ALERT) << "lost contact with proxy " << mProxyIP << ":" << mProxyPort; }
|
if (!responded) { LOG(ALERT) << "lost contact with proxy " << mProxyIP << ":" << mProxyPort; }
|
||||||
|
|
||||||
// However we got here, the SIP side of the call is cleared now.
|
//Canceled if we're canceling, otherwise clear
|
||||||
|
if (mState==MODCanceling){
|
||||||
|
mState = Canceled;
|
||||||
|
} else {
|
||||||
mState = Cleared;
|
mState = Cleared;
|
||||||
|
}
|
||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,7 +675,7 @@ SIPState SIPEngine::MTDCheckBYE()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SIPState SIPEngine::MTDSendOK()
|
SIPState SIPEngine::MTDSendBYEOK()
|
||||||
{
|
{
|
||||||
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
assert(mBYE);
|
assert(mBYE);
|
||||||
@@ -680,6 +686,17 @@ SIPState SIPEngine::MTDSendOK()
|
|||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIPState SIPEngine::MTDSendCANCELOK()
|
||||||
|
{
|
||||||
|
LOG(INFO) << "user " << mSIPUsername << " state " << mState;
|
||||||
|
assert(mCANCEL);
|
||||||
|
osip_message_t * okay = sip_b_okay(mCANCEL);
|
||||||
|
gSIPInterface.write(&mProxyAddr,okay);
|
||||||
|
osip_message_free(okay);
|
||||||
|
mState = Canceled;
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SIPState SIPEngine::MTCSendTrying()
|
SIPState SIPEngine::MTCSendTrying()
|
||||||
{
|
{
|
||||||
@@ -772,10 +789,8 @@ SIPState SIPEngine::MTCWaitForACK()
|
|||||||
// check for the CANCEL
|
// check for the CANCEL
|
||||||
else if( strcmp(ack->sip_method,"CANCEL") == 0){
|
else if( strcmp(ack->sip_method,"CANCEL") == 0){
|
||||||
LOG(INFO) << "received CANCEL";
|
LOG(INFO) << "received CANCEL";
|
||||||
osip_message_t * okay = sip_okay(ack, mSIPUsername.c_str(),mSIPIP.c_str(), mSIPPort);
|
saveCANCEL(ack, false);
|
||||||
gSIPInterface.write(&mProxyAddr,okay);
|
mState=MTDCanceling;
|
||||||
osip_message_free(okay);
|
|
||||||
mState=Fail;
|
|
||||||
}
|
}
|
||||||
// check for strays
|
// check for strays
|
||||||
else {
|
else {
|
||||||
@@ -826,10 +841,8 @@ SIPState SIPEngine::MTCCheckForCancel()
|
|||||||
// check for the CANCEL
|
// check for the CANCEL
|
||||||
else if (strcmp(msg->sip_method,"CANCEL")==0) {
|
else if (strcmp(msg->sip_method,"CANCEL")==0) {
|
||||||
LOG(INFO) << "received CANCEL";
|
LOG(INFO) << "received CANCEL";
|
||||||
osip_message_t * okay = sip_okay(msg, mSIPUsername.c_str(),mSIPIP.c_str(), mSIPPort);
|
saveCANCEL(msg, false);
|
||||||
gSIPInterface.write(&mProxyAddr,okay);
|
mState=MTDCanceling;
|
||||||
osip_message_free(okay);
|
|
||||||
mState=Fail;
|
|
||||||
}
|
}
|
||||||
// check for strays
|
// check for strays
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ enum SIPState {
|
|||||||
MODClearing,
|
MODClearing,
|
||||||
MODCanceling,
|
MODCanceling,
|
||||||
MTDClearing,
|
MTDClearing,
|
||||||
|
MTDCanceling,
|
||||||
|
Canceled,
|
||||||
Cleared,
|
Cleared,
|
||||||
Fail,
|
Fail,
|
||||||
MessageSubmit
|
MessageSubmit
|
||||||
@@ -149,6 +151,10 @@ public:
|
|||||||
/** Return the current SIP call state. */
|
/** Return the current SIP call state. */
|
||||||
SIPState state() const { return mState; }
|
SIPState state() const { return mState; }
|
||||||
|
|
||||||
|
/** Return if the call has successfully finished */
|
||||||
|
bool finished() const { return (mState==Cleared || mState==Canceled); }
|
||||||
|
|
||||||
|
|
||||||
/** Set the user to IMSI<IMSI> and generate a call ID; for mobile-originated transactions. */
|
/** Set the user to IMSI<IMSI> and generate a call ID; for mobile-originated transactions. */
|
||||||
void user( const char * IMSI );
|
void user( const char * IMSI );
|
||||||
|
|
||||||
@@ -279,7 +285,9 @@ public:
|
|||||||
//@{
|
//@{
|
||||||
SIPState MTDCheckBYE();
|
SIPState MTDCheckBYE();
|
||||||
|
|
||||||
SIPState MTDSendOK();
|
SIPState MTDSendBYEOK();
|
||||||
|
|
||||||
|
SIPState MTDSendCANCELOK();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -596,12 +596,52 @@ osip_message_t * SIP::sip_bye(const char * req_uri, const char * dialed_number,
|
|||||||
osip_message_t * SIP::sip_cancel( osip_message_t * invite)
|
osip_message_t * SIP::sip_cancel( osip_message_t * invite)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(invite==NULL){ return NULL;}
|
||||||
|
|
||||||
osip_message_t * cancel;
|
osip_message_t * cancel;
|
||||||
osip_message_init(&cancel);
|
osip_message_init(&cancel);
|
||||||
osip_message_clone(invite, &cancel);
|
//clone doesn't work -kurtis
|
||||||
|
//osip_message_clone(invite, &cancel);
|
||||||
// FIXME -- Should use the "force_update" function.
|
// FIXME -- Should use the "force_update" function.
|
||||||
cancel->message_property = 2;
|
cancel->message_property = 2;
|
||||||
|
//header stuff first
|
||||||
cancel->sip_method = strdup("CANCEL");
|
cancel->sip_method = strdup("CANCEL");
|
||||||
|
osip_message_set_version(cancel, strdup("SIP/2.0"));
|
||||||
|
|
||||||
|
//uri
|
||||||
|
osip_uri_init(&cancel->req_uri);
|
||||||
|
osip_uri_clone(invite->req_uri, &cancel->req_uri);
|
||||||
|
|
||||||
|
//via
|
||||||
|
osip_via_t * via;
|
||||||
|
char * via_str;
|
||||||
|
osip_message_get_via(invite, 0, &via);
|
||||||
|
osip_via_to_str(via, &via_str);
|
||||||
|
osip_message_set_via(cancel, via_str);
|
||||||
|
osip_free(via_str);
|
||||||
|
|
||||||
|
// from/to header
|
||||||
|
osip_from_clone(invite->from, &cancel->from);
|
||||||
|
osip_to_clone(invite->to, &cancel->to);
|
||||||
|
|
||||||
|
//contact
|
||||||
|
osip_contact_t * cont;
|
||||||
|
char * cont_str;
|
||||||
|
osip_message_get_contact(invite, 0, &cont);
|
||||||
|
osip_contact_to_str(cont, &cont_str);
|
||||||
|
osip_message_set_contact(cancel, cont_str);
|
||||||
|
osip_free(cont_str);
|
||||||
|
|
||||||
|
// Get Call-ID.
|
||||||
|
osip_call_id_clone(invite->call_id, &cancel->call_id);
|
||||||
|
|
||||||
|
// Get Cseq.
|
||||||
|
osip_cseq_t * cseq;
|
||||||
|
char * cseq_str;
|
||||||
|
cseq = osip_message_get_cseq(invite);
|
||||||
|
osip_cseq_to_str(cseq ,&cseq_str);
|
||||||
|
osip_message_set_cseq(cancel, cseq_str);
|
||||||
|
osip_free(cseq_str);
|
||||||
|
|
||||||
//update message type
|
//update message type
|
||||||
osip_cseq_set_method(cancel->cseq, strdup("CANCEL"));
|
osip_cseq_set_method(cancel->cseq, strdup("CANCEL"));
|
||||||
|
|||||||
Reference in New Issue
Block a user