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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3716 - (hide annotations) (download)
Sat Dec 4 01:23:10 2004 UTC (15 years ago) by derek
Original Path: main/sip/resiprocate/dum/Dialog.cxx
File size: 32053 byte(s)
forking related changes; more callbacks will be added to ClientInviteSession to allow forks to be quickly ignored
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     #include "resiprocate/dum/InviteSessionCreator.hxx"
12 derek 3058 #include "resiprocate/dum/InviteSessionHandler.hxx"
13 jason 2941 #include "resiprocate/dum/ServerInviteSession.hxx"
14     #include "resiprocate/dum/ServerSubscription.hxx"
15 derek 3082 #include "resiprocate/dum/SubscriptionHandler.hxx"
16 derek 3101 #include "resiprocate/dum/UsageUseException.hxx"
17 davidb 2603 #include "resiprocate/os/Logger.hxx"
18    
19 sgodin 3103 #if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK)// Used for tracking down memory leaks in Visual Studio
20     #define _CRTDBG_MAP_ALLOC
21     #include <stdlib.h>
22     #include <crtdbg.h>
23     #define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
24     #endif // defined(WIN32) && defined(_DEBUG)
25 sgodin 3102
26 davidb 2603 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
27    
28 ken 2520 using namespace resip;
29     using namespace std;
30    
31 derek 2867 Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg, DialogSet& ds)
32 derek 2995 : mDum(dum),
33 derek 2867 mDialogSet(ds),
34 derek 3089 mId("INVALID", "INVALID", "INVALID"),
35 jason 2588 mClientSubscriptions(),
36 derek 3041 mServerSubscriptions(),
37 jason 2588 mInviteSession(0),
38     mType(Fake),
39     mRouteSet(),
40 jason 2611 mLocalContact(),
41 jason 2577 mLocalCSeq(0),
42     mRemoteCSeq(0),
43 derek 2981 mRemoteTarget(),
44 derek 2995 mLocalNameAddr(),
45     mRemoteNameAddr(),
46     mCallId(msg.header(h_CallID)),
47 derek 3308 mAppDialog(0),
48     mDestroying(false)
49 jason 2577 {
50 davidb 2603 assert(msg.isExternal());
51 jason 2577
52 derek 2936
53 jason 2577 if (msg.isRequest()) // UAS
54     {
55     const SipMessage& request = msg;
56    
57     switch (request.header(h_CSeq).method())
58     {
59 jason 3433 case INVITE:
60 jason 2611 mType = Invitation;
61     break;
62    
63 jason 3433 case SUBSCRIBE:
64     case REFER:
65     case NOTIFY:
66 derek 3041 //!dcm! -- event header check
67 jason 2611 mType = Subscription;
68     break;
69    
70     default:
71     mType = Fake;
72     }
73 derek 3024 if (request.exists(h_RecordRoutes))
74     {
75     mRouteSet = request.header(h_RecordRoutes); // !jf! is this right order
76     }
77 jason 2611
78     switch (request.header(h_CSeq).method())
79     {
80 jason 3433 case INVITE:
81     case SUBSCRIBE:
82     case REFER:
83     case NOTIFY:
84 jason 3156 DebugLog ( << "UAS dialog ID creation, DS: " << ds.getId());
85 derek 2995 mId = DialogId(ds.getId(), request.header(h_From).param(p_tag));
86     mRemoteNameAddr = request.header(h_From);
87     mLocalNameAddr = request.header(h_To);
88     mLocalNameAddr.param(p_tag) = mId.getLocalTag();
89 jason 2577 if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
90     {
91 davidb 2603 const NameAddr& contact = request.header(h_Contacts).front();
92 jason 2577 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
93     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
94     {
95 jason 2611 mLocalContact = NameAddr(request.header(h_RequestLine).uri()); // update later when send a request
96 jason 2577 mRemoteTarget = contact;
97     }
98     else
99     {
100 jason 3433 InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme");
101 jason 3483 InfoLog(<< request);
102 jason 2611 throw Exception("Invalid scheme in request", __FILE__, __LINE__);
103 jason 2577 }
104     }
105     else
106     {
107 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
108 jason 3483 InfoLog (<< request);
109 jason 2611 throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__);
110 jason 2577 }
111     break;
112 davidb 2603 default:
113     break;
114 jason 2577 }
115    
116     mRemoteCSeq = request.header(h_CSeq).sequence();
117 jason 2611 mLocalCSeq = 1;
118 derek 2995
119 jason 3156 DebugLog ( << "************** Created Dialog as UAS **************" );
120     DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
121     DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
122     DebugLog ( << "mLocalContact: " << mLocalContact );
123     DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
124 jason 2577 }
125     else if (msg.isResponse())
126     {
127 derek 2995 mId = DialogId(msg);
128 jason 2577 const SipMessage& response = msg;
129 derek 2995 mRemoteNameAddr = response.header(h_To);
130     mLocalNameAddr = response.header(h_From);
131 jason 2611
132     switch (msg.header(h_CSeq).method())
133     {
134 jason 3433 case INVITE:
135 jason 2611 mType = Invitation;
136     break;
137    
138 jason 3433 case SUBSCRIBE:
139     case REFER:
140 jason 2611 mType = Subscription;
141     break;
142    
143     default:
144     mType = Fake;
145     }
146    
147 jason 2577 if (response.exists(h_RecordRoutes))
148     {
149     mRouteSet = response.header(h_RecordRoutes).reverse();
150     }
151    
152     switch (response.header(h_CSeq).method())
153     {
154 jason 3433 case INVITE:
155     case SUBSCRIBE:
156     case REFER:
157 derek 2983 if (response.header(h_StatusLine).statusCode() > 100 &&
158     response.header(h_StatusLine).statusCode() < 300)
159 jason 2577 {
160 derek 2983
161     if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
162 jason 2577 {
163 derek 2983 const NameAddr& contact = response.header(h_Contacts).front();
164     if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
165     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
166     {
167 jason 3182 BaseCreator* creator = mDialogSet.getCreator();
168 derek 2983 assert(creator);// !jf! throw or something here
169 jason 3483 assert(creator->getLastRequest().exists(h_Contacts));
170     assert(!creator->getLastRequest().header(h_Contacts).empty());
171 derek 2983 mLocalContact = creator->getLastRequest().header(h_Contacts).front();
172     mRemoteTarget = contact;
173     }
174     else
175     {
176 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
177 derek 2983 DebugLog (<< response);
178     throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
179     }
180 jason 2577 }
181     else
182     {
183 jason 3433 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
184 jason 2577 DebugLog (<< response);
185 derek 2983 throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
186 jason 2577 }
187 derek 2983 break;
188     default:
189     break;
190 jason 2577 }
191     }
192 derek 2983
193 jason 2577 mLocalCSeq = response.header(h_CSeq).sequence();
194 jason 2611 mRemoteCSeq = 0;
195 jason 3156 DebugLog ( << "************** Created Dialog as UAC **************" );
196     DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
197     DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
198     DebugLog ( << "mLocalContact: " << mLocalContact );
199     DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
200 derek 2995
201 jason 2611
202 jason 2577 }
203 derek 2867 mDialogSet.addDialog(this);
204 derek 3081 DebugLog ( <<"Dialog::Dialog " << mId);
205 jason 2577 }
206    
207 jason 2868 Dialog::~Dialog()
208     {
209 derek 3081 DebugLog ( <<"Dialog::~Dialog() ");
210    
211 derek 2981 mDestroying = true;
212 derek 3089
213     while (!mClientSubscriptions.empty())
214 derek 2981 {
215 derek 3089 delete *mClientSubscriptions.begin();
216 derek 2981 }
217 derek 3089
218     while (!mServerSubscriptions.empty())
219 derek 3041 {
220 derek 3089 delete *mServerSubscriptions.begin();
221 derek 3041 }
222 derek 3089
223 derek 2981 delete mInviteSession;
224    
225 jason 2884 mDialogSet.mDialogs.erase(this->getId());
226 derek 2976 delete mAppDialog;
227     mDialogSet.possiblyDie();
228 jason 2868 }
229    
230 jason 2588 DialogId
231     Dialog::getId() const
232     {
233     return mId;
234     }
235    
236 davidb 2604 void
237 derek 3716 Dialog::end()
238 jason 2891 {
239 derek 3006 if (mInviteSession)
240     {
241 jason 3425 mInviteSession->end();
242 derek 3006 }
243     else
244     {
245 derek 3716 //!dcm! -- end subscriptions
246 derek 3006 }
247 jason 2891 }
248    
249     void
250 davidb 2604 Dialog::dispatch(const SipMessage& msg)
251     {
252 jason 3156 DebugLog ( << "Dialog::dispatch: " << msg.brief());
253 jason 2614 if (msg.isRequest())
254 jason 2583 {
255 jason 2614 const SipMessage& request = msg;
256     switch (request.header(h_CSeq).method())
257 derek 3089 {
258 jason 3433 case INVITE: // new INVITE
259 jason 2614 if (mInviteSession == 0)
260     {
261 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new server invite session" << msg.brief());
262 jason 2885 mInviteSession = makeServerInviteSession(request);
263 jason 2614 }
264     mInviteSession->dispatch(request);
265     break;
266 jason 3433 //refactor, send bad request for BYE, INFO, CANCEL?
267     case BYE:
268 derek 2997 if (mInviteSession == 0)
269     {
270 jason 3433 InfoLog ( << "Spurious BYE" );
271 derek 2997 return;
272     }
273     else
274     {
275     mInviteSession->dispatch(request);
276     }
277     break;
278 jason 3433 case INFO:
279 derek 3255 if (mInviteSession == 0)
280     {
281     InfoLog ( << "Spurious INFO" );
282     return;
283     }
284     else
285     {
286     mInviteSession->dispatch(request);
287     }
288     break;
289 jason 3433 case ACK:
290     case CANCEL:
291 jason 2614 if (mInviteSession == 0)
292     {
293 jason 3433 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
294 jason 2614 DebugLog (<< request);
295     }
296     else
297     {
298     mInviteSession->dispatch(request);
299     }
300     break;
301 jason 3433 case SUBSCRIBE:
302 derek 3041 {
303     ServerSubscription* server = findMatchingServerSub(request);
304     if (server)
305 jason 2614 {
306 derek 3041 server->dispatch(request);
307 jason 2614 }
308 derek 3041 else
309     {
310 sgodin 3493 if (request.exists(h_Event) && request.header(h_Event).value() == "refer")
311 derek 3101 {
312     InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
313     SipMessage failure;
314     makeResponse(failure, request, 403);
315     mDum.sendResponse(failure);
316     return;
317     }
318     else
319     {
320     server = makeServerSubscription(request);
321     mServerSubscriptions.push_back(server);
322     server->dispatch(request);
323     }
324 derek 3041 }
325 derek 3361 // mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), server->getHandle(), msg);
326 derek 3041 }
327     break;
328 jason 3433 case REFER:
329 derek 3101 {
330     if (mInviteSession == 0)
331     {
332     InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
333     SipMessage failure;
334     makeResponse(failure, request, 405);
335     mDum.sendResponse(failure);
336     return;
337     }
338     else if (!request.exists(h_ReferTo))
339     {
340     InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
341     SipMessage failure;
342     makeResponse(failure, request, 400);
343     mDum.sendResponse(failure);
344     return;
345     }
346     else
347     {
348     ServerSubscription* server = findMatchingServerSub(request);
349 derek 3451 ServerSubscriptionHandle serverHandle;
350 derek 3101 if (server)
351     {
352 derek 3451 serverHandle = server->getHandle();
353 derek 3101 server->dispatch(request);
354     }
355     else
356     {
357     server = makeServerSubscription(request);
358     mServerSubscriptions.push_back(server);
359 derek 3451 serverHandle = server->getHandle();
360 derek 3101 server->dispatch(request);
361     }
362 derek 3451 mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), serverHandle, msg);
363 derek 3101 }
364     }
365     break;
366 jason 3433 case NOTIFY:
367 derek 3089 {
368     ClientSubscription* client = findMatchingClientSub(request);
369     if (client)
370 jason 2614 {
371 derek 3089 client->dispatch(request);
372     }
373     else
374     {
375 jason 3182 BaseCreator* creator = mDialogSet.getCreator();
376 jason 3433 if (creator && (creator->getLastRequest().header(h_RequestLine).method() == SUBSCRIBE ||
377     creator->getLastRequest().header(h_RequestLine).method() == REFER))
378 jason 2612 {
379 jason 3350 DebugLog (<< "Making subscription (from creator) request: " << creator->getLastRequest());
380 derek 3274 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
381 derek 3089 mClientSubscriptions.push_back(sub);
382     sub->dispatch(request);
383 jason 2612 }
384 jason 3433 else if (mInviteSession->mLastRequest.header(h_RequestLine).method() == REFER)
385 derek 3274 {
386 jason 3350 DebugLog (<< "Making subscription from refer: " << mInviteSession->mLastRequest);
387 derek 3274 ClientSubscription* sub = makeClientSubscription(mInviteSession->mLastRequest);
388     mClientSubscriptions.push_back(sub);
389     sub->dispatch(request);
390     }
391 jason 2612 else
392     {
393 derek 3179 SipMessage failure;
394     makeResponse(failure, request, 481);
395 jason 3182 failure.header(h_To).remove(p_tag); // otherwise it will be INVALID
396     InfoLog (<< "Sending 481 - no dialog created " << endl << failure);
397 derek 3179 mDum.sendResponse(failure);
398     return;
399 jason 2612 }
400 jason 2614 }
401 derek 3089 }
402     break;
403     default:
404     assert(0);
405     return;
406 jason 2583 }
407 jason 2614 }
408     else if (msg.isResponse())
409     {
410 derek 3676 if (msg.header(h_StatusLine).statusCode() >= 400
411     && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
412     {
413     //kill all usages
414     mDestroying = true;
415    
416     for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
417     it != mServerSubscriptions.end(); )
418     {
419     ServerSubscription* s = *it;
420     it++;
421     s->dialogDestroyed(msg);
422     }
423    
424     for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
425     it != mClientSubscriptions.end(); )
426     {
427     ClientSubscription* s = *it;
428     it++;
429     s->dialogDestroyed(msg);
430     }
431     if (mInviteSession)
432     {
433     mInviteSession->dialogDestroyed(msg);
434     }
435     mDestroying = false;
436     possiblyDie(); //should aways result in destruction of this
437     return;
438     }
439    
440    
441 derek 3089 if (!mDialogSet.getCreator() ||
442 derek 3308 !(msg.header(h_CSeq) == mDialogSet.getCreator()->getLastRequest().header(h_CSeq)))
443 derek 3089 {
444     SipMessage* lastRequest = 0;
445     switch (msg.header(h_CSeq).method())
446     {
447 jason 3433 case INVITE:
448     case CANCEL:
449     case REFER:
450     case BYE:
451 derek 3096 if (mInviteSession == 0)
452 derek 3089 {
453     //spurious
454     return;
455     }
456     else
457     {
458     lastRequest = &mInviteSession->mLastRequest;
459     }
460     break;
461 jason 3433 case INFO:
462 derek 3333 {
463     if (mInviteSession == 0)
464     {
465     //spurious
466     return;
467     }
468     else
469     {
470     lastRequest = &mInviteSession->mLastNit;
471     }
472     break;
473     }
474 derek 3089 default:
475     break;
476     }
477 jason 3613 if ( lastRequest && mDum.mClientAuthManager.get() && mDum.mClientAuthManager->handle( *lastRequest, msg ) )
478 derek 3089 {
479 jason 3156 InfoLog( << "about to re-send request with digest credentials" );
480 derek 3089 InfoLog( << *lastRequest );
481 derek 3308 mLocalCSeq++;
482 derek 3089 mDum.send(*lastRequest);
483     return;
484     }
485     }
486    
487 jason 2614 const SipMessage& response = msg;
488 derek 3112 int code = response.header(h_StatusLine).statusCode();
489     if (code >=200 && code < 300)
490     {
491     if (response.exists(h_RecordRoutes))
492     {
493     mRouteSet = response.header(h_RecordRoutes).reverse();
494     }
495     }
496    
497 jason 2885 // !jf! should this only be for 2xx responses? !jf! Propose no as an
498     // answer !dcm! what is he on?
499 jason 2614 switch (response.header(h_CSeq).method())
500 jason 2583 {
501 jason 3433 case INVITE:
502 jason 2614 if (mInviteSession == 0)
503     {
504 jason 2885 // #if!jf! don't think creator needs a dispatch
505     //BaseCreator* creator = mDum.findCreator(mId);
506     //assert (creator); // stray responses have been rejected already
507     //creator->dispatch(response);
508     // #endif!jf!
509 jason 3156 DebugLog ( << "Dialog::dispatch -- Created new client invite session" << msg.brief());
510 derek 2992
511 jason 2885 mInviteSession = makeClientInviteSession(response);
512     mInviteSession->dispatch(response);
513 jason 2614 }
514     else
515     {
516     mInviteSession->dispatch(response);
517     }
518     break;
519 jason 3433 case BYE:
520     case ACK:
521     case CANCEL:
522     case INFO:
523 jason 2614 if (mInviteSession != 0)
524     {
525     mInviteSession->dispatch(response);
526     }
527     // else drop on the floor
528 derek 3058 break;
529 jason 3433 case REFER:
530 jason 2614 {
531 derek 3058 int code = response.header(h_StatusLine).statusCode();
532     if (code < 300)
533 jason 2612 {
534 derek 3058 // throw it away
535     return;
536     }
537 jason 2614 else
538     {
539 derek 3058 if (mInviteSession && mDum.mInviteSessionHandler)
540     {
541     mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), response);
542     }
543     }
544     }
545     break;
546 jason 3433 case SUBSCRIBE:
547 derek 3058 {
548     int code = response.header(h_StatusLine).statusCode();
549     if (code < 300)
550     {
551     // throw it away
552     return;
553     }
554     else
555     {
556     ClientSubscription* client = findMatchingClientSub(response);
557     if (client)
558     {
559     client->dispatch(response);
560     }
561 derek 3082 else
562     {
563     //!dcm! -- can't subscribe in an existing Dialog, this is all
564 derek 3361 //a bit of a hack; currently, spurious failure messages may cause callbacks
565 derek 3082 BaseCreator* creator = mDialogSet.getCreator();
566 derek 3274 if (!creator || !creator->getLastRequest().exists(h_Event))
567     {
568     return;
569     }
570     else
571     {
572     ClientSubscriptionHandler* handler =
573     mDum.getClientSubscriptionHandler(creator->getLastRequest().header(h_Event).value());
574     if (handler)
575     {
576 derek 3361 ClientSubscription* sub = makeClientSubscription(creator->getLastRequest());
577     mClientSubscriptions.push_back(sub);
578     sub->dispatch(response);
579 derek 3274 }
580     }
581 derek 3082 }
582 jason 2614 }
583     }
584 derek 3058 break;
585 jason 3433 case NOTIFY:
586 derek 3101 {
587 derek 3274 //2xx responses are treated as retransmission quenchers(handled by
588     //the stack). Failures are dispatched to all ServerSubsscriptions,
589     //which may not be correct.
590    
591     int code = msg.header(h_StatusLine).statusCode();
592     if (code >= 300)
593 derek 3101 {
594 derek 3274 //!dcm! -- ick, write guard
595     mDestroying = true;
596     for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
597     it != mServerSubscriptions.end(); )
598     {
599     ServerSubscription* s = *it;
600     it++;
601     s->dispatch(msg);
602     }
603     mDestroying = false;
604     possiblyDie();
605 derek 3101 }
606 derek 3274 // ServerSubscription* server = findMatchingServerSub(response);
607     // if (server)
608     // {
609     // server->dispatch(response);
610     // }
611 derek 3101 }
612 derek 3155 break;
613 derek 3101 default:
614     assert(0);
615     return;
616 jason 2583 }
617     }
618 jason 2578 }
619    
620 derek 3041 ServerSubscription*
621     Dialog::findMatchingServerSub(const SipMessage& msg)
622     {
623     for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
624     i != mServerSubscriptions.end(); ++i)
625     {
626     if ((*i)->matches(msg))
627     {
628     return *i;
629     }
630     }
631     return 0;
632     }
633 jason 2612
634     ClientSubscription*
635     Dialog::findMatchingClientSub(const SipMessage& msg)
636 jason 2583 {
637 derek 2858 for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
638 jason 2612 i != mClientSubscriptions.end(); ++i)
639 jason 2583 {
640 jason 2614 if ((*i)->matches(msg))
641 jason 2612 {
642 jason 2614 return *i;
643 jason 2612 }
644     }
645 jason 2614 return 0;
646 jason 2612 }
647 jason 2585
648 jason 2941 InviteSessionHandle
649 derek 3041 Dialog::getInviteSession()
650 ken 2520 {
651 davidb 2603 if (mInviteSession)
652     {
653     return mInviteSession->getSessionHandle();
654     }
655     else
656     {
657 derek 3041 return InviteSessionHandle::NotValid();
658 davidb 2603 }
659 ken 2520 }
660    
661 jason 2941 std::vector<ClientSubscriptionHandle>
662 derek 3041 Dialog::findClientSubscriptions(const Data& event)
663 ken 2520 {
664 jason 2941 std::vector<ClientSubscriptionHandle> handles;
665 davidb 2603
666 derek 2858 for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
667 davidb 2603 i != mClientSubscriptions.end(); ++i)
668     {
669 derek 3041 if ( (*i)->getEventType() == event)
670     {
671     handles.push_back((*i)->getHandle());
672     }
673     }
674     return handles;
675     }
676    
677     std::vector<ServerSubscriptionHandle>
678     Dialog::findServerSubscriptions(const Data& event)
679     {
680     std::vector<ServerSubscriptionHandle> handles;
681    
682     for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
683     i != mServerSubscriptions.end(); ++i)
684     {
685     if ( (*i)->getEventType() == event)
686     {
687     handles.push_back((*i)->getHandle());
688     }
689     }
690     return handles;
691     }
692    
693    
694     std::vector<ClientSubscriptionHandle>
695     Dialog::getClientSubscriptions()
696     {
697     std::vector<ClientSubscriptionHandle> handles;
698    
699     for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
700     i != mClientSubscriptions.end(); ++i)
701     {
702 davidb 2603 handles.push_back((*i)->getHandle());
703     }
704    
705     return handles;
706 ken 2520 }
707    
708 derek 3041 std::vector<ServerSubscriptionHandle>
709     Dialog::getServerSubscriptions()
710     {
711     std::vector<ServerSubscriptionHandle> handles;
712    
713     for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
714     i != mServerSubscriptions.end(); ++i)
715     {
716     handles.push_back((*i)->getHandle());
717     }
718    
719     return handles;
720     }
721    
722 derek 3179 void
723     Dialog::redirected(const SipMessage& msg)
724     {
725     //Established dialogs are not destroyed by a redirect
726     if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
727     {
728     return;
729     }
730     if (mInviteSession)
731     {
732     ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
733     if (cInv)
734     {
735     cInv->redirected(msg);
736     }
737     }
738     }
739 ken 2520
740 derek 3179
741 jason 2614 #if 0
742 jason 2539 void
743 jason 2535 Dialog::processNotify(const SipMessage& notify)
744     {
745     if (notify.isRequest())
746     {
747     if (findSubscriptions().empty())
748     {
749     SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
750     if (creator)
751     {
752     creator->makeNewSubscription(notify);
753     }
754     }
755     else
756     {
757     for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
758     {
759     ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
760     if (sub && sub->matches(notify))
761     {
762     sub->process(notify);
763     break;
764     }
765     }
766     }
767     }
768     }
769 jason 2612 #endif
770 jason 2539
771    
772 derek 2813 void
773     Dialog::makeRequest(SipMessage& request, MethodTypes method)
774     {
775     RequestLine rLine(method);
776    
777 derek 2817 rLine.uri() = mRemoteTarget.uri();
778 derek 2813
779     request.header(h_RequestLine) = rLine;
780 derek 2995 request.header(h_To) = mRemoteNameAddr;
781     // request.header(h_To).param(p_tag) = mId.getRemoteTag();
782     request.header(h_From) = mLocalNameAddr;
783     // request.header(h_From).param(p_tag) = mId.getLocalTag();
784 derek 2813
785     request.header(h_CallId) = mCallId;
786 derek 2997
787     request.remove(h_RecordRoutes); //!dcm! -- all of this is rather messy
788    
789 jason 3483 request.header(h_Contacts).clear();
790 derek 2995 request.header(h_Contacts).push_front(mLocalContact);
791 derek 2813 request.header(h_CSeq).method() = method;
792     request.header(h_MaxForwards).value() = 70;
793    
794 derek 2961 //must keep old via for cancel
795 jason 3433 if (method != CANCEL)
796 derek 2961 {
797 derek 3024 request.header(h_Routes) = mRouteSet;
798 derek 2992 request.remove(h_Vias);
799 derek 2961 Via via;
800     via.param(p_branch); // will create the branch
801     request.header(h_Vias).push_front(via);
802     }
803     else
804     {
805     assert(request.exists(h_Vias));
806     }
807 sgodin 3392
808 jason 3433 //don't increment CSeq for ACK or CANCEL
809     if (method != ACK && method != CANCEL)
810 derek 2965 {
811     request.header(h_CSeq).sequence() = ++mLocalCSeq;
812     }
813 sgodin 3383 else
814     {
815 jason 3433 // ACK and cancel have a minimal header set
816 sgodin 3383 request.remove(h_Accepts);
817     request.remove(h_AcceptEncodings);
818     request.remove(h_AcceptLanguages);
819     request.remove(h_Allows);
820     request.remove(h_Requires);
821     request.remove(h_ProxyRequires);
822     request.remove(h_Supporteds);
823     }
824 sgodin 3392
825 jason 3433 // If method is INVITE then advertise required headers
826     if(method == INVITE)
827 sgodin 3392 {
828 jason 3613 if(mDum.getProfile()->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getProfile()->getAllowedMethods();
829     if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getProfile()->getSupportedEncodings();
830     if(mDum.getProfile()->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getProfile()->getSupportedLanguages();
831     if(mDum.getProfile()->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getProfile()->getSupportedOptionTags();
832 sgodin 3392 }
833    
834 jason 3433 // Remove Session Timer headers for all requests except INVITE and UPDATE
835     if(method != INVITE && method != UPDATE)
836 sgodin 3392 {
837     request.remove(h_SessionExpires);
838     request.remove(h_MinSE);
839     }
840 jason 3156 DebugLog ( << "Dialog::makeRequest: " << request );
841 derek 2813 }
842    
843 derek 2961 void
844     Dialog::makeCancel(SipMessage& request)
845     {
846 derek 3138 //minimal for cancel
847 jason 3433 request.header(h_RequestLine).method() = CANCEL;
848     request.header(h_CSeq).method() = CANCEL;
849 sgodin 3383 request.remove(h_Accepts);
850     request.remove(h_AcceptEncodings);
851     request.remove(h_AcceptLanguages);
852     request.remove(h_Allows);
853 derek 2961 request.remove(h_Requires);
854     request.remove(h_ProxyRequires);
855 sgodin 3383 request.remove(h_Supporteds);
856 derek 3138 assert(request.exists(h_Vias));
857    
858     //not sure of these
859 derek 3058 request.header(h_To).remove(p_tag);
860 derek 3138 request.remove(h_RecordRoutes);
861 jason 3483 request.header(h_Contacts).clear();
862 derek 3138 request.header(h_Contacts).push_front(mLocalContact);
863     request.header(h_MaxForwards).value() = 70;
864 derek 2961 }
865    
866 derek 2813 void
867 jason 2887 Dialog::makeResponse(SipMessage& response, const SipMessage& request, int code)
868 derek 2813 {
869     assert( code >= 100 );
870 derek 3146 response.remove(h_Contacts);
871 derek 2992 if (code < 300 && code > 100)
872 derek 2813 {
873     assert(request.isRequest());
874 jason 3433 assert(request.header(h_RequestLine).getMethod() == INVITE ||
875     request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
876     request.header(h_RequestLine).getMethod() == BYE ||
877     request.header(h_RequestLine).getMethod() == CANCEL ||
878     request.header(h_RequestLine).getMethod() == REFER ||
879     request.header(h_RequestLine).getMethod() == MESSAGE ||
880     request.header(h_RequestLine).getMethod() == NOTIFY ||
881     request.header(h_RequestLine).getMethod() == INFO ||
882     request.header(h_RequestLine).getMethod() == OPTIONS
883 derek 3082 );
884 derek 2813
885 derek 3289 // assert (request.header(h_RequestLine).getMethod() == CANCEL || // Contact header is not required for Requests that do not form a dialog
886 jason 3433 // request.header(h_RequestLine).getMethod() == BYE ||
887 derek 3289 // request.header(h_Contacts).size() == 1);
888 derek 2992 Helper::makeResponse(response, request, code, mLocalContact);
889 derek 2936 response.header(h_To).param(p_tag) = mId.getLocalTag();
890 derek 2813 }
891     else
892     {
893 derek 3274 Helper::makeResponse(response, request, code);
894 derek 3006 response.header(h_To).param(p_tag) = mId.getLocalTag();
895    
896 derek 2813 }
897 jason 3156 DebugLog ( << "Dialog::makeResponse: " << response);
898 derek 2813 }
899    
900 jason 2885
901     ClientInviteSession*
902     Dialog::makeClientInviteSession(const SipMessage& response)
903     {
904     InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
905     assert(creator); // !jf! this maybe can assert by evil UAS
906 jason 2941 //return mDum.createAppClientInviteSession(*this, *creator);
907 derek 3101 return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
908     creator->getInitialOffer(), creator->getServerSubscription());
909 jason 2885 }
910    
911    
912    
913     ClientSubscription*
914 derek 3058 Dialog::makeClientSubscription(const SipMessage& request)
915 jason 2885 {
916 derek 3058 return new ClientSubscription(mDum, *this, request);
917 jason 2885 }
918    
919    
920     ServerInviteSession*
921     Dialog::makeServerInviteSession(const SipMessage& request)
922     {
923 jason 2941 return new ServerInviteSession(mDum, *this, request);
924 jason 2885 }
925    
926     ServerSubscription*
927     Dialog::makeServerSubscription(const SipMessage& request)
928     {
929 jason 2941 return new ServerSubscription(mDum, *this, request);
930 jason 2885 }
931    
932 davidb 2603 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
933     : BaseException(msg, file, line)
934 jason 2885 {
935     }
936 davidb 2603
937 jason 2853 void
938     Dialog::update(const SipMessage& msg)
939     {
940     }
941    
942     #if 0
943 derek 2839 void
944     Dialog::setLocalContact(const NameAddr& localContact)
945     {
946     mLocalContact = localContact;
947     }
948    
949     void
950     Dialog::setRemoteTarget(const NameAddr& remoteTarget)
951     {
952     mRemoteTarget = remoteTarget;
953     }
954 jason 2853 #endif
955 derek 2839
956 derek 2858 void Dialog::possiblyDie()
957     {
958 derek 2981 if (!mDestroying)
959 derek 2858 {
960 derek 2981 if (mClientSubscriptions.empty() &&
961 derek 3041 mServerSubscriptions.empty() &&
962 derek 3089 !mInviteSession)
963 derek 2981 {
964     delete this;
965     }
966     }
967 derek 2858 }
968 derek 2862
969 derek 3308 bool
970     Dialog::matches(const SipMessage& msg)
971     {
972     //currently only responses are passed to this method
973     if (msg.isRequest())
974     {
975     return false;
976     }
977    
978     switch (msg.header(h_CSeq).method())
979     {
980 jason 3433 case INVITE:
981     case CANCEL:
982     case REFER:
983     case BYE:
984 derek 3308 if (mInviteSession == 0)
985     {
986     return false;
987     }
988     else
989     {
990     return msg.getTransactionId() == mInviteSession->mLastRequest.getTransactionId();
991     }
992     break;
993 jason 3433 case INFO:
994 derek 3308 if (mInviteSession == 0)
995     {
996     return false;
997     }
998     else
999     {
1000     return msg.getTransactionId() == mInviteSession->mLastNit.getTransactionId();
1001     }
1002     break;
1003 jason 3433 case SUBSCRIBE:
1004 derek 3308 if (mClientSubscriptions.empty())
1005     {
1006     return false;
1007     }
1008     else
1009     {
1010     for (std::list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
1011     it != mClientSubscriptions.end(); it++)
1012     {
1013     return msg.getTransactionId() == (*it)->mLastRequest.getTransactionId();
1014     }
1015     }
1016     break;
1017 jason 3433 case NOTIFY:
1018 derek 3308 if (mServerSubscriptions.empty())
1019     {
1020     return false;
1021     }
1022     else
1023     {
1024     for (std::list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
1025     it != mServerSubscriptions.end(); it++)
1026     {
1027     return msg.getTransactionId() == (*it)->mLastNotify.getTransactionId();
1028     }
1029     }
1030     break;
1031     default:
1032     return false;
1033     }
1034     return false;
1035     }
1036    
1037 jason 2884 ostream&
1038     resip::operator<<(ostream& strm, const Dialog& dialog)
1039     {
1040    
1041     return strm;
1042     }
1043    
1044 derek 3716 void
1045     Dialog::forked(const SipMessage& msg)
1046     {
1047     assert(msg.isResponse() && msg.header(h_StatusLine).statusCode() < 200);
1048    
1049     ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
1050     if (uac)
1051     {
1052     uac->forked();
1053     }
1054     }
1055    
1056     void
1057     Dialog::cancel()
1058     {
1059     ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
1060     if (uac)
1061     {
1062     uac->cancel();
1063     }
1064     }

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27