📄 invitesession.cxx
字号:
if (mNitState == NitComplete) { mNitState = NitProceeding; send(info); return; } mNITQueue.push(new QueuedNIT(info)); DebugLog(<< "refer - queuing NIT:" << info->brief()<<endl); return; } else { WarningLog (<< "Can't send INFO before Connected"); assert(0); throw UsageUseException("Can't send INFO before Connected", __FILE__, __LINE__); }}class InviteSessionInfoCommand : public DumCommandAdapter{public: InviteSessionInfoCommand(InviteSession& inviteSession, const Contents& contents) : mInviteSession(inviteSession), mContents(contents.clone()) { } virtual void executeCommand() { mInviteSession.info(*mContents); } virtual std::ostream& encodeBrief(std::ostream& strm) const { return strm << "InviteSessionInfoCommand"; }private: InviteSession& mInviteSession; std::auto_ptr<Contents> mContents;};voidInviteSession::infoCommand(const Contents& contents){ mDum.post(new InviteSessionInfoCommand(*this, contents));}voidInviteSession::message(const Contents& contents){ if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite? { SharedPtr<SipMessage> message(new SipMessage()); mDialog.makeRequest(*message, MESSAGE); // !jf! handle multipart here message->setContents(&contents); DumHelper::setOutgoingEncryptionLevel(*message, mCurrentEncryptionLevel); InfoLog (<< "Trying to send MESSAGE: " << message); if (mNitState == NitComplete) { mNitState = NitProceeding; send(message); return; } mNITQueue.push(new QueuedNIT(message)); DebugLog(<< "refer - queuing NIT:" << message->brief()<<endl); return; } else { WarningLog (<< "Can't send MESSAGE before Connected"); assert(0); throw UsageUseException("Can't send MESSAGE before Connected", __FILE__, __LINE__); }}class InviteSessionMessageCommand : public DumCommandAdapter{public: InviteSessionMessageCommand(InviteSession& inviteSession, const Contents& contents) : mInviteSession(inviteSession), mContents(contents.clone()) { } virtual void executeCommand() { mInviteSession.message(*mContents); } virtual std::ostream& encodeBrief(std::ostream& strm) const { return strm << "InviteSessionMessageCommand"; }private: InviteSession& mInviteSession; std::auto_ptr<Contents> mContents;};voidInviteSession::messageCommand(const Contents& contents){ mDum.post(new InviteSessionMessageCommand(*this, contents));}voidInviteSession::dispatch(const SipMessage& msg){ // Look for 2xx retransmissions - resend ACK and filter out of state machine if(msg.header(h_CSeq).method() == INVITE && msg.isResponse() && msg.header(h_StatusLine).statusCode() / 100 == 2) { AckMap::iterator i = mAcks.find(msg.getTransactionId()); if (i != mAcks.end()) { send(i->second); // resend ACK return; } } // !jf! do we need to handle 3xx here or is it handled elsewhere? switch (mState) { case Connected: dispatchConnected(msg); break; case SentUpdate: dispatchSentUpdate(msg); break; case SentReinvite: dispatchSentReinvite(msg); break; case SentReinviteNoOffer: dispatchSentReinviteNoOffer(msg); break; case SentReinviteAnswered: dispatchSentReinviteAnswered(msg); break; case SentUpdateGlare: case SentReinviteGlare: // The behavior is the same except for timer which is handled in dispatch(Timer) dispatchGlare(msg); break; case SentReinviteNoOfferGlare: dispatchReinviteNoOfferGlare(msg); break; case ReceivedUpdate: case ReceivedReinvite: case ReceivedReinviteNoOffer: dispatchReceivedUpdateOrReinvite(msg); break; case ReceivedReinviteSentOffer: dispatchReceivedReinviteSentOffer(msg); break; case Answered: dispatchAnswered(msg); break; case WaitingToOffer: dispatchWaitingToOffer(msg); break; case WaitingToRequestOffer: dispatchWaitingToRequestOffer(msg); break; case WaitingToTerminate: dispatchWaitingToTerminate(msg); break; case WaitingToHangup: dispatchWaitingToHangup(msg); break; case Terminated: dispatchTerminated(msg); break; case Undefined: default: assert(0); break; }}voidInviteSession::dispatch(const DumTimeout& timeout){ if (timeout.type() == DumTimeout::Retransmit200) { if (mCurrentRetransmit200) { InfoLog (<< "Retransmitting: " << endl << mInvite200->brief()); //DumHelper::setOutgoingEncryptionLevel(*mInvite200, mCurrentEncryptionLevel); send(mInvite200); mCurrentRetransmit200 *= 2; mDum.addTimerMs(DumTimeout::Retransmit200, resipMin(Timer::T2, mCurrentRetransmit200), getBaseHandle(), timeout.seq()); } } else if (timeout.type() == DumTimeout::WaitForAck) { if(mCurrentRetransmit200) // If retransmit200 timer is active then ACK is not received yet { if (timeout.seq() == mLastRemoteSessionModification->header(h_CSeq).sequence()) { mCurrentRetransmit200 = 0; // stop the 200 retransmit timer // If we are waiting for an Ack and it times out, then end with a BYE if(mState == UAS_WaitingToHangup || mState == WaitingToHangup) { sendBye(); transition(Terminated); mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended); } else if(mState == ReceivedReinviteSentOffer) { transition(Connected); mProposedLocalSdp.reset(); mProposedEncryptionLevel = DialogUsageManager::None; //!dcm! -- should this be onIllegalNegotiation? mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), 0); } else if(mState == WaitingToOffer || mState == UAS_WaitingToOffer) { assert(mProposedLocalSdp.get()); mDum.mInviteSessionHandler->onAckNotReceived(getSessionHandle()); if(!isTerminated()) { provideProposedOffer(); } } else if(mState == WaitingToRequestOffer || mState == UAS_WaitingToRequestOffer) { mDum.mInviteSessionHandler->onAckNotReceived(getSessionHandle()); if(!isTerminated()) { requestOffer(); } } else { // this is so the app can decided to ignore this. default implementation // will call end next mDum.mInviteSessionHandler->onAckNotReceived(getSessionHandle()); } } } } else if (timeout.type() == DumTimeout::CanDiscardAck) { AckMap::iterator i = mAcks.find(timeout.transactionId()); if (i != mAcks.end()) { mAcks.erase(i); } } else if (timeout.type() == DumTimeout::Glare) { if (mState == SentUpdateGlare) { transition(SentUpdate); InfoLog (<< "Retransmitting the UPDATE (glare condition timer)"); mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); // increments CSeq send(mLastLocalSessionModification); } else if (mState == SentReinviteGlare) { transition(SentReinvite); InfoLog (<< "Retransmitting the reINVITE (glare condition timer)"); mDialog.makeRequest(*mLastLocalSessionModification, INVITE); // increments CSeq startStaleReInviteTimer(); send(mLastLocalSessionModification); } else if (mState == SentReinviteNoOfferGlare) { transition(SentReinviteNoOffer); InfoLog (<< "Retransmitting the reINVITE-nooffer (glare condition timer)"); mDialog.makeRequest(*mLastLocalSessionModification, INVITE); // increments CSeq startStaleReInviteTimer(); send(mLastLocalSessionModification); } } else if (timeout.type() == DumTimeout::StaleReInvite) { if(timeout.seq() == mStaleReInviteTimerSeq) { if(mState == WaitingToTerminate) { sendBye(); transition(Terminated); mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended); } else if(mState == SentReinvite || mState == SentReinviteNoOffer) { transition(Connected); mProposedLocalSdp.reset(); mProposedEncryptionLevel = DialogUsageManager::None; // this is so the app can decide to ignore this. default implementation // will call end next - which will send a BYE mDum.mInviteSessionHandler->onStaleReInviteTimeout(getSessionHandle()); } } } else if (timeout.type() == DumTimeout::SessionExpiration) { if(timeout.seq() == mSessionTimerSeq) { // this is so the app can decide to ignore this. default implementation // will call end next - which will send a BYE mDum.mInviteSessionHandler->onSessionExpired(getSessionHandle()); } } else if (timeout.type() == DumTimeout::SessionRefresh) { if(timeout.seq() == mSessionTimerSeq) { // Note: If not connected then we must be issueing a reinvite/update or // receiving one - in either case the session timer stuff will get // reset/renegotiated - thus just ignore this referesh if(mState == Connected) { sessionRefresh(); } } }}voidInviteSession::dispatchConnected(const SipMessage& msg){ InviteSessionHandler* handler = mDum.mInviteSessionHandler; std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg); switch (toEvent(msg, sdp.get())) { case OnInvite: case OnInviteReliable: *mLastRemoteSessionModification = msg; transition(ReceivedReinviteNoOffer); //handler->onDialogModified(getSessionHandle(), None, msg); handler->onOfferRequired(getSessionHandle(), msg); break; case OnInviteOffer: case OnInviteReliableOffer: *mLastRemoteSessionModification = msg; transition(ReceivedReinvite); mCurrentEncryptionLevel = getEncryptionLevel(msg); mProposedRemoteSdp = sdp; //handler->onDialogModified(getSessionHandle(), Offer, msg); handler->onOffer(getSessionHandle(), msg, *mProposedRemoteSdp); break; case On2xx: case On2xxOffer: case On2xxAnswer: // retransmission of 200I // !jf! Need to include the answer here. sendAck(); break; case OnUpdateOffer: transition(ReceivedUpdate); // !kh! // Find out if it's an UPDATE requiring state change. // See rfc3311 5.2, 4th paragraph. *mLastRemoteSessionModification = msg; mCurrentEncryptionLevel = getEncryptionLevel(msg); mProposedRemoteSdp = sdp; handler->onOffer(getSessionHandle(), msg, *mProposedRemoteSdp); break; case OnUpdate: { // ?slg? no sdp in update - just respond immediately (likely session timer) - do we need a callback? SharedPtr<SipMessage> response(new SipMessage); *mLastRemoteSessionModification = msg; mDialog.makeResponse(*response, *mLastRemoteSessionModification, 200); handleSessionTimerRequest(*response, *mLastRemoteSessionModification); send(response); break; } case OnUpdateRejected: case On200Update: WarningLog (<< "DUM delivered an UPDATE response in an incorrect state " << endl << msg); assert(0); break; case OnAck: case OnAckAnswer: // .bwc. Don't drop ACK with SDP! mCurrentRetransmit200 = 0; // stop the 200 retransmit timer handler->onAckReceived(getSessionHandle(), msg); break; default: dispatchOthers(msg); break; }}voidInviteSession::dispatchSentUpdate(const SipMessage& msg){ InviteSessionHandler* handler = mDum.mInviteSessionHandler; std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg); switch (toEvent(msg, sdp.get())) { case OnInvite: case OnInviteReliable: case OnInviteOffer: case OnInviteReliableOffer: case OnUpdate: case OnUpdateOffer: { // glare SharedPtr<SipMessage> response(new SipMessage); mDialog.makeResponse(*response, msg, 491); send(response); break; } case On200Update: transition(Connected); handleSessionTimerResponse(msg); if (sdp.get() && mProposedLocalSdp.get()) { mCurrentEncryptionLevel = getEncryptionLevel(msg); setCurrentLocalSdp(msg); mCurrentRemoteSdp = sdp; handler->onAnswer(getSessionHandle(), msg, *mCurrentRemoteSdp); } else if(mProposedLocalSdp.get()) { // If we sent an offer in the Update Request and no answer is received handler->onIllegalNegotiation(getSessionHandle(), msg); mProposedLocalSdp.reset(); mProposedEncryptionLevel = DialogUsageManager::None; } break; case On491Update: transition(SentUpdateGlare); start491Timer(); break; case On422Update: // session timer if(msg.exists(h_MinSE)) { // Change interval to min from 422 response mSessionInterval = msg.header(h_MinSE).value();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -