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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27