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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27