⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transactionstate.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#include "resip/stack/ConnectionTerminated.hxx"#include "resip/stack/DnsInterface.hxx"#include "resip/stack/DnsResult.hxx"#include "resip/stack/Helper.hxx"#include "resip/stack/MethodTypes.hxx"#include "resip/stack/SipMessage.hxx"#include "resip/stack/SipStack.hxx"#include "resip/stack/StatisticsManager.hxx"#include "resip/stack/TimerMessage.hxx"#include "resip/stack/TransactionController.hxx"#include "resip/stack/TransactionMessage.hxx"#include "resip/stack/TransactionState.hxx"#include "resip/stack/TransactionTerminated.hxx"#include "resip/stack/TransportFailure.hxx"#include "resip/stack/TransactionUserMessage.hxx"#include "resip/stack/TransportFailure.hxx"#include "resip/stack/TransportSelector.hxx"#include "resip/stack/TransactionUser.hxx"#include "resip/stack/TuSelector.hxx"#include "rutil/DnsUtil.hxx"#include "rutil/Logger.hxx"#include "rutil/MD5Stream.hxx"#include "rutil/Socket.hxx"#include "rutil/Random.hxx"#include "rutil/WinLeakCheck.hxx"#include "resip/stack/KeepAliveMessage.hxx"using namespace resip;#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSACTIONunsigned long TransactionState::StatelessIdCounter = 0;TransactionState::TransactionState(TransactionController& controller, Machine m,                                    State s, const Data& id, TransactionUser* tu) :    mController(controller),   mMachine(m),    mState(s),   mIsCancel(false),   mIsReliable(true), // !jf!    mMsgToRetransmit(0),   mDnsResult(0),   mId(id),   mAckIsValid(false),   mWaitingForDnsResult(false),   mTransactionUser(tu),   mFailureReason(TransportFailure::None){   StackLog (<< "Creating new TransactionState: " << *this);}TransactionState* TransactionState::makeCancelTransaction(TransactionState* tr, Machine machine, const Data& tid){   TransactionState* cancel = new TransactionState(tr->mController, machine, Trying,                                                    tid, tr->mTransactionUser);   // !jf! don't set this since it will be set by TransactionState::processReliability()   //cancel->mIsReliable = tr->mIsReliable;     cancel->mResponseTarget = tr->mResponseTarget;   cancel->mIsCancel = true;   cancel->mTarget = tr->mTarget;   cancel->add(tid);   // !jf! don't call processServerNonInvite since it will delete   // the sip message which needs to get sent to the TU   cancel->processReliability(tr->mTarget.getType());   return cancel;}boolTransactionState::handleBadRequest(const resip::SipMessage& badReq, TransactionController& controller){   assert(badReq.isRequest() && badReq.method() != ACK);   try   {      SipMessage* error = Helper::makeResponse(badReq,400);      error->header(h_StatusLine).reason()+="(" + badReq.getReason() + ")";      Tuple target(badReq.getSource());      if(badReq.isExternal())      {         controller.mTransportSelector.transmit(error,target);         delete error;         return true;      }      else      {         // ?bwc? Should we put together a TransactionState here so we can         // send a 400 to the TU?         // TODO if we send the error to the TU, don't delete the error         delete error;         return false;      }   }   catch(resip::BaseException& e)   {      ErrLog(<< "Exception thrown in TransactionState::handleBadRequest."                  " This shouldn't happen. " << e);      return false;   }}TransactionState::~TransactionState(){   assert(mState != Bogus);   if (mDnsResult)   {      mDnsResult->destroy();   }   //StackLog (<< "Deleting TransactionState " << mId << " : " << this);   erase(mId);      delete mMsgToRetransmit;   mMsgToRetransmit = 0;   mState = Bogus;}voidTransactionState::process(TransactionController& controller){   TransactionMessage* message = controller.mStateMacFifo.getNext();   {      KeepAliveMessage* keepAlive = dynamic_cast<KeepAliveMessage*>(message);      if (keepAlive)      {         StackLog ( << "Sending keep alive to: " << keepAlive->getDestination());               controller.mTransportSelector.transmit(keepAlive, keepAlive->getDestination());         delete keepAlive;         return;            }      ConnectionTerminated* term = dynamic_cast<ConnectionTerminated*>(message);      if (term)      {         controller.mTuSelector.add(term);         delete term;         return;      }   }      // .bwc. We can't do anything without a tid here. Check this first.   Data tid;      try   {      tid = message->getTransactionId();   }   catch(SipMessage::Exception&)   {      // .bwc This is not our error. Do not ErrLog.      DebugLog( << "TransactionState::process dropping message with invalid tid " << message->brief());      delete message;      return;   }      SipMessage* sip = dynamic_cast<SipMessage*>(message);      if(sip)   {      // ?bwc? Should this come after checking for error conditions?      if(controller.mStack.statisticsManagerEnabled() && sip->isExternal())      {         controller.mStatsManager.received(sip);      }            // .bwc. Check for error conditions we can respond to.      if(sip->isRequest() && sip->method() != ACK)      {         if(sip->isExternal() && controller.isTUOverloaded())         {            SipMessage* tryLater = Helper::makeResponse(*sip, 503);            tryLater->header(h_RetryAfter).value() = 32 + (Random::getRandom() % 32);            tryLater->header(h_RetryAfter).comment() = "Server busy TRANS";            Tuple target(sip->getSource());            delete sip;            controller.mTransportSelector.transmit(tryLater, target);            delete tryLater;            return;         }                  if(sip->isInvalid())         {            handleBadRequest(*sip,controller);            delete sip;            return;         }               }#ifdef PEDANTIC_STACK      try      {         sip->parseAllHeaders();      }      catch(resip::ParseException& e)      {         if(sip->isRequest() && sip->method()!=ACK)         {            handleBadRequest(*sip,controller);         }                  InfoLog(<< "Exception caught by pedantic stack: " << e);      }#endif                  // This ensures that CANCEL requests form unique transactions      if (sip->method() == CANCEL)       {         tid += "cancel";      }   }         TransactionState* state = 0;   if (message->isClientTransaction()) state = controller.mClientTransactionMap.find(tid);   else state = controller.mServerTransactionMap.find(tid);      if (state && sip && sip->isExternal())   {      // .bwc. This code (if enabled) ensures that responses have the same      // CallId and tags as the request did (excepting the introduction of a       // remote tag). This is to protect dialog-stateful TUs that don't react       // gracefully when a stupid/malicious endpoint fiddles with the tags       // and/or CallId when it isn't supposed to. (DUM is one such TU)      if(state->mController.getFixBadDialogIdentifiers() &&         sip->isResponse() &&         state->mMsgToRetransmit)      {         if(sip->header(h_CallId).isWellFormed())         {            if(!(sip->header(h_CallId) ==                         state->mMsgToRetransmit->header(h_CallId)))            {               InfoLog(<< "Other end modified our Call-Id... correcting.");               sip->header(h_CallId) = state->mMsgToRetransmit->header(h_CallId);            }         }         else         {            InfoLog(<< "Other end corrupted our CallId... correcting.");            sip->header(h_CallId) = state->mMsgToRetransmit->header(h_CallId);         }         NameAddr& from = state->mMsgToRetransmit->header(h_From);         if(sip->header(h_From).isWellFormed())         {            // Overwrite tag.            if(from.exists(p_tag))            {               if(sip->header(h_From).param(p_tag) != from.param(p_tag))               {                  InfoLog(<<"Other end modified our local tag... correcting.");                  sip->header(h_From).param(p_tag) = from.param(p_tag);               }            }            else if(sip->header(h_From).exists(p_tag))            {               if(sip->header(h_From).exists(p_tag))               {                  InfoLog(<<"Other end added a local tag for us... removing.");                  sip->header(h_From).remove(p_tag);               }            }         }         else         {            InfoLog(<<"Other end corrupted our From header... replacing.");            // Whole header is hosed, overwrite.            sip->header(h_From) = from;         }         NameAddr& to = state->mMsgToRetransmit->header(h_To);         if(sip->header(h_To).isWellFormed())         {            // Overwrite tag.            if(to.exists(p_tag))            {               if(sip->header(h_To).param(p_tag) != to.param(p_tag))               {                  InfoLog(<<"Other end modified the (existing) remote tag... "                              "correcting.");                  sip->header(h_To).param(p_tag) = to.param(p_tag);               }            }         }         else         {            InfoLog(<<"Other end corrupted our To header... replacing.");            // Whole header is hosed, overwrite.            sip->header(h_To) = to;         }      }      // .bwc. This code ensures that the transaction state-machine can recover      // from ACK/200 with the same tid as the original INVITE. This problem is      // stupidly common.       if(sip->isRequest() && sip->method() == ACK && !state->mAckIsValid)      {         // Must have received an ACK to a 200;         // We will never respond to this, so nothing will need this tid for         // driving transaction state. Additionally,          InfoLog(<<"Someone sent us an ACK/200 with the same tid as the "                     "original INVITE. This is bad behavior, and should be "                     "corrected in the client.");         sip->mIsBadAck200=true;         // .bwc. This is a new stateless transaction, despite its tid.         state=0;      }   }   if (state) // found transaction for sip msg   {      StackLog (<< "Found matching transaction for " << message->brief() << " -> " << *state);      switch (state->mMachine)      {         case ClientNonInvite:            state->processClientNonInvite(message);            break;         case ClientInvite:            // ACK from TU will be Stateless            assert (!(state->isFromTU(sip) &&  sip->isRequest() && sip->method() == ACK));            state->processClientInvite(message);            break;         case ServerNonInvite:            state->processServerNonInvite(message);            break;         case ServerInvite:            state->processServerInvite(message);            break;         case Stateless:            state->processStateless(message);            break;         case ClientStale:            state->processClientStale(message);            break;         case ServerStale:            state->processServerStale(message);            break;         default:            CritLog(<<"internal state error");            assert(0);            return;      }   }   else if (sip)  // new transaction   {      StackLog (<< "No matching transaction for " << sip->brief());      TransactionUser* tu = 0;            if (sip->isExternal())      {         if (controller.mTuSelector.haveTransactionUsers() && sip->isRequest())         {            tu = controller.mTuSelector.selectTransactionUser(*sip);            if (!tu)            {               //InfoLog (<< "Didn't find a TU for " << sip->brief());               // !bwc! We really should do something other than a 500 here.               // If none of the TUs liked the request because of the Request-               // Uri scheme, we should be returning a 416, for example.               InfoLog( << "No TU found for message: " << sip->brief());                              SipMessage* noMatch = Helper::makeResponse(*sip, 500);               Tuple target(sip->getSource());               delete sip;               controller.mTransportSelector.transmit(noMatch, target);               delete noMatch;               return;            }            else            {               //InfoLog (<< "Found TU for " << sip->brief());            }         }      }      else      {         tu = sip->getTransactionUser();         if (!tu)         {            //InfoLog (<< "No TU associated with " << sip->brief());         }      }                     if (sip->isRequest())      {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -