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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8200 - (hide annotations) (download)
Fri Aug 15 19:43:07 2008 UTC (11 years, 3 months ago) by bcampen
File MIME type: text/plain
File size: 39838 byte(s)
Merge work from branches/dialog-event-20080108.

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

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