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

📄 transactionstate.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
   {
      // can't be retransmission  
      sendToWire(mMsgToRetransmit, false); 
   }
}

void
TransactionState::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 Tuple
simpleTupleForUri(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);
}

void
TransactionState::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());
         target.transport = mResponseTarget.transport;
         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().connectionId || sip->getDestination().transport)
   {
      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);
      mController.mTransportSelector.dnsResolve(mDnsResult, sip);
   }
   else // reuse the last dns tuple
   {
      assert(sip->isRequest());
      assert(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);
      }
   }
}

void
TransactionState::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.
            // !slg! TODO:  Need to blacklist only for Retry-After interval
            if (mDnsResult != 0 && mDnsResult->available() == DnsResult::Available)
            {
               mDnsResult->next();
            }
            break;
         case 408:
            if(sipMsg->getReceivedTransport() == 0 && mState == Trying)  // only blacklist if internally generated and we haven't received any responses yet
            {
               // blacklist last target.
               if (mDnsResult->available() == DnsResult::Available)
               {
                  mDnsResult->next();
               }
            }
            else
            {
               mDnsResult->success();
            }
            break;
         case 500:
         case 504:
         case 600:
            // !bwc! Only blacklist if Retry-After is present.
            // (Although, this is somewhat silly right now, since the value
            // of Retry-After is completely ignored.)
            if(sipMsg->exists(h_RetryAfter) && 
               mDnsResult->available() == DnsResult::Available)
            {
               mDnsResult->next();
            }
            else
            {
               mDnsResult->success();
            }
            break;
         default:
            mDnsResult->success();
            break;
      }
   }
   TransactionState::sendToTU(mTransactionUser, mController, msg);
}

void
TransactionState::sendToTU(TransactionUser* tu, TransactionController& controller, TransactionMessage* msg) 
{
   if (!tu)
   {
      DebugLog(<< "Send to default TU: " << std::endl << std::endl << *msg);
   }
   else
   {
	  DebugLog (<< "Send to TU: " << *tu << " " << std::endl << std::endl << *msg);
   }
   
   msg->setTransactionUser(tu);   
   controller.mTuSelector.add(msg, TimeLimitFifo<Message>::InternalElement);
}

SipMessage*
TransactionState::make100(SipMessage* request) const
{
   return (Helper::makeResponse(*request, 100));
}

void
TransactionState::add(const Data& tid)
{
   if (mMachine == ClientNonInvite || mMachine == ClientInvite || mMachine == ClientStale || mMachine == Stateless )
   {
      mController.mClientTransactionMap.add(tid, this);
   }
   else
   {
      mController.mServerTransactionMap.add(tid, this);
   }
}

void
TransactionState::erase(const Data& tid)
{
   if (mMachine == ClientNonInvite || mMachine == ClientInvite || mMachine == ClientStale || mMachine == Stateless)
   {
      mController.mClientTransactionMap.erase(tid);
   }
   else
   {
      mController.mServerTransactionMap.erase(tid);
   }
}

bool
TransactionState::isRequest(TransactionMessage* msg) const
{
   SipMessage* sip = dynamic_cast<SipMessage*>(msg);   
   return sip && sip->isRequest();
}

bool
TransactionState::isInvite(TransactionMessage* msg) const
{
   if (isRequest(msg))
   {
      SipMessage* sip = dynamic_cast<SipMessage*>(msg);
      return (sip->method()) == INVITE;
   }
   return false;
}

bool
TransactionState::isResponse(TransactionMessage* msg, int lower, int upper) const
{
   SipMessage* sip = dynamic_cast<SipMessage*>(msg);
   if (sip && sip->isResponse())
   {
      int c = sip->header(h_StatusLine).responseCode();
      return (c >= lower && c <= upper);
   }
   return false;
}

bool
TransactionState::isTimer(TransactionMessage* msg) const
{
   return dynamic_cast<TimerMessage*>(msg) != 0;
}

bool
TransactionState::isFromTU(TransactionMessage* msg) const
{
   SipMessage* sip = dynamic_cast<SipMessage*>(msg);
   return sip && !sip->isExternal();
}

bool
TransactionState::isFromWire(TransactionMessage* msg) const
{
   SipMessage* sip = dynamic_cast<SipMessage*>(msg);
   return sip && sip->isExternal();
}

bool
TransactionState::isTransportError(TransactionMessage* msg) const
{
   return dynamic_cast<TransportFailure*>(msg) != 0;
}

const Data&
TransactionState::tid(SipMessage* sip) const
{
   assert(0);
   assert (mMachine != Stateless || (mMachine == Stateless && !mId.empty()));
   assert (mMachine == Stateless || (mMachine != Stateless && sip));
   return (mId.empty() && sip) ? sip->getTransactionId() : mId;
}

void
TransactionState::terminateClientTransaction(const Data& tid)
{
   mState = Terminated;
   if (mController.mTuSelector.isTransactionUserStillRegistered(mTransactionUser) && 
       mTransactionUser->isRegisteredForTransactionTermination())
   {
      //StackLog (<< "Terminate client transaction " << tid);
      sendToTU(new TransactionTerminated(tid, true, mTransactionUser));
   }
}

void
TransactionState::terminateServerTransaction(const Data& tid)
{
   mState = Terminated;
   if (mController.mTuSelector.isTransactionUserStillRegistered(mTransactionUser) && 
       mTransactionUser->isRegisteredForTransactionTermination())
   {
      //StackLog (<< "Terminate server transaction " << tid);
      sendToTU(new TransactionTerminated(tid, false, mTransactionUser));
   }
}

std::ostream& 
resip::operator<<(std::ostream& strm, const resip::TransactionState& state)
{
   strm << "tid=" << state.mId << " [ ";
   switch (state.mMachine)
   {
      case TransactionState::ClientNonInvite:
         strm << "ClientNonInvite";
         break;
      case TransactionState::ClientInvite:
         strm << "ClientInvite";
         break;
      case TransactionState::ServerNonInvite:
         strm << "ServerNonInvite";
         break;
      case TransactionState::ServerInvite:
         strm << "ServerInvite";
         break;
      case TransactionState::Stateless:
         strm << "Stateless";
         break;
      case TransactionState::ClientStale:
         strm << "ClientStale";
  

⌨️ 快捷键说明

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