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())); } }
SIPTransaction::Ptr SIPFSMDispatch::createClientTransaction(const SIPMessage::Ptr& pRequest) { if (!pRequest->isRequest()) throw OSS::SIP::SIPException("Sending a response using sendRequest() method is illegal"); std::string id; if (!pRequest->getTransactionId(id)) throw OSS::SIP::SIPException("Unable to determine transaction identifier"); SIPTransaction::Ptr trn; SIPTransportSession::Ptr nullTransport; bool isAck = false; if (OSS::string_caseless_starts_with(pRequest->startLine(), "invite")) { // // This is an ICT // trn = _ict.findTransaction(pRequest, nullTransport); } else { // // This is an NICT // isAck = pRequest->isRequest(OSS::SIP::REQ_ACK); if (!isAck) { trn = _nict.findTransaction(pRequest, nullTransport); } } return trn; }
static SIPB2BHandler::MessageType getBodyType(const SIPMessage::Ptr& pRequest) { std::string cseq = pRequest->hdrGet("cseq"); if (cseq.empty()) return SIPB2BHandler::TYPE_INVALID; OSS::string_to_upper(cseq); if (OSS::string_ends_with(cseq, "INVITE") || OSS::string_ends_with(cseq, "UPDATE") || OSS::string_ends_with(cseq, "ACK") || OSS::string_ends_with(cseq, "PRACK")) { if (pRequest->getBody().empty()) return SIPB2BHandler::TYPE_INVALID; std::string contentType = pRequest->hdrGet("content-type"); OSS::string_to_lower(contentType); if (contentType != "application/sdp") return SIPB2BHandler::TYPE_INVALID; return SIPB2BHandler::TYPE_SDP; } return SIPB2BHandler::TYPE_INVALID; }
SIPMessage::Ptr SIPB2BTransactionManager::onAuthenticateTransaction( const SIPMessage::Ptr& pRequest, SIPB2BTransaction::Ptr pTransaction) { std::string maxForwards = pRequest->hdrGet("max-forwards"); if (maxForwards.empty()) { maxForwards = "70"; } int maxF = OSS::string_to_number<int>(maxForwards.c_str()); if (maxF == 0) { return pRequest->createResponse(SIPMessage::CODE_483_TooManyHops); } --maxF; pRequest->hdrRemove("max-forwards"); pRequest->hdrSet("Max-Forwards", OSS::string_from_number(maxF).c_str()); SIPB2BHandler::Ptr pHandler = findHandler(pRequest); if (pHandler) { return pHandler->onAuthenticateTransaction(pRequest, pTransaction); } else if (_pDefaultHandler) { return _pDefaultHandler->onAuthenticateTransaction(pRequest, pTransaction); } return pRequest->createResponse(405, "No Corresponding Handler"); }
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 EndpointListener::dispatchMessage(const SIPMessage::Ptr& pRequest) { if (_dispatch) { OSS_LOG_DEBUG(pRequest->createContextId(true) << "EndpointListener::dispatchMessage( " << pRequest->startLine() << " )"); pRequest->setProperty(OSS::PropertyMap::PROP_EndpointName, _endpointName); pRequest->commitData(); _dispatch(pRequest, _pConnection); } else { OSS_LOG_ERROR(pRequest->createContextId(true) << "EndpointListener::dispatchMessage( NULL )"); } }
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 SIPWebSocketConnection::writeMessage(SIPMessage::Ptr msg) /// Send a SIP message using this session. { if (_pServerConnection) { _pServerConnection->send(msg->data(), websocketpp::frame::opcode::BINARY); } }
void EndpointListener::monitorEvents() { OSS_LOG_NOTICE("EndpointListener::monitorEvents( " << _endpointName << " ) - STARTED processing events"); handleStart(); while(!_isTerminating) { SIPMessage::Ptr pRequest; _eventQueue.dequeue(pRequest); if (pRequest) { OSS_LOG_DEBUG(pRequest->createContextId(true) << "EndpointListener::monitorEvents( " << _endpointName << " ) - processing event " << pRequest->startLine()); onHandleEvent(pRequest); } else { OSS_LOG_DEBUG("EndpointListener::monitorEvents( " << _endpointName << " ) - dropping NULL event"); } } handleStop(); OSS_LOG_NOTICE("EndpointListener::monitorEvents( " << _endpointName << " ) TERMINATED"); }
static SIPB2BHandler::MessageType getMessageType(const SIPMessage::Ptr& pRequest) { std::string cseq = pRequest->hdrGet("cseq"); if (cseq.empty()) return SIPB2BHandler::TYPE_INVALID; OSS::string_to_upper(cseq); if (OSS::string_ends_with(cseq, "INVITE")) return SIPB2BHandler::TYPE_INVITE; else if (OSS::string_ends_with(cseq, "REGISTER")) return SIPB2BHandler::TYPE_REGISTER; else if (OSS::string_ends_with(cseq, "BYE")) return SIPB2BHandler::TYPE_BYE; else if (OSS::string_ends_with(cseq, "CANCEL")) return SIPB2BHandler::TYPE_CANCEL; else if (OSS::string_ends_with(cseq, "EXEC")) return SIPB2BHandler::TYPE_EXEC; else if (OSS::string_ends_with(cseq, "INFO")) return SIPB2BHandler::TYPE_INFO; else if (OSS::string_ends_with(cseq, "OPTIONS")) return SIPB2BHandler::TYPE_OPTIONS; else if (OSS::string_ends_with(cseq, "PRACK")) return SIPB2BHandler::TYPE_PRACK; else if (OSS::string_ends_with(cseq, "PUBLISH")) return SIPB2BHandler::TYPE_PUBLISH; else if (OSS::string_ends_with(cseq, "SUBSCRIBE")) return SIPB2BHandler::TYPE_SUBSCRIBE; else if (OSS::string_ends_with(cseq, "MESSAGE")) return SIPB2BHandler::TYPE_MESSAGE; else if (OSS::string_ends_with(cseq, "NOTIFY")) return SIPB2BHandler::TYPE_NOTIFY; else if (OSS::string_ends_with(cseq, "REFER")) return SIPB2BHandler::TYPE_REFER; else if (OSS::string_ends_with(cseq, "UPDATE")) return SIPB2BHandler::TYPE_UPDATE; else if (pRequest->isRequest()) return SIPB2BHandler::TYPE_ANY; return SIPB2BHandler::TYPE_INVALID; }
SIPMessage::Ptr SIPB2BTransactionManager::onTransactionCreated( const SIPMessage::Ptr& pRequest, SIPB2BTransaction::Ptr pTransaction) { SIPB2BHandler::Ptr pHandler = findHandler(pRequest); if (pHandler) { return pHandler->onTransactionCreated(pRequest, pTransaction); } else if (_pDefaultHandler) { return _pDefaultHandler->onTransactionCreated(pRequest, pTransaction); } return pRequest->createResponse(405, "No Corresponding Handler"); }
void OSSSIP::sendRequestDirect(const SIPMessage::Ptr& pRequest, const OSS::IPAddress& localAddress, const OSS::IPAddress& remoteAddress) { std::string transport; if (SIPVia::msgGetTopViaTransport(pRequest.get(), transport)) { std::string transportId; pRequest->getProperty("transport-id", transportId); if (transportId.empty()) transportId="0"; OSS_LOG_DEBUG("Sending request directly protocol=" << transport << " id=" << transportId); SIPTransportSession::Ptr client = _fsmDispatch.transport().createClientTransport(localAddress, remoteAddress, transport, transportId); if (client) client->writeMessage(pRequest, remoteAddress.toString(), OSS::string_from_number(remoteAddress.getPort())); else OSS_LOG_ERROR("OSSSIP::sendRequestDirect failed - Unable to create client transport"); } else { OSS_LOG_ERROR("OSSSIP::sendRequestDirect failed - Unable to determine transport protocol.") } }
SIPMessage::Ptr SIPB2BTransactionManager::onRouteTransaction( SIPMessage::Ptr& pRequest, SIPB2BTransaction::Ptr pTransaction, OSS::IPAddress& localInterface, OSS::IPAddress& target) { SIPB2BHandler::Ptr pHandler = findDomainRouter(pRequest); if (pHandler) { bool handled = false; SIPMessage::Ptr result = pHandler->onRouteTransaction(pRequest, pTransaction, localInterface, target, handled); if (handled) return result; } pHandler = findHandler(pRequest); if (pHandler) { SIPMessage::Ptr result = pHandler->onRouteTransaction(pRequest, pTransaction, localInterface, target); // // _postRouteCallback is currently set by // the SBCStaticRouter class that allows static router // to bypass the results of the javascript layer. // if (_postRouteCallback) return _postRouteCallback(pRequest, result, pTransaction, localInterface, target); return result; } else if (_pDefaultHandler) { SIPMessage::Ptr result = _pDefaultHandler->onRouteTransaction(pRequest, pTransaction, localInterface, target); // // _postRouteCallback is currently set by // the SBCStaticRouter class that allows static router // to bypass the results of the javascript layer. // if (_postRouteCallback) return _postRouteCallback(pRequest, result, pTransaction, localInterface, target); return result; } return pRequest->createResponse(405, "No Corresponding Handler"); }
void SIPTransaction::sendAckFor2xx( const SIPMessage::Ptr& pAck, const OSS::IPAddress& dialogTarget) { OSS::mutex_lock lock(_mutex); if (!_dialogTarget.isValid()) _dialogTarget = dialogTarget; if (SIPXOR::isEnabled() && _isXOREncrypted) { pAck->setProperty("xor", "1"); } if (_transport->isReliableTransport()) { writeMessage(pAck); } else { writeMessage(pAck, dialogTarget); } }
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; }
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); } } }
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 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); } }
void SIPTransaction::sendRequest( const SIPMessage::Ptr& pRequest, const OSS::IPAddress& localAddress, const OSS::IPAddress& remoteAddress, SIPTransaction::Callback callback) { OSS::mutex_lock lock(_mutex); if (!pRequest->isRequest()) { throw OSS::SIP::SIPException("Sending a REQUEST using sendRequest() is illegal!"); } if (!_pInitialRequest) { _pInitialRequest = pRequest; if (_logId.empty()) _logId = pRequest->createContextId(true); if (SIPXOR::isEnabled() && !_isXOREncrypted) { std::string isXOR; _isXOREncrypted = pRequest->getProperty("xor", isXOR) && isXOR == "1"; } } if (!_responseTU) _responseTU = callback; if (_localAddress.getPort() == 0) _localAddress = localAddress; if (_remoteAddress.getPort() == 0) _remoteAddress = remoteAddress; if (!_transport) { if (!_transportService) throw OSS::SIP::SIPException("Transport Not Ready!"); std::string transport; if (pRequest->getProperty("target-transport", transport)) { std::string transportId; pRequest->getProperty("transport-id", transportId); _transport = _transportService->createClientTransport(localAddress, remoteAddress, transport, transportId); }else if (SIPVia::msgGetTopViaTransport(pRequest.get(), transport)) { _transport = _transportService->createClientTransport(localAddress, remoteAddress, transport); } if (!_transport) throw OSS::SIP::SIPException("Unable to create transport!"); } if (_transport->isReliableTransport()) { writeMessage(pRequest); } else { writeMessage(pRequest, remoteAddress); } }
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."); } } }