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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27