📄 dialog.cxx
字号:
#include "resip/stack/Contents.hxx"#include "resip/stack/Helper.hxx"#include "resip/stack/SipMessage.hxx"#include "resip/dum/AppDialog.hxx"#include "resip/dum/BaseCreator.hxx"#include "resip/dum/ClientAuthManager.hxx"#include "resip/dum/ClientInviteSession.hxx"#include "resip/dum/ClientSubscription.hxx"#include "resip/dum/Dialog.hxx"#include "resip/dum/DialogUsageManager.hxx"#include "resip/dum/MasterProfile.hxx"#include "resip/dum/InviteSessionCreator.hxx"#include "resip/dum/InviteSessionHandler.hxx"#include "resip/dum/ServerInviteSession.hxx"#include "resip/dum/ServerSubscription.hxx"#include "resip/dum/SubscriptionHandler.hxx"#include "resip/dum/UsageUseException.hxx"#include "rutil/Logger.hxx"#include "rutil/Inserter.hxx"#include "rutil/WinLeakCheck.hxx"#define RESIPROCATE_SUBSYSTEM Subsystem::DUMusing namespace resip;using namespace std;Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg, DialogSet& ds) : mDum(dum), mDialogSet(ds), mId("INVALID", "INVALID", "INVALID"), mClientSubscriptions(), mServerSubscriptions(), mInviteSession(0), mType(Fake), mRouteSet(), mLocalContact(), mLocalCSeq(0), mRemoteCSeq(0), mRemoteTarget(), mLocalNameAddr(), mRemoteNameAddr(), mCallId(msg.header(h_CallID)), mDefaultSubExpiration(0), mAppDialog(0), mDestroying(false), mReUseDialogSet(false){ assert(msg.isExternal()); assert(msg.header(h_CSeq).method() != MESSAGE); assert(msg.header(h_CSeq).method() != REGISTER); assert(msg.header(h_CSeq).method() != PUBLISH); mNetworkAssociation.setDum(&dum); if (msg.isRequest()) // UAS { const SipMessage& request = msg; switch (request.header(h_CSeq).method()) { case INVITE: mType = Invitation; break; case SUBSCRIBE: case REFER: case NOTIFY: //!dcm! -- event header check mType = Subscription; break; default: mType = Fake; } if (request.exists(h_RecordRoutes)) { mRouteSet = request.header(h_RecordRoutes); } switch (request.header(h_CSeq).method()) { case INVITE: case SUBSCRIBE: case REFER: case NOTIFY: DebugLog ( << "UAS dialog ID creation, DS: " << ds.getId()); mId = DialogId(ds.getId(), request.header(h_From).exists(p_tag) ? request.header(h_From).param(p_tag) : Data::Empty); mRemoteNameAddr = request.header(h_From); mLocalNameAddr = request.header(h_To); mLocalNameAddr.param(p_tag) = mId.getLocalTag(); if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1) { const NameAddr& contact = request.header(h_Contacts).front(); if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) || isEqualNoCase(contact.uri().scheme(), Symbols::Sip)) { mLocalContact = NameAddr(request.header(h_RequestLine).uri()); // update later when send a request mRemoteTarget = contact; if (mDialogSet.getUserProfile()->hasOverrideHostAndPort()) { mLocalContact.uri().host() = mDialogSet.getUserProfile()->getOverrideHostAndPort().host(); mLocalContact.uri().port() = mDialogSet.getUserProfile()->getOverrideHostAndPort().port(); } } else { InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme"); InfoLog(<< request); throw Exception("Invalid scheme in request", __FILE__, __LINE__); } } else { InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact"); InfoLog (<< request); throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__); } break; default: break; } mRemoteCSeq = request.header(h_CSeq).sequence(); mLocalCSeq = 1; DebugLog ( << "************** Created Dialog as UAS **************" ); DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr ); DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr ); DebugLog ( << "mLocalContact: " << mLocalContact ); DebugLog ( << "mRemoteTarget: " << mRemoteTarget ); } else if (msg.isResponse()) { mId = DialogId(msg); const SipMessage& response = msg; mRemoteNameAddr = response.header(h_To); mLocalNameAddr = response.header(h_From); switch (msg.header(h_CSeq).method()) { case INVITE: mType = Invitation; break; case SUBSCRIBE: case REFER: mType = Subscription; break; default: mType = Fake; } if (response.exists(h_RecordRoutes)) { mRouteSet = response.header(h_RecordRoutes).reverse(); } switch (response.header(h_CSeq).method()) { case INVITE: case SUBSCRIBE: case REFER: if (response.header(h_StatusLine).statusCode() > 100 && response.header(h_StatusLine).statusCode() < 300) { if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1) { const NameAddr& contact = response.header(h_Contacts).front(); if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) || isEqualNoCase(contact.uri().scheme(), Symbols::Sip)) { BaseCreator* creator = mDialogSet.getCreator(); if( 0 == creator ) { ErrLog(<< "BaseCreator is null for DialogSet"); ErrLog(<< response); throw Exception("BaseCreator is null for DialogSet", __FILE__, __LINE__); } SharedPtr<SipMessage> lastRequest(creator->getLastRequest()); if( 0 == lastRequest.get() || !lastRequest->exists(h_Contacts) || lastRequest->header(h_Contacts).empty()) { InfoLog(<< "lastRequest does not contain a valid contact"); InfoLog(<< response); throw Exception("lastRequest does not contain a valid contact.", __FILE__, __LINE__); } mLocalContact = creator->getLastRequest()->header(h_Contacts).front(); mRemoteTarget = contact; } else { InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme"); DebugLog (<< response); throw Exception("Bad scheme in contact in response", __FILE__, __LINE__); } } else { InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact"); DebugLog (<< response); throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__); } break; default: break; } } mLocalCSeq = response.header(h_CSeq).sequence(); mRemoteCSeq = 0; DebugLog ( << "************** Created Dialog as UAC **************" ); DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr ); DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr ); DebugLog ( << "mLocalContact: " << mLocalContact ); DebugLog ( << "mRemoteTarget: " << mRemoteTarget ); } mDialogSet.addDialog(this); DebugLog ( <<"Dialog::Dialog " << mId);}Dialog::~Dialog(){ DebugLog ( <<"Dialog::~Dialog() "); mDestroying = true; while (!mClientSubscriptions.empty()) { delete *mClientSubscriptions.begin(); } while (!mServerSubscriptions.empty()) { delete *mServerSubscriptions.begin(); } delete mInviteSession; mDialogSet.mDialogs.erase(this->getId()); delete mAppDialog; if(!mReUseDialogSet) { mDialogSet.possiblyDie(); }}const DialogId&Dialog::getId() const{ return mId;}voidDialog::cancel(){ assert(mType == Invitation); ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession); assert (uac); uac->cancel();}voidDialog::end(){ if (mInviteSession) { mInviteSession->end(); } // End Subscriptions // !jrm! WARN ClientSubscription and ServerSubscription have access to this dialog and will remove themselves // from the m<client|server>Subscriptions collections in the call to end(). for (list<ClientSubscription*>::iterator it(mClientSubscriptions.begin()); it != mClientSubscriptions.end();) { ClientSubscription* c = *it; it++; c->end(); } for (list<ServerSubscription*>::iterator it2(mServerSubscriptions.begin()); it2 != mServerSubscriptions.end();) { ServerSubscription* s = *it2; it2++; s->end(); }}voidDialog::handleTargetRefresh(const SipMessage& msg){ switch(msg.header(h_CSeq).method()) { case INVITE: case UPDATE: if (msg.isRequest() || (msg.isResponse() && msg.header(h_StatusLine).statusCode()/100 == 2)) { //?dcm? modify local target; 12.2.2 of 3261 implies that the remote //target is immediately modified. Should we wait until a 2xx class //reponse is sent to a re-invite(easy when all send requests go //through Dialog) if (msg.exists(h_Contacts)) { //.dcm. replace or check then replace mRemoteTarget = msg.header(h_Contacts).front(); } } break; default: return; }}voidDialog::dispatch(const SipMessage& msg){ // !jf! Should be checking for messages with out of order CSeq and rejecting DebugLog ( << "Dialog::dispatch: " << msg.brief()); if(msg.isExternal()) { const Data& receivedTransport = msg.header(h_Vias).front().transport(); int keepAliveTime = 0; if(receivedTransport == Symbols::TCP || receivedTransport == Symbols::TLS || receivedTransport == Symbols::SCTP) { keepAliveTime = mDialogSet.getUserProfile()->getKeepAliveTimeForStream(); } else { keepAliveTime = mDialogSet.getUserProfile()->getKeepAliveTimeForDatagram(); } if(keepAliveTime > 0) { mNetworkAssociation.update(msg, keepAliveTime); } } handleTargetRefresh(msg); if (msg.isRequest()) { const SipMessage& request = msg; switch (request.header(h_CSeq).method()) { case INVITE: // new INVITE if (mInviteSession == 0) { DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief()); mInviteSession = makeServerInviteSession(request); } mInviteSession->dispatch(request); break; //refactor, send bad request for BYE, INFO, CANCEL? case BYE: if (mInviteSession == 0) { InfoLog ( << "Spurious BYE" ); return; } else { mInviteSession->dispatch(request); } break; case UPDATE: if (mInviteSession == 0) { InfoLog ( << "Spurious UPDATE" ); return; } else { mInviteSession->dispatch(request); } break; case INFO: if (mInviteSession == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -