Changeset 3810

Show
Ignore:
Timestamp:
06/19/2012 03:22:20 PM (22 months ago)
Author:
kurtis.heimerl
Message:

Fixed #932 and #905 in public. OpenBTS now responds negatively to SIP

re-invites, though the specific effect of this depends on the client
sending the re-invite. In the case of FS, it causes the RTP stream to
break. We also now complain when invites time out, sending an alert to the
user about the proxy status.

Location:
openbts/trunk
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • openbts/trunk/Control/CallControl.cpp

    r3677 r3810  
    138138        else { //we received, respond and then don't send ok 
    139139                //changed state immediately to canceling 
    140                 transaction->MODSendUNAVAIL(); 
     140                transaction->MODSendERROR(NULL, 480, "Temporarily Unavailable", true); 
    141141                //then canceled 
    142                 transaction->MODWaitForUNAVAILACK(); 
     142                transaction->MODWaitForERRORACK(true); 
    143143        } 
    144144} 
     
    338338                        } 
    339339                        else { //if we received it, send a 4** instead 
    340                                 transaction->MODSendUNAVAIL(); 
    341                                 transaction->MODWaitForUNAVAILACK(); 
     340                                transaction->MODSendERROR(NULL, 480, "Temporarily Unavailable", true); 
     341                                transaction->MODWaitForERRORACK(true); 
    342342                        } 
    343343                        transaction->GSMState(GSM::NullState); 
     
    867867                                break; 
    868868                        case SIP::Timeout: 
    869                                 LOG(NOTICE) << "SIP:Timeout, reinvite"; 
     869                                LOG(ALERT) << "MOC INVITE Timed out. Is SIP.Proxy.Speech (" << gConfig.getStr("SIP.Proxy.Speech") << ") configured correctly?"; 
    870870                                state = transaction->MOCResendINVITE(); 
    871871                                break; 
  • openbts/trunk/Control/TransactionTable.cpp

    r3677 r3810  
    421421} 
    422422 
    423 SIP::SIPState TransactionEntry::MODSendUNAVAIL() 
    424 { 
    425         ScopedLock lock(mLock); 
    426         SIP::SIPState state = mSIP.MODSendUNAVAIL(); 
     423SIP::SIPState TransactionEntry::MODSendERROR(osip_message_t * cause, int code, const char * reason, bool cancel) 
     424{ 
     425        ScopedLock lock(mLock); 
     426        SIP::SIPState state = mSIP.MODSendERROR(cause, code, reason, cancel); 
    427427        echoSIPState(state); 
    428428        return state; 
     
    453453} 
    454454 
    455 SIP::SIPState TransactionEntry::MODResendUNAVAIL() 
    456 { 
    457         ScopedLock lock(mLock); 
    458         SIP::SIPState state = mSIP.MODResendUNAVAIL(); 
     455SIP::SIPState TransactionEntry::MODResendERROR(bool cancel) 
     456{ 
     457        ScopedLock lock(mLock); 
     458        SIP::SIPState state = mSIP.MODResendERROR(cancel); 
    459459        echoSIPState(state); 
    460460        return state; 
     
    477477} 
    478478 
    479 SIP::SIPState TransactionEntry::MODWaitForUNAVAILACK() 
    480 { 
    481         ScopedLock lock(mLock); 
    482         SIP::SIPState state = mSIP.MODWaitForUNAVAILACK(); 
     479SIP::SIPState TransactionEntry::MODWaitForERRORACK(bool cancel) 
     480{ 
     481        ScopedLock lock(mLock); 
     482        SIP::SIPState state = mSIP.MODWaitForERRORACK(cancel); 
    483483        echoSIPState(state); 
    484484        return state; 
  • openbts/trunk/Control/TransactionTable.h

    r3677 r3810  
    203203 
    204204        SIP::SIPState MODSendBYE(); 
    205         SIP::SIPState MODSendUNAVAIL(); 
     205        SIP::SIPState MODSendERROR(osip_message_t * cause, int code, const char * reason, bool cancel); 
    206206        SIP::SIPState MODSendCANCEL(); 
    207207        SIP::SIPState MODResendBYE(); 
    208208        SIP::SIPState MODResendCANCEL(); 
    209         SIP::SIPState MODResendUNAVAIL(); 
     209        SIP::SIPState MODResendERROR(bool cancel); 
    210210        SIP::SIPState MODWaitForBYEOK(); 
    211211        SIP::SIPState MODWaitForCANCELOK(); 
    212         SIP::SIPState MODWaitForUNAVAILACK(); 
     212        SIP::SIPState MODWaitForERRORACK(bool cancel); 
    213213        SIP::SIPState MODWaitFor487(); 
    214214 
     
    242242                { ScopedLock lock(mLock); mSIP.saveBYE(bye,local); } 
    243243 
     244        bool sameINVITE(osip_message_t * msg) 
     245                { ScopedLock lock(mLock); return mSIP.sameINVITE(msg); } 
     246 
    244247        //@} 
    245248 
  • openbts/trunk/SIP/SIPEngine.cpp

    r3700 r3810  
    9797        mSIPIP(gConfig.getStr("SIP.Local.IP")), 
    9898        mINVITE(NULL), mLastResponse(NULL), mBYE(NULL), 
    99         mCANCEL(NULL), mUNAVAIL(NULL), mSession(NULL),  
     99        mCANCEL(NULL), mERROR(NULL), mSession(NULL),  
    100100        mTxTime(0), mRxTime(0), mState(NullState), 
    101101        mDTMF('\0'),mDTMFDuration(0) 
     
    134134        if (mBYE!=NULL) osip_message_free(mBYE); 
    135135        if (mCANCEL!=NULL) osip_message_free(mCANCEL); 
    136         if (mUNAVAIL!=NULL) osip_message_free(mUNAVAIL); 
     136        if (mERROR!=NULL) osip_message_free(mERROR); 
    137137        // FIXME -- Do we need to dispose of the RtpSesion *mSesison? 
    138138} 
     
    202202} 
    203203 
    204 void SIPEngine::saveUNAVAIL(const osip_message_t *UNAVAIL, bool mine) 
     204void SIPEngine::saveERROR(const osip_message_t *ERROR, bool mine) 
    205205{ 
    206206        // Instead of cloning, why not just keep the old one? 
    207207        // Because that doesn't work in all calling contexts. 
    208208        // This simplifies the call-handling logic. 
    209         if (mUNAVAIL!=NULL) osip_message_free(mUNAVAIL); 
    210         osip_message_clone(UNAVAIL,&mUNAVAIL); 
     209        if (mERROR!=NULL) osip_message_free(mERROR); 
     210        osip_message_clone(ERROR,&mERROR); 
    211211} 
    212212 
     
    579579} 
    580580 
    581 SIPState SIPEngine::MODSendUNAVAIL() 
    582 { 
    583         LOG(INFO) << "user " << mSIPUsername << " state " << mState; 
    584         assert(mINVITE); 
    585  
    586         osip_message_t * unavail = sip_temporarily_unavailable(mINVITE, mSIPIP.c_str(), 
    587                                                                mSIPUsername.c_str(), mSIPPort); 
     581SIPState SIPEngine::MODSendERROR(osip_message_t * cause, int code, const char * reason, bool cancel) 
     582{ 
     583        LOG(INFO) << "user " << mSIPUsername << " state " << mState; 
     584        if (NULL == cause){ 
     585                assert(mINVITE); 
     586                cause = mINVITE; 
     587        } 
     588         
     589        /* 480 is unavail */ 
     590        osip_message_t * unavail = sip_error(cause, mSIPIP.c_str(), 
     591                                             mSIPUsername.c_str(), mSIPPort,  
     592                                             code, reason); 
    588593        gSIPInterface.write(&mProxyAddr,unavail); 
    589         saveUNAVAIL(unavail, true); 
     594        saveERROR(unavail, true); 
    590595        osip_message_free(unavail); 
    591         mState = MODCanceling; 
     596        if (cancel){ 
     597                mState = MODCanceling; 
     598        } 
    592599        return mState; 
    593600} 
     
    626633} 
    627634 
    628 SIPState SIPEngine::MODResendUNAVAIL() 
    629 { 
    630         LOG(INFO) << "user " << mSIPUsername << " state " << mState; 
    631         assert(mState==MODCanceling); 
    632         assert(mUNAVAIL); 
    633         gSIPInterface.write(&mProxyAddr,mUNAVAIL); 
     635SIPState SIPEngine::MODResendERROR(bool cancel) 
     636{ 
     637        LOG(INFO) << "user " << mSIPUsername << " state " << mState; 
     638        if (cancel){ 
     639                if (mState!=MODCanceling) LOG(ERR) << "incorrect state for this method"; 
     640        } 
     641        assert(mERROR); 
     642        gSIPInterface.write(&mProxyAddr,mERROR); 
    634643        return mState; 
    635644} 
     
    727736} 
    728737 
    729 SIPState SIPEngine::MODWaitForUNAVAILACK() 
     738SIPState SIPEngine::MODWaitForERRORACK(bool cancel) 
    730739{ 
    731740        LOG(INFO) << "user " << mSIPUsername << " state " << mState; 
     
    738747                        saveResponse(ack); 
    739748                        if ((NULL == ack->sip_method) || !strncmp(ack->sip_method,"ACK", 4)) { 
    740                                 LOG(WARNING) << "unexpected response to UNAVAIL, from proxy " << mProxyIP << ":" << mProxyPort << ". Assuming other end has cleared"; 
     749                                LOG(WARNING) << "unexpected response to ERROR, from proxy " << mProxyIP << ":" << mProxyPort << ". Assuming other end has cleared"; 
    741750                        } 
    742751                        osip_message_free(ack); 
     
    744753                } 
    745754                catch (SIPTimeout& e) { 
    746                         LOG(NOTICE) << "response timeout, resending UNAVAIL"; 
    747                         MODResendUNAVAIL(); 
     755                        LOG(NOTICE) << "response timeout, resending ERROR"; 
     756                        MODResendERROR(cancel); 
    748757                } 
    749758        } 
     
    751760        if (!responded) { LOG(ALERT) << "lost contact with proxy " << mProxyIP << ":" << mProxyPort; } 
    752761 
    753         mState = Canceled; 
     762        if (cancel){ 
     763                mState = Canceled; 
     764        } 
    754765 
    755766        return mState; 
     
    12131224}; 
    12141225 
    1215  
    1216  
     1226/* reinvite stuff */ 
     1227/* return true if this is the same invite as the one we have stored */ 
     1228bool SIPEngine::sameINVITE(osip_message_t * msg){ 
     1229        assert(mINVITE); 
     1230        if (NULL == msg){ 
     1231                return false; 
     1232        } 
     1233        char* old_inv; 
     1234        size_t old_len; 
     1235        char* new_inv; 
     1236        size_t new_len; 
     1237        int res = 0; //does not match 
     1238        //this sometimes fails even though mINVITE is real. No idea -k 
     1239        osip_message_to_str(mINVITE, &old_inv, &old_len); 
     1240        osip_message_to_str(msg, &new_inv, &new_len); 
     1241        if (old_inv && new_inv){ 
     1242                res = !(strncmp(old_inv, new_inv, old_len)); 
     1243        } 
     1244        if (old_inv){ 
     1245                free(old_inv); 
     1246        } 
     1247        if (new_inv){ 
     1248                free(new_inv); 
     1249        } 
     1250        return res; 
     1251} 
    12171252 
    12181253// vim: ts=4 sw=4 
  • openbts/trunk/SIP/SIPEngine.h

    r3677 r3810  
    114114        osip_message_t * mBYE;          ///< the BYE message for this transaction 
    115115        osip_message_t * mCANCEL;       ///< the CANCEL message for this transaction 
    116         osip_message_t * mUNAVAIL;      ///< the UNAVAIL message for this transaction 
     116        osip_message_t * mERROR;        ///< the ERROR message for this transaction 
    117117        //@} 
    118118 
     
    280280        SIPState MODSendBYE(); 
    281281 
    282         SIPState MODSendUNAVAIL(); 
     282        SIPState MODSendERROR(osip_message_t * cause, int code, const char * reason, bool cancel); 
    283283 
    284284        SIPState MODSendCANCEL(); 
     
    288288        SIPState MODResendCANCEL(); 
    289289 
    290         SIPState MODResendUNAVAIL(); 
     290        SIPState MODResendERROR(bool cancel); 
    291291 
    292292        SIPState MODWaitForBYEOK(); 
     
    294294        SIPState MODWaitForCANCELOK(); 
    295295 
    296         SIPState MODWaitForUNAVAILACK(); 
     296        SIPState MODWaitForERRORACK(bool cancel); 
    297297 
    298298        SIPState MODWaitFor487(); 
     
    356356        void saveCANCEL(const osip_message_t *CANCEL, bool mine); 
    357357 
    358         /** Save a copy of a UNAVAIL message in the engine. */ 
    359         void saveUNAVAIL(const osip_message_t *UNAVAIL, bool mine); 
    360  
    361  
     358        /** Save a copy of a ERROR message in the engine. */ 
     359        void saveERROR(const osip_message_t *ERROR, bool mine); 
     360 
     361         
     362        /** Determine if this invite matches the saved one */ 
     363        bool sameINVITE(osip_message_t * msg); 
    362364 
    363365        private: 
  • openbts/trunk/SIP/SIPInterface.cpp

    r3361 r3810  
    380380                        return false; 
    381381                } 
     382                //if this is not the saved invite, it's a RE-invite. Respond saying we don't support it.  
     383                if (!transaction->sameINVITE(msg)){ 
     384                  /* don't cancel the call */ 
     385                        transaction->MODSendERROR(msg, 488, "Not Acceptable Here", false); 
     386                        /* I think we'd need to create a new transaction for this ack. Right now, just assume the ack makes it back.  
     387                           if not, we'll hear another INVITE */ 
     388                        //transaction->MODWaitForERRORACK(false); //don't cancel the call 
     389                        return false; 
     390                } 
    382391                // There is transaction already.  Send trying. 
    383392                transaction->MTCSendTrying(); 
  • openbts/trunk/SIP/SIPMessage.cpp

    r3270 r3810  
    600600} 
    601601 
    602 osip_message_t * SIP::sip_temporarily_unavailable( osip_message_t * invite,  const char * host, const char * username, short  port) 
     602osip_message_t * SIP::sip_error(osip_message_t * invite,  const char * host, const char * username, short port, short code, const char* reason) 
    603603{ 
    604604 
     
    611611        unavail->message_property = 2; 
    612612        //header stuff first 
    613         unavail->status_code = 480; 
    614         unavail->reason_phrase = strdup("Temporarily Unavailable"); 
     613        unavail->status_code = code; 
     614        unavail->reason_phrase = strdup(reason); 
    615615        osip_message_set_version(unavail, strdup("SIP/2.0")); 
    616616 
  • openbts/trunk/SIP/SIPMessage.h

    r3264 r3810  
    5656osip_message_t * sip_okay( osip_message_t * inv, const char * sip_username, const char * local_ip, short wlocal_port); 
    5757 
    58 osip_message_t * sip_temporarily_unavailable( osip_message_t * invite,  const char * host, const char * username, short  port); 
     58osip_message_t * sip_error( osip_message_t * invite,  const char * host, const char * username, short port, short code, const char* reason); 
    5959 
    6060osip_message_t * sip_info(unsigned info, const char *dialed_number, short rtp_port,const char * sip_username, short local_port, const char * local_ip, const char * proxy_ip, const char * from_tag, const char * via_branch, const osip_call_id_t* call_id_header, int cseq); 
     
    7070}; 
    7171#endif 
    72