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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3308 - (show annotations) (download)
Fri Sep 10 17:07:28 2004 UTC (15 years, 3 months ago) by derek
Original Path: main/sip/resiprocate/dum/Dialog.cxx
File size: 29004 byte(s)
added setOverrideHostAndPort for NAT traversal
if there is no to tag in a response, tid is used to dispatch to the correct dialog if one exists
temproary fix on onIllegalNegotiation; re-invite state machine needs tweaking

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 DebugLog(<< 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 DebugLog (<< 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
170 mLocalContact = creator->getLastRequest().header(h_Contacts).front();
171 mRemoteTarget = contact;
172 }
173 else
174 {
175 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
176 DebugLog (<< response);
177 throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
178 }
179 }
180 else
181 {
182 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
183 DebugLog (<< response);
184 throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
185 }
186 break;
187 default:
188 break;
189 }
190 }
191
192 mLocalCSeq = response.header(h_CSeq).sequence();
193 mRemoteCSeq = 0;
194 DebugLog ( << "************** Created Dialog as UAC **************" );
195 DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
196 DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
197 DebugLog ( << "mLocalContact: " << mLocalContact );
198 DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
199
200
201 }
202 mDialogSet.addDialog(this);
203 DebugLog ( <<"Dialog::Dialog " << mId);
204 }
205
206 Dialog::~Dialog()
207 {
208 DebugLog ( <<"Dialog::~Dialog() ");
209
210 mDestroying = true;
211
212 while (!mClientSubscriptions.empty())
213 {
214 delete *mClientSubscriptions.begin();
215 }
216
217 while (!mServerSubscriptions.empty())
218 {
219 delete *mServerSubscriptions.begin();
220 }
221
222 delete mInviteSession;
223
224 mDialogSet.mDialogs.erase(this->getId());
225 delete mAppDialog;
226 mDialogSet.possiblyDie();
227 }
228
229 DialogId
230 Dialog::getId() const
231 {
232 return mId;
233 }
234
235 void
236 Dialog::cancel()
237 {
238 if (mInviteSession)
239 {
240 mInviteSession->send(mInviteSession->end());
241 }
242 else
243 {
244 if (mDialogSet.getCreator())
245 {
246 SipMessage& request = mDialogSet.getCreator()->getLastRequest();
247 if (request.header(h_RequestLine).method() == INVITE)
248 {
249 makeCancel(request);
250 mDum.send(request);
251 delete this;
252 }
253 else
254 {
255 throw new UsageUseException("Can only CANCEL an INVITE", __FILE__, __LINE__);
256 }
257 }
258 else
259 {
260 throw new UsageUseException("Attempting to cancel UAS dialogSet", __FILE__, __LINE__);
261 }
262 }
263 }
264
265 void
266 Dialog::dispatch(const SipMessage& msg)
267 {
268 DebugLog ( << "Dialog::dispatch: " << msg.brief());
269 if (msg.isRequest())
270 {
271 const SipMessage& request = msg;
272 switch (request.header(h_CSeq).method())
273 {
274 case INVITE: // new INVITE
275 if (mInviteSession == 0)
276 {
277 DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief());
278 mInviteSession = makeServerInviteSession(request);
279 }
280 mInviteSession->dispatch(request);
281 break;
282 //refactor, send bad request for BYE, INFO, CANCEL?
283 case BYE:
284 if (mInviteSession == 0)
285 {
286 InfoLog ( << "Spurious BYE" );
287 return;
288 }
289 else
290 {
291 mInviteSession->dispatch(request);
292 }
293 break;
294 case INFO:
295 if (mInviteSession == 0)
296 {
297 InfoLog ( << "Spurious INFO" );
298 return;
299 }
300 else
301 {
302 mInviteSession->dispatch(request);
303 }
304 break;
305 case ACK:
306 case CANCEL:
307 if (mInviteSession == 0)
308 {
309 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
310 DebugLog (<< request);
311 }
312 else
313 {
314 mInviteSession->dispatch(request);
315 }
316 break;
317 case SUBSCRIBE:
318 {
319 ServerSubscription* server = findMatchingServerSub(request);
320 if (server)
321 {
322 server->dispatch(request);
323 }
324 else
325 {
326 if (request.header(h_Event).value() == "refer")
327 {
328 InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
329 SipMessage failure;
330 makeResponse(failure, request, 403);
331 mDum.sendResponse(failure);
332 return;
333 }
334 else
335 {
336 server = makeServerSubscription(request);
337 mServerSubscriptions.push_back(server);
338 server->dispatch(request);
339 }
340 }
341 mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), server->getHandle(), msg);
342 }
343 break;
344 case REFER:
345 {
346 if (mInviteSession == 0)
347 {
348 InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
349 SipMessage failure;
350 makeResponse(failure, request, 405);
351 mDum.sendResponse(failure);
352 return;
353 }
354 else if (!request.exists(h_ReferTo))
355 {
356 InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
357 SipMessage failure;
358 makeResponse(failure, request, 400);
359 mDum.sendResponse(failure);
360 return;
361 }
362 else
363 {
364 ServerSubscription* server = findMatchingServerSub(request);
365 if (server)
366 {
367 server->dispatch(request);
368 }
369 else
370 {
371 server = makeServerSubscription(request);
372 mServerSubscriptions.push_back(server);
373 server->dispatch(request);
374 }
375 mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), server->getHandle(), msg);
376 }
377 }
378 break;
379 case NOTIFY:
380 {
381 ClientSubscription* client = findMatchingClientSub(request);
382 if (client)
383 {
384 client->dispatch(request);
385 }
386 else
387 {
388 BaseCreator* creator = mDialogSet.getCreator();
389 if (creator && (creator->getLastRequest().header(h_RequestLine).method() == SUBSCRIBE ||
390 creator->getLastRequest().header(h_RequestLine).method() == REFER))
391 {
392 InfoLog (<< "Making subscription from creator: " << creator->getLastRequest());
393 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
394 mClientSubscriptions.push_back(sub);
395 sub->dispatch(request);
396 }
397 else if (mInviteSession->mLastRequest.header(h_RequestLine).method() == REFER)
398 {
399 InfoLog (<< "Making subscription from refer: " << mInviteSession->mLastRequest);
400 ClientSubscription* sub = makeClientSubscription(mInviteSession->mLastRequest);
401 mClientSubscriptions.push_back(sub);
402 sub->dispatch(request);
403 }
404 else
405 {
406 SipMessage failure;
407 makeResponse(failure, request, 481);
408 failure.header(h_To).remove(p_tag); // otherwise it will be INVALID
409 InfoLog (<< "Sending 481 - no dialog created " << endl << failure);
410 mDum.sendResponse(failure);
411 return;
412 }
413 }
414 }
415 break;
416 default:
417 assert(0);
418 return;
419 }
420 }
421 else if (msg.isResponse())
422 {
423 if (!mDialogSet.getCreator() ||
424 !(msg.header(h_CSeq) == mDialogSet.getCreator()->getLastRequest().header(h_CSeq)))
425 {
426 SipMessage* lastRequest = 0;
427 switch (msg.header(h_CSeq).method())
428 {
429 case INVITE:
430 case CANCEL:
431 case REFER:
432 case BYE:
433 case INFO:
434 if (mInviteSession == 0)
435 {
436 //spurious
437 return;
438 }
439 else
440 {
441 lastRequest = &mInviteSession->mLastRequest;
442 }
443 break;
444 default:
445 break;
446 }
447 if ( lastRequest && mDum.mClientAuthManager->handle( *lastRequest, msg ) )
448 {
449 InfoLog( << "about to re-send request with digest credentials" );
450 InfoLog( << *lastRequest );
451 mLocalCSeq++;
452 mDum.send(*lastRequest);
453 return;
454 }
455 }
456
457 const SipMessage& response = msg;
458 int code = response.header(h_StatusLine).statusCode();
459 if (code >=200 && code < 300)
460 {
461 if (response.exists(h_RecordRoutes))
462 {
463 mRouteSet = response.header(h_RecordRoutes).reverse();
464 }
465 }
466
467 // !jf! should this only be for 2xx responses? !jf! Propose no as an
468 // answer !dcm! what is he on?
469 switch (response.header(h_CSeq).method())
470 {
471 case INVITE:
472 if (mInviteSession == 0)
473 {
474 // #if!jf! don't think creator needs a dispatch
475 //BaseCreator* creator = mDum.findCreator(mId);
476 //assert (creator); // stray responses have been rejected already
477 //creator->dispatch(response);
478 // #endif!jf!
479 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
480
481 mInviteSession = makeClientInviteSession(response);
482 mInviteSession->dispatch(response);
483 }
484 else
485 {
486 mInviteSession->dispatch(response);
487 }
488 break;
489 case BYE:
490 case ACK:
491 case CANCEL:
492 case INFO:
493 if (mInviteSession != 0)
494 {
495 mInviteSession->dispatch(response);
496 }
497 // else drop on the floor
498 break;
499 case REFER:
500 {
501 int code = response.header(h_StatusLine).statusCode();
502 if (code < 300)
503 {
504 // throw it away
505 return;
506 }
507 else
508 {
509 if (mInviteSession && mDum.mInviteSessionHandler)
510 {
511 mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), response);
512 }
513 }
514 }
515 break;
516 case SUBSCRIBE:
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 ClientSubscription* client = findMatchingClientSub(response);
527 if (client)
528 {
529 client->dispatch(response);
530 }
531 else
532 {
533 //!dcm! -- can't subscribe in an existing Dialog, this is all
534 //a bit of a hack.
535 BaseCreator* creator = mDialogSet.getCreator();
536 if (!creator || !creator->getLastRequest().exists(h_Event))
537 {
538 return;
539 }
540 else
541 {
542 ClientSubscriptionHandler* handler =
543 mDum.getClientSubscriptionHandler(creator->getLastRequest().header(h_Event).value());
544 if (handler)
545 {
546 handler->onTerminated(ClientSubscriptionHandle::NotValid(), response);
547 possiblyDie();
548 }
549 }
550 }
551 }
552 }
553 break;
554 case NOTIFY:
555 {
556 //2xx responses are treated as retransmission quenchers(handled by
557 //the stack). Failures are dispatched to all ServerSubsscriptions,
558 //which may not be correct.
559
560 int code = msg.header(h_StatusLine).statusCode();
561 if (code >= 300)
562 {
563 //!dcm! -- ick, write guard
564 mDestroying = true;
565 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
566 it != mServerSubscriptions.end(); )
567 {
568 ServerSubscription* s = *it;
569 it++;
570 s->dispatch(msg);
571 }
572 mDestroying = false;
573 possiblyDie();
574 }
575 // ServerSubscription* server = findMatchingServerSub(response);
576 // if (server)
577 // {
578 // server->dispatch(response);
579 // }
580 }
581 break;
582 default:
583 assert(0);
584 return;
585 }
586 }
587 }
588
589 ServerSubscription*
590 Dialog::findMatchingServerSub(const SipMessage& msg)
591 {
592 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
593 i != mServerSubscriptions.end(); ++i)
594 {
595 if ((*i)->matches(msg))
596 {
597 return *i;
598 }
599 }
600 return 0;
601 }
602
603 ClientSubscription*
604 Dialog::findMatchingClientSub(const SipMessage& msg)
605 {
606 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
607 i != mClientSubscriptions.end(); ++i)
608 {
609 if ((*i)->matches(msg))
610 {
611 return *i;
612 }
613 }
614 return 0;
615 }
616
617 InviteSessionHandle
618 Dialog::getInviteSession()
619 {
620 if (mInviteSession)
621 {
622 return mInviteSession->getSessionHandle();
623 }
624 else
625 {
626 return InviteSessionHandle::NotValid();
627 }
628 }
629
630 std::vector<ClientSubscriptionHandle>
631 Dialog::findClientSubscriptions(const Data& event)
632 {
633 std::vector<ClientSubscriptionHandle> handles;
634
635 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
636 i != mClientSubscriptions.end(); ++i)
637 {
638 if ( (*i)->getEventType() == event)
639 {
640 handles.push_back((*i)->getHandle());
641 }
642 }
643 return handles;
644 }
645
646 std::vector<ServerSubscriptionHandle>
647 Dialog::findServerSubscriptions(const Data& event)
648 {
649 std::vector<ServerSubscriptionHandle> handles;
650
651 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
652 i != mServerSubscriptions.end(); ++i)
653 {
654 if ( (*i)->getEventType() == event)
655 {
656 handles.push_back((*i)->getHandle());
657 }
658 }
659 return handles;
660 }
661
662
663 std::vector<ClientSubscriptionHandle>
664 Dialog::getClientSubscriptions()
665 {
666 std::vector<ClientSubscriptionHandle> handles;
667
668 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
669 i != mClientSubscriptions.end(); ++i)
670 {
671 handles.push_back((*i)->getHandle());
672 }
673
674 return handles;
675 }
676
677 std::vector<ServerSubscriptionHandle>
678 Dialog::getServerSubscriptions()
679 {
680 std::vector<ServerSubscriptionHandle> handles;
681
682 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
683 i != mServerSubscriptions.end(); ++i)
684 {
685 handles.push_back((*i)->getHandle());
686 }
687
688 return handles;
689 }
690
691 void
692 Dialog::redirected(const SipMessage& msg)
693 {
694 //Established dialogs are not destroyed by a redirect
695 if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
696 {
697 return;
698 }
699 if (mInviteSession)
700 {
701 ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
702 if (cInv)
703 {
704 cInv->redirected(msg);
705 }
706 }
707 }
708
709
710 #if 0
711 void
712 Dialog::processNotify(const SipMessage& notify)
713 {
714 if (notify.isRequest())
715 {
716 if (findSubscriptions().empty())
717 {
718 SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
719 if (creator)
720 {
721 creator->makeNewSubscription(notify);
722 }
723 }
724 else
725 {
726 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
727 {
728 ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
729 if (sub && sub->matches(notify))
730 {
731 sub->process(notify);
732 break;
733 }
734 }
735 }
736 }
737 }
738 #endif
739
740
741 void
742 Dialog::makeRequest(SipMessage& request, MethodTypes method)
743 {
744 RequestLine rLine(method);
745
746 rLine.uri() = mRemoteTarget.uri();
747
748 request.header(h_RequestLine) = rLine;
749 request.header(h_To) = mRemoteNameAddr;
750 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
751 request.header(h_From) = mLocalNameAddr;
752 // request.header(h_From).param(p_tag) = mId.getLocalTag();
753
754 request.header(h_CallId) = mCallId;
755
756 request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
757
758 request.remove(h_Contacts);
759 request.header(h_Contacts).push_front(mLocalContact);
760 request.header(h_CSeq).method() = method;
761 request.header(h_MaxForwards).value() = 70;
762
763 //must keep old via for cancel
764 if (method != CANCEL)
765 {
766 request.header(h_Routes) = mRouteSet;
767 request.remove(h_Vias);
768 Via via;
769 via.param(p_branch); // will create the branch
770 request.header(h_Vias).push_front(via);
771 }
772 else
773 {
774 assert(request.exists(h_Vias));
775 }
776 //don't increment CSeq for ACK or CANCEL
777 if (method != ACK && method != CANCEL)
778 {
779 request.header(h_CSeq).sequence() = ++mLocalCSeq;
780 }
781 DebugLog ( << "Dialog::makeRequest: " << request );
782 }
783
784 void
785 Dialog::makeCancel(SipMessage& request)
786 {
787 //minimal for cancel
788 request.header(h_RequestLine).method() = CANCEL;
789 request.header(h_CSeq).method() = CANCEL;
790 request.remove(h_Requires);
791 request.remove(h_ProxyRequires);
792 assert(request.exists(h_Vias));
793
794 //not sure of these
795 request.header(h_To).remove(p_tag);
796 request.remove(h_RecordRoutes);
797 request.remove(h_Contacts);
798 request.header(h_Contacts).push_front(mLocalContact);
799 request.header(h_MaxForwards).value() = 70;
800 }
801
802 void
803 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
804 {
805 assert( code >= 100 );
806 response.remove(h_Contacts);
807 if (code < 300 && code > 100)
808 {
809 assert(request.isRequest());
810 assert(request.header(h_RequestLine).getMethod() == INVITE ||
811 request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
812 request.header(h_RequestLine).getMethod() == BYE ||
813 request.header(h_RequestLine).getMethod() == CANCEL ||
814 request.header(h_RequestLine).getMethod() == REFER ||
815 request.header(h_RequestLine).getMethod() == MESSAGE ||
816 request.header(h_RequestLine).getMethod() == NOTIFY ||
817 request.header(h_RequestLine).getMethod() == INFO ||
818 request.header(h_RequestLine).getMethod() == OPTIONS
819 );
820
821 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
822 // request.header(h_RequestLine).getMethod() == BYE ||
823 // request.header(h_Contacts).size() == 1);
824 Helper::makeResponse(response, request, code, mLocalContact);
825 response.header(h_To).param(p_tag) = mId.getLocalTag();
826 }
827 else
828 {
829 Helper::makeResponse(response, request, code);
830 response.header(h_To).param(p_tag) = mId.getLocalTag();
831
832 }
833 DebugLog ( << "Dialog::makeResponse: " << response);
834 }
835
836
837 ClientInviteSession*
838 Dialog::makeClientInviteSession(const SipMessage& response)
839 {
840 InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
841 assert(creator); // !jf! this maybe can assert by evil UAS
842 //return mDum.createAppClientInviteSession(*this, *creator);
843 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
844 creator->getInitialOffer(), creator->getServerSubscription());
845 }
846
847
848
849 ClientSubscription*
850 Dialog::makeClientSubscription(const SipMessage& request)
851 {
852 return new ClientSubscription(mDum, *this, request);
853 }
854
855
856 ServerInviteSession*
857 Dialog::makeServerInviteSession(const SipMessage& request)
858 {
859 return new ServerInviteSession(mDum, *this, request);
860 }
861
862 ServerSubscription*
863 Dialog::makeServerSubscription(const SipMessage& request)
864 {
865 return new ServerSubscription(mDum, *this, request);
866 }
867
868 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
869 : BaseException(msg, file, line)
870 {
871 }
872
873 void
874 Dialog::update(const SipMessage& msg)
875 {
876 }
877
878 #if 0
879 void
880 Dialog::setLocalContact(const NameAddr& localContact)
881 {
882 mLocalContact = localContact;
883 }
884
885 void
886 Dialog::setRemoteTarget(const NameAddr& remoteTarget)
887 {
888 mRemoteTarget = remoteTarget;
889 }
890 #endif
891
892 void Dialog::possiblyDie()
893 {
894 if (!mDestroying)
895 {
896 if (mClientSubscriptions.empty() &&
897 mServerSubscriptions.empty() &&
898 !mInviteSession)
899 {
900 delete this;
901 }
902 }
903 }
904
905 bool
906 Dialog::matches(const SipMessage& msg)
907 {
908 //currently only responses are passed to this method
909 if (msg.isRequest())
910 {
911 return false;
912 }
913
914 switch (msg.header(h_CSeq).method())
915 {
916 case INVITE:
917 case CANCEL:
918 case REFER:
919 case BYE:
920 if (mInviteSession == 0)
921 {
922 return false;
923 }
924 else
925 {
926 return msg.getTransactionId() == mInviteSession->mLastRequest.getTransactionId();
927 }
928 break;
929 case INFO:
930 if (mInviteSession == 0)
931 {
932 return false;
933 }
934 else
935 {
936 return msg.getTransactionId() == mInviteSession->mLastNit.getTransactionId();
937 }
938 break;
939 case SUBSCRIBE:
940 if (mClientSubscriptions.empty())
941 {
942 return false;
943 }
944 else
945 {
946 for (std::list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
947 it != mClientSubscriptions.end(); it++)
948 {
949 return msg.getTransactionId() == (*it)->mLastRequest.getTransactionId();
950 }
951 }
952 break;
953 case NOTIFY:
954 if (mServerSubscriptions.empty())
955 {
956 return false;
957 }
958 else
959 {
960 for (std::list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
961 it != mServerSubscriptions.end(); it++)
962 {
963 return msg.getTransactionId() == (*it)->mLastNotify.getTransactionId();
964 }
965 }
966 break;
967 default:
968 return false;
969 }
970 return false;
971 }
972
973 ostream&
974 resip::operator<<(ostream& strm, const Dialog& dialog)
975 {
976
977 return strm;
978 }
979

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27