|
reSIProcate/DialogUsageManager
9680
|
00001 00002 #if defined(HAVE_CONFIG_H) 00003 #include "config.h" 00004 #endif 00005 00006 #include "resip/stack/SecurityAttributes.hxx" 00007 #include "resip/stack/ShutdownMessage.hxx" 00008 #include "resip/stack/SipFrag.hxx" 00009 #include "resip/stack/SipMessage.hxx" 00010 #include "resip/stack/SipStack.hxx" 00011 #include "resip/stack/Helper.hxx" 00012 #include "resip/stack/TransactionUserMessage.hxx" 00013 #include "resip/stack/ConnectionTerminated.hxx" 00014 #include "resip/stack/KeepAlivePong.hxx" 00015 #include "resip/dum/AppDialog.hxx" 00016 #include "resip/dum/AppDialogSet.hxx" 00017 #include "resip/dum/AppDialogSetFactory.hxx" 00018 #include "resip/dum/BaseUsage.hxx" 00019 #include "resip/dum/ClientAuthManager.hxx" 00020 #include "resip/dum/ClientInviteSession.hxx" 00021 #include "resip/dum/ClientOutOfDialogReq.hxx" 00022 #include "resip/dum/ClientPublication.hxx" 00023 #include "resip/dum/ClientRegistration.hxx" 00024 #include "resip/dum/ClientSubscription.hxx" 00025 #include "resip/dum/DefaultServerReferHandler.hxx" 00026 #include "resip/dum/DestroyUsage.hxx" 00027 #include "resip/dum/Dialog.hxx" 00028 #include "resip/dum/DialogEventStateManager.hxx" 00029 #include "resip/dum/DialogEventHandler.hxx" 00030 #include "resip/dum/DialogUsageManager.hxx" 00031 #include "resip/dum/ClientPagerMessage.hxx" 00032 #include "resip/dum/DumException.hxx" 00033 #include "resip/dum/DumShutdownHandler.hxx" 00034 #include "resip/dum/DumFeatureMessage.hxx" 00035 #include "resip/dum/ExternalMessageBase.hxx" 00036 #include "resip/dum/ExternalMessageHandler.hxx" 00037 #include "resip/dum/InviteSessionCreator.hxx" 00038 #include "resip/dum/InviteSessionHandler.hxx" 00039 #include "resip/dum/KeepAliveManager.hxx" 00040 #include "resip/dum/KeepAliveTimeout.hxx" 00041 #include "resip/dum/MasterProfile.hxx" 00042 #include "resip/dum/OutOfDialogReqCreator.hxx" 00043 #include "resip/dum/PagerMessageCreator.hxx" 00044 #include "resip/dum/PublicationCreator.hxx" 00045 #include "resip/dum/RedirectManager.hxx" 00046 #include "resip/dum/RegistrationCreator.hxx" 00047 #include "resip/dum/RemoteCertStore.hxx" 00048 #include "resip/dum/RequestValidationHandler.hxx" 00049 #include "resip/dum/ServerAuthManager.hxx" 00050 #include "resip/dum/ServerInviteSession.hxx" 00051 #include "resip/dum/ServerPublication.hxx" 00052 #include "resip/dum/ServerSubscription.hxx" 00053 #include "resip/dum/SubscriptionCreator.hxx" 00054 #include "resip/dum/SubscriptionHandler.hxx" 00055 #include "resip/dum/UserAuthInfo.hxx" 00056 #include "resip/dum/DumFeature.hxx" 00057 #include "resip/dum/IdentityHandler.hxx" 00058 #include "resip/dum/DumDecrypted.hxx" 00059 #include "resip/dum/CertMessage.hxx" 00060 #include "resip/dum/OutgoingEvent.hxx" 00061 #include "resip/dum/DumHelper.hxx" 00062 #include "resip/dum/MergedRequestRemovalCommand.hxx" 00063 #include "rutil/Inserter.hxx" 00064 #include "rutil/Logger.hxx" 00065 #include "rutil/Random.hxx" 00066 #include "rutil/Lockable.hxx" 00067 #include "rutil/WinLeakCheck.hxx" 00068 #include "rutil/Timer.hxx" 00069 00070 #ifdef USE_SSL 00071 #include "resip/stack/ssl/Security.hxx" 00072 #include "resip/dum/ssl/EncryptionManager.hxx" 00073 #endif 00074 00075 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00076 00077 using namespace resip; 00078 using namespace std; 00079 00080 #ifdef RESIP_DUM_THREAD_DEBUG 00081 #define threadCheck() \ 00082 do \ 00083 { \ 00084 if(mThreadDebugKey) \ 00085 { \ 00086 assert(ThreadIf::tlsGetValue(mThreadDebugKey)); \ 00087 } \ 00088 } while (false) 00089 #else 00090 #define threadCheck() void() 00091 #endif 00092 00093 00094 DialogUsageManager::DialogUsageManager(SipStack& stack, bool createDefaultFeatures) : 00095 TransactionUser(TransactionUser::DoNotRegisterForTransactionTermination, 00096 TransactionUser::RegisterForConnectionTermination, 00097 TransactionUser::RegisterForKeepAlivePongs), 00098 mRedirectManager(new RedirectManager()), 00099 mInviteSessionHandler(0), 00100 mClientRegistrationHandler(0), 00101 mServerRegistrationHandler(0), 00102 mRedirectHandler(0), 00103 mDialogSetHandler(0), 00104 mRequestValidationHandler(0), 00105 mRegistrationPersistenceManager(0), 00106 mIsDefaultServerReferHandler(true), 00107 mClientPagerMessageHandler(0), 00108 mServerPagerMessageHandler(0), 00109 mDialogEventStateManager(0), 00110 mAppDialogSetFactory(new AppDialogSetFactory()), 00111 mStack(stack), 00112 mDumShutdownHandler(0), 00113 mShutdownState(Running), 00114 mThreadDebugKey(0), 00115 mHiddenThreadDebugKey(0) 00116 { 00117 //TODO -- create default features 00118 mStack.registerTransactionUser(*this); 00119 addServerSubscriptionHandler("refer", new DefaultServerReferHandler()); 00120 00121 mFifo.setDescription("DialogUsageManager::mFifo"); 00122 00123 mIncomingTarget = new IncomingTarget(*this); 00124 mOutgoingTarget = new OutgoingTarget(*this); 00125 00126 if (createDefaultFeatures) 00127 { 00128 SharedPtr<IdentityHandler> identity = SharedPtr<IdentityHandler>(new IdentityHandler(*this, *mIncomingTarget)); 00129 00130 #if defined (USE_SSL) 00131 SharedPtr<EncryptionManager> encryptionIncoming = SharedPtr<EncryptionManager>(new EncryptionManager(*this, *mIncomingTarget)); 00132 SharedPtr<EncryptionManager> encryptionOutgoing = SharedPtr<EncryptionManager>(new EncryptionManager(*this, *mOutgoingTarget)); 00133 #endif 00134 00135 // default incoming features. 00136 addIncomingFeature(identity); 00137 #if defined (USE_SSL) 00138 addIncomingFeature(encryptionIncoming); 00139 #endif 00140 00141 // default outgoing features. 00142 #if defined (USE_SSL) 00143 addOutgoingFeature(encryptionOutgoing); 00144 #endif 00145 00146 } 00147 00148 } 00149 00150 DialogUsageManager::~DialogUsageManager() 00151 { 00152 mShutdownState = Destroying; 00153 //InfoLog ( << "~DialogUsageManager" ); 00154 00155 #if(0) 00156 // !kh! 00157 DialogSetMap::iterator dialogSet = mDialogSetMap.begin(); 00158 for (; dialogSet != mDialogSetMap.end(); ++dialogSet) 00159 { 00160 delete dialogSet->second; 00161 } 00162 #endif 00163 if(!mDialogSetMap.empty()) 00164 { 00165 DebugLog(<< "DialogUsageManager::mDialogSetMap has " << mDialogSetMap.size() << " DialogSets"); 00166 DialogSetMap::const_iterator ds = mDialogSetMap.begin(); 00167 for(; ds != mDialogSetMap.end(); ++ds) 00168 { 00169 DebugLog(<< "DialgSetId:" << ds->first); 00170 DialogSet::DialogMap::const_iterator d = ds->second->mDialogs.begin(); 00171 for(; d != ds->second->mDialogs.end(); ++d) 00172 { 00173 //const Dialog* p = &(d->second); 00174 DebugLog(<<"DialogId:" << d->first << ", " << *d->second); 00175 } 00176 } 00177 } 00178 00179 while(!mDialogSetMap.empty()) 00180 { 00181 DialogSet* ds = mDialogSetMap.begin()->second; 00182 delete ds; 00183 } 00184 00185 if(mIsDefaultServerReferHandler) 00186 { 00187 delete mServerSubscriptionHandlers["refer"]; 00188 } 00189 00190 delete mIncomingTarget; 00191 delete mOutgoingTarget; 00192 00193 //InfoLog ( << "~DialogUsageManager done" ); 00194 } 00195 00196 const Data& 00197 DialogUsageManager::name() const 00198 { 00199 static Data n("DialogUsageManager"); 00200 return n; 00201 } 00202 00203 void 00204 DialogUsageManager::addTransport( TransportType protocol, 00205 int port, 00206 IpVersion version, 00207 const Data& ipInterface, 00208 const Data& sipDomainname, // only used 00209 const Data& privateKeyPassPhrase, 00210 SecurityTypes::SSLType sslType, 00211 unsigned transportFlags) 00212 { 00213 mStack.addTransport(protocol, port, version, StunDisabled, ipInterface, 00214 sipDomainname, privateKeyPassPhrase, sslType, 00215 transportFlags); 00216 } 00217 00218 SipStack& 00219 DialogUsageManager::getSipStack() 00220 { 00221 return mStack; 00222 } 00223 00224 const SipStack& 00225 DialogUsageManager::getSipStack() const 00226 { 00227 return mStack; 00228 } 00229 00230 Security* 00231 DialogUsageManager::getSecurity() 00232 { 00233 return mStack.getSecurity(); 00234 } 00235 00236 Data 00237 DialogUsageManager::getHostAddress() 00238 { 00239 return mStack.getHostAddress(); 00240 } 00241 00242 void 00243 DialogUsageManager::onAllHandlesDestroyed() 00244 { 00245 if (mDumShutdownHandler) 00246 { 00247 switch (mShutdownState) 00248 { 00249 case ShutdownRequested: 00250 InfoLog (<< "DialogUsageManager::onAllHandlesDestroyed: removing TU"); 00251 //assert(mHandleMap.empty()); 00252 mShutdownState = RemovingTransactionUser; 00253 mStack.unregisterTransactionUser(*this); 00254 break; 00255 default: 00256 break; 00257 } 00258 } 00259 } 00260 00261 00262 void 00263 DialogUsageManager::shutdown(DumShutdownHandler* h) 00264 { 00265 InfoLog (<< "shutdown: dialogSets=" << mDialogSetMap.size()); 00266 00267 mDumShutdownHandler = h; 00268 mShutdownState = ShutdownRequested; 00269 mStack.requestTransactionUserShutdown(*this); 00270 shutdownWhenEmpty(); 00271 } 00272 00273 // void 00274 // DialogUsageManager::shutdownIfNoUsages(DumShutdownHandler* h) 00275 // { 00276 // InfoLog (<< "shutdown when no usages"); 00277 // 00278 // mDumShutdownHandler = h; 00279 // mShutdownState = ShutdownRequested; 00280 // assert(0); 00281 // } 00282 00283 void 00284 DialogUsageManager::forceShutdown(DumShutdownHandler* h) 00285 { 00286 WarningLog (<< "force shutdown "); 00287 dumpHandles(); 00288 00289 mDumShutdownHandler = h; 00290 //HandleManager::shutdown(); // clear out usages 00291 mShutdownState = ShutdownRequested; 00292 DialogUsageManager::onAllHandlesDestroyed(); 00293 } 00294 00295 void DialogUsageManager::setAppDialogSetFactory(std::auto_ptr<AppDialogSetFactory> factory) 00296 { 00297 mAppDialogSetFactory = factory; 00298 } 00299 00300 SharedPtr<MasterProfile>& 00301 DialogUsageManager::getMasterProfile() 00302 { 00303 assert(mMasterProfile.get()); 00304 return mMasterProfile; 00305 } 00306 00307 SharedPtr<UserProfile>& 00308 DialogUsageManager::getMasterUserProfile() 00309 { 00310 assert(mMasterUserProfile.get()); 00311 return mMasterUserProfile; 00312 } 00313 00314 void DialogUsageManager::setMasterProfile(const SharedPtr<MasterProfile>& masterProfile) 00315 { 00316 assert(!mMasterProfile.get()); 00317 mMasterProfile = masterProfile; 00318 mMasterUserProfile = masterProfile; // required so that we can return a reference to SharedPtr<UserProfile> in getMasterUserProfile 00319 } 00320 00321 void DialogUsageManager::setKeepAliveManager(std::auto_ptr<KeepAliveManager> manager) 00322 { 00323 mKeepAliveManager = manager; 00324 mKeepAliveManager->setDialogUsageManager(this); 00325 } 00326 00327 void DialogUsageManager::setRedirectManager(std::auto_ptr<RedirectManager> manager) 00328 { 00329 mRedirectManager = manager; 00330 } 00331 00332 void DialogUsageManager::setRedirectHandler(RedirectHandler* handler) 00333 { 00334 mRedirectHandler = handler; 00335 } 00336 00337 RedirectHandler* DialogUsageManager::getRedirectHandler() 00338 { 00339 return mRedirectHandler; 00340 } 00341 00342 void 00343 DialogUsageManager::setClientAuthManager(std::auto_ptr<ClientAuthManager> manager) 00344 { 00345 mClientAuthManager = manager; 00346 } 00347 00348 void 00349 DialogUsageManager::setServerAuthManager(SharedPtr<ServerAuthManager> manager) 00350 { 00351 mIncomingFeatureList.insert(mIncomingFeatureList.begin(), manager); 00352 } 00353 00354 void 00355 DialogUsageManager::setClientRegistrationHandler(ClientRegistrationHandler* handler) 00356 { 00357 assert(!mClientRegistrationHandler); 00358 mClientRegistrationHandler = handler; 00359 } 00360 00361 void 00362 DialogUsageManager::setServerRegistrationHandler(ServerRegistrationHandler* handler) 00363 { 00364 assert(!mServerRegistrationHandler); 00365 mServerRegistrationHandler = handler; 00366 } 00367 00368 void 00369 DialogUsageManager::setDialogSetHandler(DialogSetHandler* handler) 00370 { 00371 mDialogSetHandler = handler; 00372 } 00373 00374 void 00375 DialogUsageManager::setInviteSessionHandler(InviteSessionHandler* handler) 00376 { 00377 assert(!mInviteSessionHandler); 00378 mInviteSessionHandler = handler; 00379 } 00380 00381 void 00382 DialogUsageManager::setRequestValidationHandler(RequestValidationHandler* handler) 00383 { 00384 assert(!mRequestValidationHandler); 00385 mRequestValidationHandler = handler; 00386 } 00387 00388 void 00389 DialogUsageManager::setRegistrationPersistenceManager(RegistrationPersistenceManager* manager) 00390 { 00391 assert(!mRegistrationPersistenceManager); 00392 mRegistrationPersistenceManager = manager; 00393 } 00394 00395 void 00396 DialogUsageManager::setRemoteCertStore(auto_ptr<RemoteCertStore> store) 00397 { 00398 } 00399 00400 void 00401 DialogUsageManager::addTimer(DumTimeout::Type type, unsigned long duration, 00402 BaseUsageHandle target, unsigned int cseq, unsigned int rseq) 00403 { 00404 DumTimeout t(type, duration, target, cseq, rseq); 00405 mStack.post(t, duration, this); 00406 } 00407 00408 void 00409 DialogUsageManager::addTimerMs(DumTimeout::Type type, unsigned long duration, 00410 BaseUsageHandle target, unsigned int cseq, unsigned int rseq, 00411 const Data &transactionId /*= Data::Empty*/) 00412 { 00413 DumTimeout t(type, duration, target, cseq, rseq, transactionId); 00414 mStack.postMS(t, duration, this); 00415 } 00416 00417 void 00418 DialogUsageManager::addClientSubscriptionHandler(const Data& eventType, ClientSubscriptionHandler* handler) 00419 { 00420 assert(handler); 00421 assert(mClientSubscriptionHandlers.count(eventType) == 0); 00422 mClientSubscriptionHandlers[eventType] = handler; 00423 } 00424 00425 void 00426 DialogUsageManager::addServerSubscriptionHandler(const Data& eventType, ServerSubscriptionHandler* handler) 00427 { 00428 assert(handler); 00429 //default do-nothing server side refer handler can be replaced 00430 if (eventType == "refer" && mServerSubscriptionHandlers.count(eventType)) 00431 { 00432 delete mServerSubscriptionHandlers[eventType]; 00433 mIsDefaultServerReferHandler = false; 00434 //mServerSubscriptionHandlers.erase(eventType); 00435 } 00436 00437 mServerSubscriptionHandlers[eventType] = handler; 00438 } 00439 00440 void 00441 DialogUsageManager::addClientPublicationHandler(const Data& eventType, ClientPublicationHandler* handler) 00442 { 00443 assert(handler); 00444 assert(mClientPublicationHandlers.count(eventType) == 0); 00445 mClientPublicationHandlers[eventType] = handler; 00446 } 00447 00448 void 00449 DialogUsageManager::addServerPublicationHandler(const Data& eventType, ServerPublicationHandler* handler) 00450 { 00451 assert(handler); 00452 assert(mServerPublicationHandlers.count(eventType) == 0); 00453 mServerPublicationHandlers[eventType] = handler; 00454 } 00455 00456 void 00457 DialogUsageManager::addOutOfDialogHandler(MethodTypes type, OutOfDialogHandler* handler) 00458 { 00459 assert(handler); 00460 assert(mOutOfDialogHandlers.count(type) == 0); 00461 mOutOfDialogHandlers[type] = handler; 00462 } 00463 00464 void 00465 DialogUsageManager::setClientPagerMessageHandler(ClientPagerMessageHandler* handler) 00466 { 00467 mClientPagerMessageHandler = handler; 00468 } 00469 00470 void 00471 DialogUsageManager::setServerPagerMessageHandler(ServerPagerMessageHandler* handler) 00472 { 00473 mServerPagerMessageHandler = handler; 00474 } 00475 00476 void 00477 DialogUsageManager::addExternalMessageHandler(ExternalMessageHandler* handler) 00478 { 00479 std::vector<ExternalMessageHandler*>::iterator found = std::find(mExternalMessageHandlers.begin(), mExternalMessageHandlers.end(), handler); 00480 if (found == mExternalMessageHandlers.end()) 00481 { 00482 mExternalMessageHandlers.push_back(handler); 00483 } 00484 } 00485 00486 void 00487 DialogUsageManager::removeExternalMessageHandler(ExternalMessageHandler* handler) 00488 { 00489 std::vector<ExternalMessageHandler*>::iterator found = std::find(mExternalMessageHandlers.begin(), mExternalMessageHandlers.end(), handler); 00490 if (found != mExternalMessageHandlers.end()) 00491 { 00492 mExternalMessageHandlers.erase(found); 00493 } 00494 } 00495 00496 void 00497 DialogUsageManager::clearExternalMessageHandler() 00498 { 00499 std::vector<ExternalMessageHandler*> empty; 00500 empty.swap(mExternalMessageHandlers); 00501 } 00502 00503 00504 DialogSet* 00505 DialogUsageManager::makeUacDialogSet(BaseCreator* creator, AppDialogSet* appDs) 00506 { 00507 threadCheck(); 00508 if (mDumShutdownHandler) 00509 { 00510 throw DumException("Cannot create new sessions when DUM is shutting down.", __FILE__, __LINE__); 00511 } 00512 00513 if (appDs == 0) 00514 { 00515 appDs = new AppDialogSet(*this); 00516 } 00517 DialogSet* ds = new DialogSet(creator, *this); 00518 00519 appDs->mDialogSet = ds; 00520 ds->mAppDialogSet = appDs; 00521 00522 StackLog ( << "************* Adding DialogSet ***************: " << ds->getId()); 00523 //StackLog ( << "Before: " << InserterP(mDialogSetMap) ); 00524 mDialogSetMap[ds->getId()] = ds; 00525 StackLog ( << "DialogSetMap: " << InserterP(mDialogSetMap) ); 00526 return ds; 00527 } 00528 00529 SharedPtr<SipMessage> 00530 DialogUsageManager::makeNewSession(BaseCreator* creator, AppDialogSet* appDs) 00531 { 00532 makeUacDialogSet(creator, appDs); 00533 return creator->getLastRequest(); 00534 } 00535 00536 void 00537 DialogUsageManager::makeResponse(SipMessage& response, 00538 const SipMessage& request, 00539 int responseCode, 00540 const Data& reason) const 00541 { 00542 assert(request.isRequest()); 00543 Helper::makeResponse(response, request, responseCode, reason); 00544 } 00545 00546 void 00547 DialogUsageManager::sendResponse(const SipMessage& response) 00548 { 00549 assert(response.isResponse()); 00550 mStack.send(response, this); 00551 } 00552 00553 SharedPtr<SipMessage> 00554 DialogUsageManager::makeInviteSession(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Contents* initialOffer, AppDialogSet* appDs) 00555 { 00556 return makeInviteSession(target, userProfile, initialOffer, None, 0, appDs); 00557 } 00558 00559 SharedPtr<SipMessage> 00560 DialogUsageManager::makeInviteSession(const NameAddr& target, const Contents* initialOffer, AppDialogSet* appDs) 00561 { 00562 return makeInviteSession(target, getMasterUserProfile(), initialOffer, None, 0, appDs); 00563 } 00564 00565 SharedPtr<SipMessage> 00566 DialogUsageManager::makeInviteSession(const NameAddr& target, 00567 const SharedPtr<UserProfile>& userProfile, 00568 const Contents* initialOffer, 00569 EncryptionLevel level, 00570 const Contents* alternative, 00571 AppDialogSet* appDs) 00572 { 00573 SharedPtr<SipMessage> inv = makeNewSession(new InviteSessionCreator(*this, target, userProfile, initialOffer, level, alternative), appDs); 00574 DumHelper::setOutgoingEncryptionLevel(*inv, level); 00575 return inv; 00576 } 00577 00578 SharedPtr<SipMessage> 00579 DialogUsageManager::makeInviteSession(const NameAddr& target, 00580 const Contents* initialOffer, 00581 EncryptionLevel level, 00582 const Contents* alternative, 00583 AppDialogSet* appDs) 00584 { 00585 return makeInviteSession(target, getMasterUserProfile(), initialOffer, level, alternative, appDs); 00586 } 00587 00588 SharedPtr<SipMessage> 00589 DialogUsageManager::makeInviteSession(const NameAddr& target, 00590 InviteSessionHandle sessionToReplace, 00591 const SharedPtr<UserProfile>& userProfile, 00592 const Contents* initialOffer, 00593 AppDialogSet* ads) 00594 { 00595 SharedPtr<SipMessage> inv = makeInviteSession(target, userProfile, initialOffer, ads); 00596 // add replaces header 00597 assert(sessionToReplace.isValid()); 00598 if(sessionToReplace.isValid()) 00599 { 00600 CallId replaces; 00601 DialogId id = sessionToReplace->getDialogId(); 00602 replaces.value() = id.getCallId(); 00603 replaces.param(p_toTag) = id.getRemoteTag(); 00604 replaces.param(p_fromTag) = id.getLocalTag(); 00605 inv->header(h_Replaces) = replaces; 00606 } 00607 return inv; 00608 } 00609 00610 SharedPtr<SipMessage> 00611 DialogUsageManager::makeInviteSession(const NameAddr& target, 00612 InviteSessionHandle sessionToReplace, 00613 const SharedPtr<UserProfile>& userProfile, 00614 const Contents* initialOffer, 00615 EncryptionLevel level, 00616 const Contents* alternative, 00617 AppDialogSet* ads) 00618 { 00619 SharedPtr<SipMessage> inv = makeInviteSession(target, userProfile, initialOffer, level, alternative, ads); 00620 // add replaces header 00621 assert(sessionToReplace.isValid()); 00622 if(sessionToReplace.isValid()) 00623 { 00624 CallId replaces; 00625 DialogId id = sessionToReplace->getDialogId(); 00626 replaces.value() = id.getCallId(); 00627 replaces.param(p_toTag) = id.getRemoteTag(); 00628 replaces.param(p_fromTag) = id.getLocalTag(); 00629 inv->header(h_Replaces) = replaces; 00630 } 00631 return inv; 00632 } 00633 00634 SharedPtr<SipMessage> 00635 DialogUsageManager::makeInviteSession(const NameAddr& target, 00636 InviteSessionHandle sessionToReplace, 00637 const Contents* initialOffer, 00638 EncryptionLevel level, 00639 const Contents* alternative , 00640 AppDialogSet* ads) 00641 { 00642 SharedPtr<SipMessage> inv = makeInviteSession(target, initialOffer, level, alternative, ads); 00643 // add replaces header 00644 assert(sessionToReplace.isValid()); 00645 if(sessionToReplace.isValid()) 00646 { 00647 CallId replaces; 00648 DialogId id = sessionToReplace->getDialogId(); 00649 replaces.value() = id.getCallId(); 00650 replaces.param(p_toTag) = id.getRemoteTag(); 00651 replaces.param(p_fromTag) = id.getLocalTag(); 00652 inv->header(h_Replaces) = replaces; 00653 } 00654 return inv; 00655 } 00656 00657 SharedPtr<SipMessage> 00658 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer, 00659 ServerSubscriptionHandle serverSub, 00660 const Contents* initialOffer, 00661 AppDialogSet* appDs) 00662 { 00663 return makeInviteSessionFromRefer(refer, serverSub, initialOffer, None, 0, appDs); 00664 } 00665 00666 SharedPtr<SipMessage> 00667 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer, 00668 const SharedPtr<UserProfile>& userProfile, 00669 const Contents* initialOffer, 00670 AppDialogSet* appDs) 00671 { 00672 ServerSubscriptionHandle empty; 00673 return makeInviteSessionFromRefer(refer, userProfile, empty, initialOffer, None, 0, appDs); 00674 } 00675 00676 SharedPtr<SipMessage> 00677 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer, 00678 ServerSubscriptionHandle serverSub, 00679 const Contents* initialOffer, 00680 EncryptionLevel level, 00681 const Contents* alternative, 00682 AppDialogSet* appDs) 00683 { 00684 return makeInviteSessionFromRefer(refer, serverSub.isValid() ? serverSub->mDialog.mDialogSet.getUserProfile() : getMasterUserProfile(), serverSub, initialOffer, level, alternative, appDs); 00685 } 00686 00687 SharedPtr<SipMessage> 00688 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer, 00689 const SharedPtr<UserProfile>& userProfile, 00690 ServerSubscriptionHandle serverSub, 00691 const Contents* initialOffer, 00692 EncryptionLevel level, 00693 const Contents* alternative, 00694 AppDialogSet* appDs) 00695 { 00696 if (serverSub.isValid()) 00697 { 00698 DebugLog(<< "implicit subscription"); 00699 //generate and send 100 00700 SipFrag contents; 00701 contents.message().header(h_StatusLine).statusCode() = 100; 00702 contents.message().header(h_StatusLine).reason() = "Trying"; 00703 //will be cloned...ServerSub may not have the most efficient API possible 00704 serverSub->setSubscriptionState(Active); 00705 SharedPtr<SipMessage> notify = serverSub->update(&contents); 00706 // mInviteSessionHandler->onReadyToSend(InviteSessionHandle::NotValid(), notify); 00707 serverSub->send(notify); 00708 } 00709 00710 //19.1.5 00711 NameAddr target = refer.header(h_ReferTo); 00712 target.uri().removeEmbedded(); 00713 target.uri().remove(p_method); 00714 00715 // !jf! this code assumes you have a UserProfile 00716 SharedPtr<SipMessage> inv = makeNewSession(new InviteSessionCreator(*this, 00717 target, 00718 userProfile, 00719 initialOffer, level, alternative, serverSub), appDs); 00720 DumHelper::setOutgoingEncryptionLevel(*inv, level); 00721 00722 //could pass dummy target, then apply merge rules from 19.1.5...or 00723 //makeNewSession would use rules from 19.1.5 00724 if (refer.exists(h_ReferredBy)) 00725 { 00726 inv->header(h_ReferredBy) = refer.header(h_ReferredBy); 00727 } 00728 00729 const Uri& referTo = refer.header(h_ReferTo).uri(); 00730 //19.1.5 00731 if (referTo.hasEmbedded() && referTo.embedded().exists(h_Replaces)) 00732 { 00733 inv->header(h_Replaces) = referTo.embedded().header(h_Replaces); 00734 } 00735 00736 return inv; 00737 } 00738 00739 SharedPtr<SipMessage> 00740 DialogUsageManager::makeRefer(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const H_ReferTo::Type& referTo, AppDialogSet* appDs) 00741 { 00742 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, referTo), appDs); 00743 } 00744 00745 SharedPtr<SipMessage> 00746 DialogUsageManager::makeRefer(const NameAddr& target, const H_ReferTo::Type& referTo, AppDialogSet* appDs) 00747 { 00748 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), referTo), appDs); 00749 } 00750 00751 SharedPtr<SipMessage> 00752 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType, AppDialogSet* appDs) 00753 { 00754 assert(userProfile.get()); 00755 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, userProfile->getDefaultSubscriptionTime()), appDs); 00756 } 00757 00758 SharedPtr<SipMessage> 00759 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType, 00760 UInt32 subscriptionTime, AppDialogSet* appDs) 00761 { 00762 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, subscriptionTime), appDs); 00763 } 00764 00765 SharedPtr<SipMessage> 00766 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType, 00767 UInt32 subscriptionTime, int refreshInterval, AppDialogSet* appDs) 00768 { 00769 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, subscriptionTime, refreshInterval), appDs); 00770 } 00771 00772 SharedPtr<SipMessage> 00773 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType, AppDialogSet* appDs) 00774 { 00775 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, getMasterProfile()->getDefaultSubscriptionTime()), appDs); 00776 } 00777 00778 SharedPtr<SipMessage> 00779 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType, 00780 UInt32 subscriptionTime, AppDialogSet* appDs) 00781 { 00782 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, subscriptionTime), appDs); 00783 } 00784 00785 SharedPtr<SipMessage> 00786 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType, 00787 UInt32 subscriptionTime, int refreshInterval, AppDialogSet* appDs) 00788 { 00789 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, subscriptionTime, refreshInterval), appDs); 00790 } 00791 00792 SharedPtr<SipMessage> 00793 DialogUsageManager::makeRegistration(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, AppDialogSet* appDs) 00794 { 00795 assert(userProfile.get()); 00796 return makeNewSession(new RegistrationCreator(*this, target, userProfile, userProfile->getDefaultRegistrationTime()), appDs); 00797 } 00798 00799 SharedPtr<SipMessage> 00800 DialogUsageManager::makeRegistration(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, UInt32 registrationTime, AppDialogSet* appDs) 00801 { 00802 return makeNewSession(new RegistrationCreator(*this, target, userProfile, registrationTime), appDs); 00803 } 00804 00805 SharedPtr<SipMessage> 00806 DialogUsageManager::makeRegistration(const NameAddr& target, AppDialogSet* appDs) 00807 { 00808 return makeNewSession(new RegistrationCreator(*this, target, getMasterUserProfile(), getMasterProfile()->getDefaultRegistrationTime()), appDs); 00809 } 00810 00811 SharedPtr<SipMessage> 00812 DialogUsageManager::makeRegistration(const NameAddr& target, UInt32 registrationTime, AppDialogSet* appDs) 00813 { 00814 return makeNewSession(new RegistrationCreator(*this, target, getMasterUserProfile(), registrationTime), appDs); 00815 } 00816 00817 SharedPtr<SipMessage> 00818 DialogUsageManager::makePublication(const NameAddr& targetDocument, 00819 const SharedPtr<UserProfile>& userProfile, 00820 const Contents& body, 00821 const Data& eventType, 00822 UInt32 expiresSeconds, 00823 AppDialogSet* appDs) 00824 { 00825 return makeNewSession(new PublicationCreator(*this, targetDocument, userProfile, body, eventType, expiresSeconds), appDs); 00826 } 00827 00828 SharedPtr<SipMessage> 00829 DialogUsageManager::makePublication(const NameAddr& targetDocument, 00830 const Contents& body, 00831 const Data& eventType, 00832 UInt32 expiresSeconds, 00833 AppDialogSet* appDs) 00834 { 00835 return makeNewSession(new PublicationCreator(*this, targetDocument, getMasterUserProfile(), body, eventType, expiresSeconds), appDs); 00836 } 00837 00838 SharedPtr<SipMessage> 00839 DialogUsageManager::makeOutOfDialogRequest(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const MethodTypes meth, AppDialogSet* appDs) 00840 { 00841 return makeNewSession(new OutOfDialogReqCreator(*this, meth, target, userProfile), appDs); 00842 } 00843 00844 SharedPtr<SipMessage> 00845 DialogUsageManager::makeOutOfDialogRequest(const NameAddr& target, const MethodTypes meth, AppDialogSet* appDs) 00846 { 00847 return makeNewSession(new OutOfDialogReqCreator(*this, meth, target, getMasterUserProfile()), appDs); 00848 } 00849 00850 ClientPagerMessageHandle 00851 DialogUsageManager::makePagerMessage(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, AppDialogSet* appDs) 00852 { 00853 if (!mClientPagerMessageHandler) 00854 { 00855 throw DumException("Cannot send MESSAGE messages without a ClientPagerMessageHandler", __FILE__, __LINE__); 00856 } 00857 DialogSet* ds = makeUacDialogSet(new PagerMessageCreator(*this, target, userProfile), appDs); 00858 ClientPagerMessage* cpm = new ClientPagerMessage(*this, *ds); 00859 ds->mClientPagerMessage = cpm; 00860 return cpm->getHandle(); 00861 } 00862 00863 ClientPagerMessageHandle 00864 DialogUsageManager::makePagerMessage(const NameAddr& target, AppDialogSet* appDs) 00865 { 00866 return makePagerMessage(target, getMasterUserProfile(), appDs); 00867 } 00868 00869 void 00870 DialogUsageManager::send(SharedPtr<SipMessage> msg) 00871 { 00872 // !slg! There is probably a more efficient way to get the userProfile here (pass it in?) 00873 DialogSet* ds = findDialogSet(DialogSetId(*msg)); 00874 UserProfile* userProfile; 00875 if (ds == 0) 00876 { 00877 userProfile = getMasterUserProfile().get(); 00878 } 00879 else 00880 { 00881 userProfile = ds->getUserProfile().get(); 00882 } 00883 00884 assert(userProfile); 00885 if (!userProfile->isAnonymous() && userProfile->hasUserAgent()) 00886 { 00887 msg->header(h_UserAgent).value() = userProfile->getUserAgent(); 00888 } 00889 if (userProfile->isAnonymous()) 00890 { 00891 msg->remove(h_ReplyTo); 00892 msg->remove(h_UserAgent); 00893 msg->remove(h_Organization); 00894 msg->remove(h_Server); 00895 msg->remove(h_Subject); 00896 msg->remove(h_InReplyTo); 00897 00898 msg->remove(h_CallInfos); 00899 msg->remove(h_Warnings); 00900 } 00901 00902 assert(userProfile); 00903 if (msg->isRequest() 00904 && userProfile->hasProxyRequires() 00905 && msg->header(h_RequestLine).method() != ACK 00906 && msg->header(h_RequestLine).method() != CANCEL) 00907 { 00908 msg->header(h_ProxyRequires) = userProfile->getProxyRequires(); 00909 } 00910 00911 // .bwc. This is to avoid leaving extra copies of the decorator in msg, 00912 // when the caller of this function holds onto the reference (and this 00913 // happens quite often in DUM). I would prefer to refactor such that we 00914 // are operating on a copy in this function, but this would require a lot 00915 // of work on the DumFeatureChain stuff (or, require an extra copy on top 00916 // of the one we're doing when we send the message to the stack, which 00917 // would chew up a lot of extra cycles). 00918 msg->clearOutboundDecorators(); 00919 00920 // Add outbound decorator from userprofile - note: it is important that this is 00921 // done before the call to mClientAuthManager->addAuthentication, since the ClientAuthManager 00922 // will install outbound decorators and we want these to run after the user provided ones, in 00923 // case a user provided decorator modifes the message body used in auth. 00924 SharedPtr<MessageDecorator> outboundDecorator = userProfile->getOutboundDecorator(); 00925 if (outboundDecorator.get()) 00926 { 00927 msg->addOutboundDecorator(std::auto_ptr<MessageDecorator>(outboundDecorator->clone())); 00928 } 00929 00930 if (msg->isRequest()) 00931 { 00932 // We may not need to call reset() if makeRequest is always used. 00933 if (msg->header(h_RequestLine).method() != CANCEL && 00934 msg->header(h_RequestLine).method() != ACK && 00935 msg->exists(h_Vias)) 00936 { 00937 msg->header(h_Vias).front().param(p_branch).reset(); 00938 } 00939 00940 if (msg->exists(h_Vias)) 00941 { 00942 if(!userProfile->getRportEnabled()) 00943 { 00944 msg->header(h_Vias).front().remove(p_rport); 00945 } 00946 int fixedTransportPort = userProfile->getFixedTransportPort(); 00947 if(fixedTransportPort != 0) 00948 { 00949 msg->header(h_Vias).front().sentPort() = fixedTransportPort; 00950 } 00951 const Data& fixedTransportInterface = userProfile->getFixedTransportInterface(); 00952 if(!fixedTransportInterface.empty()) 00953 { 00954 msg->header(h_Vias).front().sentHost() = fixedTransportInterface; 00955 } 00956 } 00957 00958 if (mClientAuthManager.get() && msg->header(h_RequestLine).method() != ACK) 00959 { 00960 mClientAuthManager->addAuthentication(*msg); 00961 } 00962 00963 if (msg->header(h_RequestLine).method() == INVITE) 00964 { 00965 if (ds != 0) 00966 { 00967 if (mDialogEventStateManager) 00968 { 00969 Dialog* d = ds->findDialog(*msg); 00970 if (d != 0) 00971 { 00972 mDialogEventStateManager->onConfirmed(*d, d->getInviteSession()); 00973 } 00974 else 00975 { 00976 mDialogEventStateManager->onTryingUac(*ds, *msg); 00977 } 00978 } 00979 } 00980 } 00981 } 00982 00983 DebugLog (<< "SEND: " << std::endl << std::endl << *msg); 00984 00985 OutgoingEvent* event = new OutgoingEvent(msg); 00986 outgoingProcess(auto_ptr<Message>(event)); 00987 } 00988 00989 void 00990 DialogUsageManager::sendCommand(SharedPtr<SipMessage> request) 00991 { 00992 SendCommand* s=new SendCommand(request, *this); 00993 post(s); 00994 } 00995 00996 00997 void DialogUsageManager::outgoingProcess(auto_ptr<Message> message) 00998 { 00999 Data tid = Data::Empty; 01000 { 01001 OutgoingEvent* sipMsg = dynamic_cast<OutgoingEvent*>(message.get()); 01002 if (sipMsg) 01003 { 01004 tid = sipMsg->getTransactionId(); 01005 } 01006 01007 DumFeatureMessage* featureMsg = dynamic_cast<DumFeatureMessage*>(message.get()); 01008 if (featureMsg) 01009 { 01010 InfoLog(<<"Got a DumFeatureMessage" << featureMsg); 01011 tid = featureMsg->getTransactionId(); 01012 } 01013 } 01014 01015 if (tid == Data::Empty && mOutgoingMessageInterceptor.get()) 01016 { 01017 mOutgoingMessageInterceptor->process(message.get()); 01018 return; 01019 } 01020 else if (tid != Data::Empty && !mOutgoingFeatureList.empty()) 01021 { 01022 FeatureChainMap::iterator it; 01023 //efficiently find or create FeatureChain, should prob. be a utility template 01024 { 01025 FeatureChainMap::iterator lb = mOutgoingFeatureChainMap.lower_bound(tid); 01026 if (lb != mOutgoingFeatureChainMap.end() && !(mOutgoingFeatureChainMap.key_comp()(tid, lb->first))) 01027 { 01028 it = lb; 01029 } 01030 else 01031 { 01032 it = mOutgoingFeatureChainMap.insert(lb, FeatureChainMap::value_type(tid, new DumFeatureChain(*this, mOutgoingFeatureList, *mOutgoingTarget))); 01033 } 01034 } 01035 01036 DumFeatureChain::ProcessingResult res = it->second->process(message.get()); 01037 01038 if (res & DumFeatureChain::ChainDoneBit) 01039 { 01040 delete it->second; 01041 mOutgoingFeatureChainMap.erase(it); 01042 } 01043 01044 if (res & DumFeatureChain::EventTakenBit) 01045 { 01046 message.release(); 01047 return; 01048 } 01049 } 01050 01051 OutgoingEvent* event = dynamic_cast<OutgoingEvent*>(message.get()); 01052 //assert(event); 01053 //.dcm. a TID collision can cause a message to be delivered to a finished 01054 //chain. This is probably because pseudorandom was being used on Win32. 01055 if (event) 01056 { 01057 if (event->message()->isRequest()) 01058 { 01059 DialogSet* ds = findDialogSet(DialogSetId(*event->message())); 01060 UserProfile* userProfile; 01061 if (ds == 0) 01062 { 01063 userProfile = getMasterUserProfile().get(); 01064 } 01065 else 01066 { 01067 userProfile = ds->getUserProfile().get(); 01068 } 01069 01070 assert(userProfile); 01071 01073 //optimzation here. SharedPtr would have to be changed; would 01074 //throw/assert if not unique. 01075 std::auto_ptr<SipMessage> toSend(static_cast<SipMessage*>(event->message()->clone())); 01076 01077 // .bwc. Protect ourselves from garbage with an isWellFormed() check. 01078 // (Code in Dialog doesn't check for well-formedness in the 01079 // Record-Route stack, so bad stuff there can end up here) 01080 if (event->message()->exists(h_Routes) && 01081 !event->message()->header(h_Routes).empty() && 01082 event->message()->header(h_Routes).front().isWellFormed() && 01083 !event->message()->header(h_Routes).front().uri().exists(p_lr)) 01084 { 01085 Helper::processStrictRoute(*toSend); 01086 sendUsingOutboundIfAppropriate(*userProfile, toSend); 01087 } 01088 else 01089 { 01090 sendUsingOutboundIfAppropriate(*userProfile, toSend); 01091 } 01092 } 01093 else 01094 { 01095 sendResponse(*event->message()); 01096 } 01097 } 01098 } 01099 01100 void 01101 DialogUsageManager::sendUsingOutboundIfAppropriate(UserProfile& userProfile, auto_ptr<SipMessage> msg) 01102 { 01103 //a little inefficient, branch parameter might be better 01104 DialogId id(*msg); 01105 if (userProfile.hasOutboundProxy() && 01106 (!findDialog(id) || userProfile.getForceOutboundProxyOnAllRequestsEnabled())) 01107 { 01108 DebugLog ( << "Using outbound proxy: " 01109 << userProfile.getOutboundProxy().uri() 01110 << " -> " << msg->brief()); 01111 01112 if (userProfile.getExpressOutboundAsRouteSetEnabled()) 01113 { 01114 // prepend the outbound proxy to the service route 01115 msg->header(h_Routes).push_front(NameAddr(userProfile.getOutboundProxy().uri())); 01116 if(userProfile.clientOutboundEnabled() && userProfile.mClientOutboundFlowTuple.mFlowKey != 0) 01117 { 01118 DebugLog ( << "Sending with client outbound flow tuple to express outbound" ); 01119 DebugLog ( << "Flow Tuple: " << userProfile.mClientOutboundFlowTuple << " and key: " << userProfile.mClientOutboundFlowTuple.mFlowKey); 01120 mStack.sendTo(msg, userProfile.mClientOutboundFlowTuple, this); 01121 } 01122 else 01123 { 01124 DebugLog ( << "Sending to express outbound w/o flow tuple"); 01125 mStack.send(msg, this); 01126 } 01127 } 01128 else 01129 { 01130 if(userProfile.clientOutboundEnabled() && userProfile.mClientOutboundFlowTuple.mFlowKey != 0) 01131 { 01132 DebugLog ( << "Sending to outbound (no express) with flow tuple"); 01133 mStack.sendTo(msg, userProfile.mClientOutboundFlowTuple, this); 01134 } 01135 else 01136 { 01137 DebugLog ( << "Sending to outbound uri"); 01138 mStack.sendTo(msg, userProfile.getOutboundProxy().uri(), this); 01139 } 01140 } 01141 } 01142 else 01143 { 01144 DebugLog (<< "Send: " << msg->brief()); 01145 if(userProfile.clientOutboundEnabled() && userProfile.mClientOutboundFlowTuple.mFlowKey != 0) 01146 { 01147 mStack.sendTo(msg, userProfile.mClientOutboundFlowTuple, this); 01148 } 01149 else 01150 { 01151 mStack.send(msg, this); 01152 } 01153 } 01154 } 01155 01156 01157 void 01158 DialogUsageManager::end(DialogSetId setid) 01159 { 01160 DialogSet* ds = findDialogSet(setid); 01161 if (ds == 0) 01162 { 01163 throw Exception("Request no longer exists", __FILE__, __LINE__); 01164 } 01165 else 01166 { 01167 ds->end(); 01168 } 01169 } 01170 01171 void 01172 DialogUsageManager::destroy(const BaseUsage* usage) 01173 { 01174 if (mShutdownState != Destroying) 01175 { 01176 post(new DestroyUsage(usage->mHandle)); 01177 } 01178 else 01179 { 01180 InfoLog(<< "DialogUsageManager::destroy() not posting to stack"); 01181 } 01182 } 01183 01184 void 01185 DialogUsageManager::destroy(DialogSet* dset) 01186 { 01187 if (mShutdownState != Destroying) 01188 { 01189 post(new DestroyUsage(dset)); 01190 } 01191 else 01192 { 01193 InfoLog(<< "DialogUsageManager::destroy() not posting to stack"); 01194 } 01195 } 01196 01197 void 01198 DialogUsageManager::destroy(Dialog* d) 01199 { 01200 if (mShutdownState != Destroying) 01201 { 01202 post(new DestroyUsage(d)); 01203 } 01204 else 01205 { 01206 InfoLog(<< "DialogUsageManager::destroy() not posting to stack"); 01207 } 01208 } 01209 01210 01211 Dialog* 01212 DialogUsageManager::findDialog(const DialogId& id) 01213 { 01214 DialogSet* ds = findDialogSet(id.getDialogSetId()); 01215 if (ds) 01216 { 01217 return ds->findDialog(id); 01218 } 01219 else 01220 { 01221 return 0; 01222 } 01223 } 01224 01225 01226 InviteSessionHandle 01227 DialogUsageManager::findInviteSession(DialogId id) 01228 { 01229 Dialog* dialog = findDialog(id); 01230 if (dialog && dialog->mInviteSession) 01231 { 01232 return dialog->mInviteSession->getSessionHandle(); 01233 } 01234 01235 return InviteSessionHandle::NotValid(); 01236 } 01237 01238 pair<InviteSessionHandle, int> 01239 DialogUsageManager::findInviteSession(CallId replaces) 01240 { 01241 //486/481/603 decision making logic where? App may not wish to keep track of 01242 //invitesession state 01243 //Logic is here for now. 01244 InviteSessionHandle is = findInviteSession(DialogId(replaces.value(), 01245 replaces.param(p_toTag), 01246 replaces.param(p_fromTag))); 01247 int ErrorStatusCode = 481; // Call/Transaction Does Not Exist 01248 01249 // If we matched a session - Do RFC3891 Section 3 Processing 01250 if(is.isValid()) 01251 { 01252 // Note some missing checks are: 01253 // 1. If the Replaces header field matches more than one dialog, the UA must act as 01254 // if no match was found 01255 // 2. Verify that the initiator of the new Invite is authorized 01256 if(is->isTerminated()) 01257 { 01258 ErrorStatusCode = 603; // Declined 01259 is = InviteSessionHandle::NotValid(); 01260 } 01261 else if(is->isConnected()) 01262 { 01263 // Check if early-only flag is present in replaces header 01264 if(replaces.exists(p_earlyOnly)) 01265 { 01266 ErrorStatusCode = 486; // Busy Here 01267 is = InviteSessionHandle::NotValid(); 01268 } 01269 } 01270 else if(!is->isEarly()) 01271 { 01272 // replaces can't be used on early dialogs that were not initiated by this UA - ie. InviteSession::Proceeding state 01273 ErrorStatusCode = 481; // Call/Transaction Does Not Exist 01274 is = InviteSessionHandle::NotValid(); 01275 } 01276 } 01277 return make_pair(is, ErrorStatusCode); 01278 } 01279 01280 AppDialogHandle DialogUsageManager::findAppDialog(const DialogId& id) 01281 { 01282 Dialog* pDialog = findDialog(id); 01283 01284 if(pDialog && pDialog->mAppDialog) 01285 { 01286 return pDialog->mAppDialog->getHandle(); 01287 } 01288 01289 // Return an invalid handle 01290 return AppDialogHandle(); 01291 } 01292 01293 AppDialogSetHandle DialogUsageManager::findAppDialogSet(const DialogSetId& id) 01294 { 01295 DialogSet* pDialogSet = findDialogSet(id); 01296 01297 if(pDialogSet && pDialogSet->mAppDialogSet) 01298 { 01299 return pDialogSet->mAppDialogSet->getHandle(); 01300 } 01301 01302 // Return an invalid handle 01303 return AppDialogSetHandle(); 01304 } 01305 01306 void 01307 DialogUsageManager::internalProcess(std::auto_ptr<Message> msg) 01308 { 01309 #ifdef RESIP_DUM_THREAD_DEBUG 01310 if(!mThreadDebugKey) 01311 { 01312 // .bwc. Probably means multiple threads are trying to give DUM cycles 01313 // simultaneously. 01314 assert(!mHiddenThreadDebugKey); 01315 // No d'tor needed, since we're just going to use a pointer to this. 01316 if(!ThreadIf::tlsKeyCreate(mThreadDebugKey, 0)) 01317 { 01318 // .bwc. We really could pass anything here, but for the sake of 01319 // passing a valid pointer, I have (completely arbitrarily) chosen a 01320 // pointer to the DUM. All that matters is that this value is non-null 01321 ThreadIf::tlsSetValue(mThreadDebugKey, this); 01322 } 01323 else 01324 { 01325 ErrLog(<< "ThreadIf::tlsKeyCreate() failed!"); 01326 } 01327 } 01328 #endif 01329 01330 threadCheck(); 01331 01332 // After a Stack ShutdownMessage has been received, don't do anything else in dum 01333 if (mShutdownState == Shutdown) 01334 { 01335 return; 01336 } 01337 01338 { 01339 TransactionUserMessage* tuMsg = dynamic_cast<TransactionUserMessage*>(msg.get()); 01340 if (tuMsg) 01341 { 01342 InfoLog (<< "TU unregistered "); 01343 assert(mShutdownState == RemovingTransactionUser); 01344 assert(tuMsg->type() == TransactionUserMessage::TransactionUserRemoved); 01345 mShutdownState = Shutdown; 01346 if (mDumShutdownHandler) 01347 { 01348 mDumShutdownHandler->onDumCanBeDeleted(); 01349 mDumShutdownHandler = 0; // prevent mDumShutdownHandler getting called more than once 01350 } 01351 return; 01352 } 01353 } 01354 01355 { 01356 KeepAlivePong* pong = dynamic_cast<KeepAlivePong*>(msg.get()); 01357 if (pong) 01358 { 01359 DebugLog(<< "keepalive pong received from " << pong->getFlow()); 01360 if (mKeepAliveManager.get()) 01361 { 01362 mKeepAliveManager->receivedPong(pong->getFlow()); 01363 } 01364 return; 01365 } 01366 } 01367 01368 { 01369 DestroyUsage* destroyUsage = dynamic_cast<DestroyUsage*>(msg.get()); 01370 if (destroyUsage) 01371 { 01372 //DebugLog(<< "Destroying usage" ); 01373 destroyUsage->destroy(); 01374 return; 01375 } 01376 } 01377 01378 { 01379 DumTimeout* dumMsg = dynamic_cast<DumTimeout*>(msg.get()); 01380 if (dumMsg) 01381 { 01382 //DebugLog(<< "Timeout Message" ); 01383 if (!dumMsg->getBaseUsage().isValid()) 01384 { 01385 return; 01386 } 01387 dumMsg->getBaseUsage()->dispatch(*dumMsg); 01388 return; 01389 } 01390 } 01391 01392 { 01393 KeepAliveTimeout* keepAliveMsg = dynamic_cast<KeepAliveTimeout*>(msg.get()); 01394 if (keepAliveMsg) 01395 { 01396 //DebugLog(<< "Keep Alive Message" ); 01397 if (mKeepAliveManager.get()) 01398 { 01399 mKeepAliveManager->process(*keepAliveMsg); 01400 } 01401 return; 01402 } 01403 } 01404 01405 { 01406 KeepAlivePongTimeout* keepAlivePongMsg = dynamic_cast<KeepAlivePongTimeout*>(msg.get()); 01407 if (keepAlivePongMsg) 01408 { 01409 //DebugLog(<< "Keep Alive Pong Message" ); 01410 if (mKeepAliveManager.get()) 01411 { 01412 mKeepAliveManager->process(*keepAlivePongMsg); 01413 } 01414 return; 01415 } 01416 } 01417 01418 { 01419 ConnectionTerminated* terminated = dynamic_cast<ConnectionTerminated*>(msg.get()); 01420 if (terminated) 01421 { 01422 // Notify all dialogSets, in case they need to react (ie. client outbound support) 01423 // First find all applicable dialogsets, since flow token in user profile will 01424 // be cleared by first dialogset we notify, then notify all dialogset's 01425 std::list<DialogSet*> dialogSetsToNotify; 01426 DialogSetMap::iterator it = mDialogSetMap.begin(); 01427 for(; it != mDialogSetMap.end(); it++) 01428 { 01429 if(it->second->mUserProfile->clientOutboundEnabled() && 01430 it->second->mUserProfile->getClientOutboundFlowTuple().mFlowKey == terminated->getFlow().mFlowKey && // Flow key is not part of Tuple operator=, check it first 01431 it->second->mUserProfile->getClientOutboundFlowTuple() == terminated->getFlow()) 01432 { 01433 if(it->second->getClientRegistration().isValid()) 01434 { 01435 // ensure client registrations are notified first 01436 dialogSetsToNotify.push_front(it->second); 01437 } 01438 else 01439 { 01440 dialogSetsToNotify.push_back(it->second); 01441 } 01442 } 01443 } 01444 // Now dispatch notification to all dialogsets found above 01445 std::list<DialogSet*>::iterator it2 = dialogSetsToNotify.begin(); 01446 for(; it2 != dialogSetsToNotify.end();it2++) 01447 { 01448 (*it2)->flowTerminated(terminated->getFlow()); 01449 } 01450 01451 DebugLog(<< "connection terminated message"); 01452 if (mConnectionTerminatedEventDispatcher.dispatch(msg.get())) 01453 { 01454 msg.release(); 01455 } 01456 return; 01457 } 01458 } 01459 01460 { 01461 DumCommand* command = dynamic_cast<DumCommand*>(msg.get()); 01462 if (command) 01463 { 01464 //DebugLog(<< "DumCommand" ); 01465 command->executeCommand(); 01466 return; 01467 } 01468 } 01469 01470 { 01471 ExternalMessageBase* externalMessage = dynamic_cast<ExternalMessageBase*>(msg.get()); 01472 if (externalMessage) 01473 { 01474 processExternalMessage(externalMessage); 01475 return; 01476 } 01477 } 01478 01479 incomingProcess(msg); 01480 } 01481 01482 void 01483 DialogUsageManager::processExternalMessage(ExternalMessageBase* externalMessage) 01484 { 01485 bool handled = false; 01486 for(std::vector<ExternalMessageHandler*>::iterator i = mExternalMessageHandlers.begin(); 01487 i != mExternalMessageHandlers.end(); ++i) 01488 { 01489 (*i)->onMessage(externalMessage, handled); 01490 if (handled) 01491 { 01492 break; 01493 } 01494 } 01495 } 01496 01497 void 01498 DialogUsageManager::incomingProcess(std::auto_ptr<Message> msg) 01499 { 01500 //call or create feature chain if appropriate 01501 Data tid = Data::Empty; 01502 { 01503 SipMessage* sipMsg = dynamic_cast<SipMessage*>(msg.get()); 01504 if (sipMsg) 01505 { 01506 tid = sipMsg->getTransactionId(); 01507 bool garbage=false; 01508 Data reason; 01509 01510 if(!sipMsg->header(h_From).isWellFormed()) 01511 { 01512 garbage=true; 01513 reason.append("Malformed From, ",16); 01514 } 01515 01516 if(!sipMsg->header(h_To).isWellFormed()) 01517 { 01518 garbage=true; 01519 reason.append("Malformed To, ",14); 01520 } 01521 01522 if(!sipMsg->header(h_CallId).isWellFormed()) 01523 { 01524 garbage=true; 01525 reason.append("Malformed Call-Id, ",19); 01526 } 01527 01528 if(garbage) 01529 { 01530 if(sipMsg->isRequest() && sipMsg->method()!=ACK) 01531 { 01532 // .bwc. Either we need to trim the last comma off, or make this 01533 // a proper sentence fragment. This is more fun. 01534 reason.append("fix your code!",14); 01535 SipMessage failure; 01536 makeResponse(failure, *sipMsg, 400, reason); 01537 sendResponse(failure); 01538 } 01539 01540 InfoLog (<< "Malformed header in message (" << reason << ") - rejecting/discarding: " << *sipMsg); 01541 01542 // .bwc. Only forge a response when appropriate, but return in any 01543 // case. 01544 return; 01545 } 01546 } 01547 01548 DumFeatureMessage* featureMsg = dynamic_cast<DumFeatureMessage*>(msg.get()); 01549 if (featureMsg) 01550 { 01551 //DebugLog(<<"Got a DumFeatureMessage" << featureMsg); 01552 tid = featureMsg->getTransactionId(); 01553 } 01554 } 01555 if (tid != Data::Empty && !mIncomingFeatureList.empty()) 01556 { 01557 FeatureChainMap::iterator it; 01558 //efficiently find or create FeatureChain, should prob. be a utility template 01559 { 01560 FeatureChainMap::iterator lb = mIncomingFeatureChainMap.lower_bound(tid); 01561 if (lb != mIncomingFeatureChainMap.end() && !(mIncomingFeatureChainMap.key_comp()(tid, lb->first))) 01562 { 01563 it = lb; 01564 } 01565 else 01566 { 01567 assert(dynamic_cast<SipMessage*>(msg.get())); 01568 it = mIncomingFeatureChainMap.insert(lb, FeatureChainMap::value_type(tid, new DumFeatureChain(*this, mIncomingFeatureList, *mIncomingTarget))); 01569 } 01570 } 01571 01572 DumFeatureChain::ProcessingResult res = it->second->process(msg.get()); 01573 01574 if (res & DumFeatureChain::ChainDoneBit) 01575 { 01576 delete it->second; 01577 mIncomingFeatureChainMap.erase(it); 01578 //DebugLog(<< "feature chain deleted" << endl); 01579 } 01580 01581 if (res & DumFeatureChain::EventTakenBit) 01582 { 01583 msg.release(); 01584 //DebugLog(<< "event taken"); 01585 return; 01586 } 01587 } 01588 01589 try 01590 { 01591 InfoLog (<< "Got: " << msg->brief()); 01592 DumDecrypted* decryptedMsg = dynamic_cast<DumDecrypted*>(msg.get()); 01593 SipMessage* sipMsg = 0; 01594 if (decryptedMsg) 01595 { 01596 sipMsg = decryptedMsg->decrypted(); 01597 } 01598 else 01599 { 01600 sipMsg = dynamic_cast<SipMessage*>(msg.get()); 01601 } 01602 01603 if (sipMsg) 01604 { 01605 //DebugLog ( << "DialogUsageManager::process: " << sipMsg->brief()); 01606 if (sipMsg->isRequest()) 01607 { 01608 // Validate Request URI 01609 if( !validateRequestURI(*sipMsg) ) 01610 { 01611 DebugLog (<< "Failed RequestURI validation " << *sipMsg); 01612 return; 01613 } 01614 01615 // Continue validation on all requests, except ACK and CANCEL 01616 if(sipMsg->header(h_RequestLine).method() != ACK && 01617 sipMsg->header(h_RequestLine).method() != CANCEL) 01618 { 01619 if( !validateRequiredOptions(*sipMsg) ) 01620 { 01621 DebugLog (<< "Failed required options validation " << *sipMsg); 01622 return; 01623 } 01624 if( !validate100RelSuport(*sipMsg) ) 01625 { 01626 DebugLog (<< "Remote party does not support 100rel " << *sipMsg); 01627 return; 01628 } 01629 if( getMasterProfile()->validateContentEnabled() && !validateContent(*sipMsg) ) 01630 { 01631 DebugLog (<< "Failed content validation " << *sipMsg); 01632 return; 01633 } 01634 if( getMasterProfile()->validateAcceptEnabled() && !validateAccept(*sipMsg) ) 01635 { 01636 DebugLog (<< "Failed accept validation " << *sipMsg); 01637 return; 01638 } 01639 } 01640 if (sipMsg->header(h_From).exists(p_tag)) 01641 { 01642 if (mergeRequest(*sipMsg) ) 01643 { 01644 InfoLog (<< "Merged request: " << *sipMsg); 01645 return; 01646 } 01647 } 01648 processRequest(*sipMsg); 01649 } 01650 else 01651 { 01652 processResponse(*sipMsg); 01653 } 01654 } 01655 } 01656 catch(BaseException& e) 01657 { 01658 //unparseable, bad 403 w/ 2543 trans it from FWD, etc 01659 ErrLog(<<"Illegal message rejected: " << e.getMessage()); 01660 } 01661 } 01662 01663 bool 01664 DialogUsageManager::hasEvents() const 01665 { 01666 return mFifo.messageAvailable(); 01667 } 01668 01669 // return true if there is more to do 01670 bool 01671 DialogUsageManager::process(resip::Lockable* mutex) 01672 { 01673 if (mFifo.messageAvailable()) 01674 { 01675 resip::PtrLock lock(mutex); 01676 #ifdef RESIP_DUM_THREAD_DEBUG 01677 mThreadDebugKey=mHiddenThreadDebugKey; 01678 #endif 01679 internalProcess(std::auto_ptr<Message>(mFifo.getNext())); 01680 #ifdef RESIP_DUM_THREAD_DEBUG 01681 // .bwc. Thread checking is disabled if mThreadDebugKey is 0; if the app 01682 // is using this mutex-locked process() call, we only enable thread- 01683 // checking while the mutex is locked. Accesses from another thread while 01684 // the mutex is not locked are probably intentional. However, if the app 01685 // accesses the DUM inappropriately anyway, we'll probably detect it if 01686 // it happens during the internalProcess() call. 01687 mHiddenThreadDebugKey=mThreadDebugKey; 01688 mThreadDebugKey=0; 01689 #endif 01690 } 01691 return mFifo.messageAvailable(); 01692 } 01693 01694 bool 01695 DialogUsageManager::process(int timeoutMs, resip::Lockable* mutex) 01696 { 01697 std::auto_ptr<Message> message; 01698 01699 if(timeoutMs == -1) 01700 { 01701 message.reset(mFifo.getNext()); 01702 } 01703 else 01704 { 01705 message.reset(mFifo.getNext(timeoutMs)); 01706 } 01707 if (message.get()) 01708 { 01709 resip::PtrLock lock(mutex); 01710 #ifdef RESIP_DUM_THREAD_DEBUG 01711 mThreadDebugKey=mHiddenThreadDebugKey; 01712 #endif 01713 internalProcess(message); 01714 #ifdef RESIP_DUM_THREAD_DEBUG 01715 // .bwc. Thread checking is disabled if mThreadDebugKey is 0; if the app 01716 // is using this mutex-locked process() call, we only enable thread- 01717 // checking while the mutex is locked. Accesses from another thread while 01718 // the mutex is not locked are probably intentional. However, if the app 01719 // accesses the DUM inappropriately anyway, we'll probably detect it if 01720 // it happens during the internalProcess() call. 01721 mHiddenThreadDebugKey=mThreadDebugKey; 01722 mThreadDebugKey=0; 01723 #endif 01724 } 01725 return mFifo.messageAvailable(); 01726 } 01727 01728 bool 01729 DialogUsageManager::validateRequestURI(const SipMessage& request) 01730 { 01731 // RFC3261 - 8.2.1 01732 if (!getMasterProfile()->isMethodSupported(request.header(h_RequestLine).getMethod())) 01733 { 01734 InfoLog (<< "Received an unsupported method: " << request.brief()); 01735 01736 SipMessage failure; 01737 makeResponse(failure, request, 405); 01738 failure.header(h_Allows) = getMasterProfile()->getAllowedMethods(); 01739 sendResponse(failure); 01740 01741 if(mRequestValidationHandler) 01742 mRequestValidationHandler->onInvalidMethod(request); 01743 01744 return false; 01745 } 01746 01747 // RFC3261 - 8.2.2 01748 if (!getMasterProfile()->isSchemeSupported(request.header(h_RequestLine).uri().scheme())) 01749 { 01750 InfoLog (<< "Received an unsupported scheme: " << request.brief()); 01751 SipMessage failure; 01752 makeResponse(failure, request, 416); 01753 sendResponse(failure); 01754 01755 if(mRequestValidationHandler) 01756 mRequestValidationHandler->onInvalidScheme(request); 01757 01758 return false; 01759 } 01760 01761 return true; 01762 } 01763 01764 01765 bool 01766 DialogUsageManager::validateRequiredOptions(const SipMessage& request) 01767 { 01768 // RFC 2162 - 8.2.2 01769 if(request.exists(h_Requires) && // Don't check requires if method is ACK or CANCEL 01770 (request.header(h_RequestLine).getMethod() != ACK || 01771 request.header(h_RequestLine).getMethod() != CANCEL)) 01772 { 01773 Tokens unsupported = getMasterProfile()->getUnsupportedOptionsTags(request.header(h_Requires)); 01774 if (!unsupported.empty()) 01775 { 01776 InfoLog (<< "Received an unsupported option tag(s): " << request.brief()); 01777 01778 SipMessage failure; 01779 makeResponse(failure, request, 420); 01780 failure.header(h_Unsupporteds) = unsupported; 01781 sendResponse(failure); 01782 01783 if(mRequestValidationHandler) 01784 mRequestValidationHandler->onInvalidRequiredOptions(request); 01785 01786 return false; 01787 } 01788 } 01789 01790 return true; 01791 } 01792 01793 01794 bool 01795 DialogUsageManager::validate100RelSuport(const SipMessage& request) 01796 { 01797 if(request.header(h_RequestLine).getMethod() == INVITE) 01798 { 01799 if (getMasterProfile()->getUasReliableProvisionalMode() == MasterProfile::Required) 01800 { 01801 if (!((request.exists(h_Requires) && request.header(h_Requires).find(Token(Symbols::C100rel))) 01802 || (request.exists(h_Supporteds) && request.header(h_Supporteds).find(Token(Symbols::C100rel))))) 01803 { 01804 SipMessage failure; 01805 makeResponse(failure, request, 421); 01806 failure.header(h_Requires).push_back(Token(Symbols::C100rel)); 01807 sendResponse(failure); 01808 01809 if(mRequestValidationHandler) 01810 mRequestValidationHandler->on100RelNotSupportedByRemote(request); 01811 01812 return false; 01813 } 01814 } 01815 } 01816 return true; 01817 } 01818 01819 bool 01820 DialogUsageManager::validateContent(const SipMessage& request) 01821 { 01822 // RFC3261 - 8.2.3 01823 // Don't need to validate content headers if they are specified as optional in the content-disposition 01824 if (!(request.exists(h_ContentDisposition) && 01825 request.header(h_ContentDisposition).isWellFormed() && 01826 request.header(h_ContentDisposition).exists(p_handling) && 01827 isEqualNoCase(request.header(h_ContentDisposition).param(p_handling), Symbols::Optional))) 01828 { 01829 if (request.exists(h_ContentType) && !getMasterProfile()->isMimeTypeSupported(request.header(h_RequestLine).method(), request.header(h_ContentType))) 01830 { 01831 InfoLog (<< "Received an unsupported mime type: " << request.header(h_ContentType) << " for " << request.brief()); 01832 01833 SipMessage failure; 01834 makeResponse(failure, request, 415); 01835 failure.header(h_Accepts) = getMasterProfile()->getSupportedMimeTypes(request.header(h_RequestLine).method()); 01836 sendResponse(failure); 01837 01838 if(mRequestValidationHandler) 01839 mRequestValidationHandler->onInvalidContentType(request); 01840 01841 return false; 01842 } 01843 01844 if (request.exists(h_ContentEncoding) && !getMasterProfile()->isContentEncodingSupported(request.header(h_ContentEncoding))) 01845 { 01846 InfoLog (<< "Received an unsupported mime type: " << request.header(h_ContentEncoding) << " for " << request.brief()); 01847 SipMessage failure; 01848 makeResponse(failure, request, 415); 01849 failure.header(h_AcceptEncodings) = getMasterProfile()->getSupportedEncodings(); 01850 sendResponse(failure); 01851 01852 if(mRequestValidationHandler) 01853 mRequestValidationHandler->onInvalidContentEncoding(request); 01854 01855 return false; 01856 } 01857 01858 if (getMasterProfile()->validateContentLanguageEnabled() && 01859 request.exists(h_ContentLanguages) && !getMasterProfile()->isLanguageSupported(request.header(h_ContentLanguages))) 01860 { 01861 InfoLog (<< "Received an unsupported language: " << request.header(h_ContentLanguages).front() << " for " << request.brief()); 01862 01863 SipMessage failure; 01864 makeResponse(failure, request, 415); 01865 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 01866 sendResponse(failure); 01867 01868 if(mRequestValidationHandler) 01869 mRequestValidationHandler->onInvalidContentLanguage(request); 01870 01871 return false; 01872 } 01873 } 01874 01875 return true; 01876 } 01877 01878 bool 01879 DialogUsageManager::validateAccept(const SipMessage& request) 01880 { 01881 MethodTypes method = request.header(h_RequestLine).method(); 01882 // checks for Accept to comply with SFTF test case 216 01883 if(request.exists(h_Accepts)) 01884 { 01885 for (Mimes::const_iterator i = request.header(h_Accepts).begin(); 01886 i != request.header(h_Accepts).end(); i++) 01887 { 01888 if (getMasterProfile()->isMimeTypeSupported(method, *i)) 01889 { 01890 return true; // Accept header passes validation if we support as least one of the mime types 01891 } 01892 } 01893 } 01894 // If no Accept header then application/sdp should be assumed for certain methods 01895 else if(method == INVITE || 01896 method == OPTIONS || 01897 method == PRACK || 01898 method == UPDATE) 01899 { 01900 if (getMasterProfile()->isMimeTypeSupported(request.header(h_RequestLine).method(), Mime("application", "sdp"))) 01901 { 01902 return true; 01903 } 01904 } 01905 else 01906 { 01907 // Other method without an Accept Header 01908 return true; 01909 } 01910 01911 InfoLog (<< "Received unsupported mime types in accept header: " << request.brief()); 01912 SipMessage failure; 01913 makeResponse(failure, request, 406); 01914 failure.header(h_Accepts) = getMasterProfile()->getSupportedMimeTypes(method); 01915 sendResponse(failure); 01916 01917 if(mRequestValidationHandler) 01918 mRequestValidationHandler->onInvalidAccept(request); 01919 01920 return false; 01921 } 01922 01923 bool 01924 DialogUsageManager::mergeRequest(const SipMessage& request) 01925 { 01926 assert(request.isRequest()); 01927 assert(request.isExternal()); 01928 01929 if (!request.header(h_To).exists(p_tag)) 01930 { 01931 if (mMergedRequests.count(MergedRequestKey(request, getMasterProfile()->checkReqUriInMergeDetectionEnabled()))) 01932 { 01933 SipMessage failure; 01934 makeResponse(failure, request, 482, "Merged Request"); 01935 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 01936 sendResponse(failure); 01937 return true; 01938 } 01939 } 01940 01941 return false; 01942 } 01943 01944 void 01945 DialogUsageManager::processRequest(const SipMessage& request) 01946 { 01947 DebugLog ( << "DialogUsageManager::processRequest: " << request.brief()); 01948 01949 if (mShutdownState != Running && mShutdownState != ShutdownRequested) 01950 { 01951 WarningLog (<< "Ignoring a request since we are shutting down " << request.brief()); 01952 01953 SipMessage failure; 01954 makeResponse(failure, request, 480, "UAS is shutting down"); 01955 sendResponse(failure); 01956 return; 01957 } 01958 01959 if (request.header(h_RequestLine).method() == PUBLISH) 01960 { 01961 processPublish(request); 01962 return; 01963 } 01964 01965 bool toTag = request.header(h_To).exists(p_tag); 01966 if(request.header(h_RequestLine).getMethod() == REGISTER && toTag && getMasterProfile()->allowBadRegistrationEnabled()) 01967 { 01968 toTag = false; 01969 } 01970 01971 assert(mAppDialogSetFactory.get()); 01972 // !jf! note, the logic was reversed during ye great merge of March of Ought 5 01973 if (toTag || 01974 findDialogSet(DialogSetId(request))) 01975 { 01976 switch (request.header(h_RequestLine).getMethod()) 01977 { 01978 case REGISTER: 01979 { 01980 SipMessage failure; 01981 makeResponse(failure, request, 400, "Registration requests can't have To: tags."); 01982 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 01983 sendResponse(failure); 01984 break; 01985 } 01986 01987 default: 01988 { 01989 DialogSet* ds = findDialogSet(DialogSetId(request)); 01990 if (ds == 0) 01991 { 01992 if (request.header(h_RequestLine).method() != ACK) 01993 { 01994 SipMessage failure; 01995 makeResponse(failure, request, 481); 01996 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 01997 InfoLog (<< "Rejected request (which was in a dialog) " << request.brief()); 01998 sendResponse(failure); 01999 } 02000 else 02001 { 02002 InfoLog (<< "ACK doesn't match any dialog" << request.brief()); 02003 } 02004 } 02005 else 02006 { 02007 InfoLog (<< "Handling in-dialog request: " << request.brief()); 02008 ds->dispatch(request); 02009 } 02010 } 02011 } 02012 } 02013 else 02014 { 02015 switch (request.header(h_RequestLine).getMethod()) 02016 { 02017 case ACK: 02018 DebugLog (<< "Discarding request: " << request.brief()); 02019 break; 02020 02021 case PRACK: 02022 case BYE: 02023 case UPDATE: 02024 case INFO: // !rm! in an ideal world 02025 { 02026 SipMessage failure; 02027 makeResponse(failure, request, 481); 02028 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 02029 sendResponse(failure); 02030 break; 02031 } 02032 case CANCEL: 02033 { 02034 // find the appropropriate ServerInvSession 02035 CancelMap::iterator i = mCancelMap.find(request.getTransactionId()); 02036 if (i != mCancelMap.end()) 02037 { 02038 i->second->dispatch(request); 02039 } 02040 else 02041 { 02042 InfoLog (<< "Received a CANCEL on a non-existent transaction "); 02043 SipMessage failure; 02044 makeResponse(failure, request, 481); 02045 sendResponse(failure); 02046 } 02047 break; 02048 } 02049 case PUBLISH: 02050 assert(false); 02051 return; 02052 case SUBSCRIBE: 02053 if (!checkEventPackage(request)) 02054 { 02055 InfoLog (<< "Rejecting request (unsupported package) " 02056 << request.brief()); 02057 return; 02058 } 02059 /*FALLTHRU*/ 02060 case NOTIFY : // handle unsolicited (illegal) NOTIFYs 02061 case INVITE: // new INVITE 02062 case REFER: // out-of-dialog REFER 02063 //case INFO : // handle non-dialog (illegal) INFOs 02064 case OPTIONS : // handle non-dialog OPTIONS 02065 case MESSAGE : 02066 case REGISTER: 02067 { 02068 { 02069 DialogSetId id(request); 02070 //cryptographically dangerous 02071 if(mDialogSetMap.find(id) != mDialogSetMap.end()) 02072 { 02073 // this can only happen if someone sends us a request with the same callid and from tag as one 02074 // that is in the process of destroying - since this is bad endpoint behaviour - we will 02075 // reject the request with a 400 response 02076 SipMessage badrequest; 02077 makeResponse(badrequest, request, 400); 02078 badrequest.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 02079 sendResponse(badrequest); 02080 return; 02081 } 02082 } 02083 if (mDumShutdownHandler) 02084 { 02085 SipMessage forbidden; 02086 makeResponse(forbidden, request, 480); 02087 forbidden.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 02088 sendResponse(forbidden); 02089 return; 02090 } 02091 try 02092 { 02093 DialogSet* dset = new DialogSet(request, *this); 02094 02095 StackLog ( << "*********** Calling AppDialogSetFactory *************: " << dset->getId()); 02096 AppDialogSet* appDs = mAppDialogSetFactory->createAppDialogSet(*this, request); 02097 appDs->mDialogSet = dset; 02098 dset->setUserProfile(appDs->selectUASUserProfile(request)); 02099 dset->mAppDialogSet = appDs; 02100 02101 StackLog ( << "************* Adding DialogSet ***************: " << dset->getId()); 02102 //StackLog ( << "Before: " << Inserter(mDialogSetMap) ); 02103 mDialogSetMap[dset->getId()] = dset; 02104 StackLog ( << "DialogSetMap: " << InserterP(mDialogSetMap) ); 02105 02106 dset->dispatch(request); 02107 } 02108 catch (BaseException& e) 02109 { 02110 SipMessage failure; 02111 makeResponse(failure, request, 400, e.getMessage()); 02112 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages(); 02113 sendResponse(failure); 02114 } 02115 02116 break; 02117 } 02118 case RESPONSE: 02119 case SERVICE: 02120 assert(false); 02121 break; 02122 case UNKNOWN: 02123 case MAX_METHODS: 02124 assert(false); 02125 break; 02126 } 02127 } 02128 } 02129 02130 void 02131 DialogUsageManager::processResponse(const SipMessage& response) 02132 { 02133 if (response.header(h_CSeq).method() != CANCEL) 02134 { 02135 DialogSet* ds = findDialogSet(DialogSetId(response)); 02136 02137 if (ds) 02138 { 02139 DebugLog ( << "DialogUsageManager::processResponse: " << std::endl << std::endl << response.brief()); 02140 ds->dispatch(response); 02141 } 02142 else 02143 { 02144 InfoLog (<< "Throwing away stray response: " << std::endl << std::endl << response.brief()); 02145 } 02146 } 02147 } 02148 02149 void 02150 DialogUsageManager::processPublish(const SipMessage& request) 02151 { 02152 if (!checkEventPackage(request)) 02153 { 02154 InfoLog(<< "Rejecting request (unsupported package) " << request.brief()); 02155 return; 02156 } 02157 02158 if (request.exists(h_SIPIfMatch)) 02159 { 02160 ServerPublications::iterator i = mServerPublications.find(request.header(h_SIPIfMatch).value()); 02161 if (i != mServerPublications.end()) 02162 { 02163 i->second->dispatch(request); 02164 } 02165 else 02166 { 02167 SharedPtr<SipMessage> response(new SipMessage); 02168 makeResponse(*response, request, 412); 02169 send(response); 02170 } 02171 } 02172 else 02173 { 02174 Data etag = Random::getCryptoRandomHex(8); 02175 while (mServerPublications.find(etag) != mServerPublications.end()) 02176 { 02177 etag = Random::getCryptoRandomHex(8); 02178 } 02179 02180 if (request.getContents()) 02181 { 02182 ServerPublication* sp = new ServerPublication(*this, etag, request); 02183 mServerPublications[etag] = sp; 02184 sp->dispatch(request); 02185 } 02186 else 02187 { 02188 // per 3903 (sec 6.5), a PUB w/ no SIPIfMatch must have contents. .mjf. 02189 SharedPtr<SipMessage> response(new SipMessage); 02190 makeResponse(*response, request, 400); 02191 send(response); 02192 } 02193 } 02194 } 02195 02196 bool 02197 DialogUsageManager::checkEventPackage(const SipMessage& request) 02198 { 02199 int failureCode = 0; 02200 MethodTypes method = request.header(h_RequestLine).method(); 02201 02202 // || (method == NOTIFY && !request.exists(h_SubscriptionState))) 02203 02204 if (!request.exists(h_Event)) 02205 { 02206 InfoLog (<< "No Event header in " << request.header(h_RequestLine).unknownMethodName()); 02207 failureCode = 400; 02208 } 02209 else 02210 { 02211 switch(method) 02212 { 02213 case SUBSCRIBE: 02214 if (!getServerSubscriptionHandler(request.header(h_Event).value())) 02215 { 02216 InfoLog (<< "No handler for event package for SUBSCRIBE: " 02217 << request.header(h_Event).value()); 02218 failureCode = 489; 02219 } 02220 break; 02221 case NOTIFY: 02222 if (!getClientSubscriptionHandler(request.header(h_Event).value())) 02223 { 02224 InfoLog (<< "No handler for event package for NOTIFY: " 02225 << request.header(h_Event).value()); 02226 failureCode = 489; 02227 } 02228 break; 02229 case PUBLISH: 02230 if (!getServerPublicationHandler(request.header(h_Event).value())) 02231 { 02232 InfoLog (<< "No handler for event package for PUBLISH: " 02233 << request.header(h_Event).value()); 02234 failureCode = 489; 02235 } 02236 break; 02237 default: 02238 assert(0); 02239 } 02240 } 02241 02242 if (failureCode > 0) 02243 { 02244 SharedPtr<SipMessage> response(new SipMessage); 02245 makeResponse(*response, request, failureCode); 02246 send(response); 02247 return false; 02248 } 02249 return true; 02250 } 02251 02252 DialogSet* 02253 DialogUsageManager::findDialogSet(const DialogSetId& id) 02254 { 02255 threadCheck(); 02256 StackLog ( << "Looking for dialogSet: " << id << " in map:"); 02257 StackLog ( << "DialogSetMap: " << InserterP(mDialogSetMap) ); 02258 DialogSetMap::const_iterator it = mDialogSetMap.find(id); 02259 02260 if (it == mDialogSetMap.end()) 02261 { 02262 return 0; 02263 } 02264 else 02265 { 02266 if(it->second->isDestroying()) 02267 { 02268 return 0; 02269 } 02270 else 02271 { 02272 return it->second; 02273 } 02274 } 02275 } 02276 02277 BaseCreator* 02278 DialogUsageManager::findCreator(const DialogId& id) 02279 { 02280 DialogSet* ds = findDialogSet(id.getDialogSetId()); 02281 if (ds) 02282 { 02283 return ds->getCreator(); 02284 } 02285 else 02286 { 02287 return 0; 02288 } 02289 } 02290 02291 void 02292 DialogUsageManager::removeDialogSet(const DialogSetId& dsId) 02293 { 02294 StackLog ( << "************* Removing DialogSet ***************: " << dsId); 02295 //StackLog ( << "Before: " << Inserter(mDialogSetMap) ); 02296 mDialogSetMap.erase(dsId); 02297 StackLog ( << "DialogSetMap: " << InserterP(mDialogSetMap) ); 02298 if (mRedirectManager.get()) 02299 { 02300 mRedirectManager->removeDialogSet(dsId); 02301 } 02302 } 02303 02304 ClientSubscriptionHandler* 02305 DialogUsageManager::getClientSubscriptionHandler(const Data& eventType) 02306 { 02307 map<Data, ClientSubscriptionHandler*>::iterator res = mClientSubscriptionHandlers.find(eventType); 02308 if (res != mClientSubscriptionHandlers.end()) 02309 { 02310 return res->second; 02311 } 02312 else 02313 { 02314 return 0; 02315 } 02316 } 02317 02318 ServerSubscriptionHandler* 02319 DialogUsageManager::getServerSubscriptionHandler(const Data& eventType) 02320 { 02321 map<Data, ServerSubscriptionHandler*>::iterator res = mServerSubscriptionHandlers.find(eventType); 02322 if (res != mServerSubscriptionHandlers.end()) 02323 { 02324 return res->second; 02325 } 02326 else 02327 { 02328 return 0; 02329 } 02330 } 02331 02332 ClientPublicationHandler* 02333 DialogUsageManager::getClientPublicationHandler(const Data& eventType) 02334 { 02335 map<Data, ClientPublicationHandler*>::iterator res = mClientPublicationHandlers.find(eventType); 02336 if (res != mClientPublicationHandlers.end()) 02337 { 02338 return res->second; 02339 } 02340 else 02341 { 02342 return 0; 02343 } 02344 } 02345 02346 ServerPublicationHandler* 02347 DialogUsageManager::getServerPublicationHandler(const Data& eventType) 02348 { 02349 map<Data, ServerPublicationHandler*>::iterator res = mServerPublicationHandlers.find(eventType); 02350 if (res != mServerPublicationHandlers.end()) 02351 { 02352 return res->second; 02353 } 02354 else 02355 { 02356 return 0; 02357 } 02358 } 02359 02360 OutOfDialogHandler* 02361 DialogUsageManager::getOutOfDialogHandler(const MethodTypes type) 02362 { 02363 map<MethodTypes, OutOfDialogHandler*>::iterator res = mOutOfDialogHandlers.find(type); 02364 if (res != mOutOfDialogHandlers.end()) 02365 { 02366 return res->second; 02367 } 02368 else 02369 { 02370 return 0; 02371 } 02372 } 02373 02374 void 02375 DialogUsageManager::addIncomingFeature(resip::SharedPtr<DumFeature> feat) 02376 { 02377 mIncomingFeatureList.push_back(feat); 02378 } 02379 02380 void 02381 DialogUsageManager::addOutgoingFeature(resip::SharedPtr<DumFeature> feat) 02382 { 02383 // make sure EncryptionManager is the last feature in the list. 02384 mOutgoingFeatureList.insert(mOutgoingFeatureList.begin(), feat); 02385 } 02386 02387 void 02388 DialogUsageManager::setOutgoingMessageInterceptor(SharedPtr<DumFeature> feat) 02389 { 02390 mOutgoingMessageInterceptor = feat; 02391 } 02392 02393 void 02394 DialogUsageManager::applyToAllServerSubscriptions(ServerSubscriptionFunctor* functor) 02395 { 02396 assert(functor); 02397 for (DialogSetMap::iterator it = mDialogSetMap.begin(); it != mDialogSetMap.end(); ++it) 02398 { 02399 for (DialogSet::DialogMap::iterator i = it->second->mDialogs.begin(); i != it->second->mDialogs.end(); ++i) 02400 { 02401 std::vector<ServerSubscriptionHandle> serverSubs = i->second->getServerSubscriptions(); 02402 for (std::vector<ServerSubscriptionHandle>::iterator iss = serverSubs.begin(); iss != serverSubs.end(); ++iss) 02403 { 02404 functor->apply(*iss); 02405 } 02406 } 02407 } 02408 } 02409 02410 void 02411 DialogUsageManager::applyToAllClientSubscriptions(ClientSubscriptionFunctor* functor) 02412 { 02413 assert(functor); 02414 for (DialogSetMap::iterator it = mDialogSetMap.begin(); it != mDialogSetMap.end(); ++it) 02415 { 02416 for (DialogSet::DialogMap::iterator i = it->second->mDialogs.begin(); i != it->second->mDialogs.end(); ++i) 02417 { 02418 std::vector<ClientSubscriptionHandle> clientSubs = i->second->getClientSubscriptions(); 02419 for (std::vector<ClientSubscriptionHandle>::iterator ics = clientSubs.begin(); ics != clientSubs.end(); ++ics) 02420 { 02421 functor->apply(*ics); 02422 } 02423 } 02424 } 02425 } 02426 02427 void 02428 DialogUsageManager::registerForConnectionTermination(Postable* listener) 02429 { 02430 mConnectionTerminatedEventDispatcher.addListener(listener); 02431 } 02432 02433 void 02434 DialogUsageManager::unRegisterForConnectionTermination(Postable* listener) 02435 { 02436 mConnectionTerminatedEventDispatcher.removeListener(listener); 02437 } 02438 02439 void 02440 DialogUsageManager::requestMergedRequestRemoval(const MergedRequestKey& key) 02441 { 02442 DebugLog(<< "Got merged request removal request"); 02443 MergedRequestRemovalCommand command(*this, key); 02444 mStack.postMS(command, Timer::TF, this); 02445 } 02446 02447 void 02448 DialogUsageManager::removeMergedRequest(const MergedRequestKey& key) 02449 { 02450 DebugLog(<< "Merged request removed"); 02451 mMergedRequests.erase(key); 02452 } 02453 02454 TargetCommand::Target& 02455 DialogUsageManager::dumIncomingTarget() 02456 { 02457 return *mIncomingTarget; 02458 } 02459 02460 TargetCommand::Target& 02461 DialogUsageManager::dumOutgoingTarget() 02462 { 02463 return *mOutgoingTarget; 02464 } 02465 02466 DialogEventStateManager* 02467 DialogUsageManager::createDialogEventStateManager(DialogEventHandler* handler) 02468 { 02469 if(handler) 02470 { 02471 mDialogEventStateManager = new DialogEventStateManager(); 02472 mDialogEventStateManager->mDialogEventHandler = handler; 02473 } 02474 else 02475 { 02476 delete mDialogEventStateManager; 02477 mDialogEventStateManager=0; 02478 } 02479 return mDialogEventStateManager; 02480 } 02481 02482 02483 /* ==================================================================== 02484 * The Vovida Software License, Version 1.0 02485 * 02486 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 02487 * 02488 * Redistribution and use in source and binary forms, with or without 02489 * modification, are permitted provided that the following conditions 02490 * are met: 02491 * 02492 * 1. Redistributions of source code must retain the above copyright 02493 * notice, this list of conditions and the following disclaimer. 02494 * 02495 * 2. Redistributions in binary form must reproduce the above copyright 02496 * notice, this list of conditions and the following disclaimer in 02497 * the documentation and/or other materials provided with the 02498 * distribution. 02499 * 02500 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 02501 * and "Vovida Open Communication Application Library (VOCAL)" must 02502 * not be used to endorse or promote products derived from this 02503 * software without prior written permission. For written 02504 * permission, please contact vocal@vovida.org. 02505 * 02506 * 4. Products derived from this software may not be called "VOCAL", nor 02507 * may "VOCAL" appear in their name, without prior written 02508 * permission of Vovida Networks, Inc. 02509 * 02510 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 02511 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 02512 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 02513 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 02514 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 02515 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 02516 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 02517 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 02518 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 02519 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 02520 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 02521 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 02522 * DAMAGE. 02523 * 02524 * ==================================================================== 02525 * 02526 * This software consists of voluntary contributions made by Vovida 02527 * Networks, Inc. and many individuals on behalf of Vovida Networks, 02528 * Inc. For more information on Vovida Networks, Inc., please see 02529 * <http://www.vovida.org/>. 02530 * 02531 */
1.7.5.1