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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27