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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27