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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27