📄 clientinvitesession.cxx
字号:
#include "resip/stack/SdpContents.hxx"#include "resip/dum/ClientInviteSession.hxx"#include "resip/dum/Dialog.hxx"#include "resip/dum/DialogUsageManager.hxx"#include "resip/dum/InviteSessionHandler.hxx"#include "resip/dum/DumTimeout.hxx"#include "resip/dum/MasterProfile.hxx"#include "resip/dum/ServerInviteSession.hxx"#include "resip/dum/ServerSubscription.hxx"#include "resip/dum/UsageUseException.hxx"#include "resip/dum/DumHelper.hxx"#include "resip/stack/SipFrag.hxx"#include "rutil/Logger.hxx"#include "rutil/Random.hxx"#include "rutil/compat.hxx"#include "rutil/WinLeakCheck.hxx"#define RESIPROCATE_SUBSYSTEM Subsystem::DUMusing namespace resip;using namespace std;ClientInviteSession::ClientInviteSession(DialogUsageManager& dum, Dialog& dialog, SharedPtr<SipMessage> request, const Contents* initialOffer, DialogUsageManager::EncryptionLevel level, ServerSubscriptionHandle serverSub) : InviteSession(dum, dialog), mStaleCallTimerSeq(1), mCancelledTimerSeq(1), mServerSub(serverSub){ assert(request->isRequest()); if(initialOffer) { mProposedLocalSdp = auto_ptr<Contents>(initialOffer->clone()); mProposedEncryptionLevel = level; } *mLastLocalSessionModification = *request; // Copy message, so that modifications to mLastLocalSessionModification don't effect creator->getLastRequest mState=UAC_Start;}ClientInviteSessionHandleClientInviteSession::getHandle(){ return ClientInviteSessionHandle(mDum, getBaseHandle().getId());}const SdpContents&ClientInviteSession::getEarlyMedia() const{ return *mEarlyMedia;}voidClientInviteSession::provideOffer(const SdpContents& offer, DialogUsageManager::EncryptionLevel level, const SdpContents* alternative){ InfoLog (<< toData(mState) << ": provideOffer"); switch(mState) { case UAC_EarlyWithAnswer: { transition(UAC_SentUpdateEarly); // Creates an UPDATE request with application supplied offer. mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); InviteSession::setSdp(*mLastLocalSessionModification, offer); // Remember proposed local SDP. mProposedLocalSdp = InviteSession::makeSdp(offer, alternative); mProposedEncryptionLevel = level; // Send the req and do state transition. DumHelper::setOutgoingEncryptionLevel(*mLastLocalSessionModification, mProposedEncryptionLevel); send(mLastLocalSessionModification); break; } case UAC_SentAnswer: // just queue it for later transition(UAC_QueuedUpdate); mProposedLocalSdp = InviteSession::makeSdp(offer, alternative); mProposedEncryptionLevel = level; break; case UAC_Start: case UAC_Early: case UAC_EarlyWithOffer: case UAC_Answered: case UAC_SentUpdateEarly: case UAC_ReceivedUpdateEarly: case UAC_Cancelled: case UAC_QueuedUpdate: case Terminated: assert(0); break; default: InviteSession::provideOffer(offer, level, alternative); break; }}voidClientInviteSession::provideOffer (const SdpContents& offer){ this->provideOffer(offer, mCurrentEncryptionLevel, 0);}voidClientInviteSession::provideAnswer (const SdpContents& answer){ InfoLog (<< toData(mState) << ": provideAnswer"); switch(mState) { case UAC_EarlyWithOffer: { transition(UAC_SentAnswer); // Remember proposed local SDP. mCurrentRemoteSdp = mProposedRemoteSdp; mCurrentLocalSdp = InviteSession::makeSdp(answer); // Creates an PRACK request with application supplied offer. sendPrack(answer); break; } case UAC_Answered: { transition(Connected); sendAck(&answer); mCurrentRemoteSdp = mProposedRemoteSdp; mCurrentLocalSdp = InviteSession::makeSdp(answer); // mLastSessionModification = ack; // ?slg? is this needed? break; } case UAC_ReceivedUpdateEarly: { transition(UAC_EarlyWithAnswer); //.dcm. earlyWithAnwer is a strange //name...maybe earlyEstablished? //this sequence is repeated in many places...due for refactoring. //see ReceivedUpdate handling in InviteSession. //?dcm? are session timers allowed in the early dialog? SharedPtr<SipMessage> response(new SipMessage); mDialog.makeResponse(*response, *mLastRemoteSessionModification, 200); InviteSession::setSdp(*response, answer, 0); mCurrentLocalSdp = InviteSession::makeSdp(answer); mCurrentRemoteSdp = mProposedRemoteSdp; InfoLog (<< "Sending " << response->brief()); DumHelper::setOutgoingEncryptionLevel(*response, mCurrentEncryptionLevel); send(response); break; } case UAC_Start: case UAC_Early: case UAC_EarlyWithAnswer: case UAC_SentUpdateEarly: case UAC_SentAnswer: case UAC_Cancelled: case UAC_QueuedUpdate: case Terminated: assert(0); break; default: InviteSession::provideAnswer(answer); break; }}voidClientInviteSession::end(){ end(NotSpecified);}voidClientInviteSession::end(EndReason reason){ InfoLog (<< toData(mState) << ": end"); if (mEndReason == NotSpecified) { mEndReason = reason; } switch(mState) { case UAC_Early: case UAC_EarlyWithOffer: case UAC_EarlyWithAnswer: case UAC_Answered: case UAC_SentUpdateEarly: case UAC_ReceivedUpdateEarly: case UAC_SentAnswer: case UAC_QueuedUpdate: case UAC_Cancelled: // !jf! possibly incorrect to always BYE in UAC_Cancelled { sendBye(); transition(Terminated); mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended); break; } case UAC_Start: WarningLog (<< "Try to end when in state=" << toData(mState)); assert(0); break; case Terminated: // no-op break; default: InviteSession::end(reason); break; }}voidClientInviteSession::reject (int statusCode, WarningCategory *warning){ InfoLog (<< toData(mState) << ": reject(" << statusCode << ")"); switch(mState) { case UAC_ReceivedUpdateEarly: { // Creates an PRACK request with application supplied status code. // !kh! hopefully 488.... SharedPtr<SipMessage> req(new SipMessage()); mDialog.makeRequest(*req, PRACK); req->header(h_StatusLine).statusCode() = statusCode; if(warning) { req->header(h_Warnings).push_back(*warning); } // Send the req and do state transition. send(req); transition(UAC_EarlyWithAnswer); break; } case UAC_Start: case UAC_Early: case UAC_EarlyWithOffer: case UAC_EarlyWithAnswer: case UAC_Answered: case UAC_SentUpdateEarly: case UAC_SentAnswer: case UAC_Cancelled: WarningLog (<< "Try to reject when in state=" << toData(mState)); assert(0); break; default: InviteSession::reject(statusCode, warning); break; }}voidClientInviteSession::cancel(){ switch(mState) { case UAC_Early: case UAC_EarlyWithOffer: case UAC_EarlyWithAnswer: case UAC_SentUpdateEarly: case UAC_ReceivedUpdateEarly: case UAC_SentAnswer: InfoLog (<< toData(mState) << ": cancel"); startCancelTimer(); transition(UAC_Cancelled); break; case UAC_Cancelled: // !jf! break; default: assert(0); break; }}voidClientInviteSession::onForkAccepted(){ switch(mState) { case UAC_Early: case UAC_EarlyWithOffer: case UAC_EarlyWithAnswer: case UAC_SentUpdateEarly: case UAC_ReceivedUpdateEarly: InfoLog (<< toData(mState) << ": onForkAccepted"); // !jf! should we avoid creating another timer here? I don't think it // matters. Default timer is for 32secs. This is here to handle the // cleanup on forked INVITEs that have sent a provisional response but // don't ever receive a final response. mDum.addTimerMs(DumTimeout::WaitingForForked2xx, Timer::TH, getBaseHandle(), 1); break; default: // If the dialog is already set up (or cancelled) we disregard. break; }}voidClientInviteSession::startCancelTimer(){ InfoLog (<< toData(mState) << ": startCancelTimer"); mDum.addTimerMs(DumTimeout::Cancelled, Timer::TH, getBaseHandle(), ++mCancelledTimerSeq);}voidClientInviteSession::startStaleCallTimer(){ InfoLog (<< toData(mState) << ": startStaleCallTimer"); unsigned long when = mDialog.mDialogSet.getUserProfile()->getDefaultStaleCallTime(); when += Random::getRandom() % 120; mDum.addTimer(DumTimeout::StaleCall, when, getBaseHandle(), ++mStaleCallTimerSeq);}voidClientInviteSession::sendSipFrag(const SipMessage& msg){ if (mServerSub.isValid()) { if (msg.isResponse() && mState >= UAC_Start && mState <= UAC_Cancelled) { int code = msg.header(h_StatusLine).statusCode(); if (code > 100) { SipFrag contents; contents.message().header(h_StatusLine) = msg.header(h_StatusLine); if (code < 200) { mServerSub->send(mServerSub->update(&contents)); } else { mServerSub->end(NoResource, &contents); } } } }}voidClientInviteSession::dispatch(const SipMessage& msg){ try { if (checkRseq(msg)) { return; } sendSipFrag(msg); switch(mState) { case UAC_Start: dispatchStart(msg); break; case UAC_Early: dispatchEarly(msg); break; case UAC_EarlyWithOffer: dispatchEarlyWithOffer(msg); break; case UAC_EarlyWithAnswer: dispatchEarlyWithAnswer(msg); break; case UAC_Answered: dispatchAnswered(msg); break; case UAC_SentUpdateEarly: dispatchSentUpdateEarly(msg); break; case UAC_SentUpdateEarlyGlare: dispatchSentUpdateEarlyGlare(msg); break; case UAC_ReceivedUpdateEarly: dispatchReceivedUpdateEarly(msg); break; case UAC_SentAnswer: dispatchSentAnswer(msg); break; case UAC_QueuedUpdate: dispatchQueuedUpdate(msg); break; case UAC_Cancelled: dispatchCancelled(msg); break; default: InviteSession::dispatch(msg); break; } } catch (BaseException& e) { WarningLog (<< "Caught: " << e); mDum.mInviteSessionHandler->onFailure(getHandle(), msg); end(NotSpecified); }}voidClientInviteSession::dispatch(const DumTimeout& timer){ if (timer.type() == DumTimeout::Cancelled) { if(timer.seq() == mCancelledTimerSeq) { if (mServerSub.isValid()) { SipMessage response; mDialog.makeResponse(response, *mLastLocalSessionModification, 487); sendSipFrag(response); } transition(Terminated); mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Cancelled); mDum.destroy(this); } } else if (timer.type() == DumTimeout::StaleCall) { if(timer.seq() == mStaleCallTimerSeq) { mDum.mInviteSessionHandler->onStaleCallTimeout(getHandle()); mDum.mInviteSessionHandler->terminate(getHandle()); } } else if (timer.type() == DumTimeout::WaitingForForked2xx) { transition(Terminated); mDum.mInviteSessionHandler->onForkDestroyed(getHandle()); mDum.destroy(this); } else if (timer.type() == DumTimeout::Glare) { if (mState == UAC_SentUpdateEarlyGlare) { transition(UAC_SentUpdateEarly); InfoLog (<< "Retransmitting the UPDATE (glare condition timer)"); mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); // increments CSeq send(mLastLocalSessionModification); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -