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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27