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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27