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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27