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

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

Parent Directory Parent Directory | Revision Log Revision Log


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