/[resiprocate]/main/sip/resiprocate/dum/Dialog.cxx
ViewVC logotype

Contents of /main/sip/resiprocate/dum/Dialog.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3493 - (show annotations) (download)
Fri Nov 19 19:43:26 2004 UTC (15 years, 2 months ago) by sgodin
File size: 31178 byte(s)
-safety checks for existance of Event header. 
- make session timer helper methods private
1 #include "resiprocate/Contents.hxx"
2 #include "resiprocate/Helper.hxx"
3 #include "resiprocate/SipMessage.hxx"
4 #include "resiprocate/dum/AppDialog.hxx"
5 #include "resiprocate/dum/BaseCreator.hxx"
6 #include "resiprocate/dum/ClientAuthManager.hxx"
7 #include "resiprocate/dum/ClientInviteSession.hxx"
8 #include "resiprocate/dum/ClientSubscription.hxx"
9 #include "resiprocate/dum/Dialog.hxx"
10 #include "resiprocate/dum/DialogUsageManager.hxx"
11 #include "resiprocate/dum/InviteSessionCreator.hxx"
12 #include "resiprocate/dum/InviteSessionHandler.hxx"
13 #include "resiprocate/dum/ServerInviteSession.hxx"
14 #include "resiprocate/dum/ServerSubscription.hxx"
15 #include "resiprocate/dum/SubscriptionHandler.hxx"
16 #include "resiprocate/dum/UsageUseException.hxx"
17 #include "resiprocate/os/Logger.hxx"
18
19 #if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK)// Used for tracking down memory leaks in Visual Studio
20 #define _CRTDBG_MAP_ALLOC
21 #include <stdlib.h>
22 #include <crtdbg.h>
23 #define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
24 #endif // defined(WIN32) && defined(_DEBUG)
25
26 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
27
28 using namespace resip;
29 using namespace std;
30
31 Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg, DialogSet& ds)
32 : mDum(dum),
33 mDialogSet(ds),
34 mId("INVALID", "INVALID", "INVALID"),
35 mClientSubscriptions(),
36 mServerSubscriptions(),
37 mInviteSession(0),
38 mType(Fake),
39 mRouteSet(),
40 mLocalContact(),
41 mLocalCSeq(0),
42 mRemoteCSeq(0),
43 mRemoteTarget(),
44 mLocalNameAddr(),
45 mRemoteNameAddr(),
46 mCallId(msg.header(h_CallID)),
47 mAppDialog(0),
48 mDestroying(false)
49 {
50 assert(msg.isExternal());
51
52
53 if (msg.isRequest()) // UAS
54 {
55 const SipMessage& request = msg;
56
57 switch (request.header(h_CSeq).method())
58 {
59 case INVITE:
60 mType = Invitation;
61 break;
62
63 case SUBSCRIBE:
64 case REFER:
65 case NOTIFY:
66 //!dcm! -- event header check
67 mType = Subscription;
68 break;
69
70 default:
71 mType = Fake;
72 }
73 if (request.exists(h_RecordRoutes))
74 {
75 mRouteSet = request.header(h_RecordRoutes); // !jf! is this right order
76 }
77
78 switch (request.header(h_CSeq).method())
79 {
80 case INVITE:
81 case SUBSCRIBE:
82 case REFER:
83 case NOTIFY:
84 DebugLog ( << "UAS dialog ID creation, DS: " << ds.getId());
85 mId = DialogId(ds.getId(), request.header(h_From).param(p_tag));
86 mRemoteNameAddr = request.header(h_From);
87 mLocalNameAddr = request.header(h_To);
88 mLocalNameAddr.param(p_tag) = mId.getLocalTag();
89 if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
90 {
91 const NameAddr& contact = request.header(h_Contacts).front();
92 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
93 isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
94 {
95 mLocalContact = NameAddr(request.header(h_RequestLine).uri()); // update later when send a request
96 mRemoteTarget = contact;
97 }
98 else
99 {
100 InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme");
101 InfoLog(<< request);
102 throw Exception("Invalid scheme in request", __FILE__, __LINE__);
103 }
104 }
105 else
106 {
107 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
108 InfoLog (<< request);
109 throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__);
110 }
111 break;
112 default:
113 break;
114 }
115
116 mRemoteCSeq = request.header(h_CSeq).sequence();
117 mLocalCSeq = 1;
118
119 DebugLog ( << "************** Created Dialog as UAS **************" );
120 DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
121 DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
122 DebugLog ( << "mLocalContact: " << mLocalContact );
123 DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
124 }
125 else if (msg.isResponse())
126 {
127 mId = DialogId(msg);
128 const SipMessage& response = msg;
129 mRemoteNameAddr = response.header(h_To);
130 mLocalNameAddr = response.header(h_From);
131
132 switch (msg.header(h_CSeq).method())
133 {
134 case INVITE:
135 mType = Invitation;
136 break;
137
138 case SUBSCRIBE:
139 case REFER:
140 mType = Subscription;
141 break;
142
143 default:
144 mType = Fake;
145 }
146
147 if (response.exists(h_RecordRoutes))
148 {
149 mRouteSet = response.header(h_RecordRoutes).reverse();
150 }
151
152 switch (response.header(h_CSeq).method())
153 {
154 case INVITE:
155 case SUBSCRIBE:
156 case REFER:
157 if (response.header(h_StatusLine).statusCode() > 100 &&
158 response.header(h_StatusLine).statusCode() < 300)
159 {
160
161 if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
162 {
163 const NameAddr& contact = response.header(h_Contacts).front();
164 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
165 isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
166 {
167 BaseCreator* creator = mDialogSet.getCreator();
168 assert(creator);// !jf! throw or something here
169 assert(creator->getLastRequest().exists(h_Contacts));
170 assert(!creator->getLastRequest().header(h_Contacts).empty());
171 mLocalContact = creator->getLastRequest().header(h_Contacts).front();
172 mRemoteTarget = contact;
173 }
174 else
175 {
176 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
177 DebugLog (<< response);
178 throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
179 }
180 }
181 else
182 {
183 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
184 DebugLog (<< response);
185 throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
186 }
187 break;
188 default:
189 break;
190 }
191 }
192
193 mLocalCSeq = response.header(h_CSeq).sequence();
194 mRemoteCSeq = 0;
195 DebugLog ( << "************** Created Dialog as UAC **************" );
196 DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
197 DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
198 DebugLog ( << "mLocalContact: " << mLocalContact );
199 DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
200
201
202 }
203 mDialogSet.addDialog(this);
204 DebugLog ( <<"Dialog::Dialog " << mId);
205 }
206
207 Dialog::~Dialog()
208 {
209 DebugLog ( <<"Dialog::~Dialog() ");
210
211 mDestroying = true;
212
213 while (!mClientSubscriptions.empty())
214 {
215 delete *mClientSubscriptions.begin();
216 }
217
218 while (!mServerSubscriptions.empty())
219 {
220 delete *mServerSubscriptions.begin();
221 }
222
223 delete mInviteSession;
224
225 mDialogSet.mDialogs.erase(this->getId());
226 delete mAppDialog;
227 mDialogSet.possiblyDie();
228 }
229
230 DialogId
231 Dialog::getId() const
232 {
233 return mId;
234 }
235
236 void
237 Dialog::cancel()
238 {
239 if (mInviteSession)
240 {
241 mInviteSession->end();
242 }
243 else
244 {
245 if (mDialogSet.getCreator())
246 {
247 SipMessage& request = mDialogSet.getCreator()->getLastRequest();
248 if (request.header(h_RequestLine).method() == INVITE)
249 {
250 makeCancel(request);
251 mDum.send(request);
252 delete this;
253 }
254 else
255 {
256 throw UsageUseException("Can only CANCEL an INVITE", __FILE__, __LINE__);
257 }
258 }
259 else
260 {
261 throw UsageUseException("Attempting to cancel UAS dialogSet", __FILE__, __LINE__);
262 }
263 }
264 }
265
266 void
267 Dialog::dispatch(const SipMessage& msg)
268 {
269 DebugLog ( << "Dialog::dispatch: " << msg.brief());
270 if (msg.isRequest())
271 {
272 const SipMessage& request = msg;
273 switch (request.header(h_CSeq).method())
274 {
275 case INVITE: // new INVITE
276 if (mInviteSession == 0)
277 {
278 DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief());
279 mInviteSession = makeServerInviteSession(request);
280 }
281 mInviteSession->dispatch(request);
282 break;
283 //refactor, send bad request for BYE, INFO, CANCEL?
284 case BYE:
285 if (mInviteSession == 0)
286 {
287 InfoLog ( << "Spurious BYE" );
288 return;
289 }
290 else
291 {
292 mInviteSession->dispatch(request);
293 }
294 break;
295 case INFO:
296 if (mInviteSession == 0)
297 {
298 InfoLog ( << "Spurious INFO" );
299 return;
300 }
301 else
302 {
303 mInviteSession->dispatch(request);
304 }
305 break;
306 case ACK:
307 case CANCEL:
308 if (mInviteSession == 0)
309 {
310 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
311 DebugLog (<< request);
312 }
313 else
314 {
315 mInviteSession->dispatch(request);
316 }
317 break;
318 case SUBSCRIBE:
319 {
320 ServerSubscription* server = findMatchingServerSub(request);
321 if (server)
322 {
323 server->dispatch(request);
324 }
325 else
326 {
327 if (request.exists(h_Event) && request.header(h_Event).value() == "refer")
328 {
329 InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
330 SipMessage failure;
331 makeResponse(failure, request, 403);
332 mDum.sendResponse(failure);
333 return;
334 }
335 else
336 {
337 server = makeServerSubscription(request);
338 mServerSubscriptions.push_back(server);
339 server->dispatch(request);
340 }
341 }
342 // mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), server->getHandle(), msg);
343 }
344 break;
345 case REFER:
346 {
347 if (mInviteSession == 0)
348 {
349 InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
350 SipMessage failure;
351 makeResponse(failure, request, 405);
352 mDum.sendResponse(failure);
353 return;
354 }
355 else if (!request.exists(h_ReferTo))
356 {
357 InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
358 SipMessage failure;
359 makeResponse(failure, request, 400);
360 mDum.sendResponse(failure);
361 return;
362 }
363 else
364 {
365 ServerSubscription* server = findMatchingServerSub(request);
366 ServerSubscriptionHandle serverHandle;
367 if (server)
368 {
369 serverHandle = server->getHandle();
370 server->dispatch(request);
371 }
372 else
373 {
374 server = makeServerSubscription(request);
375 mServerSubscriptions.push_back(server);
376 serverHandle = server->getHandle();
377 server->dispatch(request);
378 }
379 mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), serverHandle, msg);
380 }
381 }
382 break;
383 case NOTIFY:
384 {
385 ClientSubscription* client = findMatchingClientSub(request);
386 if (client)
387 {
388 client->dispatch(request);
389 }
390 else
391 {
392 BaseCreator* creator = mDialogSet.getCreator();
393 if (creator && (creator->getLastRequest().header(h_RequestLine).method() == SUBSCRIBE ||
394 creator->getLastRequest().header(h_RequestLine).method() == REFER))
395 {
396 DebugLog (<< "Making subscription (from creator) request: " << creator->getLastRequest());
397 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
398 mClientSubscriptions.push_back(sub);
399 sub->dispatch(request);
400 }
401 else if (mInviteSession->mLastRequest.header(h_RequestLine).method() == REFER)
402 {
403 DebugLog (<< "Making subscription from refer: " << mInviteSession->mLastRequest);
404 ClientSubscription* sub = makeClientSubscription(mInviteSession->mLastRequest);
405 mClientSubscriptions.push_back(sub);
406 sub->dispatch(request);
407 }
408 else
409 {
410 SipMessage failure;
411 makeResponse(failure, request, 481);
412 failure.header(h_To).remove(p_tag); // otherwise it will be INVALID
413 InfoLog (<< "Sending 481 - no dialog created " << endl << failure);
414 mDum.sendResponse(failure);
415 return;
416 }
417 }
418 }
419 break;
420 default:
421 assert(0);
422 return;
423 }
424 }
425 else if (msg.isResponse())
426 {
427 if (!mDialogSet.getCreator() ||
428 !(msg.header(h_CSeq) == mDialogSet.getCreator()->getLastRequest().header(h_CSeq)))
429 {
430 SipMessage* lastRequest = 0;
431 switch (msg.header(h_CSeq).method())
432 {
433 case INVITE:
434 case CANCEL:
435 case REFER:
436 case BYE:
437 if (mInviteSession == 0)
438 {
439 //spurious
440 return;
441 }
442 else
443 {
444 lastRequest = &mInviteSession->mLastRequest;
445 }
446 break;
447 case INFO:
448 {
449 if (mInviteSession == 0)
450 {
451 //spurious
452 return;
453 }
454 else
455 {
456 lastRequest = &mInviteSession->mLastNit;
457 }
458 break;
459 }
460 default:
461 break;
462 }
463 if ( lastRequest && mDum.mClientAuthManager.get() && mDum.mClientAuthManager->handle( *lastRequest, msg ) )
464 {
465 InfoLog( << "about to re-send request with digest credentials" );
466 InfoLog( << *lastRequest );
467 mLocalCSeq++;
468 mDum.send(*lastRequest);
469 return;
470 }
471 }
472
473 const SipMessage& response = msg;
474 int code = response.header(h_StatusLine).statusCode();
475 if (code >=200 && code < 300)
476 {
477 if (response.exists(h_RecordRoutes))
478 {
479 mRouteSet = response.header(h_RecordRoutes).reverse();
480 }
481 }
482
483 // !jf! should this only be for 2xx responses? !jf! Propose no as an
484 // answer !dcm! what is he on?
485 switch (response.header(h_CSeq).method())
486 {
487 case INVITE:
488 if (mInviteSession == 0)
489 {
490 // #if!jf! don't think creator needs a dispatch
491 //BaseCreator* creator = mDum.findCreator(mId);
492 //assert (creator); // stray responses have been rejected already
493 //creator->dispatch(response);
494 // #endif!jf!
495 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
496
497 mInviteSession = makeClientInviteSession(response);
498 mInviteSession->dispatch(response);
499 }
500 else
501 {
502 mInviteSession->dispatch(response);
503 }
504 break;
505 case BYE:
506 case ACK:
507 case CANCEL:
508 case INFO:
509 if (mInviteSession != 0)
510 {
511 mInviteSession->dispatch(response);
512 }
513 // else drop on the floor
514 break;
515 case REFER:
516 {
517 int code = response.header(h_StatusLine).statusCode();
518 if (code < 300)
519 {
520 // throw it away
521 return;
522 }
523 else
524 {
525 if (mInviteSession && mDum.mInviteSessionHandler)
526 {
527 mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), response);
528 }
529 }
530 }
531 break;
532 case SUBSCRIBE:
533 {
534 int code = response.header(h_StatusLine).statusCode();
535 if (code < 300)
536 {
537 // throw it away
538 return;
539 }
540 else
541 {
542 ClientSubscription* client = findMatchingClientSub(response);
543 if (client)
544 {
545 client->dispatch(response);
546 }
547 else
548 {
549 //!dcm! -- can't subscribe in an existing Dialog, this is all
550 //a bit of a hack; currently, spurious failure messages may cause callbacks
551 BaseCreator* creator = mDialogSet.getCreator();
552 if (!creator || !creator->getLastRequest().exists(h_Event))
553 {
554 return;
555 }
556 else
557 {
558 ClientSubscriptionHandler* handler =
559 mDum.getClientSubscriptionHandler(creator->getLastRequest().header(h_Event).value());
560 if (handler)
561 {
562 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
563 mClientSubscriptions.push_back(sub);
564 sub->dispatch(response);
565 }
566 }
567 }
568 }
569 }
570 break;
571 case NOTIFY:
572 {
573 //2xx responses are treated as retransmission quenchers(handled by
574 //the stack). Failures are dispatched to all ServerSubsscriptions,
575 //which may not be correct.
576
577 int code = msg.header(h_StatusLine).statusCode();
578 if (code >= 300)
579 {
580 //!dcm! -- ick, write guard
581 mDestroying = true;
582 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
583 it != mServerSubscriptions.end(); )
584 {
585 ServerSubscription* s = *it;
586 it++;
587 s->dispatch(msg);
588 }
589 mDestroying = false;
590 possiblyDie();
591 }
592 // ServerSubscription* server = findMatchingServerSub(response);
593 // if (server)
594 // {
595 // server->dispatch(response);
596 // }
597 }
598 break;
599 default:
600 assert(0);
601 return;
602 }
603 }
604 }
605
606 ServerSubscription*
607 Dialog::findMatchingServerSub(const SipMessage& msg)
608 {
609 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
610 i != mServerSubscriptions.end(); ++i)
611 {
612 if ((*i)->matches(msg))
613 {
614 return *i;
615 }
616 }
617 return 0;
618 }
619
620 ClientSubscription*
621 Dialog::findMatchingClientSub(const SipMessage& msg)
622 {
623 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
624 i != mClientSubscriptions.end(); ++i)
625 {
626 if ((*i)->matches(msg))
627 {
628 return *i;
629 }
630 }
631 return 0;
632 }
633
634 InviteSessionHandle
635 Dialog::getInviteSession()
636 {
637 if (mInviteSession)
638 {
639 return mInviteSession->getSessionHandle();
640 }
641 else
642 {
643 return InviteSessionHandle::NotValid();
644 }
645 }
646
647 std::vector<ClientSubscriptionHandle>
648 Dialog::findClientSubscriptions(const Data& event)
649 {
650 std::vector<ClientSubscriptionHandle> handles;
651
652 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
653 i != mClientSubscriptions.end(); ++i)
654 {
655 if ( (*i)->getEventType() == event)
656 {
657 handles.push_back((*i)->getHandle());
658 }
659 }
660 return handles;
661 }
662
663 std::vector<ServerSubscriptionHandle>
664 Dialog::findServerSubscriptions(const Data& event)
665 {
666 std::vector<ServerSubscriptionHandle> handles;
667
668 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
669 i != mServerSubscriptions.end(); ++i)
670 {
671 if ( (*i)->getEventType() == event)
672 {
673 handles.push_back((*i)->getHandle());
674 }
675 }
676 return handles;
677 }
678
679
680 std::vector<ClientSubscriptionHandle>
681 Dialog::getClientSubscriptions()
682 {
683 std::vector<ClientSubscriptionHandle> handles;
684
685 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
686 i != mClientSubscriptions.end(); ++i)
687 {
688 handles.push_back((*i)->getHandle());
689 }
690
691 return handles;
692 }
693
694 std::vector<ServerSubscriptionHandle>
695 Dialog::getServerSubscriptions()
696 {
697 std::vector<ServerSubscriptionHandle> handles;
698
699 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
700 i != mServerSubscriptions.end(); ++i)
701 {
702 handles.push_back((*i)->getHandle());
703 }
704
705 return handles;
706 }
707
708 void
709 Dialog::redirected(const SipMessage& msg)
710 {
711 //Established dialogs are not destroyed by a redirect
712 if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
713 {
714 return;
715 }
716 if (mInviteSession)
717 {
718 ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
719 if (cInv)
720 {
721 cInv->redirected(msg);
722 }
723 }
724 }
725
726
727 #if 0
728 void
729 Dialog::processNotify(const SipMessage& notify)
730 {
731 if (notify.isRequest())
732 {
733 if (findSubscriptions().empty())
734 {
735 SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
736 if (creator)
737 {
738 creator->makeNewSubscription(notify);
739 }
740 }
741 else
742 {
743 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
744 {
745 ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
746 if (sub && sub->matches(notify))
747 {
748 sub->process(notify);
749 break;
750 }
751 }
752 }
753 }
754 }
755 #endif
756
757
758 void
759 Dialog::makeRequest(SipMessage& request, MethodTypes method)
760 {
761 RequestLine rLine(method);
762
763 rLine.uri() = mRemoteTarget.uri();
764
765 request.header(h_RequestLine) = rLine;
766 request.header(h_To) = mRemoteNameAddr;
767 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
768 request.header(h_From) = mLocalNameAddr;
769 // request.header(h_From).param(p_tag) = mId.getLocalTag();
770
771 request.header(h_CallId) = mCallId;
772
773 request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
774
775 request.header(h_Contacts).clear();
776 request.header(h_Contacts).push_front(mLocalContact);
777 request.header(h_CSeq).method() = method;
778 request.header(h_MaxForwards).value() = 70;
779
780 //must keep old via for cancel
781 if (method != CANCEL)
782 {
783 request.header(h_Routes) = mRouteSet;
784 request.remove(h_Vias);
785 Via via;
786 via.param(p_branch); // will create the branch
787 request.header(h_Vias).push_front(via);
788 }
789 else
790 {
791 assert(request.exists(h_Vias));
792 }
793
794 //don't increment CSeq for ACK or CANCEL
795 if (method != ACK && method != CANCEL)
796 {
797 request.header(h_CSeq).sequence() = ++mLocalCSeq;
798 }
799 else
800 {
801 // ACK and cancel have a minimal header set
802 request.remove(h_Accepts);
803 request.remove(h_AcceptEncodings);
804 request.remove(h_AcceptLanguages);
805 request.remove(h_Allows);
806 request.remove(h_Requires);
807 request.remove(h_ProxyRequires);
808 request.remove(h_Supporteds);
809 }
810
811 // If method is INVITE then advertise required headers
812 if(method == INVITE)
813 {
814 if(mDum.getProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getProfile()->getAllowedMethods();
815 if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getProfile()->getSupportedEncodings();
816 if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getProfile()->getSupportedLanguages();
817 if(mDum.getProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getProfile()->getSupportedOptionTags();
818 }
819
820 // Remove Session Timer headers for all requests except INVITE and UPDATE
821 if(method != INVITE && method != UPDATE)
822 {
823 request.remove(h_SessionExpires);
824 request.remove(h_MinSE);
825 }
826 DebugLog ( << "Dialog::makeRequest: " << request );
827 }
828
829 void
830 Dialog::makeCancel(SipMessage& request)
831 {
832 //minimal for cancel
833 request.header(h_RequestLine).method() = CANCEL;
834 request.header(h_CSeq).method() = CANCEL;
835 request.remove(h_Accepts);
836 request.remove(h_AcceptEncodings);
837 request.remove(h_AcceptLanguages);
838 request.remove(h_Allows);
839 request.remove(h_Requires);
840 request.remove(h_ProxyRequires);
841 request.remove(h_Supporteds);
842 assert(request.exists(h_Vias));
843
844 //not sure of these
845 request.header(h_To).remove(p_tag);
846 request.remove(h_RecordRoutes);
847 request.header(h_Contacts).clear();
848 request.header(h_Contacts).push_front(mLocalContact);
849 request.header(h_MaxForwards).value() = 70;
850 }
851
852 void
853 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
854 {
855 assert( code >= 100 );
856 response.remove(h_Contacts);
857 if (code < 300 && code > 100)
858 {
859 assert(request.isRequest());
860 assert(request.header(h_RequestLine).getMethod() == INVITE ||
861 request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
862 request.header(h_RequestLine).getMethod() == BYE ||
863 request.header(h_RequestLine).getMethod() == CANCEL ||
864 request.header(h_RequestLine).getMethod() == REFER ||
865 request.header(h_RequestLine).getMethod() == MESSAGE ||
866 request.header(h_RequestLine).getMethod() == NOTIFY ||
867 request.header(h_RequestLine).getMethod() == INFO ||
868 request.header(h_RequestLine).getMethod() == OPTIONS
869 );
870
871 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
872 // request.header(h_RequestLine).getMethod() == BYE ||
873 // request.header(h_Contacts).size() == 1);
874 Helper::makeResponse(response, request, code, mLocalContact);
875 response.header(h_To).param(p_tag) = mId.getLocalTag();
876 }
877 else
878 {
879 Helper::makeResponse(response, request, code);
880 response.header(h_To).param(p_tag) = mId.getLocalTag();
881
882 }
883 DebugLog ( << "Dialog::makeResponse: " << response);
884 }
885
886
887 ClientInviteSession*
888 Dialog::makeClientInviteSession(const SipMessage& response)
889 {
890 InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
891 assert(creator); // !jf! this maybe can assert by evil UAS
892 //return mDum.createAppClientInviteSession(*this, *creator);
893 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
894 creator->getInitialOffer(), creator->getServerSubscription());
895 }
896
897
898
899 ClientSubscription*
900 Dialog::makeClientSubscription(const SipMessage& request)
901 {
902 return new ClientSubscription(mDum, *this, request);
903 }
904
905
906 ServerInviteSession*
907 Dialog::makeServerInviteSession(const SipMessage& request)
908 {
909 return new ServerInviteSession(mDum, *this, request);
910 }
911
912 ServerSubscription*
913 Dialog::makeServerSubscription(const SipMessage& request)
914 {
915 return new ServerSubscription(mDum, *this, request);
916 }
917
918 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
919 : BaseException(msg, file, line)
920 {
921 }
922
923 void
924 Dialog::update(const SipMessage& msg)
925 {
926 }
927
928 #if 0
929 void
930 Dialog::setLocalContact(const NameAddr& localContact)
931 {
932 mLocalContact = localContact;
933 }
934
935 void
936 Dialog::setRemoteTarget(const NameAddr& remoteTarget)
937 {
938 mRemoteTarget = remoteTarget;
939 }
940 #endif
941
942 void Dialog::possiblyDie()
943 {
944 if (!mDestroying)
945 {
946 if (mClientSubscriptions.empty() &&
947 mServerSubscriptions.empty() &&
948 !mInviteSession)
949 {
950 delete this;
951 }
952 }
953 }
954
955 bool
956 Dialog::matches(const SipMessage& msg)
957 {
958 //currently only responses are passed to this method
959 if (msg.isRequest())
960 {
961 return false;
962 }
963
964 switch (msg.header(h_CSeq).method())
965 {
966 case INVITE:
967 case CANCEL:
968 case REFER:
969 case BYE:
970 if (mInviteSession == 0)
971 {
972 return false;
973 }
974 else
975 {
976 return msg.getTransactionId() == mInviteSession->mLastRequest.getTransactionId();
977 }
978 break;
979 case INFO:
980 if (mInviteSession == 0)
981 {
982 return false;
983 }
984 else
985 {
986 return msg.getTransactionId() == mInviteSession->mLastNit.getTransactionId();
987 }
988 break;
989 case SUBSCRIBE:
990 if (mClientSubscriptions.empty())
991 {
992 return false;
993 }
994 else
995 {
996 for (std::list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
997 it != mClientSubscriptions.end(); it++)
998 {
999 return msg.getTransactionId() == (*it)->mLastRequest.getTransactionId();
1000 }
1001 }
1002 break;
1003 case NOTIFY:
1004 if (mServerSubscriptions.empty())
1005 {
1006 return false;
1007 }
1008 else
1009 {
1010 for (std::list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
1011 it != mServerSubscriptions.end(); it++)
1012 {
1013 return msg.getTransactionId() == (*it)->mLastNotify.getTransactionId();
1014 }
1015 }
1016 break;
1017 default:
1018 return false;
1019 }
1020 return false;
1021 }
1022
1023 ostream&
1024 resip::operator<<(ostream& strm, const Dialog& dialog)
1025 {
1026
1027 return strm;
1028 }
1029

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27