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."); } } }