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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3676 - (show annotations) (download)
Wed Dec 1 02:03:55 2004 UTC (15 years ago) by derek
Original Path: main/sip/resiprocate/dum/Dialog.cxx
File size: 32159 byte(s)
implmented behaviour descirbed in sparks-sipping-dialogusage for usage & dialog lifetime
ClientSubscription must accept or reject any update(but now has the ability to accept or reject updates)

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 (msg.header(h_StatusLine).statusCode() >= 400
428 && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
429 {
430 //kill all usages
431 mDestroying = true;
432
433 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
434 it != mServerSubscriptions.end(); )
435 {
436 ServerSubscription* s = *it;
437 it++;
438 s->dialogDestroyed(msg);
439 }
440
441 for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
442 it != mClientSubscriptions.end(); )
443 {
444 ClientSubscription* s = *it;
445 it++;
446 s->dialogDestroyed(msg);
447 }
448 if (mInviteSession)
449 {
450 mInviteSession->dialogDestroyed(msg);
451 }
452 mDestroying = false;
453 possiblyDie(); //should aways result in destruction of this
454 return;
455 }
456
457
458 if (!mDialogSet.getCreator() ||
459 !(msg.header(h_CSeq) == mDialogSet.getCreator()->getLastRequest().header(h_CSeq)))
460 {
461 SipMessage* lastRequest = 0;
462 switch (msg.header(h_CSeq).method())
463 {
464 case INVITE:
465 case CANCEL:
466 case REFER:
467 case BYE:
468 if (mInviteSession == 0)
469 {
470 //spurious
471 return;
472 }
473 else
474 {
475 lastRequest = &mInviteSession->mLastRequest;
476 }
477 break;
478 case INFO:
479 {
480 if (mInviteSession == 0)
481 {
482 //spurious
483 return;
484 }
485 else
486 {
487 lastRequest = &mInviteSession->mLastNit;
488 }
489 break;
490 }
491 default:
492 break;
493 }
494 if ( lastRequest && mDum.mClientAuthManager.get() && mDum.mClientAuthManager->handle( *lastRequest, msg ) )
495 {
496 InfoLog( << "about to re-send request with digest credentials" );
497 InfoLog( << *lastRequest );
498 mLocalCSeq++;
499 mDum.send(*lastRequest);
500 return;
501 }
502 }
503
504 const SipMessage& response = msg;
505 int code = response.header(h_StatusLine).statusCode();
506 if (code >=200 && code < 300)
507 {
508 if (response.exists(h_RecordRoutes))
509 {
510 mRouteSet = response.header(h_RecordRoutes).reverse();
511 }
512 }
513
514 // !jf! should this only be for 2xx responses? !jf! Propose no as an
515 // answer !dcm! what is he on?
516 switch (response.header(h_CSeq).method())
517 {
518 case INVITE:
519 if (mInviteSession == 0)
520 {
521 // #if!jf! don't think creator needs a dispatch
522 //BaseCreator* creator = mDum.findCreator(mId);
523 //assert (creator); // stray responses have been rejected already
524 //creator->dispatch(response);
525 // #endif!jf!
526 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
527
528 mInviteSession = makeClientInviteSession(response);
529 mInviteSession->dispatch(response);
530 }
531 else
532 {
533 mInviteSession->dispatch(response);
534 }
535 break;
536 case BYE:
537 case ACK:
538 case CANCEL:
539 case INFO:
540 if (mInviteSession != 0)
541 {
542 mInviteSession->dispatch(response);
543 }
544 // else drop on the floor
545 break;
546 case REFER:
547 {
548 int code = response.header(h_StatusLine).statusCode();
549 if (code < 300)
550 {
551 // throw it away
552 return;
553 }
554 else
555 {
556 if (mInviteSession && mDum.mInviteSessionHandler)
557 {
558 mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), response);
559 }
560 }
561 }
562 break;
563 case SUBSCRIBE:
564 {
565 int code = response.header(h_StatusLine).statusCode();
566 if (code < 300)
567 {
568 // throw it away
569 return;
570 }
571 else
572 {
573 ClientSubscription* client = findMatchingClientSub(response);
574 if (client)
575 {
576 client->dispatch(response);
577 }
578 else
579 {
580 //!dcm! -- can't subscribe in an existing Dialog, this is all
581 //a bit of a hack; currently, spurious failure messages may cause callbacks
582 BaseCreator* creator = mDialogSet.getCreator();
583 if (!creator || !creator->getLastRequest().exists(h_Event))
584 {
585 return;
586 }
587 else
588 {
589 ClientSubscriptionHandler* handler =
590 mDum.getClientSubscriptionHandler(creator->getLastRequest().header(h_Event).value());
591 if (handler)
592 {
593 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
594 mClientSubscriptions.push_back(sub);
595 sub->dispatch(response);
596 }
597 }
598 }
599 }
600 }
601 break;
602 case NOTIFY:
603 {
604 //2xx responses are treated as retransmission quenchers(handled by
605 //the stack). Failures are dispatched to all ServerSubsscriptions,
606 //which may not be correct.
607
608 int code = msg.header(h_StatusLine).statusCode();
609 if (code >= 300)
610 {
611 //!dcm! -- ick, write guard
612 mDestroying = true;
613 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
614 it != mServerSubscriptions.end(); )
615 {
616 ServerSubscription* s = *it;
617 it++;
618 s->dispatch(msg);
619 }
620 mDestroying = false;
621 possiblyDie();
622 }
623 // ServerSubscription* server = findMatchingServerSub(response);
624 // if (server)
625 // {
626 // server->dispatch(response);
627 // }
628 }
629 break;
630 default:
631 assert(0);
632 return;
633 }
634 }
635 }
636
637 ServerSubscription*
638 Dialog::findMatchingServerSub(const SipMessage& msg)
639 {
640 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
641 i != mServerSubscriptions.end(); ++i)
642 {
643 if ((*i)->matches(msg))
644 {
645 return *i;
646 }
647 }
648 return 0;
649 }
650
651 ClientSubscription*
652 Dialog::findMatchingClientSub(const SipMessage& msg)
653 {
654 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
655 i != mClientSubscriptions.end(); ++i)
656 {
657 if ((*i)->matches(msg))
658 {
659 return *i;
660 }
661 }
662 return 0;
663 }
664
665 InviteSessionHandle
666 Dialog::getInviteSession()
667 {
668 if (mInviteSession)
669 {
670 return mInviteSession->getSessionHandle();
671 }
672 else
673 {
674 return InviteSessionHandle::NotValid();
675 }
676 }
677
678 std::vector<ClientSubscriptionHandle>
679 Dialog::findClientSubscriptions(const Data& event)
680 {
681 std::vector<ClientSubscriptionHandle> handles;
682
683 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
684 i != mClientSubscriptions.end(); ++i)
685 {
686 if ( (*i)->getEventType() == event)
687 {
688 handles.push_back((*i)->getHandle());
689 }
690 }
691 return handles;
692 }
693
694 std::vector<ServerSubscriptionHandle>
695 Dialog::findServerSubscriptions(const Data& event)
696 {
697 std::vector<ServerSubscriptionHandle> handles;
698
699 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
700 i != mServerSubscriptions.end(); ++i)
701 {
702 if ( (*i)->getEventType() == event)
703 {
704 handles.push_back((*i)->getHandle());
705 }
706 }
707 return handles;
708 }
709
710
711 std::vector<ClientSubscriptionHandle>
712 Dialog::getClientSubscriptions()
713 {
714 std::vector<ClientSubscriptionHandle> handles;
715
716 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
717 i != mClientSubscriptions.end(); ++i)
718 {
719 handles.push_back((*i)->getHandle());
720 }
721
722 return handles;
723 }
724
725 std::vector<ServerSubscriptionHandle>
726 Dialog::getServerSubscriptions()
727 {
728 std::vector<ServerSubscriptionHandle> handles;
729
730 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
731 i != mServerSubscriptions.end(); ++i)
732 {
733 handles.push_back((*i)->getHandle());
734 }
735
736 return handles;
737 }
738
739 void
740 Dialog::redirected(const SipMessage& msg)
741 {
742 //Established dialogs are not destroyed by a redirect
743 if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
744 {
745 return;
746 }
747 if (mInviteSession)
748 {
749 ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
750 if (cInv)
751 {
752 cInv->redirected(msg);
753 }
754 }
755 }
756
757
758 #if 0
759 void
760 Dialog::processNotify(const SipMessage& notify)
761 {
762 if (notify.isRequest())
763 {
764 if (findSubscriptions().empty())
765 {
766 SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
767 if (creator)
768 {
769 creator->makeNewSubscription(notify);
770 }
771 }
772 else
773 {
774 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
775 {
776 ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
777 if (sub && sub->matches(notify))
778 {
779 sub->process(notify);
780 break;
781 }
782 }
783 }
784 }
785 }
786 #endif
787
788
789 void
790 Dialog::makeRequest(SipMessage& request, MethodTypes method)
791 {
792 RequestLine rLine(method);
793
794 rLine.uri() = mRemoteTarget.uri();
795
796 request.header(h_RequestLine) = rLine;
797 request.header(h_To) = mRemoteNameAddr;
798 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
799 request.header(h_From) = mLocalNameAddr;
800 // request.header(h_From).param(p_tag) = mId.getLocalTag();
801
802 request.header(h_CallId) = mCallId;
803
804 request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
805
806 request.header(h_Contacts).clear();
807 request.header(h_Contacts).push_front(mLocalContact);
808 request.header(h_CSeq).method() = method;
809 request.header(h_MaxForwards).value() = 70;
810
811 //must keep old via for cancel
812 if (method != CANCEL)
813 {
814 request.header(h_Routes) = mRouteSet;
815 request.remove(h_Vias);
816 Via via;
817 via.param(p_branch); // will create the branch
818 request.header(h_Vias).push_front(via);
819 }
820 else
821 {
822 assert(request.exists(h_Vias));
823 }
824
825 //don't increment CSeq for ACK or CANCEL
826 if (method != ACK && method != CANCEL)
827 {
828 request.header(h_CSeq).sequence() = ++mLocalCSeq;
829 }
830 else
831 {
832 // ACK and cancel have a minimal header set
833 request.remove(h_Accepts);
834 request.remove(h_AcceptEncodings);
835 request.remove(h_AcceptLanguages);
836 request.remove(h_Allows);
837 request.remove(h_Requires);
838 request.remove(h_ProxyRequires);
839 request.remove(h_Supporteds);
840 }
841
842 // If method is INVITE then advertise required headers
843 if(method == INVITE)
844 {
845 if(mDum.getProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getProfile()->getAllowedMethods();
846 if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getProfile()->getSupportedEncodings();
847 if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getProfile()->getSupportedLanguages();
848 if(mDum.getProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getProfile()->getSupportedOptionTags();
849 }
850
851 // Remove Session Timer headers for all requests except INVITE and UPDATE
852 if(method != INVITE && method != UPDATE)
853 {
854 request.remove(h_SessionExpires);
855 request.remove(h_MinSE);
856 }
857 DebugLog ( << "Dialog::makeRequest: " << request );
858 }
859
860 void
861 Dialog::makeCancel(SipMessage& request)
862 {
863 //minimal for cancel
864 request.header(h_RequestLine).method() = CANCEL;
865 request.header(h_CSeq).method() = CANCEL;
866 request.remove(h_Accepts);
867 request.remove(h_AcceptEncodings);
868 request.remove(h_AcceptLanguages);
869 request.remove(h_Allows);
870 request.remove(h_Requires);
871 request.remove(h_ProxyRequires);
872 request.remove(h_Supporteds);
873 assert(request.exists(h_Vias));
874
875 //not sure of these
876 request.header(h_To).remove(p_tag);
877 request.remove(h_RecordRoutes);
878 request.header(h_Contacts).clear();
879 request.header(h_Contacts).push_front(mLocalContact);
880 request.header(h_MaxForwards).value() = 70;
881 }
882
883 void
884 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
885 {
886 assert( code >= 100 );
887 response.remove(h_Contacts);
888 if (code < 300 && code > 100)
889 {
890 assert(request.isRequest());
891 assert(request.header(h_RequestLine).getMethod() == INVITE ||
892 request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
893 request.header(h_RequestLine).getMethod() == BYE ||
894 request.header(h_RequestLine).getMethod() == CANCEL ||
895 request.header(h_RequestLine).getMethod() == REFER ||
896 request.header(h_RequestLine).getMethod() == MESSAGE ||
897 request.header(h_RequestLine).getMethod() == NOTIFY ||
898 request.header(h_RequestLine).getMethod() == INFO ||
899 request.header(h_RequestLine).getMethod() == OPTIONS
900 );
901
902 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
903 // request.header(h_RequestLine).getMethod() == BYE ||
904 // request.header(h_Contacts).size() == 1);
905 Helper::makeResponse(response, request, code, mLocalContact);
906 response.header(h_To).param(p_tag) = mId.getLocalTag();
907 }
908 else
909 {
910 Helper::makeResponse(response, request, code);
911 response.header(h_To).param(p_tag) = mId.getLocalTag();
912
913 }
914 DebugLog ( << "Dialog::makeResponse: " << response);
915 }
916
917
918 ClientInviteSession*
919 Dialog::makeClientInviteSession(const SipMessage& response)
920 {
921 InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
922 assert(creator); // !jf! this maybe can assert by evil UAS
923 //return mDum.createAppClientInviteSession(*this, *creator);
924 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
925 creator->getInitialOffer(), creator->getServerSubscription());
926 }
927
928
929
930 ClientSubscription*
931 Dialog::makeClientSubscription(const SipMessage& request)
932 {
933 return new ClientSubscription(mDum, *this, request);
934 }
935
936
937 ServerInviteSession*
938 Dialog::makeServerInviteSession(const SipMessage& request)
939 {
940 return new ServerInviteSession(mDum, *this, request);
941 }
942
943 ServerSubscription*
944 Dialog::makeServerSubscription(const SipMessage& request)
945 {
946 return new ServerSubscription(mDum, *this, request);
947 }
948
949 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
950 : BaseException(msg, file, line)
951 {
952 }
953
954 void
955 Dialog::update(const SipMessage& msg)
956 {
957 }
958
959 #if 0
960 void
961 Dialog::setLocalContact(const NameAddr& localContact)
962 {
963 mLocalContact = localContact;
964 }
965
966 void
967 Dialog::setRemoteTarget(const NameAddr& remoteTarget)
968 {
969 mRemoteTarget = remoteTarget;
970 }
971 #endif
972
973 void Dialog::possiblyDie()
974 {
975 if (!mDestroying)
976 {
977 if (mClientSubscriptions.empty() &&
978 mServerSubscriptions.empty() &&
979 !mInviteSession)
980 {
981 delete this;
982 }
983 }
984 }
985
986 bool
987 Dialog::matches(const SipMessage& msg)
988 {
989 //currently only responses are passed to this method
990 if (msg.isRequest())
991 {
992 return false;
993 }
994
995 switch (msg.header(h_CSeq).method())
996 {
997 case INVITE:
998 case CANCEL:
999 case REFER:
1000 case BYE:
1001 if (mInviteSession == 0)
1002 {
1003 return false;
1004 }
1005 else
1006 {
1007 return msg.getTransactionId() == mInviteSession->mLastRequest.getTransactionId();
1008 }
1009 break;
1010 case INFO:
1011 if (mInviteSession == 0)
1012 {
1013 return false;
1014 }
1015 else
1016 {
1017 return msg.getTransactionId() == mInviteSession->mLastNit.getTransactionId();
1018 }
1019 break;
1020 case SUBSCRIBE:
1021 if (mClientSubscriptions.empty())
1022 {
1023 return false;
1024 }
1025 else
1026 {
1027 for (std::list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
1028 it != mClientSubscriptions.end(); it++)
1029 {
1030 return msg.getTransactionId() == (*it)->mLastRequest.getTransactionId();
1031 }
1032 }
1033 break;
1034 case NOTIFY:
1035 if (mServerSubscriptions.empty())
1036 {
1037 return false;
1038 }
1039 else
1040 {
1041 for (std::list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
1042 it != mServerSubscriptions.end(); it++)
1043 {
1044 return msg.getTransactionId() == (*it)->mLastNotify.getTransactionId();
1045 }
1046 }
1047 break;
1048 default:
1049 return false;
1050 }
1051 return false;
1052 }
1053
1054 ostream&
1055 resip::operator<<(ostream& strm, const Dialog& dialog)
1056 {
1057
1058 return strm;
1059 }
1060

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27