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

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

Parent Directory Parent Directory | Revision Log Revision Log


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