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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6075 - (hide annotations) (download)
Tue Mar 14 02:59:12 2006 UTC (13 years, 9 months ago) by jason
File MIME type: text/plain
File size: 35205 byte(s)
added support for privacy as per rfc3325

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