Exemple #1
0
bool SIPNict::isCompleted() const
{
  SIPTransaction::Ptr pTransaction = static_cast<SIPTransaction::WeakPtr*>(_owner)->lock();
  if (!pTransaction)
    return true; /// If we can't lock the transaction pointer it means it is termianted
  return  pTransaction->getState() >= COMPLETED;
}
SIPTransaction::Ptr SIPTransaction::findBranch(const SIPMessage::Ptr& pRequest)
{
  //
  // Only a parent transaction can have branches
  //
  if(!isParent())
    return SIPTransaction::Ptr();

  OSS::mutex_critic_sec_lock lock(_branchesMutex);
  SIPTransaction::Ptr foundBranch;
  std::string branch = pRequest->getToTag();
  if (branch.empty())
    return SIPTransaction::Ptr();

  Branches::iterator pBranch = _branches.find(branch);
  
  //
  // Branch is non-existent.  Create a new one and attach a new FSM to it
  //
  if (pBranch == _branches.end())
  {
    foundBranch = SIPTransaction::Ptr(new SIPTransaction(shared_from_this()));
    _owner->onAttachFSM(foundBranch);
    foundBranch->fsm()->setRequest(fsm()->getRequest());
    foundBranch->_owner = _owner;
    foundBranch->_responseTU = _responseTU;
    _branches[branch] = foundBranch;
  }
  else
  {
    foundBranch = pBranch->second;
  }
  return foundBranch;
}
void SIPIctPool::onAttachFSM(const SIPTransaction::Ptr& pTransaction)
{
  if (!pTransaction->fsm())
  {
    pTransaction->type() = SIPTransaction::TYPE_ICT;
    pTransaction->fsm() = SIPIct::Ptr(new SIPIct(_ioService, _timerProps));
    pTransaction->fsm()->setOwner(new SIPTransaction::WeakPtr(pTransaction));
    pTransaction->fsm()->dispatch() = dispatch();
  }
}
Exemple #4
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);
  }
}
Exemple #5
0
void SIPNict::handleRequestTimeout()
{
  SIPTransaction::Ptr pTransaction = static_cast<SIPTransaction::WeakPtr*>(_owner)->lock();
  if (!pTransaction)
    return;

  int state = pTransaction->getState();
  if (state == SIPTransaction::TRN_STATE_TERMINATED || state == COMPLETED)
    return;

  cancelTimerK();
  cancelTimerE();
  cancelTimerF();
  pTransaction->handleTimeoutNICT();
  pTransaction->terminate();
}
SIPTransaction::SIPTransaction(SIPTransaction::Ptr pParent) :
  _type(pParent->getType()),
  _owner(0),
  _transportService(0),
  _state(TRN_STATE_IDLE),
  _localAddress(),
  _remoteAddress(),
  _sendAddress(),
  _dialogTarget(),
  _isXOREncrypted(false),
  _pParent(pParent),
  _isParent(false)
{
  _id = pParent->getId();
  _logId = pParent->getLogId();
  std::ostringstream logMsg;
  logMsg << _logId << getTypeString() << " " << _id << " CREATED";
  OSS::log_debug(logMsg.str());
}
Exemple #7
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;
}
Exemple #8
0
void SIPFSMDispatch::sendRequest(
  const SIPMessage::Ptr& pRequest,
  const OSS::Net::IPAddress& localAddress,
  const OSS::Net::IPAddress& remoteAddress,
  SIPTransaction::Callback& callback,
  SIPTransaction::TerminateCallback& terminateCallback)
{
  SIPTransaction::Ptr trn = createClientTransaction(pRequest);
 
  if (trn)
  {
    if (!trn->transportService())
    {
      //
      // This is a newly created transaction
      //
      trn->transportService() = &_transport;
      trn->localAddress() = localAddress;
      trn->remoteAddress() = remoteAddress;
    }
    trn->sendRequest(pRequest, localAddress, remoteAddress, callback, terminateCallback);
  }
}
Exemple #9
0
void SIPNict::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport)
{
  SIPTransaction::Ptr pTransaction = static_cast<SIPTransaction::WeakPtr*>(_owner)->lock();
  if (!pTransaction)
    return;


  int state = pTransaction->getState();
  if (!pMsg->isResponse() || state == SIPTransaction::TRN_STATE_TERMINATED || state == COMPLETED)
    return;

  bool is2xx = pMsg->is2xx();

  SIPTransaction::Ptr pParent = pTransaction->getParent();

  switch (pTransaction->getState())
  {
  case SIPTransaction::TRN_STATE_IDLE:
  case TRYING:
    if (pMsg->is1xx())
    {
      pTransaction->setState(PROCEEDING);
      if (!pTransaction->isParent() && pParent && pParent->getState() < PROCEEDING)
        pParent->setState(PROCEEDING);

      pTransaction->informTU(pMsg, pTransport);
    }
    else 
    {
      if (pTransaction->isParent() && !is2xx)
      {
        //
        // If we are the parent or this is and error response
        // cancel e and f timers
        //
        cancelTimerE();
        cancelTimerF();
      }
      else if (!pTransaction->isParent() && is2xx)
      {
        //
        // If this is a branch and it is a 2xx reponse,
        // then cancel both parents timers as sell
        //
        cancelTimerE();
        cancelTimerF();

        if (pParent)
        {
          pParent->fsm()->cancelTimerE();
          pParent->fsm()->cancelTimerF();
          pParent->setState(COMPLETED);
        }
      }
      else if (!pTransaction->isParent() && !is2xx)
      {
        //
        // If this is a branch and it is an error reponse,
        // then cancel both parent timers as well if there
        // is only one branch
        //
        cancelTimerE();
        cancelTimerF();

        if (pParent && pParent->getBranchCount() == 1)
        {
          pParent->fsm()->cancelTimerE();
          pParent->fsm()->cancelTimerF();
          pParent->setState(COMPLETED);
        }
      }

      pTransaction->setState(COMPLETED);
      pTransaction->informTU(pMsg, pTransport);
      
      if (!pTransport->isReliableTransport())
      {
        //
        // Start the longest time we want to handle retransmissions of 200 OK
        //
        startTimerK();
      }
      else
      {
        pTransaction->setState(SIPTransaction::TRN_STATE_TERMINATED);
        if (is2xx || pTransaction->allBranchesCompleted())
        {
          if (pParent)
            pParent->setState(SIPTransaction::TRN_STATE_TERMINATED);
        }
      }
    }
    break;
  case PROCEEDING:
    if (pMsg->is1xx())
    {
      pTransaction->informTU(pMsg, pTransport);
    }
    else 
    {
      if (pTransaction->isParent() && !is2xx)
      {
        //
        // If we are the parent or this is and error response
        // cancel e and f timers
        //
        cancelTimerE();
        cancelTimerF();
      }
      else if (!pTransaction->isParent() && is2xx)
      {
        //
        // If this is a branch and it is a 2xx reponse,
        // then cancel both parent timers as sell
        //
        cancelTimerE();
        cancelTimerF();
        if (pParent)
        {
          pParent->fsm()->cancelTimerE();
          pParent->fsm()->cancelTimerF();
          pParent->setState(COMPLETED);
        }
      }
      else if (!pTransaction->isParent() && !is2xx)
      {
        //
        // If this is a branch and it is an error reponse,
        // then cancel both parent timers as well if there
        // is only one branch
        //
        cancelTimerE();
        cancelTimerF();

        if (pParent)
        {
          if (pParent->getBranchCount() == 1)
          {
            pParent->fsm()->cancelTimerE();
            pParent->fsm()->cancelTimerF();
            pParent->setState(COMPLETED);
          }
        }
      }
      
      pTransaction->setState(COMPLETED);
      pTransaction->informTU(pMsg, pTransport);
      if (!pTransport->isReliableTransport())
      {
        //
        // Start the longest time we want to handle retransmissions of 200 OK
        //
        startTimerK();
      }
      else
      {
        pTransaction->setState(SIPTransaction::TRN_STATE_TERMINATED);
        if (is2xx || pTransaction->allBranchesCompleted())
          if (pParent)
            pParent->setState(SIPTransaction::TRN_STATE_TERMINATED);

      }
    }
    break;
  case COMPLETED:
    break;
  }

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

  if (pParent && pParent->getState() == SIPTransaction::TRN_STATE_TERMINATED)
      pParent->terminate();

}
void SIPTransaction::sendResponse(
  const SIPMessage::Ptr& pResponse,
  const OSS::IPAddress& sendAddress)
{
  if (!pResponse->isResponse())
    throw OSS::SIP::SIPException("Sending a REQUEST using sendResponse() is illegal!");

  SIPTransaction::Ptr pParent = getParent();

  if (!_transport && isParent())
    throw OSS::SIP::SIPException("Transport Not Ready!");
  else if (!isParent() && pParent)
    _transport = pParent->_transport;

  if (_sendAddress.getPort() == 0)
    _sendAddress = sendAddress;

  SIPTransaction::Ptr pBranch = findBranch(pResponse);

  if (pBranch)
  {
    pBranch->sendResponse(pResponse, sendAddress);
    return;
  }
  else
  {
    //
    // No branch is found.  This instance will handle the response
    //
    if (_transport && _transport->isReliableTransport())
    {
      if (_transport->writeKeepAlive())
      {
        writeMessage(pResponse);
      }
      else
      {
        //
        // Keep-alive failed so create a new transport
        //
        if (_localAddress.isValid() && _sendAddress.isValid())
        {
          //
          // According to RFC 3261, if there is any transport failure, we must try to
          // re-estabish a connectoin to the via sentby parameter instead
          //
          std::string transport;
          if (SIPVia::msgGetTopViaTransport(pResponse.get(), transport))
          {
            _transport = _transportService->createClientTransport(_localAddress, _sendAddress, transport);
            writeMessage(pResponse);
          }
        }
        else
        {
          OSS_LOG_ERROR("SIPTransaction::sendResponse - Unable to re-establish transport to send response.");
        }

      }
    }
    else if (_transport)
    {
      //
      // This is UDP so a keep-alive check won't do us any good
      //
      writeMessage(pResponse, _sendAddress);
    }
    else
    {
      OSS_LOG_ERROR("SIPTransaction::sendResponse - Transport is NULL.");
    }
  }
}
void SIPTransaction::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport)
{
  OSS::mutex_lock lock(_mutex);

  bool isAck = pMsg->isRequest("ACK");

  if (pMsg->isRequest() && !_pInitialRequest && !isAck)
    _pInitialRequest = pMsg;

  if (_logId.empty())
    _logId = pMsg->createContextId(true);

  if (!_transport)
    _transport = pTransport;

  if (!_localAddress.isValid())
    _localAddress = pTransport->getLocalAddress();

  if (!_remoteAddress.isValid())
    _remoteAddress = pTransport->getRemoteAddress();

  if (SIPXOR::isEnabled() && !_isXOREncrypted)
  {
    std::string isXOR;
    _isXOREncrypted = pMsg->getProperty("xor", isXOR) && isXOR == "1";
  }

  if (isParent())
  {
    std::ostringstream logMsg;
    logMsg << _logId << "<<< " << pMsg->startLine()
    << " LEN: " << pTransport->getLastReadCount()
    << " SRC: " << _remoteAddress.toIpPortString()
    << " DST: " << _localAddress.toIpPortString()
    << " EXT: " << "[" << pTransport->getExternalAddress() << "]"
    << " FURI: " << pMsg->hdrGet("from")
    << " ENC: " << _isXOREncrypted
    << " PROT: " << pTransport->getTransportScheme();
    OSS::log_information(logMsg.str());

    if (OSS::log_get_level() >= OSS::PRIO_DEBUG)
      OSS::log_debug(pMsg->createLoggerData());
  }

  //
  // If this is a request and is not an ACK, then the parent IST fsm must always handle it
  //
  if (isParent() && pMsg->isRequest() && !isAck)
  {
    _fsm->onReceivedMessage(pMsg, pTransport);
  }
  else if (!pMsg->isRequest() || isAck)
  {
    //
    // This is a response or an ACK and the transaction could have branched out
    //
    if (!isParent())
    {
      _fsm->onReceivedMessage(pMsg, pTransport);
    }
    else
    {
      SIPTransaction::Ptr pBranch = findBranch(pMsg);
      if (pBranch)
        pBranch->onReceivedMessage(pMsg, pTransport);
      else
        _fsm->onReceivedMessage(pMsg, pTransport);
    }
  }
}
Exemple #12
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);
  }
}