예제 #1
0
void SIPNict::handleRetransmitRequest()
{
  SIPTransaction::Ptr pTransaction = static_cast<SIPTransaction::WeakPtr*>(_owner)->lock();
  if (!pTransaction)
    return;

  if (pTransaction->getState() == SIPTransaction::TRN_STATE_TERMINATED)
    return;

  if (pTransaction->getState() <= PROCEEDING)
  {
    if (pTransaction->transport()->isReliableTransport())
      pTransaction->transport()->writeMessage(_pRequest);
    else
      pTransaction->transport()->writeMessage(_pRequest,
        pTransaction->remoteAddress().toString(),
        OSS::string_from_number<unsigned short>(pTransaction->remoteAddress().getPort()));
    //
    // Restart Timer E with a compounded value
    //
    if (_timerEMultiplier == 0)
      _timerEMultiplier = 2;
    else
      _timerEMultiplier = 4;

    if ( pTransaction->getState() != PROCEEDING)
      _timerEValue = _timerEValue * _timerEMultiplier > _timerProps.timerT2() ? _timerProps.timerT2() : _timerProps.timerT1() *_timerEMultiplier;
    else
      _timerEValue = _timerProps.timerT2();

    startTimerE(_timerEValue);
  }
}
예제 #2
0
bool SIPNict::onSendMessage(SIPMessage::Ptr pMsg)
{
  SIPTransaction::Ptr pTransaction = static_cast<SIPTransaction::WeakPtr*>(_owner)->lock();
  if (!pTransaction)
    return false;

  if (pTransaction->getState() == SIPTransaction::TRN_STATE_IDLE)
  {
    startTimerMaxLifetime(300000); /// five minutes
    _pRequest = pMsg;
    pTransaction->setState(TRYING);

    std::string sTimeout;
    if (pMsg->getProperty(OSS::PropertyMap::PROP_TransactionTimeout, sTimeout) && !sTimeout.empty())
    {
      _timerEValue = OSS::string_to_number<unsigned long>(sTimeout.c_str()) / 64;
    }
    else
    {
      _timerEValue = _timerProps.timerE();
    }

    if (!pTransaction->transport()->isReliableTransport())
    {
      startTimerE(_timerEValue);
      startTimerF(_timerEValue*64);
    }
    else
    {
      startTimerF(RELIABLE_TIMER_F_VALUE);
    }
    
    return true;
  }
  return false;
}
예제 #3
0
void SIPFSMDispatch::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport)
{
  if (!pTransport->isEndpoint() && pTransport->getLastReadCount() < MIN_DATAGRAM_SIZE && !pTransport->isReliableTransport())
  {
    //
    // datagram is too short to be a SIP Message
    // Bailing out.  Take note that streamed connection
    // can split SIP messages to smaller frames
    // and the last frame can be smaller than MIN_DATAGRAM_SIZE
    // so we do not impose a limit for streams
    //
    return;
  }

  try
  {
    pMsg->parse();
  }
  catch(OSS::Exception e)
  {
    std::ostringstream logMsg;
    logMsg << "Incoming message failed to be parsed - " << e.message()
      << " LEN: " << pTransport->getLastReadCount()
      << " SRC: " << pTransport->getRemoteAddress().toIpPortString();
    OSS::log_warning(logMsg.str());
    return;
  }

  std::string id;
  if (!pMsg->getTransactionId(id))
    return;  // don't throw here
             // we don't have control over what we receive from the transport

  SIPTransaction::Ptr trn;
  SIPTransaction::Type transactionType = SIPTransaction::TYPE_UNKNOWN;
  if (pMsg->isRequest())
  {
    if (OSS::string_caseless_starts_with(pMsg->startLine(), "invite"))
    {
      transactionType = SIPTransaction::TYPE_IST;
      if (_istBlocker.has(id))
      {
        OSS_LOG_WARNING("Blocked request retransmission - " <<  pMsg->startLine());
        return;
      }
      
      trn = _ist.findTransaction(pMsg, pTransport);
    }
    else if (OSS::string_caseless_starts_with(pMsg->startLine(), "ack"))
    {
      //
      // ACK for error responses will get matched to a transaction
      //
      transactionType = SIPTransaction::TYPE_IST;
      trn = _ist.findTransaction(pMsg, pTransport, false);
    }
    else
    {
      transactionType = SIPTransaction::TYPE_NIST;
      trn = _nist.findTransaction(pMsg, pTransport);
    }
  }
  else if (!pMsg->isRequest())
  {
    std::string cseq;
    cseq = pMsg->hdrGet(OSS::SIP::HDR_CSEQ);
    if (OSS::string_caseless_ends_with(cseq, "invite"))
    {
      transactionType = SIPTransaction::TYPE_ICT;
      trn = _ict.findTransaction(pMsg, pTransport, false);
    }
    else
    {
      transactionType = SIPTransaction::TYPE_NICT;
      trn = _nict.findTransaction(pMsg, pTransport, false);
    }
  }
  if (trn)
  {
    std::ostringstream logMsg;
    if (!trn->getLogId().empty())
    {
      logMsg << trn->getLogId() << "Found Transaction " << trn->getId();
      OSS::log_debug(logMsg.str());
    }
    else
    {
      trn->setLogId(pMsg->createContextId(true));
      logMsg << trn->getLogId() << "Transaction " << trn->getId() << " CREATED";
      OSS::log_information(logMsg.str());
    }
  }

  if (!trn)
  {
    //
    // We did not get a transaction, check if this is an ack and find the IST ACK transaction
    //
    if (transactionType == SIPTransaction::TYPE_IST && pMsg->isRequest("ACK"))
    {
        //
        // No IST is existing in the ackable Pool.
        // Report this ACK as orphaned to the UA CORE
        //
        if (_ackOr2xxTransactionHandler)
          _ackOr2xxTransactionHandler(pMsg, pTransport);
    }
    else if (transactionType == SIPTransaction::TYPE_ICT && pMsg->is2xx())
    {
      if (_ackOr2xxTransactionHandler)
        _ackOr2xxTransactionHandler(pMsg, pTransport);
    }
    else
    {
      std::ostringstream logMsg;
      logMsg << pMsg->createContextId(true) << "Unable to match incoming request to a transaction - "
        << pMsg->startLine();
      OSS::log_warning(logMsg.str());
    }
  }
  else
  {
    if (!trn->transportService())
    {
      //
      // This is a newly created transaction
      //
      trn->transportService() = &_transport;
      trn->transport() = pTransport;
    }
    trn->onReceivedMessage(pMsg, pTransport);
  }
}