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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6902 - (hide annotations) (download)
Mon Jan 22 15:23:08 2007 UTC (13 years ago) by sgodin
File MIME type: text/plain
File size: 37302 byte(s)
- fix to Dialog.cxx so that only 2xx responses to the original UAC request set the routeset 
1 derek 5283 #include "resip/stack/Contents.hxx"
2     #include "resip/stack/Helper.hxx"
3     #include "resip/stack/SipMessage.hxx"
4 jason 5276 #include "resip/dum/AppDialog.hxx"
5     #include "resip/dum/BaseCreator.hxx"
6     #include "resip/dum/ClientAuthManager.hxx"
7     #include "resip/dum/ClientInviteSession.hxx"
8     #include "resip/dum/ClientSubscription.hxx"
9     #include "resip/dum/Dialog.hxx"
10     #include "resip/dum/DialogUsageManager.hxx"
11     #include "resip/dum/MasterProfile.hxx"
12     #include "resip/dum/InviteSessionCreator.hxx"
13     #include "resip/dum/InviteSessionHandler.hxx"
14     #include "resip/dum/ServerInviteSession.hxx"
15     #include "resip/dum/ServerSubscription.hxx"
16     #include "resip/dum/SubscriptionHandler.hxx"
17     #include "resip/dum/UsageUseException.hxx"
18     #include "rutil/Logger.hxx"
19     #include "rutil/Inserter.hxx"
20     #include "rutil/WinLeakCheck.hxx"
21 davidb 2603
22     #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
23    
24 ken 2520 using namespace resip;
25     using namespace std;
26    
27 jason 4010 Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg, DialogSet& ds)
28 derek 2995 : mDum(dum),
29 derek 2867 mDialogSet(ds),
30 derek 3089 mId("INVALID", "INVALID", "INVALID"),
31 jason 2588 mClientSubscriptions(),
32 derek 3041 mServerSubscriptions(),
33 jason 2588 mInviteSession(0),
34     mType(Fake),
35     mRouteSet(),
36 jason 2611 mLocalContact(),
37 jason 2577 mLocalCSeq(0),
38     mRemoteCSeq(0),
39 derek 2981 mRemoteTarget(),
40 derek 2995 mLocalNameAddr(),
41     mRemoteNameAddr(),
42     mCallId(msg.header(h_CallID)),
43 mfroman 6495 mDefaultSubExpiration(0),
44 derek 3308 mAppDialog(0),
45 sgodin 5265 mDestroying(false),
46     mReUseDialogSet(false)
47 jason 2577 {
48 davidb 2603 assert(msg.isExternal());
49 jason 2577
50 jason 4010 assert(msg.header(h_CSeq).method() != MESSAGE);
51 derek 3750 assert(msg.header(h_CSeq).method() != REGISTER);
52     assert(msg.header(h_CSeq).method() != PUBLISH);
53    
54 derek 4062 mNetworkAssociation.setDum(&dum);
55    
56 jason 2577 if (msg.isRequest()) // UAS
57     {
58     const SipMessage& request = msg;
59    
60     switch (request.header(h_CSeq).method())
61     {
62 jason 3433 case INVITE:
63 jason 2611 mType = Invitation;
64     break;
65 jason 4010
66 jason 3433 case SUBSCRIBE:
67     case REFER:
68     case NOTIFY:
69 derek 3041 //!dcm! -- event header check
70 jason 2611 mType = Subscription;
71     break;
72    
73     default:
74     mType = Fake;
75     }
76 derek 3024 if (request.exists(h_RecordRoutes))
77     {
78 sgodin 6902 mRouteSet = request.header(h_RecordRoutes);
79 derek 3024 }
80 jason 2611
81     switch (request.header(h_CSeq).method())
82     {
83 jason 3433 case INVITE:
84     case SUBSCRIBE:
85     case REFER:
86     case NOTIFY:
87 jason 4010 DebugLog ( << "UAS dialog ID creation, DS: " << ds.getId());
88 derek 6410 mId = DialogId(ds.getId(),
89     request.header(h_From).exists(p_tag) ? request.header(h_From).param(p_tag) : Data::Empty);
90    
91 derek 2995 mRemoteNameAddr = request.header(h_From);
92     mLocalNameAddr = request.header(h_To);
93     mLocalNameAddr.param(p_tag) = mId.getLocalTag();
94 jason 2577 if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
95     {
96 davidb 2603 const NameAddr& contact = request.header(h_Contacts).front();
97 jason 2577 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
98     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
99     {
100 jason 4010 mLocalContact = NameAddr(request.header(h_RequestLine).uri()); // update later when send a request
101 jason 2577 mRemoteTarget = contact;
102 moetje 6160 if (mDialogSet.getUserProfile()->hasOverrideHostAndPort())
103     {
104     mLocalContact.uri().host() = mDialogSet.getUserProfile()->getOverrideHostAndPort().host();
105     mLocalContact.uri().port() = mDialogSet.getUserProfile()->getOverrideHostAndPort().port();
106     }
107 jason 2577 }
108     else
109     {
110 jason 3433 InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme");
111 jason 3483 InfoLog(<< request);
112 jason 2611 throw Exception("Invalid scheme in request", __FILE__, __LINE__);
113 jason 2577 }
114     }
115     else
116     {
117 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
118 jason 3483 InfoLog (<< request);
119 jason 2611 throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__);
120 jason 2577 }
121     break;
122 davidb 2603 default:
123     break;
124 jason 2577 }
125 jason 4010
126 jason 2577 mRemoteCSeq = request.header(h_CSeq).sequence();
127 jason 2611 mLocalCSeq = 1;
128 derek 2995
129 jason 4010 DebugLog ( << "************** Created Dialog as UAS **************" );
130     DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
131     DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
132 jason 3156 DebugLog ( << "mLocalContact: " << mLocalContact );
133     DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
134 jason 2577 }
135     else if (msg.isResponse())
136     {
137 jason 4010 mId = DialogId(msg);
138 jason 2577 const SipMessage& response = msg;
139 derek 2995 mRemoteNameAddr = response.header(h_To);
140     mLocalNameAddr = response.header(h_From);
141 jason 2611
142     switch (msg.header(h_CSeq).method())
143     {
144 jason 3433 case INVITE:
145 jason 2611 mType = Invitation;
146     break;
147 jason 4010
148 jason 3433 case SUBSCRIBE:
149     case REFER:
150 jason 2611 mType = Subscription;
151     break;
152    
153     default:
154     mType = Fake;
155     }
156    
157 jason 2577 if (response.exists(h_RecordRoutes))
158     {
159     mRouteSet = response.header(h_RecordRoutes).reverse();
160     }
161    
162     switch (response.header(h_CSeq).method())
163     {
164 jason 3433 case INVITE:
165     case SUBSCRIBE:
166     case REFER:
167 derek 2983 if (response.header(h_StatusLine).statusCode() > 100 &&
168     response.header(h_StatusLine).statusCode() < 300)
169 jason 2577 {
170 jason 4010
171 derek 2983 if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
172 jason 2577 {
173 derek 2983 const NameAddr& contact = response.header(h_Contacts).front();
174     if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
175 sgodin 6873 isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
176 derek 2983 {
177 jmatthewsr 6872 BaseCreator* creator = mDialogSet.getCreator();
178    
179 sgodin 6873 if( 0 == creator )
180     {
181     ErrLog(<< "BaseCreator is null for DialogSet");
182     ErrLog(<< response);
183     throw Exception("BaseCreator is null for DialogSet", __FILE__, __LINE__);
184     }
185    
186     SharedPtr<SipMessage> lastRequest(creator->getLastRequest());
187    
188 sgodin 6888 if( 0 == lastRequest.get() ||
189 sgodin 6873 !lastRequest->exists(h_Contacts) ||
190     lastRequest->header(h_Contacts).empty())
191     {
192     InfoLog(<< "lastRequest does not contain a valid contact");
193     InfoLog(<< response);
194     throw Exception("lastRequest does not contain a valid contact.", __FILE__, __LINE__);
195     }
196 daniel 5757 mLocalContact = creator->getLastRequest()->header(h_Contacts).front();
197 derek 2983 mRemoteTarget = contact;
198     }
199     else
200     {
201 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
202 derek 2983 DebugLog (<< response);
203     throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
204     }
205 jason 2577 }
206     else
207     {
208 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
209 jason 2577 DebugLog (<< response);
210 derek 2983 throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
211 jason 2577 }
212 derek 2983 break;
213     default:
214     break;
215 jason 2577 }
216     }
217 jason 4010
218 jason 2577 mLocalCSeq = response.header(h_CSeq).sequence();
219 jason 2611 mRemoteCSeq = 0;
220 jason 4010 DebugLog ( << "************** Created Dialog as UAC **************" );
221     DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
222     DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
223 jason 3156 DebugLog ( << "mLocalContact: " << mLocalContact );
224     DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
225 derek 2995
226 jason 4010
227 jason 2577 }
228 derek 2867 mDialogSet.addDialog(this);
229 derek 3081 DebugLog ( <<"Dialog::Dialog " << mId);
230 jason 2577 }
231    
232 jason 2868 Dialog::~Dialog()
233     {
234 derek 3081 DebugLog ( <<"Dialog::~Dialog() ");
235 jason 4010
236 derek 2981 mDestroying = true;
237 derek 3089
238     while (!mClientSubscriptions.empty())
239 derek 2981 {
240 derek 3089 delete *mClientSubscriptions.begin();
241 derek 2981 }
242 derek 3089
243     while (!mServerSubscriptions.empty())
244 derek 3041 {
245 derek 3089 delete *mServerSubscriptions.begin();
246 derek 3041 }
247 derek 3089
248 derek 2981 delete mInviteSession;
249 jason 2884 mDialogSet.mDialogs.erase(this->getId());
250 derek 2976 delete mAppDialog;
251 sgodin 5265 if(!mReUseDialogSet)
252     {
253     mDialogSet.possiblyDie();
254     }
255 jason 2868 }
256    
257 cktam 4408 const DialogId&
258 jason 2588 Dialog::getId() const
259     {
260     return mId;
261     }
262    
263 davidb 2604 void
264 jason 4010 Dialog::cancel()
265     {
266     assert(mType == Invitation);
267     ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
268     assert (uac);
269     uac->cancel();
270     }
271    
272     void
273 derek 3716 Dialog::end()
274 jason 2891 {
275 derek 3006 if (mInviteSession)
276     {
277 jason 3425 mInviteSession->end();
278 derek 3006 }
279     else
280     {
281 derek 3716 //!dcm! -- end subscriptions
282 derek 3006 }
283 jason 2891 }
284    
285     void
286 jason 3934 Dialog::handleTargetRefresh(const SipMessage& msg)
287     {
288     switch(msg.header(h_CSeq).method())
289     {
290     case INVITE:
291     case UPDATE:
292     if (msg.isRequest() || (msg.isResponse() && msg.header(h_StatusLine).statusCode()/100 == 2))
293     {
294     //?dcm? modify local target; 12.2.2 of 3261 implies that the remote
295     //target is immediately modified. Should we wait until a 2xx class
296     //reponse is sent to a re-invite(easy when all send requests go
297     //through Dialog)
298     if (msg.exists(h_Contacts))
299     {
300     //.dcm. replace or check then replace
301     mRemoteTarget = msg.header(h_Contacts).front();
302     }
303     }
304     break;
305     default:
306     return;
307     }
308     }
309    
310     void
311 davidb 2604 Dialog::dispatch(const SipMessage& msg)
312     {
313 jason 4010 // !jf! Should be checking for messages with out of order CSeq and rejecting
314    
315 jason 3156 DebugLog ( << "Dialog::dispatch: " << msg.brief());
316 daniel 5599
317 sgodin 6093 if(msg.isExternal())
318 sgodin 4113 {
319 sgodin 6093 const Data& receivedTransport = msg.header(h_Vias).front().transport();
320 daniel 5599 int keepAliveTime = 0;
321 sgodin 6093 if(receivedTransport == Symbols::TCP ||
322     receivedTransport == Symbols::TLS ||
323     receivedTransport == Symbols::SCTP)
324 daniel 5599 {
325     keepAliveTime = mDialogSet.getUserProfile()->getKeepAliveTimeForStream();
326     }
327     else
328     {
329     keepAliveTime = mDialogSet.getUserProfile()->getKeepAliveTimeForDatagram();
330     }
331    
332     if(keepAliveTime > 0)
333     {
334     mNetworkAssociation.update(msg, keepAliveTime);
335     }
336 sgodin 4113 }
337 daniel 5599
338 jason 3934 handleTargetRefresh(msg);
339 jason 2614 if (msg.isRequest())
340 jason 2583 {
341 jason 2614 const SipMessage& request = msg;
342     switch (request.header(h_CSeq).method())
343 jason 4010 {
344 jason 3433 case INVITE: // new INVITE
345 jason 2614 if (mInviteSession == 0)
346     {
347 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief());
348 jason 2885 mInviteSession = makeServerInviteSession(request);
349 jason 2614 }
350     mInviteSession->dispatch(request);
351     break;
352 jason 3433 //refactor, send bad request for BYE, INFO, CANCEL?
353     case BYE:
354 derek 2997 if (mInviteSession == 0)
355     {
356 jason 3433 InfoLog ( << "Spurious BYE" );
357 jason 4010 return;
358 derek 2997 }
359     else
360     {
361     mInviteSession->dispatch(request);
362     }
363     break;
364 jason 4010 case UPDATE:
365     if (mInviteSession == 0)
366     {
367     InfoLog ( << "Spurious UPDATE" );
368     return;
369     }
370     else
371     {
372     mInviteSession->dispatch(request);
373     }
374     break;
375 jason 3433 case INFO:
376 derek 3255 if (mInviteSession == 0)
377     {
378     InfoLog ( << "Spurious INFO" );
379 jason 4010 return;
380 derek 3255 }
381     else
382     {
383     mInviteSession->dispatch(request);
384     }
385     break;
386 sgodin 5265 case MESSAGE:
387     if (mInviteSession == 0)
388     {
389     InfoLog ( << "Spurious MESSAGE" );
390     return;
391     }
392     else
393     {
394     mInviteSession->dispatch(request);
395     }
396     break;
397 jason 3433 case ACK:
398     case CANCEL:
399 jason 2614 if (mInviteSession == 0)
400     {
401 jason 3433 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
402 jason 2614 DebugLog (<< request);
403     }
404     else
405     {
406     mInviteSession->dispatch(request);
407     }
408     break;
409 jason 3433 case SUBSCRIBE:
410 derek 3041 {
411     ServerSubscription* server = findMatchingServerSub(request);
412     if (server)
413 jason 2614 {
414 derek 3041 server->dispatch(request);
415 jason 2614 }
416 derek 3041 else
417     {
418 sgodin 3493 if (request.exists(h_Event) && request.header(h_Event).value() == "refer")
419 derek 3101 {
420     InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
421     SipMessage failure;
422     makeResponse(failure, request, 403);
423     mDum.sendResponse(failure);
424     return;
425     }
426     else
427     {
428 daniel 5738 if (mDum.checkEventPackage(request))
429     {
430     server = makeServerSubscription(request);
431     mServerSubscriptions.push_back(server);
432     server->dispatch(request);
433     }
434 derek 3101 }
435 derek 3041 }
436     }
437     break;
438 jason 3433 case REFER:
439 derek 3101 {
440 daniel 6126 // if (mInviteSession == 0)
441     // {
442     // InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
443     // SipMessage failure;
444     // makeResponse(failure, request, 603);
445     // mDum.sendResponse(failure);
446     // return;
447     // }
448     // else
449    
450     if (!request.exists(h_ReferTo))
451 derek 3101 {
452     InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
453     SipMessage failure;
454     makeResponse(failure, request, 400);
455     mDum.sendResponse(failure);
456     return;
457     }
458     else
459     {
460 daniel 5830 if (request.exists(h_ReferSub) && request.header(h_ReferSub).value()=="false")
461 derek 3101 {
462 daniel 6126 assert(mInviteSession);
463 daniel 5830 mInviteSession->referNoSub(msg);
464 derek 3101 }
465     else
466     {
467 daniel 5830 ServerSubscription* server = findMatchingServerSub(request);
468     ServerSubscriptionHandle serverHandle;
469     if (server)
470     {
471     serverHandle = server->getHandle();
472     server->dispatch(request);
473     }
474     else
475     {
476     server = makeServerSubscription(request);
477     mServerSubscriptions.push_back(server);
478     serverHandle = server->getHandle();
479     server->dispatch(request);
480     }
481 daniel 6126
482     if (mInviteSession)
483     {
484     mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), serverHandle, msg);
485     }
486    
487 derek 3101 }
488     }
489     }
490     break;
491 jason 3433 case NOTIFY:
492 derek 3089 {
493     ClientSubscription* client = findMatchingClientSub(request);
494     if (client)
495 jason 2614 {
496 derek 3089 client->dispatch(request);
497     }
498     else
499     {
500 jason 3182 BaseCreator* creator = mDialogSet.getCreator();
501 daniel 5757 if (creator && (creator->getLastRequest()->header(h_RequestLine).method() == SUBSCRIBE ||
502 daniel 5830 creator->getLastRequest()->header(h_RequestLine).method() == REFER))
503 jason 2612 {
504 daniel 5757 DebugLog (<< "Making subscription (from creator) request: " << *creator->getLastRequest());
505     ClientSubscription* sub = makeClientSubscription(*creator->getLastRequest());
506 derek 3089 mClientSubscriptions.push_back(sub);
507     sub->dispatch(request);
508 jason 2612 }
509     else
510     {
511 jason 4010 if (mInviteSession != 0 && (!msg.exists(h_Event) || msg.header(h_Event).value() == "refer"))
512     {
513     DebugLog (<< "Making subscription from NOTIFY: " << msg);
514     ClientSubscription* sub = makeClientSubscription(msg);
515     mClientSubscriptions.push_back(sub);
516 derek 6119 ClientSubscriptionHandle client = sub->getHandle();
517     mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), client, msg);
518     mInviteSession->mSentRefer = false;
519 jason 4010 sub->dispatch(request);
520     }
521     else
522     {
523 daniel 5757 SharedPtr<SipMessage> response(new SipMessage);
524     makeResponse(*response, msg, 406);
525 jason 4010 send(response);
526     }
527     }
528 jason 2614 }
529 derek 3089 }
530     break;
531     default:
532     assert(0);
533     return;
534 jason 2583 }
535 jason 2614 }
536     else if (msg.isResponse())
537     {
538 jason 4010 // !jf! There is a substantial change in how this works in teltel-branch
539     // from how it worked in main branch pre merge.
540     // If the response doesn't match a cseq for a request I've sent, ignore
541     // the response
542     RequestMap::iterator r = mRequests.find(msg.header(h_CSeq).sequence());
543     if (r != mRequests.end())
544 derek 3089 {
545 sgodin 6197 bool handledByAuth = false;
546 derek 4803 if (mDum.mClientAuthManager.get() &&
547 daniel 5757 mDum.mClientAuthManager->handle(*mDialogSet.getUserProfile(), *r->second, msg))
548 derek 3089 {
549 daniel 5757 InfoLog( << "about to re-send request with digest credentials" << r->second->brief());
550 jason 4010
551 daniel 5757 assert (r->second->isRequest());
552 jason 4010
553     mLocalCSeq++;
554     send(r->second);
555 sgodin 6197 handledByAuth = true;
556 derek 3089 }
557 jason 4010 mRequests.erase(r);
558 sgodin 6197 if (handledByAuth) return;
559 derek 3089 }
560 derek 5642
561 jason 2614 const SipMessage& response = msg;
562 derek 3112 int code = response.header(h_StatusLine).statusCode();
563 sgodin 6902 // If this is a 200 response to the initial request, then store the routeset (if present)
564     if (creator && (creator->getLastRequest()->header(h_CSeq).sequence() == response.header(h_CSeq).sequence()) && code >=200 && code < 300)
565 derek 3112 {
566     if (response.exists(h_RecordRoutes))
567     {
568     mRouteSet = response.header(h_RecordRoutes).reverse();
569     }
570     }
571 jason 4010
572 jason 2885 // !jf! should this only be for 2xx responses? !jf! Propose no as an
573     // answer !dcm! what is he on?
574 jason 2614 switch (response.header(h_CSeq).method())
575 jason 2583 {
576 jason 3433 case INVITE:
577 jason 2614 if (mInviteSession == 0)
578     {
579 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
580 derek 2992
581 jason 2885 mInviteSession = makeClientInviteSession(response);
582     mInviteSession->dispatch(response);
583 jason 2614 }
584     else
585     {
586     mInviteSession->dispatch(response);
587     }
588     break;
589 jason 3433 case BYE:
590     case ACK:
591     case CANCEL:
592     case INFO:
593 sgodin 5265 case MESSAGE:
594 jason 4010 case UPDATE:
595     if (mInviteSession)
596 jason 2614 {
597     mInviteSession->dispatch(response);
598     }
599     // else drop on the floor
600 jason 4010 break;
601    
602     case REFER:
603 sgodin 4021 if(mInviteSession)
604 jason 2612 {
605 sgodin 4021 mInviteSession->mSentRefer = false;
606    
607     if (code >= 300)
608     {
609     mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), msg);
610     }
611 daniel 5830 else
612     {
613 daniel 6074 //!dys! the OR condition below is not draft compliant.
614     if (!mInviteSession->mReferSub &&
615     ((msg.exists(h_ReferSub) && msg.header(h_ReferSub).value()=="false") ||
616     !msg.exists(h_ReferSub)))
617 daniel 5830 {
618 daniel 6074 DebugLog(<< "refer accepted with norefersub");
619 daniel 5830 mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), ClientSubscriptionHandle::NotValid(), msg);
620     }
621     // else no need for action - first Notify will cause onReferAccepted to be called
622     }
623 daniel 6126 break;
624 jason 4010 }
625 daniel 6126 // fall through, out of dialog refer was sent.
626 mfroman 6495
627 jason 3433 case SUBSCRIBE:
628 derek 3058 {
629     int code = response.header(h_StatusLine).statusCode();
630 daniel 5767 ClientSubscription* client = findMatchingClientSub(response);
631     if (client)
632 derek 3058 {
633 daniel 5767 client->dispatch(response);
634     }
635     else if (code < 300)
636     {
637 mfroman 6495 /*
638     we're capturing the value from the expires header off
639     the 2xx because the ClientSubscription is only created
640     after receiving the NOTIFY that comes (usually) after
641     this 2xx. We really should be creating the
642     ClientSubscription at either the 2xx or the NOTIFY
643     whichever arrives first. .mjf.
644     Note: we're capturing a duration here (not the
645     absolute time because all the inputs to
646     ClientSubscription desling with the expiration are expecting
647     duration type values from the headers. .mjf.
648     */
649     mDefaultSubExpiration = response.header(h_Expires).value();
650 derek 3058 return;
651 jason 4010 }
652 derek 3058 else
653     {
654 daniel 5767 //!dcm! -- can't subscribe in an existing Dialog, this is all
655     //a bit of a hack; currently, spurious failure messages may cause callbacks
656     BaseCreator* creator = mDialogSet.getCreator();
657     if (!creator || !creator->getLastRequest()->exists(h_Event))
658 derek 3058 {
659 daniel 5767 return;
660 derek 3058 }
661 derek 3082 else
662     {
663 daniel 5767 ClientSubscriptionHandler* handler =
664     mDum.getClientSubscriptionHandler(creator->getLastRequest()->header(h_Event).value());
665     if (handler)
666 derek 3274 {
667 daniel 5767 ClientSubscription* sub = makeClientSubscription(*creator->getLastRequest());
668     mClientSubscriptions.push_back(sub);
669     sub->dispatch(response);
670 derek 3274 }
671 derek 3082 }
672 jason 2614 }
673 daniel 5767
674 jason 2614 }
675 derek 3058 break;
676 jason 3433 case NOTIFY:
677 derek 3101 {
678 derek 3274 //2xx responses are treated as retransmission quenchers(handled by
679     //the stack). Failures are dispatched to all ServerSubsscriptions,
680     //which may not be correct.
681    
682     int code = msg.header(h_StatusLine).statusCode();
683     if (code >= 300)
684 derek 3101 {
685 derek 3274 //!dcm! -- ick, write guard
686 jason 4010 mDestroying = true;
687 derek 3274 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
688     it != mServerSubscriptions.end(); )
689     {
690     ServerSubscription* s = *it;
691     it++;
692     s->dispatch(msg);
693     }
694     mDestroying = false;
695     possiblyDie();
696 derek 3101 }
697 derek 3274 // ServerSubscription* server = findMatchingServerSub(response);
698     // if (server)
699     // {
700     // server->dispatch(response);
701     // }
702 derek 3101 }
703 jason 4010 break;
704 derek 3101 default:
705     assert(0);
706     return;
707 jason 2583 }
708 jason 4010
709     #if 0 // merged from head back to teltel-branch
710     if (msg.header(h_StatusLine).statusCode() >= 400
711 derek 3750 && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
712     {
713     //kill all usages
714 jason 4010 mDestroying = true;
715    
716 derek 3750 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
717     it != mServerSubscriptions.end(); )
718     {
719     ServerSubscription* s = *it;
720     it++;
721     s->dialogDestroyed(msg);
722 jason 4010 }
723 derek 3750
724     for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
725     it != mClientSubscriptions.end(); )
726     {
727     ClientSubscription* s = *it;
728     it++;
729     s->dialogDestroyed(msg);
730     }
731     if (mInviteSession)
732     {
733     mInviteSession->dialogDestroyed(msg);
734     }
735     mDestroying = false;
736     possiblyDie(); //should aways result in destruction of this
737 jason 4010 return;
738     }
739 derek 3750 #endif
740 jason 2583 }
741 jason 2578 }
742    
743 jason 4010 ServerSubscription*
744 derek 3041 Dialog::findMatchingServerSub(const SipMessage& msg)
745     {
746 jason 4010 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
747 derek 3041 i != mServerSubscriptions.end(); ++i)
748     {
749     if ((*i)->matches(msg))
750     {
751     return *i;
752     }
753     }
754     return 0;
755     }
756 jason 2612
757 jason 4010 ClientSubscription*
758 jason 2612 Dialog::findMatchingClientSub(const SipMessage& msg)
759 jason 2583 {
760 jason 4010 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
761 jason 2612 i != mClientSubscriptions.end(); ++i)
762 jason 2583 {
763 jason 2614 if ((*i)->matches(msg))
764 jason 2612 {
765 jason 2614 return *i;
766 jason 2612 }
767     }
768 jason 2614 return 0;
769 jason 2612 }
770 jason 2585
771 jason 2941 InviteSessionHandle
772 derek 3041 Dialog::getInviteSession()
773 ken 2520 {
774 davidb 2603 if (mInviteSession)
775     {
776     return mInviteSession->getSessionHandle();
777     }
778     else
779     {
780 derek 3041 return InviteSessionHandle::NotValid();
781 davidb 2603 }
782 ken 2520 }
783    
784 jason 4010 std::vector<ClientSubscriptionHandle>
785 derek 3041 Dialog::findClientSubscriptions(const Data& event)
786 ken 2520 {
787 jason 2941 std::vector<ClientSubscriptionHandle> handles;
788 jason 4010
789 derek 2858 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
790 davidb 2603 i != mClientSubscriptions.end(); ++i)
791     {
792 derek 3041 if ( (*i)->getEventType() == event)
793     {
794     handles.push_back((*i)->getHandle());
795     }
796     }
797     return handles;
798     }
799    
800 jason 4010 std::vector<ServerSubscriptionHandle>
801 derek 3041 Dialog::findServerSubscriptions(const Data& event)
802     {
803     std::vector<ServerSubscriptionHandle> handles;
804 jason 4010
805 derek 3041 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
806     i != mServerSubscriptions.end(); ++i)
807     {
808     if ( (*i)->getEventType() == event)
809     {
810     handles.push_back((*i)->getHandle());
811     }
812     }
813     return handles;
814     }
815    
816 jason 4010 std::vector<ClientSubscriptionHandle>
817 derek 3041 Dialog::getClientSubscriptions()
818     {
819     std::vector<ClientSubscriptionHandle> handles;
820 jason 4010
821 derek 3041 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
822     i != mClientSubscriptions.end(); ++i)
823     {
824 davidb 2603 handles.push_back((*i)->getHandle());
825     }
826    
827     return handles;
828 ken 2520 }
829    
830 jason 4010 std::vector<ServerSubscriptionHandle>
831 derek 3041 Dialog::getServerSubscriptions()
832     {
833     std::vector<ServerSubscriptionHandle> handles;
834 jason 4010
835 derek 3041 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
836     i != mServerSubscriptions.end(); ++i)
837     {
838     handles.push_back((*i)->getHandle());
839     }
840    
841     return handles;
842     }
843    
844 jason 4010 void
845 derek 3179 Dialog::redirected(const SipMessage& msg)
846     {
847     //Established dialogs are not destroyed by a redirect
848     if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
849     {
850     return;
851     }
852     if (mInviteSession)
853     {
854     ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
855     if (cInv)
856     {
857 jason 4010 cInv->handleRedirect(msg);
858 sgodin 5265 mReUseDialogSet = true; // Set flag so that DialogSet will not be destroyed and new Request can use it
859 derek 3179 }
860     }
861     }
862 ken 2520
863 jason 2539 void
864 derek 2813 Dialog::makeRequest(SipMessage& request, MethodTypes method)
865     {
866     RequestLine rLine(method);
867    
868 derek 2817 rLine.uri() = mRemoteTarget.uri();
869 jason 4010
870 derek 2813 request.header(h_RequestLine) = rLine;
871 jason 4010 request.header(h_To) = mRemoteNameAddr;
872 derek 2995 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
873 jason 4010 request.header(h_From) = mLocalNameAddr;
874     // request.header(h_From).param(p_tag) = mId.getLocalTag();
875 derek 2813
876     request.header(h_CallId) = mCallId;
877 derek 2997
878     request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
879 sgodin 6198 request.remove(h_Replaces);
880 derek 2997
881 jason 4010 request.remove(h_Contacts);
882     request.header(h_Contacts).push_front(mLocalContact);
883    
884 derek 2813 request.header(h_CSeq).method() = method;
885     request.header(h_MaxForwards).value() = 70;
886    
887 derek 2961 //must keep old via for cancel
888 jason 3433 if (method != CANCEL)
889 derek 2961 {
890 derek 3024 request.header(h_Routes) = mRouteSet;
891 jason 4010 request.remove(h_Vias);
892 derek 2961 Via via;
893     via.param(p_branch); // will create the branch
894     request.header(h_Vias).push_front(via);
895     }
896     else
897     {
898     assert(request.exists(h_Vias));
899     }
900 sgodin 3392
901 jason 3433 //don't increment CSeq for ACK or CANCEL
902     if (method != ACK && method != CANCEL)
903 derek 2965 {
904     request.header(h_CSeq).sequence() = ++mLocalCSeq;
905     }
906 sgodin 3383 else
907     {
908 jason 3433 // ACK and cancel have a minimal header set
909 sgodin 3383 request.remove(h_Accepts);
910     request.remove(h_AcceptEncodings);
911     request.remove(h_AcceptLanguages);
912     request.remove(h_Allows);
913     request.remove(h_Requires);
914     request.remove(h_ProxyRequires);
915     request.remove(h_Supporteds);
916 sgodin 5586 // request.header(h_CSeq).sequence() = ?; // Caller should provide original request, or modify CSeq to proper value after calling this method
917 sgodin 3383 }
918 sgodin 3392
919 jason 3433 // If method is INVITE then advertise required headers
920 jason 4010 if(method == INVITE || method == UPDATE)
921 sgodin 3392 {
922 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
923     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
924     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
925 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) request.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
926 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
927 sgodin 3392 }
928    
929 jason 6075 if (mDialogSet.mUserProfile->isAnonymous())
930     {
931     request.header(h_Privacys).push_back(Token(Symbols::id));
932     }
933    
934 jmatthewsr 6643 DebugLog ( << "Dialog::makeRequest: " << std::endl << std::endl << request );
935 derek 2813 }
936    
937 derek 3138
938 jason 4010 void
939 jason 2887 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
940 derek 2813 {
941     assert( code >= 100 );
942 jason 4010 response.remove(h_Contacts);
943 derek 2992 if (code < 300 && code > 100)
944 derek 2813 {
945     assert(request.isRequest());
946 jason 3433 assert(request.header(h_RequestLine).getMethod() == INVITE ||
947     request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
948     request.header(h_RequestLine).getMethod() == BYE ||
949     request.header(h_RequestLine).getMethod() == CANCEL ||
950     request.header(h_RequestLine).getMethod() == REFER ||
951     request.header(h_RequestLine).getMethod() == MESSAGE ||
952     request.header(h_RequestLine).getMethod() == NOTIFY ||
953     request.header(h_RequestLine).getMethod() == INFO ||
954 jason 4010 request.header(h_RequestLine).getMethod() == OPTIONS ||
955     request.header(h_RequestLine).getMethod() == UPDATE
956 derek 3082 );
957 jason 4010
958 derek 3289 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
959 jason 3433 // request.header(h_RequestLine).getMethod() == BYE ||
960 derek 3289 // request.header(h_Contacts).size() == 1);
961 derek 2992 Helper::makeResponse(response, request, code, mLocalContact);
962 derek 2936 response.header(h_To).param(p_tag) = mId.getLocalTag();
963 jason 4010
964     if((request.header(h_RequestLine).getMethod() == INVITE ||
965     request.header(h_RequestLine).getMethod() == UPDATE)
966     && code >= 200 && code < 300)
967     {
968     // Check if we should add our capabilites to the invite success response
969     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) response.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
970     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) response.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
971     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) response.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
972 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) response.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
973 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) response.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
974     }
975 derek 2813 }
976     else
977     {
978 derek 3274 Helper::makeResponse(response, request, code);
979 derek 3006 response.header(h_To).param(p_tag) = mId.getLocalTag();
980 derek 2813 }
981 moetje 6159
982 jmatthewsr 6643 DebugLog ( << "Dialog::makeResponse: " << std::endl << std::endl << response);
983 derek 2813 }
984    
985 jason 2885
986     ClientInviteSession*
987     Dialog::makeClientInviteSession(const SipMessage& response)
988     {
989     InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
990     assert(creator); // !jf! this maybe can assert by evil UAS
991 jason 2941 //return mDum.createAppClientInviteSession(*this, *creator);
992 jason 4010 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
993 daniel 5068 creator->getInitialOffer(), creator->getEncryptionLevel(), creator->getServerSubscription());
994 jason 2885 }
995    
996    
997    
998     ClientSubscription*
999 derek 3058 Dialog::makeClientSubscription(const SipMessage& request)
1000 jason 2885 {
1001 mfroman 6495 return new ClientSubscription(mDum, *this, request, mDefaultSubExpiration);
1002 jason 2885 }
1003    
1004    
1005     ServerInviteSession*
1006     Dialog::makeServerInviteSession(const SipMessage& request)
1007     {
1008 jason 2941 return new ServerInviteSession(mDum, *this, request);
1009 jason 2885 }
1010    
1011 jason 4010 ServerSubscription*
1012 jason 2885 Dialog::makeServerSubscription(const SipMessage& request)
1013     {
1014 jason 2941 return new ServerSubscription(mDum, *this, request);
1015 jason 2885 }
1016    
1017 davidb 2603 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
1018     : BaseException(msg, file, line)
1019 jason 2885 {
1020     }
1021 davidb 2603
1022 jason 4010
1023 jason 2853 void
1024 daniel 5757 Dialog::send(SharedPtr<SipMessage> msg)
1025 jason 2853 {
1026 daniel 5757 if (msg->isRequest() && msg->header(h_CSeq).method() != ACK)
1027 jason 4010 {
1028 daniel 5757 mRequests[msg->header(h_CSeq).sequence()] = msg;
1029 jason 4010 }
1030 daniel 5383 mDum.send(msg);
1031 jason 2853 }
1032    
1033 jason 4010 void
1034     Dialog::onForkAccepted()
1035 derek 2839 {
1036 jason 4010 ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
1037     if (uac)
1038     {
1039     uac->onForkAccepted();
1040     }
1041 derek 2839 }
1042    
1043 derek 2858 void Dialog::possiblyDie()
1044     {
1045 sgodin 5596 // !slg! Note: dialogs should really stick around for 32s, in order to ensure that all 2xx retransmissions get 481 correctly
1046 derek 2981 if (!mDestroying)
1047 derek 2858 {
1048 derek 2981 if (mClientSubscriptions.empty() &&
1049 derek 3041 mServerSubscriptions.empty() &&
1050 derek 3089 !mInviteSession)
1051 derek 2981 {
1052 sgodin 5042 mDestroying = true;
1053 jason 4010 mDum.destroy(this);
1054 derek 2981 }
1055 derek 3308 }
1056     }
1057    
1058 jason 4010 ostream&
1059 jason 2884 resip::operator<<(ostream& strm, const Dialog& dialog)
1060     {
1061 jason 4010 strm
1062     << "mClientSubscriptions("
1063     << dialog.mClientSubscriptions.size()
1064     << "), "
1065     << "mServerSubscriptions("
1066     << dialog.mServerSubscriptions.size()
1067     << ")";
1068 jason 2884 return strm;
1069     }
1070    
1071 derek 3716
1072 jason 4010 /* ====================================================================
1073     * The Vovida Software License, Version 1.0
1074     *
1075     * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1076     *
1077     * Redistribution and use in source and binary forms, with or without
1078     * modification, are permitted provided that the following conditions
1079     * are met:
1080     *
1081     * 1. Redistributions of source code must retain the above copyright
1082     * notice, this list of conditions and the following disclaimer.
1083     *
1084     * 2. Redistributions in binary form must reproduce the above copyright
1085     * notice, this list of conditions and the following disclaimer in
1086     * the documentation and/or other materials provided with the
1087     * distribution.
1088     *
1089     * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1090     * and "Vovida Open Communication Application Library (VOCAL)" must
1091     * not be used to endorse or promote products derived from this
1092     * software without prior written permission. For written
1093     * permission, please contact vocal@vovida.org.
1094     *
1095     * 4. Products derived from this software may not be called "VOCAL", nor
1096     * may "VOCAL" appear in their name, without prior written
1097     * permission of Vovida Networks, Inc.
1098     *
1099     * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1100     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1101     * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1102     * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1103     * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1104     * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1105     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1106     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1107     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1108     * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1109     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1110     * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1111     * DAMAGE.
1112     *
1113     * ====================================================================
1114     *
1115     * This software consists of voluntary contributions made by Vovida
1116     * Networks, Inc. and many individuals on behalf of Vovida Networks,
1117     * Inc. For more information on Vovida Networks, Inc., please see
1118     * <http://www.vovida.org/>.
1119     *
1120     */
1121 derek 3716
1122 jason 5459

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27