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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27