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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6198 - (hide annotations) (download)
Mon May 8 20:00:25 2006 UTC (13 years, 7 months ago) by sgodin
File MIME type: text/plain
File size: 35632 byte(s)
- Dialog.cxx - remove replaces header from newly created requests
- InviteSession.cxx - populate tags in replaces header correctly if session to be replaces is a UAS Session

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