/[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 2588 - (show annotations) (download)
Sun Apr 11 18:30:31 2004 UTC (15 years, 9 months ago) by jason
File size: 13271 byte(s)
*** empty log message ***

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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27