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

Contents of /main/resip/dum/InviteSession.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2978 - (show annotations) (download)
Fri Jun 11 23:53:24 2004 UTC (15 years, 6 months ago) by derek
Original Path: main/sip/resiprocate/dum/InviteSession.cxx
File size: 13855 byte(s)
coding, coding, coding... no design changes.
1 #include "resiprocate/SipMessage.hxx"
2 #include "resiprocate/SdpContents.hxx"
3 #include "resiprocate/dum/Dialog.hxx"
4 #include "resiprocate/dum/DialogUsageManager.hxx"
5 #include "resiprocate/dum/InviteSession.hxx"
6 #include "resiprocate/dum/InviteSessionHandler.hxx"
7 #include "resiprocate/dum/UsageUseException.hxx"
8 #include "resiprocate/os/Logger.hxx"
9
10 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
11
12 using namespace resip;
13
14 InviteSession::InviteSession(DialogUsageManager& dum, Dialog& dialog, State initialState)
15 : BaseUsage(dum, dialog),
16 mState(initialState),
17 mOfferState(Nothing),
18 mCurrentLocalSdp(0),
19 mCurrentRemoteSdp(0),
20 mProposedLocalSdp(0),
21 mProposedRemoteSdp(0),
22 mNextOfferOrAnswerSdp(0)
23 {
24 assert(mDum.mInviteSessionHandler);
25 }
26
27 InviteSession::~InviteSession()
28 {
29 delete mCurrentLocalSdp;
30 delete mCurrentRemoteSdp;
31 delete mProposedLocalSdp;
32 delete mProposedRemoteSdp;
33 delete mNextOfferOrAnswerSdp;
34 mDialog.mInviteSession = 0;
35 }
36
37 void
38 InviteSession::setOffer(const SdpContents* sdp)
39 {
40 if (mProposedRemoteSdp)
41 {
42 throw UsageUseException("Cannot set an offer with an oustanding remote offer", __FILE__, __LINE__);
43 }
44 mNextOfferOrAnswerSdp = static_cast<SdpContents*>(sdp->clone());
45 }
46
47 void
48 InviteSession::setAnswer(const SdpContents* sdp)
49 {
50 if (mProposedLocalSdp )
51 {
52 throw UsageUseException("Cannot set an answer with an oustanding offer", __FILE__, __LINE__);
53 }
54 mNextOfferOrAnswerSdp = static_cast<SdpContents*>(sdp->clone());
55 }
56
57 const SdpContents*
58 InviteSession::getLocalSdp()
59 {
60 return mCurrentLocalSdp;
61 }
62
63 const SdpContents*
64 InviteSession::getRemoteSdp()
65 {
66 return mCurrentRemoteSdp;
67 }
68
69 InviteSessionHandle
70 InviteSession::getSessionHandle()
71 {
72 return InviteSessionHandle(mDum, getBaseHandle().getId());
73 }
74
75 void
76 InviteSession::dispatch(const SipMessage& msg)
77 {
78 std::pair<OfferAnswerType, const SdpContents*> offans;
79 offans = InviteSession::getOfferOrAnswer(msg);
80
81 switch(mState)
82 {
83 case Terminated:
84 //!dcm! -- 481 behaviour here, should pretty much die on anything
85 if (msg.isResponse() && msg.header(h_StatusLine).statusCode() == 200 && msg.header(h_CSeq).method() == BYE)
86 {
87 delete this;
88 }
89 break;
90 case Connected:
91 // reINVITE
92 if (msg.isRequest())
93 {
94 switch(msg.header(h_RequestLine).method())
95 {
96 case INVITE:
97 mDialog.update(msg);
98 mDum.mInviteSessionHandler->onDialogModified(getSessionHandle(), msg);
99
100 if (offans.first != None)
101 {
102 incomingSdp(msg, offans.second);
103 }
104 break;
105
106 case BYE:
107 mState = Terminated;
108 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), msg);
109 mDialog.makeResponse(mLastResponse, msg, 200);
110 send(mLastResponse);
111 break;
112
113 case UPDATE:
114 assert(0);
115 break;
116
117 case INFO:
118 mDum.mInviteSessionHandler->onInfo(getSessionHandle(), msg);
119 break;
120
121 case REFER:
122 assert(0); // !jf!
123 mDum.mInviteSessionHandler->onRefer(getSessionHandle(), msg);
124 break;
125
126 default:
127 InfoLog (<< "Ignoring request in an INVITE dialog: " << msg.brief());
128 break;
129 }
130 }
131 case Accepting:
132 if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK)
133 {
134 //cancel 200 retransmission timer
135 mState = Connected;
136 mDum.mInviteSessionHandler->onConnected(getSessionHandle(), msg);
137 if (offans.first != None)
138 {
139 InviteSession::incomingSdp(msg, offans.second);
140 }
141 }
142 else
143 {
144 assert(0); // !dcm! -- usual nonsence message behaviour question
145 }
146 break;
147 default:
148 assert(0); //all other cases should be handled in base classes
149 }
150 }
151
152 SipMessage&
153 InviteSession::makeRefer(const H_ReferTo::Type& referTo)
154 {
155 }
156
157 SipMessage&
158 InviteSession::end()
159 {
160 switch (mState)
161 {
162 case Terminated:
163 throw UsageUseException("Cannot end a session that has already been cancelled.", __FILE__, __LINE__);
164 break;
165 case Connected:
166 mDialog.makeRequest(mLastRequest, BYE);
167 mState = Terminated;
168 return mLastRequest;
169 break;
170 default:
171 assert(0); // out of states
172 }
173 }
174
175 // If sdp==0, it means the last offer failed
176 // !dcm! -- eventually handle confused UA's that send offers/answers at
177 // inappropriate times, probably with a different callback
178 void
179 InviteSession::incomingSdp(const SipMessage& msg, const SdpContents* sdp)
180 {
181 switch (mOfferState)
182 {
183 case Nothing:
184 assert(mCurrentLocalSdp == 0);
185 assert(mCurrentRemoteSdp == 0);
186 mProposedRemoteSdp = static_cast<SdpContents*>(sdp->clone());
187 mOfferState = Offerred;
188 mDum.mInviteSessionHandler->onOffer(getSessionHandle(), msg, sdp);
189 break;
190
191 case Offerred:
192 mCurrentLocalSdp = mProposedLocalSdp;
193 mCurrentRemoteSdp = static_cast<SdpContents*>(sdp->clone());
194 mProposedLocalSdp = 0;
195 mProposedRemoteSdp = 0;
196 mOfferState = Answered;
197 mDum.mInviteSessionHandler->onAnswer(getSessionHandle(), msg, sdp);
198 break;
199
200 case Answered:
201 assert(mProposedLocalSdp == 0);
202 assert(mProposedRemoteSdp == 0);
203 mProposedRemoteSdp = static_cast<SdpContents*>(sdp->clone());
204 mOfferState = CounterOfferred;
205 mDum.mInviteSessionHandler->onOffer(getSessionHandle(), msg, sdp);
206 break;
207
208 case CounterOfferred:
209 assert(mCurrentLocalSdp);
210 assert(mCurrentRemoteSdp);
211 mOfferState = Answered;
212 if (sdp)
213 {
214 delete mCurrentLocalSdp;
215 delete mCurrentRemoteSdp;
216 mCurrentLocalSdp = mProposedLocalSdp;
217 mCurrentRemoteSdp = static_cast<SdpContents*>(sdp->clone());
218 mProposedLocalSdp = 0;
219 mProposedRemoteSdp = 0;
220 mOfferState = Answered;
221 mDum.mInviteSessionHandler->onAnswer(getSessionHandle(), msg, sdp);
222 }
223 else
224 {
225 mProposedLocalSdp = 0;
226 mProposedRemoteSdp = 0;
227 // !jf! is this right?
228 mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), msg);
229 }
230 break;
231 }
232 }
233
234 void
235 InviteSession::send(SipMessage& msg)
236 {
237 if (msg.isRequest())
238 {
239 //unless the message is an ACK(in which case it is mAck)
240 //strip out the SDP after sending
241 if (msg.header(h_RequestLine).getMethod() == ACK)
242 {
243 mDum.send(msg);
244 }
245 else
246 {
247 mDum.send(msg);
248 msg.releaseContents();
249 }
250 }
251 else
252 {
253 int code = msg.header(h_StatusLine).statusCode();
254 //!dcm! -- probably kill this object earlier, handle 200 to bye in
255 //DialogUsageManager...very soon
256 if (msg.header(h_CSeq).method() == BYE && code == 200) //!dcm! -- not 2xx?
257
258 {
259 mState = Terminated;
260 mDum.send(msg);
261 delete this;
262 }
263 else if (code >= 200 && code < 300 && msg.header(h_CSeq).method() == INVITE)
264 {
265 assert(&msg == &mFinalResponse);
266 //!dcm! -- start timer...this should be mFinalResponse...maybe assign here in
267 //case the user wants to be very strange
268 if (mNextOfferOrAnswerSdp)
269 {
270 msg.setContents(static_cast<SdpContents*>(mNextOfferOrAnswerSdp->clone()));
271 sendSdp(mNextOfferOrAnswerSdp);
272 }
273 mDum.send(msg);
274 }
275 else
276 {
277 mDum.send(msg);
278 msg.releaseContents();
279 }
280 }
281 }
282
283 void
284 InviteSession::sendSdp(SdpContents* sdp)
285 {
286 switch (mOfferState)
287 {
288 case Nothing:
289 assert(mCurrentLocalSdp == 0);
290 assert(mCurrentRemoteSdp == 0);
291 mProposedLocalSdp = sdp;
292 mOfferState = Offerred;
293 break;
294
295 case Offerred:
296 mCurrentLocalSdp = sdp;
297 mCurrentRemoteSdp = mProposedRemoteSdp;
298 mProposedLocalSdp = 0;
299 mProposedRemoteSdp = 0;
300 mOfferState = Answered;
301 break;
302
303 case Answered:
304 assert(mProposedLocalSdp == 0);
305 assert(mProposedRemoteSdp == 0);
306 mProposedLocalSdp = sdp;
307 mOfferState = CounterOfferred;
308 break;
309
310 case CounterOfferred:
311 assert(mCurrentLocalSdp);
312 assert(mCurrentRemoteSdp);
313 if (sdp)
314 {
315 mCurrentLocalSdp = static_cast<SdpContents*>(sdp->clone());
316 mCurrentRemoteSdp = mProposedRemoteSdp;
317 }
318 else
319 {
320 mProposedLocalSdp = 0;
321 mProposedRemoteSdp = 0;
322 }
323 mOfferState = Answered;
324 break;
325 }
326 }
327
328 std::pair<InviteSession::OfferAnswerType, const SdpContents*>
329 InviteSession::getOfferOrAnswer(const SipMessage& msg) const
330 {
331 std::pair<InviteSession::OfferAnswerType, const SdpContents*> ret;
332 ret.first = None;
333
334 const SdpContents* contents = dynamic_cast<const SdpContents*>(msg.getContents());
335 if (contents)
336 {
337 static Token c100rel(Symbols::C100rel);
338 if (msg.isRequest() || msg.header(h_StatusLine).responseCode() == 200 ||
339 msg.exists(h_Supporteds) && msg.header(h_Supporteds).find(c100rel))
340 {
341 switch (mOfferState)
342 {
343 case None:
344 ret.first = Offer;
345 ret.second = contents;
346 break;
347
348 case Offerred:
349 ret.first = Answer;
350 ret.second = contents;
351 break;
352
353 case Answered:
354 ret.first = Offer;
355 ret.second = contents;
356 break;
357
358 case CounterOfferred:
359 ret.first = Answer;
360 ret.second = contents;
361 break;
362 }
363 }
364 }
365 return ret;
366 }
367
368 void
369 InviteSession::copyAuthorizations(SipMessage& request)
370 {
371 #if 0
372 if (mLastRequest.exists(h_ProxyAuthorizations))
373 {
374 // should make the next auth (change nextNonce)
375 request.header(h_ProxyAuthorizations) = mLastRequest.header(h_ProxyAuthorizations);
376 }
377 if (mLastRequest.exists(h_ProxyAuthorizations))
378 {
379 // should make the next auth (change nextNonce)
380 request.header(h_ProxyAuthorizations) = mLastRequest.header(h_ProxyAuthorizations);
381 }
382 #endif
383 }
384
385 SipMessage&
386 InviteSession::rejectOffer(int statusCode)
387 {
388 mDialog.makeResponse(mLastResponse, mLastRequest, statusCode);
389 return mLastResponse;
390 }
391
392 SipMessage&
393 InviteSession::targetRefresh(const NameAddr& localUri)
394 {
395 assert(0);
396 }
397
398 void
399 InviteSession::makeAck()
400 {
401 mAck = mLastRequest;
402 mDialog.makeRequest(mAck, ACK);
403 if (mNextOfferOrAnswerSdp)
404 {
405 mAck.setContents(static_cast<SdpContents*>(mNextOfferOrAnswerSdp->clone()));
406 sendSdp(mNextOfferOrAnswerSdp);
407 }
408 }
409
410 SipMessage&
411 InviteSession::reInvite(const SdpContents* offer)
412 {
413 }
414
415 /* ====================================================================
416 * The Vovida Software License, Version 1.0
417 *
418 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
419 *
420 * Redistribution and use in source and binary forms, with or without
421 * modification, are permitted provided that the following conditions
422 * are met:
423 *
424 * 1. Redistributions of source code must retain the above copyright
425 * notice, this list of conditions and the following disclaimer.
426 *
427 * 2. Redistributions in binary form must reproduce the above copyright
428 * notice, this list of conditions and the following disclaimer in
429 * the documentation and/or other materials provided with the
430
431 * distribution.
432 *
433 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
434 * and "Vovida Open Communication Application Library (VOCAL)" must
435 * not be used to endorse or promote products derived from this
436 * software without prior written permission. For written
437 * permission, please contact vocal@vovida.org.
438 *
439 * 4. Products derived from this software may not be called "VOCAL", nor
440 * may "VOCAL" appear in their name, without prior written
441 * permission of Vovida Networks, Inc.
442 *
443 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
444 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
445 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
446 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
447 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
448 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
449 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
450 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
451 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
452 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
453 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
454 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
455 * DAMAGE.
456 *
457 * ====================================================================
458 *
459 * This software consists of voluntary contributions made by Vovida
460 * Networks, Inc. and many individuals on behalf of Vovida Networks,
461 * Inc. For more information on Vovida Networks, Inc., please see
462 * <http://www.vovida.org/>.
463 *
464 */

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27