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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6904 - (hide annotations) (download)
Mon Jan 22 19:19:10 2007 UTC (12 years, 10 months ago) by sgodin
File MIME type: text/plain
File size: 37356 byte(s)
- compilation fix
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 sgodin 6904 BaseCreator* creator = mDialogSet.getCreator();
565 sgodin 6902 if (creator && (creator->getLastRequest()->header(h_CSeq).sequence() == response.header(h_CSeq).sequence()) && code >=200 && code < 300)
566 derek 3112 {
567     if (response.exists(h_RecordRoutes))
568     {
569     mRouteSet = response.header(h_RecordRoutes).reverse();
570     }
571     }
572 jason 4010
573 jason 2885 // !jf! should this only be for 2xx responses? !jf! Propose no as an
574     // answer !dcm! what is he on?
575 jason 2614 switch (response.header(h_CSeq).method())
576 jason 2583 {
577 jason 3433 case INVITE:
578 jason 2614 if (mInviteSession == 0)
579     {
580 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
581 derek 2992
582 jason 2885 mInviteSession = makeClientInviteSession(response);
583     mInviteSession->dispatch(response);
584 jason 2614 }
585     else
586     {
587     mInviteSession->dispatch(response);
588     }
589     break;
590 jason 3433 case BYE:
591     case ACK:
592     case CANCEL:
593     case INFO:
594 sgodin 5265 case MESSAGE:
595 jason 4010 case UPDATE:
596     if (mInviteSession)
597 jason 2614 {
598     mInviteSession->dispatch(response);
599     }
600     // else drop on the floor
601 jason 4010 break;
602    
603     case REFER:
604 sgodin 4021 if(mInviteSession)
605 jason 2612 {
606 sgodin 4021 mInviteSession->mSentRefer = false;
607    
608     if (code >= 300)
609     {
610     mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), msg);
611     }
612 daniel 5830 else
613     {
614 daniel 6074 //!dys! the OR condition below is not draft compliant.
615     if (!mInviteSession->mReferSub &&
616     ((msg.exists(h_ReferSub) && msg.header(h_ReferSub).value()=="false") ||
617     !msg.exists(h_ReferSub)))
618 daniel 5830 {
619 daniel 6074 DebugLog(<< "refer accepted with norefersub");
620 daniel 5830 mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), ClientSubscriptionHandle::NotValid(), msg);
621     }
622     // else no need for action - first Notify will cause onReferAccepted to be called
623     }
624 daniel 6126 break;
625 jason 4010 }
626 daniel 6126 // fall through, out of dialog refer was sent.
627 mfroman 6495
628 jason 3433 case SUBSCRIBE:
629 derek 3058 {
630     int code = response.header(h_StatusLine).statusCode();
631 daniel 5767 ClientSubscription* client = findMatchingClientSub(response);
632     if (client)
633 derek 3058 {
634 daniel 5767 client->dispatch(response);
635     }
636     else if (code < 300)
637     {
638 mfroman 6495 /*
639     we're capturing the value from the expires header off
640     the 2xx because the ClientSubscription is only created
641     after receiving the NOTIFY that comes (usually) after
642     this 2xx. We really should be creating the
643     ClientSubscription at either the 2xx or the NOTIFY
644     whichever arrives first. .mjf.
645     Note: we're capturing a duration here (not the
646     absolute time because all the inputs to
647     ClientSubscription desling with the expiration are expecting
648     duration type values from the headers. .mjf.
649     */
650     mDefaultSubExpiration = response.header(h_Expires).value();
651 derek 3058 return;
652 jason 4010 }
653 derek 3058 else
654     {
655 daniel 5767 //!dcm! -- can't subscribe in an existing Dialog, this is all
656     //a bit of a hack; currently, spurious failure messages may cause callbacks
657     BaseCreator* creator = mDialogSet.getCreator();
658     if (!creator || !creator->getLastRequest()->exists(h_Event))
659 derek 3058 {
660 daniel 5767 return;
661 derek 3058 }
662 derek 3082 else
663     {
664 daniel 5767 ClientSubscriptionHandler* handler =
665     mDum.getClientSubscriptionHandler(creator->getLastRequest()->header(h_Event).value());
666     if (handler)
667 derek 3274 {
668 daniel 5767 ClientSubscription* sub = makeClientSubscription(*creator->getLastRequest());
669     mClientSubscriptions.push_back(sub);
670     sub->dispatch(response);
671 derek 3274 }
672 derek 3082 }
673 jason 2614 }
674 daniel 5767
675 jason 2614 }
676 derek 3058 break;
677 jason 3433 case NOTIFY:
678 derek 3101 {
679 derek 3274 //2xx responses are treated as retransmission quenchers(handled by
680     //the stack). Failures are dispatched to all ServerSubsscriptions,
681     //which may not be correct.
682    
683     int code = msg.header(h_StatusLine).statusCode();
684     if (code >= 300)
685 derek 3101 {
686 derek 3274 //!dcm! -- ick, write guard
687 jason 4010 mDestroying = true;
688 derek 3274 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
689     it != mServerSubscriptions.end(); )
690     {
691     ServerSubscription* s = *it;
692     it++;
693     s->dispatch(msg);
694     }
695     mDestroying = false;
696     possiblyDie();
697 derek 3101 }
698 derek 3274 // ServerSubscription* server = findMatchingServerSub(response);
699     // if (server)
700     // {
701     // server->dispatch(response);
702     // }
703 derek 3101 }
704 jason 4010 break;
705 derek 3101 default:
706     assert(0);
707     return;
708 jason 2583 }
709 jason 4010
710     #if 0 // merged from head back to teltel-branch
711     if (msg.header(h_StatusLine).statusCode() >= 400
712 derek 3750 && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
713     {
714     //kill all usages
715 jason 4010 mDestroying = true;
716    
717 derek 3750 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
718     it != mServerSubscriptions.end(); )
719     {
720     ServerSubscription* s = *it;
721     it++;
722     s->dialogDestroyed(msg);
723 jason 4010 }
724 derek 3750
725     for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
726     it != mClientSubscriptions.end(); )
727     {
728     ClientSubscription* s = *it;
729     it++;
730     s->dialogDestroyed(msg);
731     }
732     if (mInviteSession)
733     {
734     mInviteSession->dialogDestroyed(msg);
735     }
736     mDestroying = false;
737     possiblyDie(); //should aways result in destruction of this
738 jason 4010 return;
739     }
740 derek 3750 #endif
741 jason 2583 }
742 jason 2578 }
743    
744 jason 4010 ServerSubscription*
745 derek 3041 Dialog::findMatchingServerSub(const SipMessage& msg)
746     {
747 jason 4010 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
748 derek 3041 i != mServerSubscriptions.end(); ++i)
749     {
750     if ((*i)->matches(msg))
751     {
752     return *i;
753     }
754     }
755     return 0;
756     }
757 jason 2612
758 jason 4010 ClientSubscription*
759 jason 2612 Dialog::findMatchingClientSub(const SipMessage& msg)
760 jason 2583 {
761 jason 4010 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
762 jason 2612 i != mClientSubscriptions.end(); ++i)
763 jason 2583 {
764 jason 2614 if ((*i)->matches(msg))
765 jason 2612 {
766 jason 2614 return *i;
767 jason 2612 }
768     }
769 jason 2614 return 0;
770 jason 2612 }
771 jason 2585
772 jason 2941 InviteSessionHandle
773 derek 3041 Dialog::getInviteSession()
774 ken 2520 {
775 davidb 2603 if (mInviteSession)
776     {
777     return mInviteSession->getSessionHandle();
778     }
779     else
780     {
781 derek 3041 return InviteSessionHandle::NotValid();
782 davidb 2603 }
783 ken 2520 }
784    
785 jason 4010 std::vector<ClientSubscriptionHandle>
786 derek 3041 Dialog::findClientSubscriptions(const Data& event)
787 ken 2520 {
788 jason 2941 std::vector<ClientSubscriptionHandle> handles;
789 jason 4010
790 derek 2858 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
791 davidb 2603 i != mClientSubscriptions.end(); ++i)
792     {
793 derek 3041 if ( (*i)->getEventType() == event)
794     {
795     handles.push_back((*i)->getHandle());
796     }
797     }
798     return handles;
799     }
800    
801 jason 4010 std::vector<ServerSubscriptionHandle>
802 derek 3041 Dialog::findServerSubscriptions(const Data& event)
803     {
804     std::vector<ServerSubscriptionHandle> handles;
805 jason 4010
806 derek 3041 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
807     i != mServerSubscriptions.end(); ++i)
808     {
809     if ( (*i)->getEventType() == event)
810     {
811     handles.push_back((*i)->getHandle());
812     }
813     }
814     return handles;
815     }
816    
817 jason 4010 std::vector<ClientSubscriptionHandle>
818 derek 3041 Dialog::getClientSubscriptions()
819     {
820     std::vector<ClientSubscriptionHandle> handles;
821 jason 4010
822 derek 3041 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
823     i != mClientSubscriptions.end(); ++i)
824     {
825 davidb 2603 handles.push_back((*i)->getHandle());
826     }
827    
828     return handles;
829 ken 2520 }
830    
831 jason 4010 std::vector<ServerSubscriptionHandle>
832 derek 3041 Dialog::getServerSubscriptions()
833     {
834     std::vector<ServerSubscriptionHandle> handles;
835 jason 4010
836 derek 3041 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
837     i != mServerSubscriptions.end(); ++i)
838     {
839     handles.push_back((*i)->getHandle());
840     }
841    
842     return handles;
843     }
844    
845 jason 4010 void
846 derek 3179 Dialog::redirected(const SipMessage& msg)
847     {
848     //Established dialogs are not destroyed by a redirect
849     if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
850     {
851     return;
852     }
853     if (mInviteSession)
854     {
855     ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
856     if (cInv)
857     {
858 jason 4010 cInv->handleRedirect(msg);
859 sgodin 5265 mReUseDialogSet = true; // Set flag so that DialogSet will not be destroyed and new Request can use it
860 derek 3179 }
861     }
862     }
863 ken 2520
864 jason 2539 void
865 derek 2813 Dialog::makeRequest(SipMessage& request, MethodTypes method)
866     {
867     RequestLine rLine(method);
868    
869 derek 2817 rLine.uri() = mRemoteTarget.uri();
870 jason 4010
871 derek 2813 request.header(h_RequestLine) = rLine;
872 jason 4010 request.header(h_To) = mRemoteNameAddr;
873 derek 2995 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
874 jason 4010 request.header(h_From) = mLocalNameAddr;
875     // request.header(h_From).param(p_tag) = mId.getLocalTag();
876 derek 2813
877     request.header(h_CallId) = mCallId;
878 derek 2997
879     request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
880 sgodin 6198 request.remove(h_Replaces);
881 derek 2997
882 jason 4010 request.remove(h_Contacts);
883     request.header(h_Contacts).push_front(mLocalContact);
884    
885 derek 2813 request.header(h_CSeq).method() = method;
886     request.header(h_MaxForwards).value() = 70;
887    
888 derek 2961 //must keep old via for cancel
889 jason 3433 if (method != CANCEL)
890 derek 2961 {
891 derek 3024 request.header(h_Routes) = mRouteSet;
892 jason 4010 request.remove(h_Vias);
893 derek 2961 Via via;
894     via.param(p_branch); // will create the branch
895     request.header(h_Vias).push_front(via);
896     }
897     else
898     {
899     assert(request.exists(h_Vias));
900     }
901 sgodin 3392
902 jason 3433 //don't increment CSeq for ACK or CANCEL
903     if (method != ACK && method != CANCEL)
904 derek 2965 {
905     request.header(h_CSeq).sequence() = ++mLocalCSeq;
906     }
907 sgodin 3383 else
908     {
909 jason 3433 // ACK and cancel have a minimal header set
910 sgodin 3383 request.remove(h_Accepts);
911     request.remove(h_AcceptEncodings);
912     request.remove(h_AcceptLanguages);
913     request.remove(h_Allows);
914     request.remove(h_Requires);
915     request.remove(h_ProxyRequires);
916     request.remove(h_Supporteds);
917 sgodin 5586 // request.header(h_CSeq).sequence() = ?; // Caller should provide original request, or modify CSeq to proper value after calling this method
918 sgodin 3383 }
919 sgodin 3392
920 jason 3433 // If method is INVITE then advertise required headers
921 jason 4010 if(method == INVITE || method == UPDATE)
922 sgodin 3392 {
923 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
924     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
925     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
926 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) request.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
927 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
928 sgodin 3392 }
929    
930 jason 6075 if (mDialogSet.mUserProfile->isAnonymous())
931     {
932     request.header(h_Privacys).push_back(Token(Symbols::id));
933     }
934    
935 jmatthewsr 6643 DebugLog ( << "Dialog::makeRequest: " << std::endl << std::endl << request );
936 derek 2813 }
937    
938 derek 3138
939 jason 4010 void
940 jason 2887 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
941 derek 2813 {
942     assert( code >= 100 );
943 jason 4010 response.remove(h_Contacts);
944 derek 2992 if (code < 300 && code > 100)
945 derek 2813 {
946     assert(request.isRequest());
947 jason 3433 assert(request.header(h_RequestLine).getMethod() == INVITE ||
948     request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
949     request.header(h_RequestLine).getMethod() == BYE ||
950     request.header(h_RequestLine).getMethod() == CANCEL ||
951     request.header(h_RequestLine).getMethod() == REFER ||
952     request.header(h_RequestLine).getMethod() == MESSAGE ||
953     request.header(h_RequestLine).getMethod() == NOTIFY ||
954     request.header(h_RequestLine).getMethod() == INFO ||
955 jason 4010 request.header(h_RequestLine).getMethod() == OPTIONS ||
956     request.header(h_RequestLine).getMethod() == UPDATE
957 derek 3082 );
958 jason 4010
959 derek 3289 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
960 jason 3433 // request.header(h_RequestLine).getMethod() == BYE ||
961 derek 3289 // request.header(h_Contacts).size() == 1);
962 derek 2992 Helper::makeResponse(response, request, code, mLocalContact);
963 derek 2936 response.header(h_To).param(p_tag) = mId.getLocalTag();
964 jason 4010
965     if((request.header(h_RequestLine).getMethod() == INVITE ||
966     request.header(h_RequestLine).getMethod() == UPDATE)
967     && code >= 200 && code < 300)
968     {
969     // Check if we should add our capabilites to the invite success response
970     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) response.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
971     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) response.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
972     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) response.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
973 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) response.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
974 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) response.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
975     }
976 derek 2813 }
977     else
978     {
979 derek 3274 Helper::makeResponse(response, request, code);
980 derek 3006 response.header(h_To).param(p_tag) = mId.getLocalTag();
981 derek 2813 }
982 moetje 6159
983 jmatthewsr 6643 DebugLog ( << "Dialog::makeResponse: " << std::endl << std::endl << response);
984 derek 2813 }
985    
986 jason 2885
987     ClientInviteSession*
988     Dialog::makeClientInviteSession(const SipMessage& response)
989     {
990     InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
991     assert(creator); // !jf! this maybe can assert by evil UAS
992 jason 2941 //return mDum.createAppClientInviteSession(*this, *creator);
993 jason 4010 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
994 daniel 5068 creator->getInitialOffer(), creator->getEncryptionLevel(), creator->getServerSubscription());
995 jason 2885 }
996    
997    
998    
999     ClientSubscription*
1000 derek 3058 Dialog::makeClientSubscription(const SipMessage& request)
1001 jason 2885 {
1002 mfroman 6495 return new ClientSubscription(mDum, *this, request, mDefaultSubExpiration);
1003 jason 2885 }
1004    
1005    
1006     ServerInviteSession*
1007     Dialog::makeServerInviteSession(const SipMessage& request)
1008     {
1009 jason 2941 return new ServerInviteSession(mDum, *this, request);
1010 jason 2885 }
1011    
1012 jason 4010 ServerSubscription*
1013 jason 2885 Dialog::makeServerSubscription(const SipMessage& request)
1014     {
1015 jason 2941 return new ServerSubscription(mDum, *this, request);
1016 jason 2885 }
1017    
1018 davidb 2603 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
1019     : BaseException(msg, file, line)
1020 jason 2885 {
1021     }
1022 davidb 2603
1023 jason 4010
1024 jason 2853 void
1025 daniel 5757 Dialog::send(SharedPtr<SipMessage> msg)
1026 jason 2853 {
1027 daniel 5757 if (msg->isRequest() && msg->header(h_CSeq).method() != ACK)
1028 jason 4010 {
1029 daniel 5757 mRequests[msg->header(h_CSeq).sequence()] = msg;
1030 jason 4010 }
1031 daniel 5383 mDum.send(msg);
1032 jason 2853 }
1033    
1034 jason 4010 void
1035     Dialog::onForkAccepted()
1036 derek 2839 {
1037 jason 4010 ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
1038     if (uac)
1039     {
1040     uac->onForkAccepted();
1041     }
1042 derek 2839 }
1043    
1044 derek 2858 void Dialog::possiblyDie()
1045     {
1046 sgodin 5596 // !slg! Note: dialogs should really stick around for 32s, in order to ensure that all 2xx retransmissions get 481 correctly
1047 derek 2981 if (!mDestroying)
1048 derek 2858 {
1049 derek 2981 if (mClientSubscriptions.empty() &&
1050 derek 3041 mServerSubscriptions.empty() &&
1051 derek 3089 !mInviteSession)
1052 derek 2981 {
1053 sgodin 5042 mDestroying = true;
1054 jason 4010 mDum.destroy(this);
1055 derek 2981 }
1056 derek 3308 }
1057     }
1058    
1059 jason 4010 ostream&
1060 jason 2884 resip::operator<<(ostream& strm, const Dialog& dialog)
1061     {
1062 jason 4010 strm
1063     << "mClientSubscriptions("
1064     << dialog.mClientSubscriptions.size()
1065     << "), "
1066     << "mServerSubscriptions("
1067     << dialog.mServerSubscriptions.size()
1068     << ")";
1069 jason 2884 return strm;
1070     }
1071    
1072 derek 3716
1073 jason 4010 /* ====================================================================
1074     * The Vovida Software License, Version 1.0
1075     *
1076     * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1077     *
1078     * Redistribution and use in source and binary forms, with or without
1079     * modification, are permitted provided that the following conditions
1080     * are met:
1081     *
1082     * 1. Redistributions of source code must retain the above copyright
1083     * notice, this list of conditions and the following disclaimer.
1084     *
1085     * 2. Redistributions in binary form must reproduce the above copyright
1086     * notice, this list of conditions and the following disclaimer in
1087     * the documentation and/or other materials provided with the
1088     * distribution.
1089     *
1090     * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1091     * and "Vovida Open Communication Application Library (VOCAL)" must
1092     * not be used to endorse or promote products derived from this
1093     * software without prior written permission. For written
1094     * permission, please contact vocal@vovida.org.
1095     *
1096     * 4. Products derived from this software may not be called "VOCAL", nor
1097     * may "VOCAL" appear in their name, without prior written
1098     * permission of Vovida Networks, Inc.
1099     *
1100     * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1101     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1102     * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1103     * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1104     * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1105     * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1106     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1107     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1108     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1109     * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1110     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1111     * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1112     * DAMAGE.
1113     *
1114     * ====================================================================
1115     *
1116     * This software consists of voluntary contributions made by Vovida
1117     * Networks, Inc. and many individuals on behalf of Vovida Networks,
1118     * Inc. For more information on Vovida Networks, Inc., please see
1119     * <http://www.vovida.org/>.
1120     *
1121     */
1122 derek 3716
1123 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