/[resiprocate]/main/resip/dum/DialogUsageManager.cxx
ViewVC logotype

Contents of /main/resip/dum/DialogUsageManager.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6160 - (show annotations) (download)
Tue Apr 18 20:17:30 2006 UTC (13 years, 9 months ago) by moetje
File MIME type: text/plain
File size: 60447 byte(s)
- made setOverrideHostAndPort effective also for UAS situations as discussed on the list
- corrected my previous checkin to use spaces instead of tabs

1 #include "resip/stack/Security.hxx"
2 #include "resip/stack/SecurityAttributes.hxx"
3 #include "resip/stack/ShutdownMessage.hxx"
4 #include "resip/stack/SipFrag.hxx"
5 #include "resip/stack/SipMessage.hxx"
6 #include "resip/stack/SipStack.hxx"
7 #include "resip/stack/Helper.hxx"
8 #include "resip/stack/TransactionUserMessage.hxx"
9 #include "resip/stack/ConnectionTerminated.hxx"
10 #include "resip/dum/AppDialog.hxx"
11 #include "resip/dum/AppDialogSet.hxx"
12 #include "resip/dum/AppDialogSetFactory.hxx"
13 #include "resip/dum/BaseUsage.hxx"
14 #include "resip/dum/ClientAuthManager.hxx"
15 #include "resip/dum/ClientInviteSession.hxx"
16 #include "resip/dum/ClientOutOfDialogReq.hxx"
17 #include "resip/dum/ClientPublication.hxx"
18 #include "resip/dum/ClientRegistration.hxx"
19 #include "resip/dum/ClientSubscription.hxx"
20 #include "resip/dum/DefaultServerReferHandler.hxx"
21 #include "resip/dum/DestroyUsage.hxx"
22 #include "resip/dum/Dialog.hxx"
23 #include "resip/dum/DialogUsageManager.hxx"
24 #include "resip/dum/ClientPagerMessage.hxx"
25 #include "resip/dum/DumException.hxx"
26 #include "resip/dum/DumShutdownHandler.hxx"
27 #include "resip/dum/DumFeatureMessage.hxx"
28 #include "resip/dum/InviteSessionCreator.hxx"
29 #include "resip/dum/InviteSessionHandler.hxx"
30 #include "resip/dum/KeepAliveManager.hxx"
31 #include "resip/dum/KeepAliveTimeout.hxx"
32 #include "resip/dum/MasterProfile.hxx"
33 #include "resip/dum/OutOfDialogReqCreator.hxx"
34 #include "resip/dum/PagerMessageCreator.hxx"
35 #include "resip/dum/PublicationCreator.hxx"
36 #include "resip/dum/RedirectManager.hxx"
37 #include "resip/dum/RegistrationCreator.hxx"
38 #include "resip/dum/ServerAuthManager.hxx"
39 #include "resip/dum/ServerInviteSession.hxx"
40 #include "resip/dum/ServerPublication.hxx"
41 #include "resip/dum/ServerSubscription.hxx"
42 #include "resip/dum/SubscriptionCreator.hxx"
43 #include "resip/dum/SubscriptionHandler.hxx"
44 #include "resip/dum/UserAuthInfo.hxx"
45 #include "resip/dum/DumFeature.hxx"
46 #include "resip/dum/EncryptionManager.hxx"
47 #include "resip/dum/IdentityHandler.hxx"
48 #include "resip/dum/DumDecrypted.hxx"
49 #include "resip/dum/CertMessage.hxx"
50 #include "resip/dum/OutgoingEvent.hxx"
51 #include "resip/dum/DumHelper.hxx"
52 #include "resip/dum/MergedRequestRemovalCommand.hxx"
53 #include "rutil/Inserter.hxx"
54 #include "rutil/Logger.hxx"
55 #include "rutil/Random.hxx"
56 #include "rutil/WinLeakCheck.hxx"
57 #include "rutil/Timer.hxx"
58
59 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
60
61 using namespace resip;
62 using namespace std;
63
64 DialogUsageManager::DialogUsageManager(SipStack& stack, bool createDefaultFeatures) :
65 TransactionUser(TransactionUser::DoNotRegisterForTransactionTermination, TransactionUser::RegisterForConnectionTermination),
66 mRedirectManager(new RedirectManager()),
67 mInviteSessionHandler(0),
68 mClientRegistrationHandler(0),
69 mServerRegistrationHandler(0),
70 mRedirectHandler(0),
71 mDialogSetHandler(0),
72 mRegistrationPersistenceManager(0),
73 mIsDefaultServerReferHandler(true),
74 mClientPagerMessageHandler(0),
75 mServerPagerMessageHandler(0),
76 mAppDialogSetFactory(new AppDialogSetFactory()),
77 mStack(stack),
78 mDumShutdownHandler(0),
79 mShutdownState(Running)
80 {
81 //TODO -- create default features
82 mStack.registerTransactionUser(*this);
83 addServerSubscriptionHandler("refer", new DefaultServerReferHandler());
84
85 mIncomingTarget = new IncomingTarget(*this);
86 mOutgoingTarget = new OutgoingTarget(*this);
87
88 if (createDefaultFeatures)
89 {
90 SharedPtr<IdentityHandler> identity = SharedPtr<IdentityHandler>(new IdentityHandler(*this, *mIncomingTarget));
91
92 #if defined (USE_SSL)
93 SharedPtr<EncryptionManager> encryptionIncoming = SharedPtr<EncryptionManager>(new EncryptionManager(*this, *mIncomingTarget));
94 SharedPtr<EncryptionManager> encryptionOutgoing = SharedPtr<EncryptionManager>(new EncryptionManager(*this, *mOutgoingTarget));
95 #endif
96
97 // default incoming features.
98 addIncomingFeature(identity);
99 #if defined (USE_SSL)
100 addIncomingFeature(encryptionIncoming);
101 #endif
102
103 // default outgoing features.
104 #if defined (USE_SSL)
105 addOutgoingFeature(encryptionOutgoing);
106 #endif
107
108 }
109
110 }
111
112 DialogUsageManager::~DialogUsageManager()
113 {
114 mShutdownState = Destroying;
115 //InfoLog ( << "~DialogUsageManager" );
116
117 #if(0)
118 // !kh!
119 DialogSetMap::iterator dialogSet = mDialogSetMap.begin();
120 for (; dialogSet != mDialogSetMap.end(); ++dialogSet)
121 {
122 delete dialogSet->second;
123 }
124 #endif
125 if(!mDialogSetMap.empty())
126 {
127 DebugLog(<< "DialogUsageManager::mDialogSetMap has " << mDialogSetMap.size() << " DialogSets");
128 DialogSetMap::const_iterator ds = mDialogSetMap.begin();
129 for(; ds != mDialogSetMap.end(); ++ds)
130 {
131 DebugLog(<< "DialgSetId:" << ds->first);
132 DialogSet::DialogMap::const_iterator d = ds->second->mDialogs.begin();
133 for(; d != ds->second->mDialogs.end(); ++d)
134 {
135 //const Dialog* p = &(d->second);
136 DebugLog(<<"DialogId:" << d->first << ", " << *d->second);
137 }
138 }
139 }
140
141 while(!mDialogSetMap.empty())
142 {
143 DialogSet* ds = mDialogSetMap.begin()->second;
144 delete ds;
145 }
146
147 if(mIsDefaultServerReferHandler)
148 {
149 delete mServerSubscriptionHandlers["refer"];
150 }
151
152 delete mIncomingTarget;
153 delete mOutgoingTarget;
154
155 //InfoLog ( << "~DialogUsageManager done" );
156 }
157
158 const Data&
159 DialogUsageManager::name() const
160 {
161 static Data n("DialogUsageManager");
162 return n;
163 }
164
165 void
166 DialogUsageManager::addTransport( TransportType protocol,
167 int port,
168 IpVersion version,
169 const Data& ipInterface,
170 const Data& sipDomainname, // only used
171 const Data& privateKeyPassPhrase,
172 SecurityTypes::SSLType sslType)
173 {
174 mStack.addTransport(protocol, port, version, StunDisabled, ipInterface,
175 sipDomainname, privateKeyPassPhrase, sslType);
176 }
177
178 SipStack&
179 DialogUsageManager::getSipStack()
180 {
181 return mStack;
182 }
183
184 Security*
185 DialogUsageManager::getSecurity()
186 {
187 return mStack.getSecurity();
188 }
189
190 Data
191 DialogUsageManager::getHostAddress()
192 {
193 return mStack.getHostAddress();
194 }
195
196 void
197 DialogUsageManager::onAllHandlesDestroyed()
198 {
199 if (mDumShutdownHandler)
200 {
201 switch (mShutdownState)
202 {
203 case ShutdownRequested:
204 InfoLog (<< "DialogUsageManager::onAllHandlesDestroyed: removing TU");
205 //assert(mHandleMap.empty());
206 mShutdownState = RemovingTransactionUser;
207 mStack.unregisterTransactionUser(*this);
208 break;
209 default:
210 break;
211 }
212 }
213 }
214
215
216 void
217 DialogUsageManager::shutdown(DumShutdownHandler* h, unsigned long giveUpSeconds)
218 {
219 InfoLog (<< "shutdown giveup=" << giveUpSeconds << " dialogSets=" << mDialogSetMap.size());
220
221 mDumShutdownHandler = h;
222 mShutdownState = ShutdownRequested;
223 mStack.requestTransactionUserShutdown(*this);
224 shutdownWhenEmpty();
225 }
226
227 void
228 DialogUsageManager::shutdownIfNoUsages(DumShutdownHandler* h, unsigned long giveUpSeconds)
229 {
230 InfoLog (<< "shutdown when no usages giveup=" << giveUpSeconds);
231
232 mDumShutdownHandler = h;
233 mShutdownState = ShutdownRequested;
234 assert(0);
235 }
236
237 void
238 DialogUsageManager::forceShutdown(DumShutdownHandler* h)
239 {
240 WarningLog (<< "force shutdown ");
241 dumpHandles();
242
243 mDumShutdownHandler = h;
244 //HandleManager::shutdown(); // clear out usages
245 mShutdownState = ShutdownRequested;
246 DialogUsageManager::onAllHandlesDestroyed();
247 }
248
249 void DialogUsageManager::setAppDialogSetFactory(std::auto_ptr<AppDialogSetFactory> factory)
250 {
251 mAppDialogSetFactory = factory;
252 }
253
254 SharedPtr<MasterProfile>&
255 DialogUsageManager::getMasterProfile()
256 {
257 assert(mMasterProfile.get());
258 return mMasterProfile;
259 }
260
261 SharedPtr<UserProfile>&
262 DialogUsageManager::getMasterUserProfile()
263 {
264 assert(mMasterUserProfile.get());
265 return mMasterUserProfile;
266 }
267
268 void DialogUsageManager::setMasterProfile(const SharedPtr<MasterProfile>& masterProfile)
269 {
270 assert(!mMasterProfile.get());
271 mMasterProfile = masterProfile;
272 mMasterUserProfile = masterProfile; // required so that we can return a reference to SharedPtr<UserProfile> in getMasterUserProfile
273 }
274
275 void DialogUsageManager::setKeepAliveManager(std::auto_ptr<KeepAliveManager> manager)
276 {
277 mKeepAliveManager = manager;
278 mKeepAliveManager->setDialogUsageManager(this);
279 }
280
281 void DialogUsageManager::setRedirectManager(std::auto_ptr<RedirectManager> manager)
282 {
283 mRedirectManager = manager;
284 }
285
286 void DialogUsageManager::setRedirectHandler(RedirectHandler* handler)
287 {
288 mRedirectHandler = handler;
289 }
290
291 RedirectHandler* DialogUsageManager::getRedirectHandler()
292 {
293 return mRedirectHandler;
294 }
295
296 void
297 DialogUsageManager::setClientAuthManager(std::auto_ptr<ClientAuthManager> manager)
298 {
299 mClientAuthManager = manager;
300 }
301
302 void
303 DialogUsageManager::setServerAuthManager(SharedPtr<ServerAuthManager> manager)
304 {
305 mIncomingFeatureList.insert(mIncomingFeatureList.begin(), manager);
306 }
307
308 void
309 DialogUsageManager::setClientRegistrationHandler(ClientRegistrationHandler* handler)
310 {
311 assert(!mClientRegistrationHandler);
312 mClientRegistrationHandler = handler;
313 }
314
315 void
316 DialogUsageManager::setServerRegistrationHandler(ServerRegistrationHandler* handler)
317 {
318 assert(!mServerRegistrationHandler);
319 mServerRegistrationHandler = handler;
320 }
321
322 void
323 DialogUsageManager::setDialogSetHandler(DialogSetHandler* handler)
324 {
325 mDialogSetHandler = handler;
326 }
327
328 void
329 DialogUsageManager::setInviteSessionHandler(InviteSessionHandler* handler)
330 {
331 assert(!mInviteSessionHandler);
332 mInviteSessionHandler = handler;
333 }
334
335 void
336 DialogUsageManager::setRegistrationPersistenceManager(RegistrationPersistenceManager* manager)
337 {
338 assert(!mRegistrationPersistenceManager);
339 mRegistrationPersistenceManager = manager;
340 }
341
342 void
343 DialogUsageManager::setRemoteCertStore(auto_ptr<RemoteCertStore> store)
344 {
345 }
346
347 void
348 DialogUsageManager::addTimer(DumTimeout::Type type, unsigned long duration,
349 BaseUsageHandle target, int cseq, int rseq)
350 {
351 DumTimeout t(type, duration, target, cseq, rseq);
352 mStack.post(t, duration, this);
353 }
354
355 void
356 DialogUsageManager::addTimerMs(DumTimeout::Type type, unsigned long duration,
357 BaseUsageHandle target, int cseq, int rseq)
358 {
359 DumTimeout t(type, duration, target, cseq, rseq);
360 mStack.postMS(t, duration, this);
361 }
362
363 void
364 DialogUsageManager::addClientSubscriptionHandler(const Data& eventType, ClientSubscriptionHandler* handler)
365 {
366 assert(handler);
367 assert(mClientSubscriptionHandlers.count(eventType) == 0);
368 mClientSubscriptionHandlers[eventType] = handler;
369 }
370
371 void
372 DialogUsageManager::addServerSubscriptionHandler(const Data& eventType, ServerSubscriptionHandler* handler)
373 {
374 assert(handler);
375 //default do-nothing server side refer handler can be replaced
376 if (eventType == "refer" && mServerSubscriptionHandlers.count(eventType))
377 {
378 delete mServerSubscriptionHandlers[eventType];
379 mIsDefaultServerReferHandler = false;
380 //mServerSubscriptionHandlers.erase(eventType);
381 }
382
383 mServerSubscriptionHandlers[eventType] = handler;
384 }
385
386 void
387 DialogUsageManager::addClientPublicationHandler(const Data& eventType, ClientPublicationHandler* handler)
388 {
389 assert(handler);
390 assert(mClientPublicationHandlers.count(eventType) == 0);
391 mClientPublicationHandlers[eventType] = handler;
392 }
393
394 void
395 DialogUsageManager::addServerPublicationHandler(const Data& eventType, ServerPublicationHandler* handler)
396 {
397 assert(handler);
398 assert(mServerPublicationHandlers.count(eventType) == 0);
399 mServerPublicationHandlers[eventType] = handler;
400 }
401
402 void
403 DialogUsageManager::addOutOfDialogHandler(MethodTypes type, OutOfDialogHandler* handler)
404 {
405 assert(handler);
406 assert(mOutOfDialogHandlers.count(type) == 0);
407 mOutOfDialogHandlers[type] = handler;
408 }
409
410 void
411 DialogUsageManager::setClientPagerMessageHandler(ClientPagerMessageHandler* handler)
412 {
413 mClientPagerMessageHandler = handler;
414 }
415
416 void
417 DialogUsageManager::setServerPagerMessageHandler(ServerPagerMessageHandler* handler)
418 {
419 mServerPagerMessageHandler = handler;
420 }
421
422 DialogSet*
423 DialogUsageManager::makeUacDialogSet(BaseCreator* creator, AppDialogSet* appDs)
424 {
425 if (mDumShutdownHandler)
426 {
427 throw DumException("Cannot create new sessions when DUM is shutting down.", __FILE__, __LINE__);
428 }
429
430 if (appDs == 0)
431 {
432 appDs = new AppDialogSet(*this);
433 }
434 DialogSet* ds = new DialogSet(creator, *this);
435
436 appDs->mDialogSet = ds;
437 ds->mAppDialogSet = appDs;
438
439 DebugLog ( << "************* Adding DialogSet ***************" );
440 DebugLog ( << "Before: " << Inserter(mDialogSetMap) );
441 mDialogSetMap[ds->getId()] = ds;
442 DebugLog ( << "After: " << Inserter(mDialogSetMap) );
443 return ds;
444 }
445
446 SharedPtr<SipMessage>
447 DialogUsageManager::makeNewSession(BaseCreator* creator, AppDialogSet* appDs)
448 {
449 makeUacDialogSet(creator, appDs);
450 return creator->getLastRequest();
451 }
452
453 void
454 DialogUsageManager::makeResponse(SipMessage& response,
455 const SipMessage& request,
456 int responseCode,
457 const Data& reason) const
458 {
459 assert(request.isRequest());
460 Helper::makeResponse(response, request, responseCode, reason);
461 }
462
463 void
464 DialogUsageManager::sendResponse(const SipMessage& response)
465 {
466 assert(response.isResponse());
467 mStack.send(response, this);
468 }
469
470 SharedPtr<SipMessage>
471 DialogUsageManager::makeInviteSession(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const SdpContents* initialOffer, AppDialogSet* appDs)
472 {
473 return makeInviteSession(target, userProfile, initialOffer, None, 0, appDs);
474 }
475
476 SharedPtr<SipMessage>
477 DialogUsageManager::makeInviteSession(const NameAddr& target, const SdpContents* initialOffer, AppDialogSet* appDs)
478 {
479 return makeInviteSession(target, getMasterUserProfile(), initialOffer, None, 0, appDs);
480 }
481
482 SharedPtr<SipMessage>
483 DialogUsageManager::makeInviteSession(const NameAddr& target,
484 const SharedPtr<UserProfile>& userProfile,
485 const SdpContents* initialOffer,
486 EncryptionLevel level,
487 const SdpContents* alternative,
488 AppDialogSet* appDs)
489 {
490 SharedPtr<SipMessage> inv = makeNewSession(new InviteSessionCreator(*this, target, userProfile, initialOffer, level, alternative), appDs);
491 DumHelper::setOutgoingEncryptionLevel(*inv, level);
492
493 return inv;
494 }
495
496 SharedPtr<SipMessage>
497 DialogUsageManager::makeInviteSession(const NameAddr& target,
498 const SdpContents* initialOffer,
499 EncryptionLevel level,
500 const SdpContents* alternative,
501 AppDialogSet* appDs)
502 {
503 return makeInviteSession(target, getMasterUserProfile(), initialOffer, level, alternative, appDs);
504 }
505
506 SharedPtr<SipMessage>
507 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer,
508 ServerSubscriptionHandle serverSub,
509 const SdpContents* initialOffer,
510 AppDialogSet* appDs)
511 {
512 return makeInviteSessionFromRefer(refer, serverSub, initialOffer, None, 0, appDs);
513 }
514
515 SharedPtr<SipMessage>
516 DialogUsageManager::makeInviteSessionFromRefer(const SipMessage& refer,
517 ServerSubscriptionHandle serverSub,
518 const SdpContents* initialOffer,
519 EncryptionLevel level,
520 const SdpContents* alternative,
521 AppDialogSet* appDs)
522 {
523 if (serverSub.isValid())
524 {
525 DebugLog(<< "implicit subscription");
526 //generate and send 100
527 SipFrag contents;
528 contents.message().header(h_StatusLine).statusCode() = 100;
529 contents.message().header(h_StatusLine).reason() = "Trying";
530 //will be cloned...ServerSub may not have the most efficient API possible
531 serverSub->setSubscriptionState(Active);
532 SharedPtr<SipMessage> notify = serverSub->update(&contents);
533 // mInviteSessionHandler->onReadyToSend(InviteSessionHandle::NotValid(), notify);
534 serverSub->send(notify);
535 }
536
537 //19.1.5
538 NameAddr target = refer.header(h_ReferTo);
539 target.uri().removeEmbedded();
540 target.uri().remove(p_method);
541
542 // !jf! this code assumes you have a UserProfile
543 SharedPtr<SipMessage> inv = makeNewSession(new InviteSessionCreator(*this,
544 target,
545 serverSub.isValid() ? serverSub->mDialog.mDialogSet.getUserProfile() : getMasterUserProfile(),
546 initialOffer, level, alternative, serverSub), appDs);
547 DumHelper::setOutgoingEncryptionLevel(*inv, level);
548
549 //could pass dummy target, then apply merge rules from 19.1.5...or
550 //makeNewSession would use rules from 19.1.5
551 if (refer.exists(h_ReferredBy))
552 {
553 inv->header(h_ReferredBy) = refer.header(h_ReferredBy);
554 }
555
556 const Uri& referTo = refer.header(h_ReferTo).uri();
557 //19.1.5
558 if (referTo.hasEmbedded() && referTo.embedded().exists(h_Replaces))
559 {
560 inv->header(h_Replaces) = referTo.embedded().header(h_Replaces);
561 }
562 return inv;
563 }
564
565 SharedPtr<SipMessage>
566 DialogUsageManager::makeRefer(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const H_ReferTo::Type& referTo, AppDialogSet* appDs)
567 {
568 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, referTo), appDs);
569 }
570
571 SharedPtr<SipMessage>
572 DialogUsageManager::makeRefer(const NameAddr& target, const H_ReferTo::Type& referTo, AppDialogSet* appDs)
573 {
574 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), referTo), appDs);
575 }
576
577 SharedPtr<SipMessage>
578 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType, AppDialogSet* appDs)
579 {
580 assert(userProfile.get());
581 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, userProfile->getDefaultSubscriptionTime()), appDs);
582 }
583
584 SharedPtr<SipMessage>
585 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType,
586 int subscriptionTime, AppDialogSet* appDs)
587 {
588 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, subscriptionTime), appDs);
589 }
590
591 SharedPtr<SipMessage>
592 DialogUsageManager::makeSubscription(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const Data& eventType,
593 int subscriptionTime, int refreshInterval, AppDialogSet* appDs)
594 {
595 return makeNewSession(new SubscriptionCreator(*this, target, userProfile, eventType, subscriptionTime, refreshInterval), appDs);
596 }
597
598 SharedPtr<SipMessage>
599 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType, AppDialogSet* appDs)
600 {
601 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, getMasterProfile()->getDefaultSubscriptionTime()), appDs);
602 }
603
604 SharedPtr<SipMessage>
605 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType,
606 int subscriptionTime, AppDialogSet* appDs)
607 {
608 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, subscriptionTime), appDs);
609 }
610
611 SharedPtr<SipMessage>
612 DialogUsageManager::makeSubscription(const NameAddr& target, const Data& eventType,
613 int subscriptionTime, int refreshInterval, AppDialogSet* appDs)
614 {
615 return makeNewSession(new SubscriptionCreator(*this, target, getMasterUserProfile(), eventType, subscriptionTime, refreshInterval), appDs);
616 }
617
618 SharedPtr<SipMessage>
619 DialogUsageManager::makeRegistration(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, AppDialogSet* appDs)
620 {
621 assert(userProfile.get());
622 return makeNewSession(new RegistrationCreator(*this, target, userProfile, userProfile->getDefaultRegistrationTime()), appDs);
623 }
624
625 SharedPtr<SipMessage>
626 DialogUsageManager::makeRegistration(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, int registrationTime, AppDialogSet* appDs)
627 {
628 return makeNewSession(new RegistrationCreator(*this, target, userProfile, registrationTime), appDs);
629 }
630
631 SharedPtr<SipMessage>
632 DialogUsageManager::makeRegistration(const NameAddr& target, AppDialogSet* appDs)
633 {
634 return makeNewSession(new RegistrationCreator(*this, target, getMasterUserProfile(), getMasterProfile()->getDefaultRegistrationTime()), appDs);
635 }
636
637 SharedPtr<SipMessage>
638 DialogUsageManager::makeRegistration(const NameAddr& target, int registrationTime, AppDialogSet* appDs)
639 {
640 return makeNewSession(new RegistrationCreator(*this, target, getMasterUserProfile(), registrationTime), appDs);
641 }
642
643 SharedPtr<SipMessage>
644 DialogUsageManager::makePublication(const NameAddr& targetDocument,
645 const SharedPtr<UserProfile>& userProfile,
646 const Contents& body,
647 const Data& eventType,
648 unsigned expiresSeconds,
649 AppDialogSet* appDs)
650 {
651 return makeNewSession(new PublicationCreator(*this, targetDocument, userProfile, body, eventType, expiresSeconds), appDs);
652 }
653
654 SharedPtr<SipMessage>
655 DialogUsageManager::makePublication(const NameAddr& targetDocument,
656 const Contents& body,
657 const Data& eventType,
658 unsigned expiresSeconds,
659 AppDialogSet* appDs)
660 {
661 return makeNewSession(new PublicationCreator(*this, targetDocument, getMasterUserProfile(), body, eventType, expiresSeconds), appDs);
662 }
663
664 SharedPtr<SipMessage>
665 DialogUsageManager::makeOutOfDialogRequest(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, const MethodTypes meth, AppDialogSet* appDs)
666 {
667 return makeNewSession(new OutOfDialogReqCreator(*this, meth, target, userProfile), appDs);
668 }
669
670 SharedPtr<SipMessage>
671 DialogUsageManager::makeOutOfDialogRequest(const NameAddr& target, const MethodTypes meth, AppDialogSet* appDs)
672 {
673 return makeNewSession(new OutOfDialogReqCreator(*this, meth, target, getMasterUserProfile()), appDs);
674 }
675
676 ClientPagerMessageHandle
677 DialogUsageManager::makePagerMessage(const NameAddr& target, const SharedPtr<UserProfile>& userProfile, AppDialogSet* appDs)
678 {
679 if (!mClientPagerMessageHandler)
680 {
681 throw DumException("Cannot send MESSAGE messages without a ClientPagerMessageHandler", __FILE__, __LINE__);
682 }
683 DialogSet* ds = makeUacDialogSet(new PagerMessageCreator(*this, target, userProfile), appDs);
684 ClientPagerMessage* cpm = new ClientPagerMessage(*this, *ds);
685 ds->mClientPagerMessage = cpm;
686 return cpm->getHandle();
687 }
688
689 ClientPagerMessageHandle
690 DialogUsageManager::makePagerMessage(const NameAddr& target, AppDialogSet* appDs)
691 {
692 return makePagerMessage(target, getMasterUserProfile(), appDs);
693 }
694
695 void
696 DialogUsageManager::send(SharedPtr<SipMessage> msg)
697 {
698 // !slg! There is probably a more efficient way to get the userProfile here (pass it in?)
699 DialogSet* ds = findDialogSet(DialogSetId(*msg));
700 UserProfile* userProfile;
701 if (ds == 0)
702 {
703 userProfile = getMasterUserProfile().get();
704 }
705 else
706 {
707 userProfile = ds->getUserProfile().get();
708 }
709
710 assert(userProfile);
711 if (!userProfile->isAnonymous() && userProfile->hasUserAgent())
712 {
713 msg->header(h_UserAgent).value() = userProfile->getUserAgent();
714 }
715 if (userProfile->isAnonymous())
716 {
717 msg->remove(h_ReplyTo);
718 msg->remove(h_UserAgent);
719 msg->remove(h_Organization);
720 msg->remove(h_Server);
721 msg->remove(h_Subject);
722 msg->remove(h_InReplyTo);
723
724 msg->remove(h_CallInfos);
725 msg->remove(h_Warnings);
726 }
727
728 assert(userProfile);
729 if (msg->isRequest()
730 && userProfile->hasProxyRequires()
731 && msg->header(h_RequestLine).method() != ACK
732 && msg->header(h_RequestLine).method() != CANCEL)
733 {
734 msg->header(h_ProxyRequires) = userProfile->getProxyRequires();
735 }
736
737 if (msg->isRequest())
738 {
739 // We may not need to call reset() if makeRequest is always used.
740 if (msg->header(h_RequestLine).method() != CANCEL &&
741 msg->header(h_RequestLine).method() != ACK &&
742 msg->exists(h_Vias))
743 {
744 msg->header(h_Vias).front().param(p_branch).reset();
745 }
746
747 if (msg->exists(h_Vias))
748 {
749 if(!userProfile->getRportEnabled())
750 {
751 msg->header(h_Vias).front().remove(p_rport);
752 }
753 int fixedTransportPort = userProfile->getFixedTransportPort();
754 if(fixedTransportPort != 0)
755 {
756 msg->header(h_Vias).front().sentPort() = fixedTransportPort;
757 }
758 const Data& fixedTransportInterface = userProfile->getFixedTransportInterface();
759 if(!fixedTransportInterface.empty())
760 {
761 msg->header(h_Vias).front().sentHost() = fixedTransportInterface;
762 }
763 }
764
765 if (mClientAuthManager.get() && msg->header(h_RequestLine).method() != ACK)
766 {
767 mClientAuthManager->addAuthentication(*msg);
768 }
769
770 // Add outbound decorator from userprofile
771 SharedPtr<MessageDecorator> outboundDecorator = userProfile->getOutboundDecorator();
772 if (outboundDecorator.get())
773 {
774 msg->addOutboundDecorator(outboundDecorator.get());
775 }
776 }
777
778 DebugLog (<< "SEND: " << *msg);
779
780 OutgoingEvent* event = new OutgoingEvent(msg);
781 outgoingProcess(auto_ptr<Message>(event));
782 }
783
784 void DialogUsageManager::outgoingProcess(auto_ptr<Message> message)
785 {
786 Data tid = Data::Empty;
787 {
788 OutgoingEvent* sipMsg = dynamic_cast<OutgoingEvent*>(message.get());
789 if (sipMsg)
790 {
791 tid = sipMsg->getTransactionId();
792 }
793
794 DumFeatureMessage* featureMsg = dynamic_cast<DumFeatureMessage*>(message.get());
795 if (featureMsg)
796 {
797 InfoLog(<<"Got a DumFeatureMessage" << featureMsg);
798 tid = featureMsg->getTransactionId();
799 }
800 }
801
802 if (tid == Data::Empty && mOutgoingMessageInterceptor.get())
803 {
804 mOutgoingMessageInterceptor->process(message.get());
805 return;
806 }
807 else if (tid != Data::Empty && !mOutgoingFeatureList.empty())
808 {
809 FeatureChainMap::iterator it;
810 //efficiently find or create FeatureChain, should prob. be a utility template
811 {
812 FeatureChainMap::iterator lb = mOutgoingFeatureChainMap.lower_bound(tid);
813 if (lb != mOutgoingFeatureChainMap.end() && !(mOutgoingFeatureChainMap.key_comp()(tid, lb->first)))
814 {
815 it = lb;
816 }
817 else
818 {
819 it = mOutgoingFeatureChainMap.insert(lb, FeatureChainMap::value_type(tid, new DumFeatureChain(*this, mOutgoingFeatureList, *mOutgoingTarget)));
820 }
821 }
822
823 DumFeatureChain::ProcessingResult res = it->second->process(message.get());
824
825 if (res & DumFeatureChain::ChainDoneBit)
826 {
827 delete it->second;
828 mOutgoingFeatureChainMap.erase(it);
829 }
830
831 if (res & DumFeatureChain::EventTakenBit)
832 {
833 message.release();
834 return;
835 }
836 }
837
838 OutgoingEvent* event = dynamic_cast<OutgoingEvent*>(message.get());
839 assert(event);
840 if (event)
841 {
842 if (event->message()->isRequest())
843 {
844 DialogSet* ds = findDialogSet(DialogSetId(*event->message()));
845 UserProfile* userProfile;
846 if (ds == 0)
847 {
848 userProfile = getMasterUserProfile().get();
849 }
850 else
851 {
852 userProfile = ds->getUserProfile().get();
853 }
854
855 assert(userProfile);
856
857 //!dcm! -- unique SharedPtr to auto_ptr conversion prob. a worthwhile
858 //optimzation here. SharedPtr would ahve to be changed; would
859 //throw/assert if not unique.
860 std::auto_ptr<SipMessage> toSend(static_cast<SipMessage*>(event->message()->clone()));
861
862 if (event->message()->exists(h_Routes) &&
863 !event->message()->header(h_Routes).empty() &&
864 !event->message()->header(h_Routes).front().uri().exists(p_lr))
865 {
866 Helper::processStrictRoute(*toSend);
867 sendUsingOutboundIfAppropriate(*userProfile, toSend);
868 }
869 else
870 {
871 sendUsingOutboundIfAppropriate(*userProfile, toSend);
872 }
873 }
874 else
875 {
876 sendResponse(*event->message());
877 }
878 }
879 }
880
881 void
882 DialogUsageManager::sendUsingOutboundIfAppropriate(UserProfile& userProfile, auto_ptr<SipMessage> msg)
883 {
884 //a little inefficient, branch parameter might be better
885 DialogId id(*msg);
886 if (userProfile.hasOutboundProxy() && !findDialog(id))
887 {
888 // prepend the outbound proxy to the service route
889 msg->header(h_Routes).push_front(NameAddr(userProfile.getOutboundProxy().uri()));
890
891 DebugLog ( << "Using outbound proxy: "
892 << userProfile.getOutboundProxy().uri()
893 << " -> " << msg->brief());
894 mStack.send(msg, this);
895 }
896 else
897 {
898 DebugLog (<< "Send: " << msg->brief());
899 mStack.send(msg, this);
900 }
901 }
902
903
904 void
905 DialogUsageManager::end(DialogSetId setid)
906 {
907 DialogSet* ds = findDialogSet(setid);
908 if (ds == 0)
909 {
910 throw Exception("Request no longer exists", __FILE__, __LINE__);
911 }
912 else
913 {
914 ds->end();
915 }
916 }
917
918 void
919 DialogUsageManager::destroy(const BaseUsage* usage)
920 {
921 if (mShutdownState != Destroying)
922 {
923 post(new DestroyUsage(usage->mHandle));
924 }
925 else
926 {
927 InfoLog(<< "DialogUsageManager::destroy() not posting to stack");
928 }
929 }
930
931 void
932 DialogUsageManager::destroy(DialogSet* dset)
933 {
934 if (mShutdownState != Destroying)
935 {
936 post(new DestroyUsage(dset));
937 }
938 else
939 {
940 InfoLog(<< "DialogUsageManager::destroy() not posting to stack");
941 }
942 }
943
944 void
945 DialogUsageManager::destroy(Dialog* d)
946 {
947 if (mShutdownState != Destroying)
948 {
949 post(new DestroyUsage(d));
950 }
951 else
952 {
953 InfoLog(<< "DialogUsageManager::destroy() not posting to stack");
954 }
955 }
956
957
958 Dialog*
959 DialogUsageManager::findDialog(const DialogId& id)
960 {
961 DialogSet* ds = findDialogSet(id.getDialogSetId());
962 if (ds)
963 {
964 return ds->findDialog(id);
965 }
966 else
967 {
968 return 0;
969 }
970 }
971
972
973 InviteSessionHandle
974 DialogUsageManager::findInviteSession(DialogId id)
975 {
976 Dialog* dialog = findDialog(id);
977 if (dialog && dialog->mInviteSession)
978 {
979 return dialog->mInviteSession->getSessionHandle();
980 }
981 else
982 {
983 return InviteSessionHandle::NotValid();
984 }
985 }
986
987 pair<InviteSessionHandle, int>
988 DialogUsageManager::findInviteSession(CallId replaces)
989 {
990 //486/481/603 decision making logic where? App may not wish to keep track of
991 //invitesession state
992 //Logic is here for now.
993 InviteSessionHandle is = findInviteSession(DialogId(replaces.value(),
994 replaces.param(p_toTag),
995 replaces.param(p_fromTag)));
996 int ErrorStatusCode = 481; // Call/Transaction Does Not Exist
997
998 // If we matched a session - Do RFC3891 Section 3 Processing
999 if(!(is == InviteSessionHandle::NotValid()))
1000 {
1001 // Note some missing checks are:
1002 // 1. If the Replaces header field matches more than one dialog, the UA must act as
1003 // if no match was found
1004 // 2. Verify that the initiator of the new Invite is authorized
1005 if(is->isTerminated())
1006 {
1007 ErrorStatusCode = 603; // Declined
1008 is = InviteSessionHandle::NotValid();
1009 }
1010 else if(is->isConnected())
1011 {
1012 // Check if early-only flag is present in replaces header
1013 if(replaces.exists(p_earlyOnly))
1014 {
1015 ErrorStatusCode = 486; // Busy Here
1016 is = InviteSessionHandle::NotValid();
1017 }
1018 }
1019 else if(!is->isEarly())
1020 {
1021 // replaces can't be used on early dialogs that were not initiated by this UA - ie. InviteSession::Proceeding state
1022 ErrorStatusCode = 481; // Call/Transaction Does Not Exist
1023 is = InviteSessionHandle::NotValid();
1024 }
1025 }
1026 return make_pair(is, ErrorStatusCode);
1027 }
1028
1029 void
1030 DialogUsageManager::internalProcess(std::auto_ptr<Message> msg)
1031 {
1032 // After a Stack ShutdownMessage has been received, don't do anything else in dum
1033 if (mShutdownState == Shutdown)
1034 {
1035 return;
1036 }
1037
1038 TransactionUserMessage* tuMsg = dynamic_cast<TransactionUserMessage*>(msg.get());
1039 if (tuMsg)
1040 {
1041 InfoLog (<< "TU unregistered ");
1042 assert(mShutdownState == RemovingTransactionUser);
1043 assert(tuMsg->type() == TransactionUserMessage::TransactionUserRemoved);
1044 mShutdownState = Shutdown;
1045 if (mDumShutdownHandler)
1046 {
1047 mDumShutdownHandler->onDumCanBeDeleted();
1048 mDumShutdownHandler = 0; // prevent mDumShutdownHandler getting called more than once
1049 }
1050 return;
1051 }
1052
1053 DestroyUsage* destroyUsage = dynamic_cast<DestroyUsage*>(msg.get());
1054 if (destroyUsage)
1055 {
1056 //DebugLog(<< "Destroying usage" );
1057 destroyUsage->destroy();
1058 return;
1059 }
1060
1061 DumTimeout* dumMsg = dynamic_cast<DumTimeout*>(msg.get());
1062 if (dumMsg)
1063 {
1064 //DebugLog(<< "Timeout Message" );
1065 if (!dumMsg->getBaseUsage().isValid())
1066 {
1067 return;
1068 }
1069
1070 dumMsg->getBaseUsage()->dispatch(*dumMsg);
1071 return;
1072 }
1073
1074 KeepAliveTimeout* keepAliveMsg = dynamic_cast<KeepAliveTimeout*>(msg.get());
1075 if (keepAliveMsg)
1076 {
1077 //DebugLog(<< "Keep Alive Message" );
1078 if (mKeepAliveManager.get())
1079 {
1080 mKeepAliveManager->process(*keepAliveMsg);
1081 }
1082 return;
1083 }
1084
1085 ConnectionTerminated* terminated = dynamic_cast<ConnectionTerminated*>(msg.get());
1086 if (terminated)
1087 {
1088 DebugLog(<< "connection terminated message");
1089 if (mConnectionTerminatedEventDispatcher.dispatch(msg.get()))
1090 {
1091 msg.release();
1092 }
1093 return;
1094 }
1095
1096 DumCommand* command = dynamic_cast<DumCommand*>(msg.get());
1097 if (command)
1098 {
1099 //DebugLog(<< "DumCommand" );
1100 command->executeCommand();
1101 return;
1102 }
1103
1104 incomingProcess(msg);
1105 }
1106
1107 void DialogUsageManager::incomingProcess(std::auto_ptr<Message> msg)
1108 {
1109 //call or create feature chain if appropriate
1110 Data tid = Data::Empty;
1111 {
1112 SipMessage* sipMsg = dynamic_cast<SipMessage*>(msg.get());
1113 if (sipMsg)
1114 {
1115 tid = sipMsg->getTransactionId();
1116 }
1117
1118 DumFeatureMessage* featureMsg = dynamic_cast<DumFeatureMessage*>(msg.get());
1119 if (featureMsg)
1120 {
1121 //DebugLog(<<"Got a DumFeatureMessage" << featureMsg);
1122 tid = featureMsg->getTransactionId();
1123 }
1124 }
1125 if (tid != Data::Empty && !mIncomingFeatureList.empty())
1126 {
1127 FeatureChainMap::iterator it;
1128 //efficiently find or create FeatureChain, should prob. be a utility template
1129 {
1130 FeatureChainMap::iterator lb = mIncomingFeatureChainMap.lower_bound(tid);
1131 if (lb != mIncomingFeatureChainMap.end() && !(mIncomingFeatureChainMap.key_comp()(tid, lb->first)))
1132 {
1133 it = lb;
1134 }
1135 else
1136 {
1137 assert(dynamic_cast<SipMessage*>(msg.get()));
1138 it = mIncomingFeatureChainMap.insert(lb, FeatureChainMap::value_type(tid, new DumFeatureChain(*this, mIncomingFeatureList, *mIncomingTarget)));
1139 }
1140 }
1141
1142 DumFeatureChain::ProcessingResult res = it->second->process(msg.get());
1143
1144 if (res & DumFeatureChain::ChainDoneBit)
1145 {
1146 delete it->second;
1147 mIncomingFeatureChainMap.erase(it);
1148 //DebugLog(<< "feature chain deleted" << endl);
1149 }
1150
1151 if (res & DumFeatureChain::EventTakenBit)
1152 {
1153 msg.release();
1154 //DebugLog(<< "event taken");
1155 return;
1156 }
1157 }
1158
1159 try
1160 {
1161 InfoLog (<< "Got: " << msg->brief());
1162 DumDecrypted* decryptedMsg = dynamic_cast<DumDecrypted*>(msg.get());
1163 SipMessage* sipMsg = 0;
1164 if (decryptedMsg)
1165 {
1166 sipMsg = decryptedMsg->decrypted();
1167 }
1168 else
1169 {
1170 sipMsg = dynamic_cast<SipMessage*>(msg.get());
1171 }
1172
1173 if (sipMsg)
1174 {
1175 //DebugLog ( << "DialogUsageManager::process: " << sipMsg->brief());
1176 if (sipMsg->isRequest())
1177 {
1178 // Validate Request URI
1179 if( !validateRequestURI(*sipMsg) )
1180 {
1181 DebugLog (<< "Failed RequestURI validation " << *sipMsg);
1182 return;
1183 }
1184
1185 // Continue validation on all requests, except ACK and CANCEL
1186 if(sipMsg->header(h_RequestLine).method() != ACK &&
1187 sipMsg->header(h_RequestLine).method() != CANCEL)
1188 {
1189 if( !validateRequiredOptions(*sipMsg) )
1190 {
1191 DebugLog (<< "Failed required options validation " << *sipMsg);
1192 return;
1193 }
1194 if( getMasterProfile()->validateContentEnabled() && !validateContent(*sipMsg) )
1195 {
1196 DebugLog (<< "Failed content validation " << *sipMsg);
1197 return;
1198 }
1199 if( getMasterProfile()->validateAcceptEnabled() && !validateAccept(*sipMsg) )
1200 {
1201 DebugLog (<< "Failed accept validation " << *sipMsg);
1202 return;
1203 }
1204 }
1205 if (sipMsg->header(h_From).exists(p_tag))
1206 {
1207 if (mergeRequest(*sipMsg) )
1208 {
1209 InfoLog (<< "Merged request: " << *sipMsg);
1210 return;
1211 }
1212 }
1213 processRequest(*sipMsg);
1214 }
1215 else
1216 {
1217 processResponse(*sipMsg);
1218 }
1219 }
1220 }
1221 catch(BaseException& e)
1222 {
1223 //unparseable, bad 403 w/ 2543 trans it from FWD, etc
1224 ErrLog(<<"Illegal message rejected: " << e.getMessage());
1225 }
1226 }
1227
1228 // return true if there is more to do
1229 bool
1230 DialogUsageManager::process()
1231 {
1232 if (mFifo.messageAvailable())
1233 {
1234 internalProcess(std::auto_ptr<Message>(mFifo.getNext()));
1235 }
1236 return mFifo.messageAvailable();
1237 }
1238
1239 bool
1240 DialogUsageManager::validateRequestURI(const SipMessage& request)
1241 {
1242 // RFC3261 - 8.2.1
1243 if (!getMasterProfile()->isMethodSupported(request.header(h_RequestLine).getMethod()))
1244 {
1245 InfoLog (<< "Received an unsupported method: " << request.brief());
1246
1247 SipMessage failure;
1248 makeResponse(failure, request, 405);
1249 failure.header(h_Allows) = getMasterProfile()->getAllowedMethods();
1250 sendResponse(failure);
1251
1252 return false;
1253 }
1254
1255 // RFC3261 - 8.2.2
1256 if (!getMasterProfile()->isSchemeSupported(request.header(h_RequestLine).uri().scheme()))
1257 {
1258 InfoLog (<< "Received an unsupported scheme: " << request.brief());
1259 SipMessage failure;
1260 makeResponse(failure, request, 416);
1261 sendResponse(failure);
1262
1263 return false;
1264 }
1265
1266 return true;
1267 }
1268
1269
1270 bool
1271 DialogUsageManager::validateRequiredOptions(const SipMessage& request)
1272 {
1273 // RFC 2162 - 8.2.2
1274 if(request.exists(h_Requires) && // Don't check requires if method is ACK or CANCEL
1275 (request.header(h_RequestLine).getMethod() != ACK ||
1276 request.header(h_RequestLine).getMethod() != CANCEL))
1277 {
1278 Tokens unsupported = getMasterProfile()->getUnsupportedOptionsTags(request.header(h_Requires));
1279 if (!unsupported.empty())
1280 {
1281 InfoLog (<< "Received an unsupported option tag(s): " << request.brief());
1282
1283 SipMessage failure;
1284 makeResponse(failure, request, 420);
1285 failure.header(h_Unsupporteds) = unsupported;
1286 sendResponse(failure);
1287
1288 return false;
1289 }
1290 }
1291
1292 return true;
1293 }
1294
1295 bool
1296 DialogUsageManager::validateContent(const SipMessage& request)
1297 {
1298 // RFC3261 - 8.2.3
1299 // Don't need to validate content headers if they are specified as optional in the content-disposition
1300 if (!(request.exists(h_ContentDisposition) &&
1301 request.header(h_ContentDisposition).exists(p_handling) &&
1302 isEqualNoCase(request.header(h_ContentDisposition).param(p_handling), Symbols::Optional)))
1303 {
1304 if (request.exists(h_ContentType) && !getMasterProfile()->isMimeTypeSupported(request.header(h_RequestLine).method(), request.header(h_ContentType)))
1305 {
1306 InfoLog (<< "Received an unsupported mime type: " << request.header(h_ContentType) << " for " << request.brief());
1307
1308 SipMessage failure;
1309 makeResponse(failure, request, 415);
1310 failure.header(h_Accepts) = getMasterProfile()->getSupportedMimeTypes(request.header(h_RequestLine).method());
1311 sendResponse(failure);
1312
1313 return false;
1314 }
1315
1316 if (request.exists(h_ContentEncoding) && !getMasterProfile()->isContentEncodingSupported(request.header(h_ContentEncoding)))
1317 {
1318 InfoLog (<< "Received an unsupported mime type: " << request.header(h_ContentEncoding) << " for " << request.brief());
1319 SipMessage failure;
1320 makeResponse(failure, request, 415);
1321 failure.header(h_AcceptEncodings) = getMasterProfile()->getSupportedEncodings();
1322 sendResponse(failure);
1323
1324 return false;
1325 }
1326
1327 if (getMasterProfile()->validateContentLanguageEnabled() &&
1328 request.exists(h_ContentLanguages) && !getMasterProfile()->isLanguageSupported(request.header(h_ContentLanguages)))
1329 {
1330 InfoLog (<< "Received an unsupported language: " << request.header(h_ContentLanguages).front() << " for " << request.brief());
1331
1332 SipMessage failure;
1333 makeResponse(failure, request, 415);
1334 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1335 sendResponse(failure);
1336
1337 return false;
1338 }
1339 }
1340
1341 return true;
1342 }
1343
1344 bool
1345 DialogUsageManager::validateAccept(const SipMessage& request)
1346 {
1347 MethodTypes method = request.header(h_RequestLine).method();
1348 // checks for Accept to comply with SFTF test case 216
1349 if(request.exists(h_Accepts))
1350 {
1351 for (Mimes::const_iterator i = request.header(h_Accepts).begin();
1352 i != request.header(h_Accepts).end(); i++)
1353 {
1354 if (getMasterProfile()->isMimeTypeSupported(method, *i))
1355 {
1356 return true; // Accept header passes validation if we support as least one of the mime types
1357 }
1358 }
1359 }
1360 // If no Accept header then application/sdp should be assumed for certain methods
1361 else if(method == INVITE ||
1362 method == OPTIONS ||
1363 method == PRACK ||
1364 method == UPDATE)
1365 {
1366 if (getMasterProfile()->isMimeTypeSupported(request.header(h_RequestLine).method(), Mime("application", "sdp")))
1367 {
1368 return true;
1369 }
1370 }
1371 else
1372 {
1373 // Other method without an Accept Header
1374 return true;
1375 }
1376
1377 InfoLog (<< "Received unsupported mime types in accept header: " << request.brief());
1378 SipMessage failure;
1379 makeResponse(failure, request, 406);
1380 failure.header(h_Accepts) = getMasterProfile()->getSupportedMimeTypes(method);
1381 sendResponse(failure);
1382 return false;
1383 }
1384
1385 bool
1386 DialogUsageManager::mergeRequest(const SipMessage& request)
1387 {
1388 assert(request.isRequest());
1389 assert(request.isExternal());
1390
1391 if (!request.header(h_To).exists(p_tag))
1392 {
1393 if (mMergedRequests.count(MergedRequestKey(request)))
1394 {
1395 SipMessage failure;
1396 makeResponse(failure, request, 482, "Merged Request");
1397 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1398 sendResponse(failure);
1399 return true;
1400 }
1401 }
1402
1403 return false;
1404 }
1405
1406 void
1407 DialogUsageManager::processRequest(const SipMessage& request)
1408 {
1409 DebugLog ( << "DialogUsageManager::processRequest: " << request.brief());
1410
1411 if (mShutdownState != Running && mShutdownState != ShutdownRequested)
1412 {
1413 WarningLog (<< "Ignoring a request since we are shutting down " << request.brief());
1414
1415 SipMessage failure;
1416 makeResponse(failure, request, 480, "UAS is shutting down");
1417 sendResponse(failure);
1418 return;
1419 }
1420
1421 if (request.header(h_RequestLine).method() == PUBLISH)
1422 {
1423 processPublish(request);
1424 return;
1425 }
1426
1427 bool toTag = request.header(h_To).exists(p_tag);
1428 if(request.header(h_RequestLine).getMethod() == REGISTER && toTag && getMasterProfile()->allowBadRegistrationEnabled())
1429 {
1430 toTag = false;
1431 }
1432
1433 assert(mAppDialogSetFactory.get());
1434 // !jf! note, the logic was reversed during ye great merge of March of Ought 5
1435 if (toTag ||
1436 findDialogSet(DialogSetId(request)))
1437 {
1438 switch (request.header(h_RequestLine).getMethod())
1439 {
1440 case REGISTER:
1441 {
1442 SipMessage failure;
1443 makeResponse(failure, request, 400, "Registration requests can't have To: tags.");
1444 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1445 sendResponse(failure);
1446 break;
1447 }
1448
1449 default:
1450 {
1451 DialogSet* ds = findDialogSet(DialogSetId(request));
1452 if (ds == 0)
1453 {
1454 if (request.header(h_RequestLine).method() != ACK)
1455 {
1456 SipMessage failure;
1457 makeResponse(failure, request, 481);
1458 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1459 InfoLog (<< "Rejected request (which was in a dialog) " << request.brief());
1460 sendResponse(failure);
1461 }
1462 else
1463 {
1464 InfoLog (<< "ACK doesn't match any dialog" << request.brief());
1465 }
1466 }
1467 else
1468 {
1469 InfoLog (<< "Handling in-dialog request: " << request.brief());
1470 ds->dispatch(request);
1471 }
1472 }
1473 }
1474 }
1475 else
1476 {
1477 switch (request.header(h_RequestLine).getMethod())
1478 {
1479 case ACK:
1480 DebugLog (<< "Discarding request: " << request.brief());
1481 break;
1482
1483 case PRACK:
1484 case BYE:
1485 case UPDATE:
1486 case INFO: // !rm! in an ideal world
1487 {
1488 SipMessage failure;
1489 makeResponse(failure, request, 481);
1490 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1491 sendResponse(failure);
1492 break;
1493 }
1494 case CANCEL:
1495 {
1496 // find the appropropriate ServerInvSession
1497 CancelMap::iterator i = mCancelMap.find(request.getTransactionId());
1498 if (i != mCancelMap.end())
1499 {
1500 i->second->dispatch(request);
1501 }
1502 else
1503 {
1504 InfoLog (<< "Received a CANCEL on a non-existent transaction ");
1505 SipMessage failure;
1506 makeResponse(failure, request, 481);
1507 sendResponse(failure);
1508 }
1509 break;
1510 }
1511 case PUBLISH:
1512 assert(false);
1513 case SUBSCRIBE:
1514 if (!checkEventPackage(request))
1515 {
1516 InfoLog (<< "Rejecting request (unsupported package) "
1517 << request.brief());
1518 return;
1519 }
1520 case NOTIFY : // handle unsolicited (illegal) NOTIFYs
1521 case INVITE: // new INVITE
1522 case REFER: // out-of-dialog REFER
1523 //case INFO : // handle non-dialog (illegal) INFOs
1524 case OPTIONS : // handle non-dialog OPTIONS
1525 case MESSAGE :
1526 case REGISTER:
1527 {
1528 {
1529 DialogSetId id(request);
1530 //cryptographically dangerous
1531 assert(mDialogSetMap.find(id) == mDialogSetMap.end());
1532 }
1533 if (mDumShutdownHandler)
1534 {
1535 SipMessage forbidden;
1536 makeResponse(forbidden, request, 480);
1537 forbidden.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1538 sendResponse(forbidden);
1539 return;
1540 }
1541 try
1542 {
1543 DialogSet* dset = new DialogSet(request, *this);
1544
1545 DebugLog ( << "*********** Calling AppDialogSetFactory *************" );
1546 AppDialogSet* appDs = mAppDialogSetFactory->createAppDialogSet(*this, request);
1547 appDs->mDialogSet = dset;
1548 dset->setUserProfile(appDs->selectUASUserProfile(request));
1549 dset->mAppDialogSet = appDs;
1550
1551 DebugLog ( << "************* Adding DialogSet ***************" );
1552 DebugLog ( << "Before: " << Inserter(mDialogSetMap) );
1553 mDialogSetMap[dset->getId()] = dset;
1554 DebugLog ( << "After: Req" << Inserter(mDialogSetMap) );
1555
1556 dset->dispatch(request);
1557 }
1558 catch (BaseException& e)
1559 {
1560 SipMessage failure;
1561 makeResponse(failure, request, 400, e.getMessage());
1562 failure.header(h_AcceptLanguages) = getMasterProfile()->getSupportedLanguages();
1563 sendResponse(failure);
1564 }
1565
1566 break;
1567 }
1568 case RESPONSE:
1569 case SERVICE:
1570 assert(false);
1571 break;
1572 case UNKNOWN:
1573 case MAX_METHODS:
1574 assert(false);
1575 break;
1576 }
1577 }
1578 }
1579
1580 void
1581 DialogUsageManager::processResponse(const SipMessage& response)
1582 {
1583 if (response.header(h_CSeq).method() != CANCEL)
1584 {
1585 DialogSet* ds = findDialogSet(DialogSetId(response));
1586
1587 if (ds)
1588 {
1589 DebugLog ( << "DialogUsageManager::processResponse: " << response.brief());
1590 ds->dispatch(response);
1591 }
1592 else
1593 {
1594 InfoLog (<< "Throwing away stray response: " << response.brief());
1595 }
1596 }
1597 }
1598
1599 void
1600 DialogUsageManager::processPublish(const SipMessage& request)
1601 {
1602 if (!checkEventPackage(request))
1603 {
1604 InfoLog(<< "Rejecting request (unsupported package) " << request.brief());
1605 return;
1606 }
1607
1608 if (request.exists(h_SIPIfMatch))
1609 {
1610 ServerPublications::iterator i = mServerPublications.find(request.header(h_SIPIfMatch).value());
1611 if (i != mServerPublications.end())
1612 {
1613 i->second->dispatch(request);
1614 }
1615 else
1616 {
1617 SharedPtr<SipMessage> response(new SipMessage);
1618 makeResponse(*response, request, 412);
1619 send(response);
1620 }
1621 }
1622 else
1623 {
1624 Data etag = Random::getCryptoRandom(8);
1625 while (mServerPublications.find(etag) != mServerPublications.end())
1626 {
1627 etag = Random::getCryptoRandom(8);
1628 }
1629
1630 ServerPublication* sp = new ServerPublication(*this, etag, request);
1631 mServerPublications[etag] = sp;
1632 sp->dispatch(request);
1633 }
1634 }
1635
1636 bool
1637 DialogUsageManager::checkEventPackage(const SipMessage& request)
1638 {
1639 int failureCode = 0;
1640 MethodTypes method = request.header(h_RequestLine).method();
1641
1642 // || (method == NOTIFY && !request.exists(h_SubscriptionState)))
1643
1644 if (!request.exists(h_Event))
1645 {
1646 InfoLog (<< "No Event header in " << request.header(h_RequestLine).unknownMethodName());
1647 failureCode = 400;
1648 }
1649 else
1650 {
1651 switch(method)
1652 {
1653 case SUBSCRIBE:
1654 if (!getServerSubscriptionHandler(request.header(h_Event).value()))
1655 {
1656 InfoLog (<< "No handler for event package for SUBSCRIBE: "
1657 << request.header(h_Event).value());
1658 failureCode = 489;
1659 }
1660 break;
1661 case NOTIFY:
1662 if (!getClientSubscriptionHandler(request.header(h_Event).value()))
1663 {
1664 InfoLog (<< "No handler for event package for NOTIFY: "
1665 << request.header(h_Event).value());
1666 failureCode = 489;
1667 }
1668 break;
1669 case PUBLISH:
1670 if (!getServerPublicationHandler(request.header(h_Event).value()))
1671 {
1672 InfoLog (<< "No handler for event package for PUBLISH: "
1673 << request.header(h_Event).value());
1674 failureCode = 489;
1675 }
1676 break;
1677 default:
1678 assert(0);
1679 }
1680 }
1681
1682 if (failureCode > 0)
1683 {
1684 SharedPtr<SipMessage> response(new SipMessage);
1685 makeResponse(*response, request, failureCode);
1686 send(response);
1687 return false;
1688 }
1689 return true;
1690 }
1691
1692 DialogSet*
1693 DialogUsageManager::findDialogSet(const DialogSetId& id)
1694 {
1695 DebugLog ( << "Looking for dialogSet: " << id << " in map:" );
1696 DebugLog ( << Inserter(mDialogSetMap) );
1697 DialogSetMap::const_iterator it = mDialogSetMap.find(id);
1698
1699 if (it == mDialogSetMap.end())
1700 {
1701 return 0;
1702 }
1703 else
1704 {
1705 if(it->second->isDestroying())
1706 {
1707 return 0;
1708 }
1709 else
1710 {
1711 return it->second;
1712 }
1713 }
1714 }
1715
1716 BaseCreator*
1717 DialogUsageManager::findCreator(const DialogId& id)
1718 {
1719 DialogSet* ds = findDialogSet(id.getDialogSetId());
1720 if (ds)
1721 {
1722 return ds->getCreator();
1723 }
1724 else
1725 {
1726 return 0;
1727 }
1728 }
1729
1730 void
1731 DialogUsageManager::removeDialogSet(const DialogSetId& dsId)
1732 {
1733 DebugLog ( << "************* Removing DialogSet ***************" );
1734 DebugLog ( << "Before: " << Inserter(mDialogSetMap) );
1735 mDialogSetMap.erase(dsId);
1736 DebugLog ( << "After: " << Inserter(mDialogSetMap) );
1737 if (mRedirectManager.get())
1738 {
1739 mRedirectManager->removeDialogSet(dsId);
1740 }
1741 }
1742
1743 ClientSubscriptionHandler*
1744 DialogUsageManager::getClientSubscriptionHandler(const Data& eventType)
1745 {
1746 map<Data, ClientSubscriptionHandler*>::iterator res = mClientSubscriptionHandlers.find(eventType);
1747 if (res != mClientSubscriptionHandlers.end())
1748 {
1749 return res->second;
1750 }
1751 else
1752 {
1753 return 0;
1754 }
1755 }
1756
1757 ServerSubscriptionHandler*
1758 DialogUsageManager::getServerSubscriptionHandler(const Data& eventType)
1759 {
1760 map<Data, ServerSubscriptionHandler*>::iterator res = mServerSubscriptionHandlers.find(eventType);
1761 if (res != mServerSubscriptionHandlers.end())
1762 {
1763 return res->second;
1764 }
1765 else
1766 {
1767 return 0;
1768 }
1769 }
1770
1771 ClientPublicationHandler*
1772 DialogUsageManager::getClientPublicationHandler(const Data& eventType)
1773 {
1774 map<Data, ClientPublicationHandler*>::iterator res = mClientPublicationHandlers.find(eventType);
1775 if (res != mClientPublicationHandlers.end())
1776 {
1777 return res->second;
1778 }
1779 else
1780 {
1781 return 0;
1782 }
1783 }
1784
1785 ServerPublicationHandler*
1786 DialogUsageManager::getServerPublicationHandler(const Data& eventType)
1787 {
1788 map<Data, ServerPublicationHandler*>::iterator res = mServerPublicationHandlers.find(eventType);
1789 if (res != mServerPublicationHandlers.end())
1790 {
1791 return res->second;
1792 }
1793 else
1794 {
1795 return 0;
1796 }
1797 }
1798
1799 OutOfDialogHandler*
1800 DialogUsageManager::getOutOfDialogHandler(const MethodTypes type)
1801 {
1802 map<MethodTypes, OutOfDialogHandler*>::iterator res = mOutOfDialogHandlers.find(type);
1803 if (res != mOutOfDialogHandlers.end())
1804 {
1805 return res->second;
1806 }
1807 else
1808 {
1809 return 0;
1810 }
1811 }
1812
1813 void
1814 DialogUsageManager::addIncomingFeature(resip::SharedPtr<DumFeature> feat)
1815 {
1816 mIncomingFeatureList.push_back(feat);
1817 }
1818
1819 void
1820 DialogUsageManager::addOutgoingFeature(resip::SharedPtr<DumFeature> feat)
1821 {
1822 // make sure EncryptionManager is the last feature in the list.
1823 mOutgoingFeatureList.insert(mOutgoingFeatureList.begin(), feat);
1824 }
1825
1826 void
1827 DialogUsageManager::setOutgoingMessageInterceptor(SharedPtr<DumFeature> feat)
1828 {
1829 mOutgoingMessageInterceptor = feat;
1830 }
1831
1832 void
1833 DialogUsageManager::applyToAllServerSubscriptions(ServerSubscriptionFunctor* functor)
1834 {
1835 assert(functor);
1836 for (DialogSetMap::iterator it = mDialogSetMap.begin(); it != mDialogSetMap.end(); ++it)
1837 {
1838 for (DialogSet::DialogMap::iterator i = it->second->mDialogs.begin(); i != it->second->mDialogs.end(); ++i)
1839 {
1840 std::vector<ServerSubscriptionHandle> serverSubs = i->second->getServerSubscriptions();
1841 for (std::vector<ServerSubscriptionHandle>::iterator iss = serverSubs.begin(); iss != serverSubs.end(); ++iss)
1842 {
1843 functor->apply(*iss);
1844 }
1845 }
1846 }
1847 }
1848
1849 void
1850 DialogUsageManager::applyToAllClientSubscriptions(ClientSubscriptionFunctor* functor)
1851 {
1852 assert(functor);
1853 for (DialogSetMap::iterator it = mDialogSetMap.begin(); it != mDialogSetMap.end(); ++it)
1854 {
1855 for (DialogSet::DialogMap::iterator i = it->second->mDialogs.begin(); i != it->second->mDialogs.end(); ++i)
1856 {
1857 std::vector<ClientSubscriptionHandle> clientSubs = i->second->getClientSubscriptions();
1858 for (std::vector<ClientSubscriptionHandle>::iterator ics = clientSubs.begin(); ics != clientSubs.end(); ++ics)
1859 {
1860 functor->apply(*ics);
1861 }
1862 }
1863 }
1864 }
1865
1866 void
1867 DialogUsageManager::registerForConnectionTermination(Postable* listener)
1868 {
1869 mConnectionTerminatedEventDispatcher.addListener(listener);
1870 }
1871
1872 void
1873 DialogUsageManager::unRegisterForConnectionTermination(Postable* listener)
1874 {
1875 mConnectionTerminatedEventDispatcher.removeListener(listener);
1876 }
1877
1878 void
1879 DialogUsageManager::requestMergedRequestRemoval(const MergedRequestKey& key)
1880 {
1881 DebugLog(<< "Got merged request removal request");
1882 MergedRequestRemovalCommand command(*this, key);
1883 mStack.postMS(command, Timer::TF, this);
1884 }
1885
1886 void
1887 DialogUsageManager::removeMergedRequest(const MergedRequestKey& key)
1888 {
1889 DebugLog(<< "Merged request removed");
1890 mMergedRequests.erase(key);
1891 }
1892
1893
1894 /* ====================================================================
1895 * The Vovida Software License, Version 1.0
1896 *
1897 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1898 *
1899 * Redistribution and use in source and binary forms, with or without
1900 * modification, are permitted provided that the following conditions
1901 * are met:
1902 *
1903 * 1. Redistributions of source code must retain the above copyright
1904 * notice, this list of conditions and the following disclaimer.
1905 *
1906 * 2. Redistributions in binary form must reproduce the above copyright
1907 * notice, this list of conditions and the following disclaimer in
1908 * the documentation and/or other materials provided with the
1909 * distribution.
1910 *
1911 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1912 * and "Vovida Open Communication Application Library (VOCAL)" must
1913 * not be used to endorse or promote products derived from this
1914 * software without prior written permission. For written
1915 * permission, please contact vocal@vovida.org.
1916 *
1917 * 4. Products derived from this software may not be called "VOCAL", nor
1918 * may "VOCAL" appear in their name, without prior written
1919 * permission of Vovida Networks, Inc.
1920 *
1921 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1922 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1923 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1924 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1925 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1926 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1927 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1928 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1929 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1930 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1931 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1932 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1933 * DAMAGE.
1934 *
1935 * ====================================================================
1936 *
1937 * This software consists of voluntary contributions made by Vovida
1938 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1939 * Inc. For more information on Vovida Networks, Inc., please see
1940 * <http://www.vovida.org/>.
1941 *
1942 */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27