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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27