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

📄 transactionstate.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
            // !bwc!            // An interesting consequence occurs if our failover ultimately            // sends to the same instance of a resip stack; we increment the             // transport sequence in our branch parameter, but any resip-based            // stack will ignore this change, and process this "new" request as            // a retransmission! Furthermore, our state will be out of phase            // with the state at the remote endpoint, and if we have sent a            // PRACK, it will know (and stuff will break)!            // TODO What else needs to be done here to safely revert our state?            mState=Calling;         }         shouldFailover=true;      }   }   if(mDnsResult)   {      // .bwc. Greylist for 32s      // !bwc! TODO make this duration configurable.      mDnsResult->greylistLast(Timer::getTimeMs()+32000);   }         if(shouldFailover)   {      InfoLog (<< "Try sending request to a different dns result");      assert(mMsgToRetransmit);      if (failure->getFailureReason() > mFailureReason)      {         mFailureReason = failure->getFailureReason();      }            if (mMsgToRetransmit->isRequest() && mMsgToRetransmit->method() == CANCEL)      {         WarningLog (<< "Failed to deliver a CANCEL request");         StackLog (<< *this);         assert(mIsCancel);         // In the case of a client-initiated CANCEL, we don't want to         // try other transports in the case of transport error as the         // CANCEL MUST be sent to the same IP/PORT as the orig. INVITE.         //?dcm? insepct failure enum?         SipMessage* response = Helper::makeResponse(*mMsgToRetransmit, 503);         WarningCategory warning;         warning.hostname() = DnsUtil::getLocalHostName();         warning.code() = 499;         warning.text() = "Failed to deliver CANCEL using the same transport as the INVITE was used";         response->header(h_Warnings).push_back(warning);                  sendToTU(response);         return;      }      assert(!mIsCancel);      if (mDnsResult)      {               switch (mDnsResult->available())         {            case DnsResult::Available:               restoreOriginalContactAndVia();               mTarget = mDnsResult->next();               processReliability(mTarget.getType());               sendToWire(mMsgToRetransmit);               break;                        case DnsResult::Pending:               mWaitingForDnsResult=true;               restoreOriginalContactAndVia();               break;            case DnsResult::Finished:               processNoDnsResults();               break;            case DnsResult::Destroyed:            default:               InfoLog (<< "Bad state: " << *this);               assert(0);         }      }   }}// called by DnsResultvoidTransactionState::rewriteRequest(const Uri& rewrite){   // !bwc! TODO We need to address the race-conditions caused by callbacks   // into a class whose thread-safety is accomplished through message-passing.   // This function could very easily be called while other processing is   // taking place due to a message from the state-machine fifo. In the end, I   // imagine that we will need to have the callback place a message onto the   // queue, and move all the code below into a function that handles that   // message.   assert(mMsgToRetransmit->isRequest());   if (mMsgToRetransmit->header(h_RequestLine).uri() != rewrite)   {      InfoLog (<< "Rewriting request-uri to " << rewrite);      mMsgToRetransmit->header(h_RequestLine).uri() = rewrite;   }}void TransactionState::handle(DnsResult* result){   // !bwc! TODO We need to address the race-conditions caused by callbacks   // into a class whose thread-safety is accomplished through message-passing.   // This function could very easily be called while other processing is   // taking place due to a message from the state-machine fifo. In the end, I   // imagine that we will need to have the callback place a message onto the   // queue, and move all the code below into a function that handles that   // message.   // got a DNS response, so send the current message   StackLog (<< *this << " got DNS result: " << *result);      // .bwc. Were we expecting something from mDnsResult?   if (mWaitingForDnsResult)    {      assert(mDnsResult);      switch (mDnsResult->available())      {         case DnsResult::Available:            mWaitingForDnsResult=false;            mTarget = mDnsResult->next();            processReliability(mTarget.getType());            mController.mTransportSelector.transmit(mMsgToRetransmit, mTarget);            break;                     case DnsResult::Finished:            mWaitingForDnsResult=false;            processNoDnsResults();            break;         case DnsResult::Pending:            break;                     case DnsResult::Destroyed:         default:            assert(0);            break;      }   }}voidTransactionState::processReliability(TransportType type){   switch (type)   {      case UDP:      case DCCP:         if (mIsReliable)         {            mIsReliable = false;            StackLog (<< "Unreliable transport: " << *this);            switch (mMachine)            {               case ClientNonInvite:                  mController.mTimers.add(Timer::TimerE1, mId, Timer::T1 );                  break;                                 case ClientInvite:                  mController.mTimers.add(Timer::TimerA, mId, Timer::T1 );                  break;               default:                  break;            }         }         break;               default:         if (!mIsReliable)         {            mIsReliable = true;         }         break;   }}// !ah! only used one place, so leaving it here instead of making a helper.// !ah! broken out for clarity -- only used for forceTargets.// Expects that host portion is IP address notation.static const TuplesimpleTupleForUri(const Uri& uri){   const Data& host = uri.host();   int port = uri.port();   resip::TransportType transport = UNKNOWN_TRANSPORT;   if (uri.exists(p_transport))   {      transport = Tuple::toTransport(uri.param(p_transport));   }   if (transport == UNKNOWN_TRANSPORT)   {      transport = UDP;   }   if (port == 0)   {      switch(transport)      {         case TLS:            port = Symbols::DefaultSipsPort;            break;         case UDP:         case TCP:         default:            port = Symbols::DefaultSipPort;            break;         // !ah! SCTP?      }   }   return Tuple(host,port,transport);}voidTransactionState::sendToWire(TransactionMessage* msg, bool resend) {   SipMessage* sip = dynamic_cast<SipMessage*>(msg);   if (!sip)   {      CritLog(<<"sendToWire: message not a sip message at address " << (void*)msg);      assert(sip);      return;   }   if(mController.mStack.statisticsManagerEnabled())   {      mController.mStatsManager.sent(sip, resend);   }   // !jf! for responses, go back to source always (not RFC exactly)   if (mMachine == ServerNonInvite || mMachine == ServerInvite || mMachine == ServerStale)   {      assert(mDnsResult == 0);      assert(sip->exists(h_Vias));      assert(!sip->header(h_Vias).empty());      Tuple target(mResponseTarget);      if (sip->hasForceTarget())      {         target = simpleTupleForUri(sip->getForceTarget());         StackLog(<<"!ah! response with force target going to : "<<target);      }      else if (sip->header(h_Vias).front().exists(p_rport) && sip->header(h_Vias).front().param(p_rport).hasValue())      {         target.setPort(sip->header(h_Vias).front().param(p_rport).port());         StackLog(<< "rport present in response, sending to " << target);      }      else      {         StackLog(<< "tid=" << sip->getTransactionId() << " sending to : " << target);      }      if (resend)      {         mController.mTransportSelector.retransmit(sip, target);      }      else      {         mController.mTransportSelector.transmit(sip, target);      }   }   else if (sip->getDestination().mFlowKey || mTarget.mFlowKey)   {      if (resend)      {         if (mTarget.transport)         {            mController.mTransportSelector.retransmit(sip, mTarget);         }         else         {            DebugLog (<< "No transport found(network could be down) for " << sip->brief());         }      }      else      {         // !bwc! We have the FlowKey. This completely specifies our Transport         // (and Connection, if applicable)         if(!mTarget.mFlowKey)         {            DebugLog(<< "Sending to tuple: " << sip->getDestination());            mTarget = sip->getDestination();            processReliability(mTarget.getType());         }         mController.mTransportSelector.transmit(sip, mTarget); // dns not used      }   }   else if (mDnsResult == 0 && !mIsCancel) // no dns query yet   {      StackLog (<< "sendToWire with no dns result: " << *this);      assert(sip->isRequest());      assert(!mIsCancel);      mDnsResult = mController.mTransportSelector.createDnsResult(this);      mWaitingForDnsResult=true;      mController.mTransportSelector.dnsResolve(mDnsResult, sip);   }   else // reuse the last dns tuple   {      assert(sip->isRequest());      if(mTarget.getType() != UNKNOWN_TRANSPORT)      {         if (resend)         {            if (mTarget.transport)            {               mController.mTransportSelector.retransmit(sip, mTarget);            }            else            {               DebugLog (<< "No transport found(network could be down) for " << sip->brief());            }         }         else         {            mController.mTransportSelector.transmit(sip, mTarget);         }      }      else      {         // .bwc. While the resolver was attempting to find a target, another         // request came down from the TU. This could be a bug in the TU, or          // could be a retransmission of an ACK/200. Either way, we cannot         // expect to ever be able to send this request (nowhere to store it         // temporarily).         DebugLog(<< "Received a second request from the TU for a transaction"                     " that already existed, before the DNS subsystem was done "                     "resolving the target for the first request. Either the TU"                     " has messed up, or it is retransmitting ACK/200 (the only"                     " valid case for this to happen)");      }   }}voidTransactionState::sendToTU(TransactionMessage* msg) const{   SipMessage* sipMsg = dynamic_cast<SipMessage*>(msg);   if (sipMsg && sipMsg->isResponse() && mDnsResult)   {      // whitelisting rules.      switch (sipMsg->header(h_StatusLine).statusCode())      {         case 503:            // blacklist last target.            // .bwc. If there is no Retry-After, we do not blacklist            // (see RFC 3261 sec 21.5.4 para 1)            if(sipMsg->exists(resip::h_RetryAfter) &&                sipMsg->header(resip::h_RetryAfter).isWellFormed())            {               unsigned int relativeExpiry= sipMsg->header(resip::h_RetryAfter).value();                              mDnsResult->blacklistLast(resip::Timer::getTimeMs()+relativeExpiry*1000);            }                     break;         case 408:            if(sipMsg->getReceivedTransport() == 0 &&                   (mState == Trying || mState==Calling))  // only greylist if internally generated and we haven't received any responses yet            {               // greylist last target.               // ?bwc? How long do we greylist this for? Probably should make               // this configurable. TODO               mDnsResult->greylistLast(resip::Timer::getTimeMs() + 32000);            }            break;         default:            // !bwc! Debatable.            mDnsResult->whitelistLast();            break;      }   }   TransactionState::sendToTU(mTransactionUser, mController, msg);}voidTransactionState::sendToTU(TransactionUser* tu, TransactionController& controller, TransactionMessage* msg) {  

⌨️ 快捷键说明

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