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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27