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