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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2817 - (hide annotations) (download)
Sat May 29 03:24:24 2004 UTC (15 years, 6 months ago) by derek
Original Path: main/sip/resiprocate/dum/Dialog.cxx
File size: 16738 byte(s)
fixed build errors
1 davidb 2603 #include "resiprocate/SipMessage.hxx"
2     #include "resiprocate/Contents.hxx"
3 jason 2614 #include "resiprocate/Helper.hxx"
4 davidb 2603 #include "resiprocate/os/Logger.hxx"
5    
6 jason 2611 #include "BaseCreator.hxx"
7 jason 2598 #include "Dialog.hxx"
8 davidb 2603 #include "DialogUsageManager.hxx"
9 jason 2614 #include "ClientOutOfDialogReq.hxx"
10 ken 2520
11 davidb 2603 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
12    
13 ken 2520 using namespace resip;
14     using namespace std;
15    
16 ken 2556 class ServerInviteSession;
17    
18 jason 2611 Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg)
19 jason 2577 : mId(msg),
20     mDum(dum),
21 jason 2588 mClientSubscriptions(),
22     mServerSubscription(0),
23     mInviteSession(0),
24     mClientRegistration(0),
25     mServerRegistration(0),
26     mClientPublication(0),
27     mServerPublication(0),
28 jason 2614 mClientOutOfDialogRequests(),
29     mServerOutOfDialogRequest(0),
30 jason 2588 mType(Fake),
31     mLocalTag(),
32     mRemoteTag(),
33     mCallId(msg.header(h_CallID)),
34     mRouteSet(),
35 jason 2611 mLocalContact(),
36 jason 2577 mLocalCSeq(0),
37     mRemoteCSeq(0),
38 jason 2588 mRemoteTarget()
39 jason 2577 {
40 davidb 2603 assert(msg.isExternal());
41 jason 2577
42     if (msg.isRequest()) // UAS
43     {
44     const SipMessage& request = msg;
45    
46     switch (request.header(h_CSeq).method())
47     {
48     case INVITE:
49 jason 2611 mType = Invitation;
50     break;
51    
52 davidb 2603 case SUBSCRIBE:
53 jason 2611 case REFER:
54     case NOTIFY:
55     mType = Subscription;
56     break;
57    
58     default:
59     mType = Fake;
60     }
61    
62     mRouteSet = request.header(h_RecordRoutes); // !jf! is this right order
63    
64     switch (request.header(h_CSeq).method())
65     {
66     case INVITE:
67     case SUBSCRIBE:
68     case REFER:
69 jason 2577 if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
70     {
71 davidb 2603 const NameAddr& contact = request.header(h_Contacts).front();
72 jason 2577 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
73     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
74     {
75 jason 2611 mLocalContact = NameAddr(request.header(h_RequestLine).uri()); // update later when send a request
76 jason 2577 mRemoteTarget = contact;
77     }
78     else
79     {
80 davidb 2603 InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme");
81     DebugLog(<< request);
82 jason 2611 throw Exception("Invalid scheme in request", __FILE__, __LINE__);
83 jason 2577 }
84     }
85     else
86     {
87     InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
88     DebugLog (<< request);
89 jason 2611 throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__);
90 jason 2577 }
91     break;
92 davidb 2603 default:
93     break;
94 jason 2577 }
95    
96     mRemoteCSeq = request.header(h_CSeq).sequence();
97 jason 2611 mLocalCSeq = 1;
98 jason 2577
99 davidb 2603 if (request.header(h_From).exists(p_tag) ) // 2543 compat
100 jason 2577 {
101 davidb 2603 mRemoteTag = request.header(h_From).param(p_tag);
102 jason 2577 }
103 davidb 2603 if ( request.header(h_To).exists(p_tag) ) // 2543 compat
104 jason 2577 {
105 davidb 2603 mLocalTag = request.header(h_To).param(p_tag);
106 jason 2577 }
107     }
108     else if (msg.isResponse())
109     {
110     const SipMessage& response = msg;
111 jason 2611
112     switch (msg.header(h_CSeq).method())
113     {
114     case INVITE:
115     mType = Invitation;
116     break;
117    
118     case SUBSCRIBE:
119     case REFER:
120     mType = Subscription;
121     break;
122    
123     default:
124     mType = Fake;
125     }
126    
127 jason 2577 if (response.exists(h_RecordRoutes))
128     {
129     mRouteSet = response.header(h_RecordRoutes).reverse();
130     }
131    
132     switch (response.header(h_CSeq).method())
133     {
134     case INVITE:
135 davidb 2603 case SUBSCRIBE:
136 jason 2611 case REFER:
137 jason 2577 if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
138     {
139 davidb 2603 const NameAddr& contact = response.header(h_Contacts).front();
140 jason 2577 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
141     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
142     {
143 jason 2612 BaseCreator* creator = mDum.findCreator(mId);
144     assert(creator);// !jf! throw or something here
145    
146     mLocalContact = creator->getLastRequest().header(h_Contacts).front();
147 jason 2577 mRemoteTarget = contact;
148     }
149     else
150     {
151     InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
152     DebugLog (<< response);
153 jason 2611 throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
154 jason 2577 }
155     }
156     else
157     {
158     InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
159     DebugLog (<< response);
160 jason 2611 throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
161 jason 2577 }
162     break;
163 davidb 2603 default:
164     break;
165 jason 2577 }
166    
167     mLocalCSeq = response.header(h_CSeq).sequence();
168 jason 2611 mRemoteCSeq = 0;
169    
170 jason 2577 if ( response.header(h_From).exists(p_tag) ) // 2543 compat
171     {
172     mLocalTag = response.header(h_From).param(p_tag);
173     }
174     if ( response.header(h_To).exists(p_tag) ) // 2543 compat
175     {
176     mRemoteTag = response.header(h_To).param(p_tag);
177     }
178     }
179     }
180    
181 jason 2588 DialogId
182     Dialog::getId() const
183     {
184     return mId;
185     }
186    
187 davidb 2604 void
188     Dialog::dispatch(const SipMessage& msg)
189     {
190 jason 2614 if (msg.isRequest())
191 jason 2583 {
192 jason 2614 const SipMessage& request = msg;
193     switch (request.header(h_CSeq).method())
194 jason 2583 {
195 jason 2614 case INVITE: // new INVITE
196     if (mInviteSession == 0)
197     {
198     mInviteSession = mDum.makeServerInviteSession(*this, request);
199     }
200     mInviteSession->dispatch(request);
201     break;
202 jason 2583
203 jason 2614 case ACK:
204     case CANCEL:
205     if (mInviteSession == 0)
206     {
207     InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
208     DebugLog (<< request);
209     }
210     else
211     {
212     mInviteSession->dispatch(request);
213     }
214     break;
215    
216     case SUBSCRIBE:
217     case REFER: //!jf! does this create a server subs?
218     if (mServerSubscription == 0)
219     {
220     mServerSubscription = mDum.makeServerSubscription(*this, request);
221     }
222    
223     mServerSubscription->dispatch(request);
224     break;
225    
226     case NOTIFY:
227     if (request.header(h_To).exists(p_tag))
228     {
229     ClientSubscription* client = findMatchingClientSub(request);
230     if (client)
231 jason 2612 {
232 jason 2614 client->dispatch(request);
233 jason 2612 }
234     else
235     {
236 jason 2614 BaseCreator* creator = mDum.findCreator(mId);
237     if (creator)
238 jason 2612 {
239 jason 2614 ClientSubscription* sub = mDum.makeClientSubscription(*this, request);
240     mClientSubscriptions.push_back(sub);
241     sub->dispatch(request);
242 jason 2612 }
243     else
244     {
245 jason 2614 std::auto_ptr<SipMessage> failure(Helper::makeResponse(request, 481));
246     mDum.send(*failure);
247     return;
248 jason 2612 }
249     }
250 jason 2614 }
251     else // no to tag - unsolicited notify
252     {
253     assert(mServerOutOfDialogRequest == 0);
254     mServerOutOfDialogRequest = mDum.makeServerOutOfDialog(*this, request);
255     mServerOutOfDialogRequest->dispatch(request);
256     }
257     break;
258 jason 2583
259 jason 2614 case PUBLISH:
260     if (mServerPublication == 0)
261     {
262     mServerPublication = mDum.makeServerPublication(*this, request);
263     }
264     mServerPublication->dispatch(request);
265     break;
266 jason 2612
267 jason 2614 case REGISTER:
268     if (mServerRegistration == 0)
269     {
270     mServerRegistration = mDum.makeServerRegistration(*this, request);
271     }
272     mServerRegistration->dispatch(request);
273     break;
274 jason 2584
275 jason 2614 default:
276     // only can be one ServerOutOfDialogReq at a time
277     assert(mServerOutOfDialogRequest == 0);
278     mServerOutOfDialogRequest = mDum.makeServerOutOfDialog(*this, request);
279     mServerOutOfDialogRequest->dispatch(request);
280     break;
281 jason 2583 }
282 jason 2614 }
283     else if (msg.isResponse())
284     {
285     const SipMessage& response = msg;
286     // !jf! should this only be for 2xx responses?
287     switch (response.header(h_CSeq).method())
288 jason 2583 {
289 jason 2614 case INVITE:
290     if (mInviteSession == 0)
291     {
292     BaseCreator* creator = mDum.findCreator(mId);
293     assert (creator);
294     creator->dispatch(response);
295     if (response.header(h_StatusLine).statusCode() != 100)
296 jason 2612 {
297 jason 2614 mInviteSession = mDum.makeClientInviteSession(*this, response);
298     mInviteSession->dispatch(response);
299 jason 2612 }
300 jason 2614 }
301     else
302     {
303     mInviteSession->dispatch(response);
304     }
305     break;
306 jason 2584
307 jason 2614 case ACK:
308     case CANCEL:
309     if (mInviteSession != 0)
310     {
311     mInviteSession->dispatch(response);
312     }
313     // else drop on the floor
314     break;
315 jason 2584
316 jason 2614 case SUBSCRIBE:
317     case REFER:
318     {
319     ClientSubscription* client = findMatchingClientSub(response);
320     if (client)
321 jason 2612 {
322 jason 2614 client->dispatch(response);
323 jason 2612 }
324 jason 2614 else
325     {
326     ClientSubscription* sub = mDum.makeClientSubscription(*this, response);
327     mClientSubscriptions.push_back(sub);
328     sub->dispatch(response);
329     }
330     break;
331     }
332 jason 2584
333 jason 2614 case PUBLISH:
334     if (mClientPublication == 0)
335     {
336     mClientPublication = mDum.makeClientPublication(*this, response);
337     }
338     mClientPublication->dispatch(response);
339     break;
340 jason 2584
341 jason 2614 case REGISTER:
342     if (mClientRegistration == 0)
343     {
344     mClientRegistration = mDum.makeClientRegistration(*this, response);
345     }
346     mClientRegistration->dispatch(response);
347     break;
348 jason 2584
349 jason 2614 // unsolicited - not allowed but commonly implemented
350     // by large companies with a bridge as their logo
351     case NOTIFY:
352     case INFO:
353 jason 2612
354 jason 2614 default:
355     {
356     ClientOutOfDialogReq* req = findMatchingClientOutOfDialogReq(response);
357     if (req == 0)
358 jason 2612 {
359 jason 2726 req = mDum.makeClientOutOfDialogReq(*this, response);
360 jason 2614 mClientOutOfDialogRequests.push_back(req);
361     }
362     req->dispatch(response);
363     break;
364 jason 2584 }
365 jason 2583 }
366     }
367 jason 2578 }
368    
369 jason 2612
370     ClientSubscription*
371     Dialog::findMatchingClientSub(const SipMessage& msg)
372 jason 2583 {
373 jason 2612 for (std::vector<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
374     i != mClientSubscriptions.end(); ++i)
375 jason 2583 {
376 jason 2614 if ((*i)->matches(msg))
377 jason 2612 {
378 jason 2614 return *i;
379 jason 2612 }
380     }
381 jason 2614 return 0;
382 jason 2612 }
383 jason 2585
384 jason 2614 ClientOutOfDialogReq*
385 jason 2612 Dialog::findMatchingClientOutOfDialogReq(const SipMessage& msg)
386     {
387 jason 2614 for (std::vector<ClientOutOfDialogReq*>::iterator i=mClientOutOfDialogRequests.begin();
388 jason 2612 i != mClientOutOfDialogRequests.end(); ++i)
389     {
390 jason 2614 if ((*i)->matches(msg))
391 jason 2612 {
392 jason 2614 return *i;
393 jason 2612 }
394 jason 2583 }
395 jason 2614 return 0;
396 jason 2583 }
397    
398 jason 2612
399 davidb 2603 InviteSession::Handle
400     Dialog::findInviteSession()
401 ken 2520 {
402 davidb 2603 if (mInviteSession)
403     {
404     return mInviteSession->getSessionHandle();
405     }
406     else
407     {
408     throw BaseUsage::Exception("no such invite session",
409     __FILE__, __LINE__);
410     }
411 ken 2520 }
412    
413 davidb 2603 std::vector<ClientSubscription::Handle>
414     Dialog::findClientSubscriptions()
415 ken 2520 {
416 davidb 2603 std::vector<ClientSubscription::Handle> handles;
417    
418     for (std::vector<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
419     i != mClientSubscriptions.end(); ++i)
420     {
421     handles.push_back((*i)->getHandle());
422     }
423    
424     return handles;
425 ken 2520 }
426    
427 davidb 2603 ClientRegistration::Handle
428     Dialog::findClientRegistration()
429 ken 2520 {
430 davidb 2603 if (mClientRegistration)
431     {
432     return mClientRegistration->getHandle();
433     }
434     else
435     {
436 davidb 2604 throw BaseUsage::Exception("no such client registration",
437 davidb 2603 __FILE__, __LINE__);
438     }
439 ken 2520 }
440    
441 davidb 2603 ServerRegistration::Handle
442     Dialog::findServerRegistration()
443 ken 2520 {
444 davidb 2603 if (mServerRegistration)
445     {
446     return mServerRegistration->getHandle();
447     }
448     else
449     {
450 davidb 2604 throw BaseUsage::Exception("no such server registration",
451 davidb 2603 __FILE__, __LINE__);
452     }
453 ken 2520 }
454    
455 davidb 2604 ClientPublication::Handle
456     Dialog::findClientPublication()
457     {
458     if (mClientPublication)
459     {
460     return mClientPublication->getHandle();
461     }
462     else
463     {
464     throw BaseUsage::Exception("no such client publication",
465     __FILE__, __LINE__);
466     }
467     }
468 ken 2520
469 davidb 2604 ServerPublication::Handle
470     Dialog::findServerPublication()
471 ken 2520 {
472 davidb 2604 if (mServerPublication)
473     {
474     return mServerPublication->getHandle();
475     }
476     else
477     {
478     throw BaseUsage::Exception("no such server publication",
479     __FILE__, __LINE__);
480     }
481 ken 2520 }
482 jason 2535
483 jason 2614 #if 0
484 davidb 2604 ClientOutOfDialogReq::Handle
485     Dialog::findClientOutOfDialog()
486 jason 2539 {
487 jason 2614 if (mClientOutOfDialogRequests)
488 jason 2539 {
489 davidb 2604 return mClientOutOfDialogReq->getHandle();
490 jason 2577 }
491 davidb 2604 else
492 jason 2577 {
493 davidb 2604 throw BaseUsage::Exception("no such client out of dialog",
494     __FILE__, __LINE__);
495 jason 2577 }
496 davidb 2604 }
497 jason 2614 #endif
498 davidb 2604
499     ServerOutOfDialogReq::Handle
500     Dialog::findServerOutOfDialog()
501     {
502 jason 2614 if (mServerOutOfDialogRequest)
503 davidb 2604 {
504 jason 2614 return mServerOutOfDialogRequest->getHandle();
505 davidb 2604 }
506 jason 2577 else
507     {
508 davidb 2604 throw BaseUsage::Exception("no such server out of dialog",
509     __FILE__, __LINE__);
510 jason 2577 }
511 jason 2539 }
512    
513 davidb 2604 #if 0
514 jason 2539 void
515 jason 2535 Dialog::processNotify(const SipMessage& notify)
516     {
517     if (notify.isRequest())
518     {
519     if (findSubscriptions().empty())
520     {
521     SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
522     if (creator)
523     {
524     creator->makeNewSubscription(notify);
525     }
526     }
527     else
528     {
529     for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
530     {
531     ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
532     if (sub && sub->matches(notify))
533     {
534     sub->process(notify);
535     break;
536     }
537     }
538     }
539     }
540     }
541 jason 2612 #endif
542 jason 2539
543    
544 derek 2813 void
545     Dialog::makeRequest(SipMessage& request, MethodTypes method)
546     {
547     RequestLine rLine(method);
548    
549 derek 2817 rLine.uri() = mRemoteTarget.uri();
550 derek 2813
551     request.header(h_RequestLine) = rLine;
552 derek 2817 request.header(h_To) = mRemoteTarget;
553 derek 2813 request.header(h_To).param(p_tag) = mRemoteTag;
554     request.header(h_From) = mLocalContact;
555     request.header(h_From).param(p_tag) = mLocalTag;
556    
557     request.header(h_CallId) = mCallId;
558     request.header(h_Routes) = mRouteSet;
559     request.header(h_Contacts).push_front(mLocalContact);
560     request.header(h_CSeq).method() = method;
561     request.header(h_MaxForwards).value() = 70;
562    
563     Via via;
564     via.param(p_branch); // will create the branch
565     request.header(h_Vias).push_front(via);
566    
567     request.header(h_CSeq).sequence() = ++mLocalCSeq;
568     }
569    
570    
571     void
572     Dialog::makeResponse(const SipMessage& request, SipMessage& response, int code)
573     {
574     assert( code >= 100 );
575     response.header(h_To).param(p_tag) = mLocalTag;
576     if ( (code < 300) && (code > 100) )
577     {
578     assert(request.isRequest());
579     assert(request.header(h_RequestLine).getMethod() == INVITE ||
580     request.header(h_RequestLine).getMethod() == SUBSCRIBE);
581    
582     assert (request.header(h_Contacts).size() == 1);
583     response.header(h_To).param(p_tag) = mLocalTag;
584    
585 derek 2817 Helper::makeResponse(response, request, code);
586 derek 2813
587     if (!request.exists(h_Contacts) && request.header(h_Contacts).size() != 1)
588     {
589     InfoLog (<< "Request doesn't have a contact header or more than one contact, so can't create dialog");
590     DebugLog (<< request);
591     throw Exception("Invalid or missing contact header in request", __FILE__,__LINE__);
592     }
593    
594 derek 2817 assert (response.header(h_To).exists(p_tag));
595 derek 2813 }
596     else
597     {
598 derek 2817 Helper::makeResponse(response, request, code, mLocalContact);
599 derek 2813 }
600     }
601    
602 davidb 2603 Dialog::Exception::Exception(const Data& msg, const Data& file, int line)
603     : BaseException(msg, file, line)
604     {}
605    

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27