/[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 2603 - (show annotations) (download)
Sun Apr 11 23:41:33 2004 UTC (15 years, 9 months ago) by davidb
File size: 13187 byte(s)
slouching towards compile...

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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27