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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5596 - (hide annotations) (download)
Tue Nov 1 21:52:16 2005 UTC (14 years, 1 month ago) by sgodin
File size: 34191 byte(s)
-fix issue with receiving 2xx retrans when dialog is destroying - reported by Justin Matthews

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 jason 3483 assert(creator->getLastRequest().exists(h_Contacts));
172     assert(!creator->getLastRequest().header(h_Contacts).empty());
173 derek 2983 mLocalContact = creator->getLastRequest().header(h_Contacts).front();
174     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 sgodin 4113 int keepAliveTime = mDialogSet.getUserProfile()->getKeepAliveTime();
294     if(keepAliveTime > 0)
295     {
296     mNetworkAssociation.update(msg, keepAliveTime);
297     }
298 jason 3934 handleTargetRefresh(msg);
299 jason 2614 if (msg.isRequest())
300 jason 2583 {
301 jason 2614 const SipMessage& request = msg;
302     switch (request.header(h_CSeq).method())
303 jason 4010 {
304 jason 3433 case INVITE: // new INVITE
305 jason 2614 if (mInviteSession == 0)
306     {
307 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief());
308 jason 2885 mInviteSession = makeServerInviteSession(request);
309 jason 2614 }
310     mInviteSession->dispatch(request);
311     break;
312 jason 3433 //refactor, send bad request for BYE, INFO, CANCEL?
313     case BYE:
314 derek 2997 if (mInviteSession == 0)
315     {
316 jason 3433 InfoLog ( << "Spurious BYE" );
317 jason 4010 return;
318 derek 2997 }
319     else
320     {
321     mInviteSession->dispatch(request);
322     }
323     break;
324 jason 4010 case UPDATE:
325     if (mInviteSession == 0)
326     {
327     InfoLog ( << "Spurious UPDATE" );
328     return;
329     }
330     else
331     {
332     mInviteSession->dispatch(request);
333     }
334     break;
335 jason 3433 case INFO:
336 derek 3255 if (mInviteSession == 0)
337     {
338     InfoLog ( << "Spurious INFO" );
339 jason 4010 return;
340 derek 3255 }
341     else
342     {
343     mInviteSession->dispatch(request);
344     }
345     break;
346 sgodin 5265 case MESSAGE:
347     if (mInviteSession == 0)
348     {
349     InfoLog ( << "Spurious MESSAGE" );
350     return;
351     }
352     else
353     {
354     mInviteSession->dispatch(request);
355     }
356     break;
357 jason 3433 case ACK:
358     case CANCEL:
359 jason 2614 if (mInviteSession == 0)
360     {
361 jason 3433 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
362 jason 2614 DebugLog (<< request);
363     }
364     else
365     {
366     mInviteSession->dispatch(request);
367     }
368     break;
369 jason 3433 case SUBSCRIBE:
370 derek 3041 {
371     ServerSubscription* server = findMatchingServerSub(request);
372     if (server)
373 jason 2614 {
374 derek 3041 server->dispatch(request);
375 jason 2614 }
376 derek 3041 else
377     {
378 sgodin 3493 if (request.exists(h_Event) && request.header(h_Event).value() == "refer")
379 derek 3101 {
380     InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
381     SipMessage failure;
382     makeResponse(failure, request, 403);
383     mDum.sendResponse(failure);
384     return;
385     }
386     else
387     {
388     server = makeServerSubscription(request);
389     mServerSubscriptions.push_back(server);
390     server->dispatch(request);
391     }
392 derek 3041 }
393     }
394     break;
395 jason 3433 case REFER:
396 derek 3101 {
397     if (mInviteSession == 0)
398     {
399     InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
400     SipMessage failure;
401 jason 3934 makeResponse(failure, request, 603);
402 derek 3101 mDum.sendResponse(failure);
403     return;
404     }
405     else if (!request.exists(h_ReferTo))
406     {
407     InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
408     SipMessage failure;
409     makeResponse(failure, request, 400);
410     mDum.sendResponse(failure);
411     return;
412     }
413     else
414     {
415     ServerSubscription* server = findMatchingServerSub(request);
416 derek 3451 ServerSubscriptionHandle serverHandle;
417 derek 3101 if (server)
418     {
419 derek 3451 serverHandle = server->getHandle();
420 derek 3101 server->dispatch(request);
421     }
422     else
423     {
424     server = makeServerSubscription(request);
425     mServerSubscriptions.push_back(server);
426 derek 3451 serverHandle = server->getHandle();
427 derek 3101 server->dispatch(request);
428     }
429 jason 4010 mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), serverHandle, msg);
430 derek 3101 }
431     }
432     break;
433 jason 3433 case NOTIFY:
434 derek 3089 {
435     ClientSubscription* client = findMatchingClientSub(request);
436     if (client)
437 jason 2614 {
438 derek 3089 client->dispatch(request);
439     }
440     else
441     {
442 jason 3182 BaseCreator* creator = mDialogSet.getCreator();
443 jason 3433 if (creator && (creator->getLastRequest().header(h_RequestLine).method() == SUBSCRIBE ||
444 sgodin 5001 creator->getLastRequest().header(h_RequestLine).method() == REFER)) // ?slg? OOD Refer? Click-to-Call?
445 jason 2612 {
446 jason 3350 DebugLog (<< "Making subscription (from creator) request: " << creator->getLastRequest());
447 derek 3274 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
448 derek 3089 mClientSubscriptions.push_back(sub);
449     sub->dispatch(request);
450 jason 2612 }
451     else
452     {
453 jason 4010 if (mInviteSession != 0 && (!msg.exists(h_Event) || msg.header(h_Event).value() == "refer"))
454     {
455     DebugLog (<< "Making subscription from NOTIFY: " << msg);
456     ClientSubscription* sub = makeClientSubscription(msg);
457     mClientSubscriptions.push_back(sub);
458 sgodin 4021 ClientSubscriptionHandle client = sub->getHandle();
459 jason 4010 sub->dispatch(request);
460 sgodin 4021 mInviteSession->mSentRefer = false;
461 jason 4010 if (client.isValid())
462     {
463 sgodin 4021 mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), client, msg);
464 jason 4010 }
465     else
466     {
467 sgodin 4021 mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), msg);
468 jason 4010 }
469     }
470     else
471     {
472     SipMessage response;
473     makeResponse(response, msg, 406);
474     send(response);
475     }
476     }
477 jason 2614 }
478 derek 3089 }
479     break;
480     default:
481     assert(0);
482     return;
483 jason 2583 }
484 jason 2614 }
485     else if (msg.isResponse())
486     {
487 jason 4010 // !jf! There is a substantial change in how this works in teltel-branch
488     // from how it worked in main branch pre merge.
489     // If the response doesn't match a cseq for a request I've sent, ignore
490     // the response
491     RequestMap::iterator r = mRequests.find(msg.header(h_CSeq).sequence());
492     if (r != mRequests.end())
493 derek 3089 {
494 derek 4803 bool handledByAuth = false;
495     if (mDum.mClientAuthManager.get() &&
496     mDum.mClientAuthManager->handle(*mDialogSet.getUserProfile(), r->second, msg))
497 derek 3089 {
498 jason 4010 InfoLog( << "about to re-send request with digest credentials" );
499     InfoLog( << r->second );
500    
501     assert (r->second.isRequest());
502    
503     mLocalCSeq++;
504     send(r->second);
505 derek 4803 handledByAuth = true;
506 sgodin 5586
507     if((r->second.header(h_RequestLine).method() == INVITE || r->second.header(h_RequestLine).method() == UPDATE) &&
508     mInviteSession != 0)
509     {
510     // Copy INVITE or UPDATE with Authorization headers back to InviteSession - needed to populate ACKs with Authoriziation headers
511     mInviteSession->mLastSessionModification = r->second;
512     }
513 derek 3089 }
514 jason 4010 mRequests.erase(r);
515 derek 4803 if (handledByAuth) return;
516 derek 3089 }
517 jason 4010
518 jason 2614 const SipMessage& response = msg;
519 derek 3112 int code = response.header(h_StatusLine).statusCode();
520     if (code >=200 && code < 300)
521     {
522     if (response.exists(h_RecordRoutes))
523     {
524     mRouteSet = response.header(h_RecordRoutes).reverse();
525     }
526     }
527 jason 4010
528 jason 2885 // !jf! should this only be for 2xx responses? !jf! Propose no as an
529     // answer !dcm! what is he on?
530 jason 2614 switch (response.header(h_CSeq).method())
531 jason 2583 {
532 jason 3433 case INVITE:
533 jason 2614 if (mInviteSession == 0)
534     {
535 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
536 derek 2992
537 jason 2885 mInviteSession = makeClientInviteSession(response);
538     mInviteSession->dispatch(response);
539 jason 2614 }
540     else
541     {
542     mInviteSession->dispatch(response);
543     }
544     break;
545 jason 3433 case BYE:
546     case ACK:
547     case CANCEL:
548     case INFO:
549 sgodin 5265 case MESSAGE:
550 jason 4010 case UPDATE:
551     if (mInviteSession)
552 jason 2614 {
553     mInviteSession->dispatch(response);
554     }
555     // else drop on the floor
556 jason 4010 break;
557    
558     case REFER:
559 sgodin 4021 if(mInviteSession)
560 jason 2612 {
561 sgodin 4021 mInviteSession->mSentRefer = false;
562    
563     if (code >= 300)
564     {
565     mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), msg);
566     }
567     // else no need for action - first Notify will cause onReferAccepted to be called
568 jason 4010 }
569     break;
570    
571 jason 3433 case SUBSCRIBE:
572 derek 3058 {
573     int code = response.header(h_StatusLine).statusCode();
574     if (code < 300)
575     {
576     // throw it away
577     return;
578 jason 4010 }
579 derek 3058 else
580     {
581     ClientSubscription* client = findMatchingClientSub(response);
582     if (client)
583     {
584     client->dispatch(response);
585     }
586 derek 3082 else
587     {
588 jason 4010 //!dcm! -- can't subscribe in an existing Dialog, this is all
589 derek 3361 //a bit of a hack; currently, spurious failure messages may cause callbacks
590 derek 3082 BaseCreator* creator = mDialogSet.getCreator();
591 derek 3274 if (!creator || !creator->getLastRequest().exists(h_Event))
592     {
593     return;
594     }
595     else
596     {
597 jason 4010 ClientSubscriptionHandler* handler =
598 derek 3274 mDum.getClientSubscriptionHandler(creator->getLastRequest().header(h_Event).value());
599     if (handler)
600     {
601 derek 3361 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
602     mClientSubscriptions.push_back(sub);
603     sub->dispatch(response);
604 derek 3274 }
605     }
606 derek 3082 }
607 jason 2614 }
608     }
609 derek 3058 break;
610 jason 3433 case NOTIFY:
611 derek 3101 {
612 derek 3274 //2xx responses are treated as retransmission quenchers(handled by
613     //the stack). Failures are dispatched to all ServerSubsscriptions,
614     //which may not be correct.
615    
616     int code = msg.header(h_StatusLine).statusCode();
617     if (code >= 300)
618 derek 3101 {
619 derek 3274 //!dcm! -- ick, write guard
620 jason 4010 mDestroying = true;
621 derek 3274 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
622     it != mServerSubscriptions.end(); )
623     {
624     ServerSubscription* s = *it;
625     it++;
626     s->dispatch(msg);
627     }
628     mDestroying = false;
629     possiblyDie();
630 derek 3101 }
631 derek 3274 // ServerSubscription* server = findMatchingServerSub(response);
632     // if (server)
633     // {
634     // server->dispatch(response);
635     // }
636 derek 3101 }
637 jason 4010 break;
638 derek 3101 default:
639     assert(0);
640     return;
641 jason 2583 }
642 jason 4010
643     #if 0 // merged from head back to teltel-branch
644     if (msg.header(h_StatusLine).statusCode() >= 400
645 derek 3750 && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
646     {
647     //kill all usages
648 jason 4010 mDestroying = true;
649    
650 derek 3750 for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
651     it != mServerSubscriptions.end(); )
652     {
653     ServerSubscription* s = *it;
654     it++;
655     s->dialogDestroyed(msg);
656 jason 4010 }
657 derek 3750
658     for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
659     it != mClientSubscriptions.end(); )
660     {
661     ClientSubscription* s = *it;
662     it++;
663     s->dialogDestroyed(msg);
664     }
665     if (mInviteSession)
666     {
667     mInviteSession->dialogDestroyed(msg);
668     }
669     mDestroying = false;
670     possiblyDie(); //should aways result in destruction of this
671 jason 4010 return;
672     }
673 derek 3750 #endif
674 jason 2583 }
675 jason 2578 }
676    
677 jason 4010 ServerSubscription*
678 derek 3041 Dialog::findMatchingServerSub(const SipMessage& msg)
679     {
680 jason 4010 for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
681 derek 3041 i != mServerSubscriptions.end(); ++i)
682     {
683     if ((*i)->matches(msg))
684     {
685     return *i;
686     }
687     }
688     return 0;
689     }
690 jason 2612
691 jason 4010 ClientSubscription*
692 jason 2612 Dialog::findMatchingClientSub(const SipMessage& msg)
693 jason 2583 {
694 jason 4010 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
695 jason 2612 i != mClientSubscriptions.end(); ++i)
696 jason 2583 {
697 jason 2614 if ((*i)->matches(msg))
698 jason 2612 {
699 jason 2614 return *i;
700 jason 2612 }
701     }
702 jason 2614 return 0;
703 jason 2612 }
704 jason 2585
705 jason 2941 InviteSessionHandle
706 derek 3041 Dialog::getInviteSession()
707 ken 2520 {
708 davidb 2603 if (mInviteSession)
709     {
710     return mInviteSession->getSessionHandle();
711     }
712     else
713     {
714 derek 3041 return InviteSessionHandle::NotValid();
715 davidb 2603 }
716 ken 2520 }
717    
718 jason 4010 std::vector<ClientSubscriptionHandle>
719 derek 3041 Dialog::findClientSubscriptions(const Data& event)
720 ken 2520 {
721 jason 2941 std::vector<ClientSubscriptionHandle> handles;
722 jason 4010
723 derek 2858 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
724 davidb 2603 i != mClientSubscriptions.end(); ++i)
725     {
726 derek 3041 if ( (*i)->getEventType() == event)
727     {
728     handles.push_back((*i)->getHandle());
729     }
730     }
731     return handles;
732     }
733    
734 jason 4010 std::vector<ServerSubscriptionHandle>
735 derek 3041 Dialog::findServerSubscriptions(const Data& event)
736     {
737     std::vector<ServerSubscriptionHandle> handles;
738 jason 4010
739 derek 3041 for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
740     i != mServerSubscriptions.end(); ++i)
741     {
742     if ( (*i)->getEventType() == event)
743     {
744     handles.push_back((*i)->getHandle());
745     }
746     }
747     return handles;
748     }
749    
750 jason 4010 std::vector<ClientSubscriptionHandle>
751 derek 3041 Dialog::getClientSubscriptions()
752     {
753     std::vector<ClientSubscriptionHandle> handles;
754 jason 4010
755 derek 3041 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
756     i != mClientSubscriptions.end(); ++i)
757     {
758 davidb 2603 handles.push_back((*i)->getHandle());
759     }
760    
761     return handles;
762 ken 2520 }
763    
764 jason 4010 std::vector<ServerSubscriptionHandle>
765 derek 3041 Dialog::getServerSubscriptions()
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     handles.push_back((*i)->getHandle());
773     }
774    
775     return handles;
776     }
777    
778 jason 4010 void
779 derek 3179 Dialog::redirected(const SipMessage& msg)
780     {
781     //Established dialogs are not destroyed by a redirect
782     if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
783     {
784     return;
785     }
786     if (mInviteSession)
787     {
788     ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
789     if (cInv)
790     {
791 jason 4010 cInv->handleRedirect(msg);
792 sgodin 5265 mReUseDialogSet = true; // Set flag so that DialogSet will not be destroyed and new Request can use it
793 derek 3179 }
794     }
795     }
796 ken 2520
797 jason 2539 void
798 derek 2813 Dialog::makeRequest(SipMessage& request, MethodTypes method)
799     {
800     RequestLine rLine(method);
801    
802 derek 2817 rLine.uri() = mRemoteTarget.uri();
803 jason 4010
804 derek 2813 request.header(h_RequestLine) = rLine;
805 jason 4010 request.header(h_To) = mRemoteNameAddr;
806 derek 2995 // request.header(h_To).param(p_tag) = mId.getRemoteTag();
807 jason 4010 request.header(h_From) = mLocalNameAddr;
808     // request.header(h_From).param(p_tag) = mId.getLocalTag();
809 derek 2813
810     request.header(h_CallId) = mCallId;
811 derek 2997
812     request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
813    
814 jason 4010 request.remove(h_Contacts);
815     request.header(h_Contacts).push_front(mLocalContact);
816    
817 derek 2813 request.header(h_CSeq).method() = method;
818     request.header(h_MaxForwards).value() = 70;
819    
820 derek 2961 //must keep old via for cancel
821 jason 3433 if (method != CANCEL)
822 derek 2961 {
823 derek 3024 request.header(h_Routes) = mRouteSet;
824 jason 4010 request.remove(h_Vias);
825 derek 2961 Via via;
826     via.param(p_branch); // will create the branch
827     request.header(h_Vias).push_front(via);
828     }
829     else
830     {
831     assert(request.exists(h_Vias));
832     }
833 sgodin 3392
834 jason 3433 //don't increment CSeq for ACK or CANCEL
835     if (method != ACK && method != CANCEL)
836 derek 2965 {
837     request.header(h_CSeq).sequence() = ++mLocalCSeq;
838     }
839 sgodin 3383 else
840     {
841 jason 3433 // ACK and cancel have a minimal header set
842 sgodin 3383 request.remove(h_Accepts);
843     request.remove(h_AcceptEncodings);
844     request.remove(h_AcceptLanguages);
845     request.remove(h_Allows);
846     request.remove(h_Requires);
847     request.remove(h_ProxyRequires);
848     request.remove(h_Supporteds);
849 sgodin 5586 // request.header(h_CSeq).sequence() = ?; // Caller should provide original request, or modify CSeq to proper value after calling this method
850 sgodin 3383 }
851 sgodin 3392
852 jason 3433 // If method is INVITE then advertise required headers
853 jason 4010 if(method == INVITE || method == UPDATE)
854 sgodin 3392 {
855 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
856     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
857     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
858 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) request.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
859 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
860 sgodin 3392 }
861    
862 jason 3156 DebugLog ( << "Dialog::makeRequest: " << request );
863 derek 2813 }
864    
865 derek 3138
866 jason 4010 void
867 jason 2887 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
868 derek 2813 {
869     assert( code >= 100 );
870 jason 4010 response.remove(h_Contacts);
871 derek 2992 if (code < 300 && code > 100)
872 derek 2813 {
873     assert(request.isRequest());
874 jason 3433 assert(request.header(h_RequestLine).getMethod() == INVITE ||
875     request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
876     request.header(h_RequestLine).getMethod() == BYE ||
877     request.header(h_RequestLine).getMethod() == CANCEL ||
878     request.header(h_RequestLine).getMethod() == REFER ||
879     request.header(h_RequestLine).getMethod() == MESSAGE ||
880     request.header(h_RequestLine).getMethod() == NOTIFY ||
881     request.header(h_RequestLine).getMethod() == INFO ||
882 jason 4010 request.header(h_RequestLine).getMethod() == OPTIONS ||
883     request.header(h_RequestLine).getMethod() == UPDATE
884 derek 3082 );
885 jason 4010
886 derek 3289 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
887 jason 3433 // request.header(h_RequestLine).getMethod() == BYE ||
888 derek 3289 // request.header(h_Contacts).size() == 1);
889 derek 2992 Helper::makeResponse(response, request, code, mLocalContact);
890 derek 2936 response.header(h_To).param(p_tag) = mId.getLocalTag();
891 jason 4010
892     if((request.header(h_RequestLine).getMethod() == INVITE ||
893     request.header(h_RequestLine).getMethod() == UPDATE)
894     && code >= 200 && code < 300)
895     {
896     // Check if we should add our capabilites to the invite success response
897     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Allow)) response.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
898     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) response.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
899     if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) response.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
900 jason 5459 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::AllowEvents)) response.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
901 jason 4010 if(mDialogSet.getUserProfile()->isAdvertisedCapability(Headers::Supported)) response.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
902     }
903 derek 2813 }
904     else
905     {
906 derek 3274 Helper::makeResponse(response, request, code);
907 derek 3006 response.header(h_To).param(p_tag) = mId.getLocalTag();
908 derek 2813 }
909 jason 4010 DebugLog ( << "Dialog::makeResponse: " << response);
910 derek 2813 }
911    
912 jason 2885
913     ClientInviteSession*
914     Dialog::makeClientInviteSession(const SipMessage& response)
915     {
916     InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
917     assert(creator); // !jf! this maybe can assert by evil UAS
918 jason 2941 //return mDum.createAppClientInviteSession(*this, *creator);
919 jason 4010 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
920 daniel 5068 creator->getInitialOffer(), creator->getEncryptionLevel(), creator->getServerSubscription());
921 jason 2885 }
922    
923    
924    
925     ClientSubscription*
926 derek 3058 Dialog::makeClientSubscription(const SipMessage& request)
927 jason 2885 {
928 derek 3058 return new ClientSubscription(mDum, *this, request);
929 jason 2885 }
930    
931    
932     ServerInviteSession*
933     Dialog::makeServerInviteSession(const SipMessage& request)
934     {
935 jason 2941 return new ServerInviteSession(mDum, *this, request);
936 jason 2885 }
937    
938 jason 4010 ServerSubscription*
939 jason 2885 Dialog::makeServerSubscription(const SipMessage& request)
940     {
941 jason 2941 return new ServerSubscription(mDum, *this, request);
942 jason 2885 }
943    
944 davidb 2603 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
945     : BaseException(msg, file, line)
946 jason 2885 {
947     }
948 davidb 2603
949 jason 4010
950 jason 2853 void
951 daniel 5383 Dialog::send(SipMessage& msg)
952 jason 2853 {
953 jason 4010 if (msg.isRequest() && msg.header(h_CSeq).method() != ACK)
954     {
955     mRequests[msg.header(h_CSeq).sequence()] = msg;
956     }
957 daniel 5383 mDum.send(msg);
958 jason 2853 }
959    
960 jason 4010 void
961     Dialog::onForkAccepted()
962 derek 2839 {
963 jason 4010 ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
964     if (uac)
965     {
966     uac->onForkAccepted();
967     }
968 derek 2839 }
969    
970 derek 2858 void Dialog::possiblyDie()
971     {
972 sgodin 5596 // !slg! Note: dialogs should really stick around for 32s, in order to ensure that all 2xx retransmissions get 481 correctly
973 derek 2981 if (!mDestroying)
974 derek 2858 {
975 derek 2981 if (mClientSubscriptions.empty() &&
976 derek 3041 mServerSubscriptions.empty() &&
977 derek 3089 !mInviteSession)
978 derek 2981 {
979 sgodin 5042 mDestroying = true;
980 jason 4010 mDum.destroy(this);
981 derek 2981 }
982 derek 3308 }
983     }
984    
985 jason 4010 ostream&
986 jason 2884 resip::operator<<(ostream& strm, const Dialog& dialog)
987     {
988 jason 4010 strm
989     << "mClientSubscriptions("
990     << dialog.mClientSubscriptions.size()
991     << "), "
992     << "mServerSubscriptions("
993     << dialog.mServerSubscriptions.size()
994     << ")";
995 jason 2884 return strm;
996     }
997    
998 derek 3716
999 jason 4010 /* ====================================================================
1000     * The Vovida Software License, Version 1.0
1001     *
1002     * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1003     *
1004     * Redistribution and use in source and binary forms, with or without
1005     * modification, are permitted provided that the following conditions
1006     * are met:
1007     *
1008     * 1. Redistributions of source code must retain the above copyright
1009     * notice, this list of conditions and the following disclaimer.
1010     *
1011     * 2. Redistributions in binary form must reproduce the above copyright
1012     * notice, this list of conditions and the following disclaimer in
1013     * the documentation and/or other materials provided with the
1014     * distribution.
1015     *
1016     * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1017     * and "Vovida Open Communication Application Library (VOCAL)" must
1018     * not be used to endorse or promote products derived from this
1019     * software without prior written permission. For written
1020     * permission, please contact vocal@vovida.org.
1021     *
1022     * 4. Products derived from this software may not be called "VOCAL", nor
1023     * may "VOCAL" appear in their name, without prior written
1024     * permission of Vovida Networks, Inc.
1025     *
1026     * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1027     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1028     * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1029     * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1030     * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1031     * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1032     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1033     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1034     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1035     * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1036     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1037     * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1038     * DAMAGE.
1039     *
1040     * ====================================================================
1041     *
1042     * This software consists of voluntary contributions made by Vovida
1043     * Networks, Inc. and many individuals on behalf of Vovida Networks,
1044     * Inc. For more information on Vovida Networks, Inc., please see
1045     * <http://www.vovida.org/>.
1046     *
1047     */
1048 derek 3716
1049 jason 5459

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27