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

Contents of /main/sip/resiprocate/dum/Dialog.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2598 - (show annotations) (download)
Sun Apr 11 20:16:20 2004 UTC (15 years, 9 months ago) by jason
File size: 13147 byte(s)
*** empty log message ***

1 #include "resiprocate/Contents.hxx"
2 #include "Dialog.hxx"
3 #include "ClientInviteSession.hxx"
4
5 using namespace resip;
6 using namespace std;
7
8 class ServerInviteSession;
9
10 Dialog::Dialog(DialogUsageManager& dum, const SipMessage& msg)
11 : mId(msg),
12 mDum(dum),
13 mClientSubscriptions(),
14 mServerSubscription(0),
15 mInviteSession(0),
16 mClientRegistration(0),
17 mServerRegistration(0),
18 mClientPublication(0),
19 mServerPublication(0),
20 mClientOutOfDialogReq(0),
21 mServerOutOfDialogReq(0),
22 mType(Fake),
23 mLocalTag(),
24 mRemoteTag(),
25 mCallId(msg.header(h_CallID)),
26 mRouteSet(),
27 mMe(),
28 mLocalCSeq(0),
29 mRemoteCSeq(0),
30 mRemoteTarget()
31 {
32 assert(msg.isFromWire());
33
34 if (request.header(h_CSeq).method() == INVITE)
35 {
36 mType = Invitation;
37 }
38 else if (request.header(h_CSeq).method() == SUBSCRIBE)
39 {
40 mType = Subscription;
41 }
42
43 if (msg.isRequest()) // UAS
44 {
45 const SipMessage& request = msg;
46 mRouteSet = request.header(h_RecordRoutes);
47
48 switch (request.header(h_CSeq).method())
49 {
50 case INVITE:
51 case SUBSRIBE:
52 if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
53 {
54 NameAddr& contact = request.header(h_Contacts).front();
55 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
56 isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
57 {
58 mRemoteTarget = contact;
59 }
60 else
61 {
62 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
63 DebugLog (<< request);
64 throw Exception("Invalid dialog", __FILE__, __LINE__);
65 }
66 }
67 else
68 {
69 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
70 DebugLog (<< request);
71 throw Exception("Invalid dialog", __FILE__, __LINE__);
72 }
73 break;
74 }
75
76 mRemoteCSeq = request.header(h_CSeq).sequence();
77 mLocalCSeq = 0;
78
79 if ( response.header(h_From).exists(p_tag) ) // 2543 compat
80 {
81 mRemoteTag = response.header(h_From).param(p_tag);
82 }
83 if ( response.header(h_To).exists(p_tag) ) // 2543 compat
84 {
85 mLocalTag = response.header(h_To).param(p_tag);
86 }
87 mMe = response.header(h_To);
88
89 //mDialogId = mCallId;
90 //mDialogId.param(p_toTag) = mLocalTag;
91 //mDialogId.param(p_fromTag) = mRemoteTag;
92 }
93 else if (msg.isResponse())
94 {
95 const SipMessage& response = msg;
96 if (response.exists(h_RecordRoutes))
97 {
98 mRouteSet = response.header(h_RecordRoutes).reverse();
99 }
100
101 switch (response.header(h_CSeq).method())
102 {
103 case INVITE:
104 case SUBSRIBE:
105 if (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
106 {
107 NameAddr& contact = response.header(h_Contacts).front();
108 if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
109 isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
110 {
111 mRemoteTarget = contact;
112 }
113 else
114 {
115 InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
116 DebugLog (<< response);
117 throw Exception("Invalid dialog", __FILE__, __LINE__);
118 }
119 }
120 else
121 {
122 InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
123 DebugLog (<< response);
124 throw Exception("Invalid dialog", __FILE__, __LINE__);
125 }
126 break;
127 }
128
129 mLocalCSeq = response.header(h_CSeq).sequence();
130
131 if ( response.header(h_From).exists(p_tag) ) // 2543 compat
132 {
133 mLocalTag = response.header(h_From).param(p_tag);
134 }
135 if ( response.header(h_To).exists(p_tag) ) // 2543 compat
136 {
137 mRemoteTag = response.header(h_To).param(p_tag);
138 }
139 mMe = response.header(h_From);
140
141 //mDialogId = mCallId;
142 //mDialogId.param(p_toTag) = mLocalTag;
143 //mDialogId.param(p_fromTag) = mRemoteTag;
144 }
145 }
146
147 DialogId
148 Dialog::getId() const
149 {
150 return mId;
151 }
152
153
154 void
155 Dialog::dispatch(const SipMessage& msg)
156 {
157 BaseUsage* usage = findUsage(msg);
158 if (usage)
159 {
160 usage->dispatch(msg);
161 }
162 else // no matching usage
163 {
164 if (msg.isRequest())
165 {
166 switch (msg.header(h_CSeq).method())
167 {
168 case INVITE: // new INVITE
169 usage = mDum.createServerInviteSession(msg);
170 break;
171
172 case ACK:
173 case CANCEL:
174 InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
175 DebugLog (<< msg);
176 break;
177
178 case SUBSCRIBE:
179 case REFER: //!jf! does this create a server subs?
180 usage = mDum.createServerSubscription(msg);
181 break;
182
183 case NOTIFY:
184 usage = mDum.createClientSubscription(msg);
185 break;
186
187 case PUBLISH:
188 usage = mDum.createServerPublication(msg);
189 break;
190
191 case REGISTER:
192 usage = mDum.createServerRegistration(msg);
193 break;
194
195 default:
196 usage = mDum.createServerOutOfDialog(msg);
197 break;
198 }
199 }
200 else if (msg.isResponse())
201 {
202 // !jf! should this only be for 2xx responses?
203 switch (msg.header(h_CSeq).method())
204 {
205 case INVITE:
206 usage = mDum.createClientInviteSession(msg);
207 break;
208
209 case ACK:
210 case CANCEL:
211 // Drop on the floor
212 break;
213
214 case SUBSCRIBE:
215 case REFER: //!jf! does this create a server subs?
216 usage = mDum.createClientSubscription(msg);
217 break;
218
219 case NOTIFY:
220 usage = mDum.createClientSubscription(msg);
221 break;
222
223 case PUBLISH:
224 usage = mDum.createClientPublication(msg);
225 break;
226
227 case REGISTER:
228 usage = mDum.createClientRegistration(msg);
229 break;
230
231 default:
232 usage = mDum.createClientOutOfDialog(msg);
233 break;
234 }
235 }
236
237 assert(usage);
238 mUsages.push_back(usage);
239 }
240 }
241
242 BaseUsage*
243 Dialog::findUsage(const SipMessage& msg)
244 {
245 switch (msg.header(h_CSeq).method())
246 {
247 case INVITE: // new INVITE
248 case CANCEL:
249 case ACK:
250 return mInviteSession;
251
252 case SUBSCRIBE:
253 case REFER:
254 case NOTIFY:
255 for (std::vector<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
256 i != mClientSubscriptions.end(); i++)
257 {
258 if (i->matches(msg))
259 {
260 return *i;
261 }
262 }
263 break;
264 case REGISTER:
265 InfoLog (<< "Received REGISTER inside an existing dialog. This is not supported. ");
266 DebugLog (<< msg);
267 break;
268
269 case PUBLISH:
270 if (msg.isRequest())
271 {
272 return mServerPublication;
273 }
274 else if (msg.isRequest())
275 {
276 return mClientPublication;
277 }
278 break;
279
280 default:
281 if (msg.isRequest())
282 {
283 return mServerOutOfDialogReq;
284 }
285 else if (msg.isRequest())
286 {
287 return mClientOutOfDialogReq;
288 }
289 break;
290 }
291 return 0;
292 }
293
294 DialogId Dialog::getId() const
295 {
296 return mId;
297 }
298
299 BaseUsage&
300 Dialog::findInvSession()
301 {
302 std::list<BaseUsage*>::iterator it = mUsages.begin();
303 BaseUsage *usage;
304 while (it != mUsages.end())
305 {
306 usage = it->next();
307 if ((dynamic_cast<ClientInviteSession*>(usage) != NULL) ||
308 (dynamic_cast<ServerInviteSession*>(usage) != NULL))
309 {
310 return *usage;
311 }
312 }
313 return BaseUsage::empty();
314 }
315
316 UsageSet
317 Dialog::findSubscriptions()
318 {
319 std::list<BaseUsage*>::iterator it = mUsages.begin();
320 BaseUsage *usage;
321 UsageSet usageSet;
322 while (it != mUsages.end())
323 {
324 usage = it.next();
325 if ((dynamic_cast<ClientSubscription*>(usage) != null) ||
326 (dynamic_cast<ServerSubscription*>(usage) != null))
327 {
328 usageSet.push_back(*usage);
329 }
330 }
331 return usageSet:
332 }
333
334 BaseUsage&
335 Dialog::findRegistration()
336 {
337 std::list<BaseUsage*>::iterator it = mUsages.begin();
338 BaseUsage *usage;
339 while (it != mUsages.end())
340 {
341 usage = it.next();
342 if ((dynamic_cast<CientRegistration*>(usage) != null) ||
343 (dynamic_cast<ServerRegistration*>(usage) != null))
344 {
345 return *usage;
346 }
347 }
348 return BaseUsage::empty();
349 }
350
351
352 BaseUsage&
353 Dialog::findPublication()
354 {
355 std::list<BaseUsage*>::iterator it = mUsages.begin();
356 BaseUsage *usage;
357 while (it != mUsages.end())
358 {
359 usage = it.next();
360 if ((dynamic_cast<CientPublication*>(usage) != null) ||
361 (dynamic_cast<ServerPublication*>(usage) != null))
362 {
363 return *usage;
364 }
365 }
366 return BaseUsage::empty();
367 }
368
369 UsageSet
370 Dialog::findOutOfDialogs()
371 {
372 std::list<BaseUsage*>::iterator it = mUsages.begin();
373 BaseUsage *usage;
374 UsageSet usageSet;
375 while (it != mUsages.end())
376 {
377 usage = it.next();
378 if ((dynamic_cast<ClientOutOfDialogReq*>(usage) != null) ||
379 (dynamic_cast<ServerOutOfDialogReq*>(usage) != null))
380 {
381 usageSet.push_back(*usage);
382 }
383 }
384 return usageSet:
385 }
386
387 void
388 Dialog::dispatch(const SipMessage& msg)
389 {
390 if (msg.isRequest())
391 {
392 switch (request.header(h_RequestLine).getMethod())
393 {
394 // a NOTIFY is the only request that can
395 // create a full dialog (when the 2xx from the
396 // SUBSCRIBE arrives *after* the NOTIFY
397 case NOTIFY :
398 processNotify(msg);
399 break;
400
401 case REFER:
402 // !jf! wierdo
403 // affects an InvSession and a ServerSubscription
404 break;
405
406 case SUBSCRIBE:
407 processSubscribe(msg);
408 break;
409
410 case CANCEL:
411 // should only occur when canceling a re-INVITE
412 case INVITE:
413 // should only occur for a re-INVITE
414 case ACK:
415 case PRACK:
416 case BYE:
417 case UPDATE:
418 case INFO:
419 processInviteRelated(msg);
420 break;
421
422 case REGISTER:
423 {
424 assert(0); // already handled
425 break;
426 }
427
428 case PUBLISH:
429 assert(0);
430 break;
431
432 case MESSAGE:
433 case OPTIONS:
434 assert(0);
435 break;
436
437 default:
438 assert(0);
439 break;
440 }
441 }
442 else if (msg.isResponse())
443 {
444
445 }
446 else
447 {
448 assert(0);
449 }
450 }
451
452 void
453 Dialog::processNotify(const SipMessage& notify)
454 {
455 if (notify.isRequest())
456 {
457 if (findSubscriptions().empty())
458 {
459 SubscriptionCreator* creator = dynamic_cast<SubscriptionCreator*>(DialogSetId(notify).getCreator());
460 if (creator)
461 {
462 creator->makeNewSubscription(notify);
463 }
464 }
465 else
466 {
467 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
468 {
469 ClientSubscription* sub = dynamic_cast<ClientSubscription*>(*i);
470 if (sub && sub->matches(notify))
471 {
472 sub->process(notify);
473 break;
474 }
475 }
476 }
477 }
478 }
479
480 void
481 Dialog::processSubscribe(const SipMessage& subscribe)
482 {
483 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
484 {
485 ServerSubscription* sub = dynamic_cast<ServerSubscription*>(*i);
486 if (sub && sub->matches(subscribe))
487 {
488 sub->process(subscribe); // a resubscribe or unsubscribe
489 return;
490 }
491 }
492
493 // a subscribe on an existing dialog with a different BaseUsage
494 ServerSubscription* sub = new ServerSubscription(mDum, subscribe);
495 }
496
497 void
498 Dialog::processInviteRelated(const SipMessage& msg)
499 {
500 for (std::list<BaseUsage*>::iterator i=mUsages.begin(); i!=mUsages.end(); i++)
501 {
502 ServerInvSession* server = dynamic_cast<ServerInvSession*>(*i);
503 ClientInvSession* client = dynamic_cast<ClientInvSession*>(*i);
504 if (server)
505 {
506 server->process(msg);
507 break;
508 }
509 else if (client)
510 {
511 client->process(msg);
512 break;
513 }
514 }
515 }

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27