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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27