reSIProcate/DialogUsageManager  9680
DialogUsageManager.cxx
Go to the documentation of this file.
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  */