void SIPTransaction::writeMessage(SIPMessage::Ptr pMsg)
{
  OSS::mutex_lock lock(_mutex);

  if (!_transport)
  {
    OSS_LOG_ERROR("SIPTransaction::writeMessage - Transport is NULL while attempting to send a request.");
    return;
  }

  if (SIPXOR::isEnabled() && _isXOREncrypted)
  {
    pMsg->setProperty("xor", "1");
  }

  std::ostringstream logMsg;
  logMsg << _logId << ">>> " << pMsg->startLine()
  << " LEN: " << pMsg->data().size()
  << " SRC: " << _transport->getLocalAddress().toIpPortString()
  << " DST: " << _transport->getRemoteAddress().toIpPortString()
  << " ENC: " << _isXOREncrypted
  << " PROT: " << _transport->getTransportScheme();
  OSS::log_information(logMsg.str());

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

  if (_fsm->onSendMessage(pMsg))
  {
    _transport->writeMessage(pMsg);
  }
}
void SIPTransaction::writeMessage(SIPMessage::Ptr pMsg, const OSS::IPAddress& remoteAddress)
{
  OSS::mutex_lock lock(_mutex);

  if (!_transport)
  {
    OSS_LOG_ERROR("SIPTransaction::writeMessage does not have a transport to use");
    return;
  }

  if (SIPXOR::isEnabled() && _isXOREncrypted)
  {
    pMsg->setProperty("xor", "1");
  }

  if (_fsm->onSendMessage(pMsg))
  {
    std::ostringstream logMsg;
    logMsg << _logId << ">>> " << pMsg->startLine()
    << " LEN: " << pMsg->data().size()
    << " SRC: " << _transport->getLocalAddress().toIpPortString()
    << " DST: " << remoteAddress.toIpPortString()
    << " ENC: " << _isXOREncrypted
    << " PROT: " << _transport->getTransportScheme();
    OSS::log_information(logMsg.str());
    if (OSS::log_get_level() >= OSS::PRIO_DEBUG)
      OSS::log_debug(pMsg->createLoggerData());

    _transport->writeMessage(pMsg,
    remoteAddress.toString(),
    OSS::string_from_number<unsigned short>(remoteAddress.getPort()));
  }
}
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);
    }
  }
}