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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5505 - (hide annotations) (download)
Fri Oct 7 19:58:39 2005 UTC (14 years, 2 months ago) by daniel
File size: 60554 byte(s)
Added a virtual method onReadyToSend in BaseUsage. The BaseUsage send() calls onReadyToSend before calling send on DUM. Any usage can override this method to give application a chance to adorn the message. The default onReadyToSend does nothing. Callback onReadyToSend is also added in InviteSessoinHandler, ServerSubscriptionHandler, and ClientSubscriptionHandler.
1 derek 5283 #include "resip/stack/MultipartMixedContents.hxx"
2     #include "resip/stack/MultipartAlternativeContents.hxx"
3     #include "resip/stack/SdpContents.hxx"
4     #include "resip/stack/SipMessage.hxx"
5     #include "resip/stack/Helper.hxx"
6 jason 5276 #include "resip/dum/Dialog.hxx"
7     #include "resip/dum/DialogUsageManager.hxx"
8     #include "resip/dum/InviteSession.hxx"
9     #include "resip/dum/ServerInviteSession.hxx"
10     #include "resip/dum/ClientSubscription.hxx"
11     #include "resip/dum/ServerSubscription.hxx"
12     #include "resip/dum/ClientInviteSession.hxx"
13     #include "resip/dum/InviteSessionHandler.hxx"
14     #include "resip/dum/MasterProfile.hxx"
15     #include "resip/dum/UsageUseException.hxx"
16 daniel 5383 #include "resip/dum/DumHelper.hxx"
17 jason 5276 #include "rutil/Inserter.hxx"
18     #include "rutil/Logger.hxx"
19     #include "rutil/Timer.hxx"
20     #include "rutil/Random.hxx"
21     #include "rutil/compat.hxx"
22     #include "rutil/WinLeakCheck.hxx"
23 jason 2555
24 sgodin 3314 // Remove warning about 'this' use in initiator list - pointer is only stored
25     #if defined(WIN32)
26 jason 4010 #pragma warning( disable : 4355 ) // using this in base member initializer list
27     #pragma warning( disable : 4800 ) // forcing value to bool (performance warning)
28 sgodin 3314 #endif
29 derek 3092
30 jason 2856 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
31 jason 4010 #define THROW(msg) throw DialogUsage::Exception(msg, __FILE__,__LINE__);
32 jason 2846
33 davidb 2603 using namespace resip;
34 derek 3255 using namespace std;
35 davidb 2603
36 jason 4010 InviteSession::InviteSession(DialogUsageManager& dum, Dialog& dialog)
37 derek 3089 : DialogUsage(dum, dialog),
38 jason 4010 mState(Undefined),
39 derek 3255 mNitState(NitComplete),
40 jason 4010 mCurrentRetransmit200(0),
41 sgodin 3392 mSessionInterval(0),
42 sgodin 4691 mMinSE(90),
43     mSessionRefresher(false),
44 sgodin 3392 mSessionTimerSeq(0),
45 daniel 5068 mSentRefer(false),
46     mCurrentEncryptionLevel(DialogUsageManager::None),
47     mProposedEncryptionLevel(DialogUsageManager::None)
48 jason 2555 {
49 jason 4010 DebugLog ( << "^^^ InviteSession::InviteSession " << this);
50 jason 2846 assert(mDum.mInviteSessionHandler);
51 jason 2555 }
52    
53 derek 2858 InviteSession::~InviteSession()
54     {
55 jason 4010 DebugLog ( << "^^^ InviteSession::~InviteSession " << this);
56 derek 2858 mDialog.mInviteSession = 0;
57     }
58 jason 2846
59 jason 4010 void
60     InviteSession::dialogDestroyed(const SipMessage& msg)
61 derek 3064 {
62 jason 4010 assert(0);
63    
64     // !jf! Is this correct? Merged from main...
65     // !jf! what reason - guessed for now?
66     //mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::PeerEnded, msg);
67     //delete this;
68     }
69    
70     const SdpContents&
71     InviteSession::getLocalSdp() const
72     {
73     return *mCurrentLocalSdp;
74     }
75    
76     const SdpContents&
77     InviteSession::getRemoteSdp() const
78     {
79     return *mCurrentRemoteSdp;
80     }
81    
82 jason 5459 const Data&
83     InviteSession::getDialogId() const
84     {
85     return mDialog.getId().getCallId();
86     }
87    
88 jason 4010 InviteSessionHandle
89     InviteSession::getSessionHandle()
90     {
91     return InviteSessionHandle(mDum, getBaseHandle().getId());
92     }
93    
94     void InviteSession::storePeerCapabilities(const SipMessage& msg)
95     {
96     // !slg! ToDo - add methods to get this data, App may be interested
97     if (msg.exists(h_Allows))
98 derek 3064 {
99 jason 4010 mPeerSupportedMethods = msg.header(h_Allows);
100 derek 3064 }
101 jason 4010 if (msg.exists(h_Supporteds))
102     {
103     mPeerSupportedOptionTags = msg.header(h_Supporteds);
104     }
105     if (msg.exists(h_AcceptEncodings))
106     {
107     mPeerSupportedEncodings = msg.header(h_AcceptEncodings);
108     }
109     if (msg.exists(h_AcceptLanguages))
110     {
111     mPeerSupportedLanguages = msg.header(h_AcceptLanguages);
112     }
113 jason 5459 if (msg.exists(h_AllowEvents))
114     {
115     mPeerAllowedEvents = msg.header(h_AllowEvents);
116     }
117 jason 4010 if (msg.exists(h_Accepts))
118     {
119     mPeerSupportedMimeTypes = msg.header(h_Accepts);
120     }
121 derek 3064 }
122    
123 jason 4010 bool
124     InviteSession::updateMethodSupported() const
125 derek 3255 {
126 jason 4010 // Check if Update is supported locally
127     if(mDum.getMasterProfile()->isMethodSupported(UPDATE))
128     {
129     // Check if peer supports UPDATE
130     return mPeerSupportedMethods.find(Token("UPDATE"));
131     }
132     return false;
133     }
134 sgodin 3392
135 jason 4010 const NameAddr&
136     InviteSession::myAddr() const
137     {
138     return mDialog.mLocalNameAddr;
139     }
140 sgodin 3392
141 jason 4010 const NameAddr&
142     InviteSession::peerAddr() const
143     {
144     return mDialog.mRemoteNameAddr;
145     }
146 sgodin 3392
147 jason 4010 bool
148     InviteSession::isConnected() const
149     {
150     switch (mState)
151     {
152     case Connected:
153     case SentUpdate:
154     case SentUpdateGlare:
155     case SentReinvite:
156     case SentReinviteGlare:
157     case ReceivedUpdate:
158     case ReceivedReinvite:
159     case ReceivedReinviteNoOffer:
160     case Answered:
161     case WaitingToOffer:
162     return true;
163    
164     default:
165     return false;
166     }
167 derek 3255 }
168 derek 3064
169 jason 4010 bool
170     InviteSession::isEarly() const
171 derek 3064 {
172 jason 4010 switch (mState)
173 derek 3064 {
174 jason 4010 case UAC_Start:
175     case UAC_Early:
176     case UAC_EarlyWithOffer:
177     case UAC_EarlyWithAnswer:
178 jason 5466
179 jason 4010 //case UAC_Answered:
180     //case UAC_Terminated:
181     case UAC_SentUpdateEarly:
182     case UAC_SentUpdateConnected:
183     case UAC_ReceivedUpdateEarly:
184     //case UAC_SentAnswer:
185     case UAC_QueuedUpdate:
186 jason 5466
187     case UAS_Start:
188     case UAS_Offer:
189     case UAS_OfferProvidedAnswer:
190     case UAS_EarlyOffer:
191     case UAS_EarlyProvidedAnswer:
192     case UAS_EarlyNoOffer:
193     case UAS_FirstEarlyReliable:
194     case UAS_EarlyReliable:
195 jason 4010 return true;
196    
197     default:
198     return false;
199 derek 3064 }
200 jason 4010 }
201 derek 3064
202 jason 4010
203     bool
204     InviteSession::isTerminated() const
205     {
206     switch (mState)
207     {
208     case Terminated:
209     case WaitingToTerminate:
210 sgodin 5377 case WaitingToHangup:
211 jason 4010 case UAC_Cancelled:
212     case UAS_WaitingToTerminate:
213     case UAS_WaitingToHangup:
214     return true;
215     default:
216     return false;
217     }
218     }
219    
220     std::ostream&
221     InviteSession::dump(std::ostream& strm) const
222     {
223     strm << "INVITE: " << mId
224     << " " << toData(mState)
225     << " ADDR=" << myAddr()
226     << " PEER=" << peerAddr();
227     return strm;
228     }
229    
230 jason 2866 void
231 daniel 5068 InviteSession::provideOffer(const SdpContents& offer,
232     DialogUsageManager::EncryptionLevel level,
233     const SdpContents* alternative)
234 jason 2866 {
235 jason 4010 switch (mState)
236 derek 2965 {
237 jason 4010 case Connected:
238     case WaitingToOffer:
239     case UAS_WaitingToOffer:
240     if (updateMethodSupported())
241     {
242     transition(SentUpdate);
243     mDialog.makeRequest(mLastSessionModification, UPDATE);
244     }
245     else
246     {
247     transition(SentReinvite);
248     mDialog.makeRequest(mLastSessionModification, INVITE);
249 sgodin 5499 }
250     mLastSessionModification.remove(h_ProxyAuthorizations); // remove remote credentials.
251 sgodin 4369 setSessionTimerHeaders(mLastSessionModification);
252 jason 4010
253     InfoLog (<< "Sending " << mLastSessionModification.brief());
254 daniel 5068 InviteSession::setSdp(mLastSessionModification, offer, alternative);
255     mProposedLocalSdp = InviteSession::makeSdp(offer, alternative);
256     mProposedEncryptionLevel = level;
257 daniel 5383 DumHelper::setOutgoingEncrptionLevel(mLastSessionModification, mProposedEncryptionLevel);
258 daniel 5505 // call send to give app an chance to adorn the message.
259     send(mLastSessionModification);
260 jason 4010 break;
261    
262     case Answered:
263     // queue the offer to be sent after the ACK is received
264     transition(WaitingToOffer);
265 daniel 5068 mProposedEncryptionLevel = level;
266     mProposedLocalSdp = InviteSession::makeSdp(offer, alternative);
267 jason 4010 break;
268    
269 derek 5355 case ReceivedReinviteNoOffer:
270     assert(!mProposedRemoteSdp.get());
271     transition(ReceivedReinviteSentOffer);
272     mDialog.makeResponse(mInvite200, mLastSessionModification, 200);
273     handleSessionTimerRequest(mInvite200, mLastSessionModification);
274     InviteSession::setSdp(mInvite200, offer, 0);
275     mProposedLocalSdp = InviteSession::makeSdp(offer);
276    
277     InfoLog (<< "Sending " << mInvite200.brief());
278 daniel 5383 DumHelper::setOutgoingEncrptionLevel(mInvite200, mCurrentEncryptionLevel);
279 daniel 5505 send(mInvite200);
280 derek 5355 startRetransmit200Timer();
281     break;
282    
283    
284 sgodin 5001 // ?slg? Can we handle all of the states listed in isConnected() ???
285 jason 4010 default:
286     WarningLog (<< "Can't provideOffer when not in Connected state");
287     throw DialogUsage::Exception("Can't provide an offer", __FILE__,__LINE__);
288 derek 2965 }
289 jason 2866 }
290    
291     void
292 daniel 5068 InviteSession::provideOffer(const SdpContents& offer)
293     {
294     return provideOffer(offer, mCurrentEncryptionLevel, 0);
295     }
296    
297     void
298 jason 4010 InviteSession::provideAnswer(const SdpContents& answer)
299 jason 2866 {
300 jason 4010 switch (mState)
301 derek 2965 {
302 jason 4010 case ReceivedReinvite:
303     transition(Connected);
304     mDialog.makeResponse(mInvite200, mLastSessionModification, 200);
305     handleSessionTimerRequest(mInvite200, mLastSessionModification);
306 daniel 5068 InviteSession::setSdp(mInvite200, answer, 0);
307 jason 4010 mCurrentLocalSdp = InviteSession::makeSdp(answer);
308     mCurrentRemoteSdp = mProposedRemoteSdp;
309     InfoLog (<< "Sending " << mInvite200.brief());
310 daniel 5383 DumHelper::setOutgoingEncrptionLevel(mInvite200, mCurrentEncryptionLevel);
311 daniel 5505 send(mInvite200);
312 jason 4010 startRetransmit200Timer();
313     break;
314    
315     case ReceivedUpdate: // same as ReceivedReinvite case.
316     {
317     transition(Connected);
318    
319     SipMessage response;
320     mDialog.makeResponse(response, mLastSessionModification, 200);
321     handleSessionTimerRequest(response, mLastSessionModification);
322 daniel 5068 InviteSession::setSdp(response, answer, 0);
323 jason 4010 mCurrentLocalSdp = InviteSession::makeSdp(answer);
324     mCurrentRemoteSdp = mProposedRemoteSdp;
325     InfoLog (<< "Sending " << response.brief());
326 daniel 5383 DumHelper::setOutgoingEncrptionLevel(response, mCurrentEncryptionLevel);
327 daniel 5505 send(response);
328 jason 4010 break;
329     }
330    
331     default:
332 sgodin 4394 WarningLog (<< "Can't provideAnswer when not in Connected state");
333 jason 4010 throw DialogUsage::Exception("Can't provide an offer", __FILE__,__LINE__);
334 derek 2965 }
335 jason 2866 }
336    
337 jason 4010 void
338     InviteSession::end()
339 jason 2555 {
340 jason 4010 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
341    
342     switch (mState)
343     {
344     case Connected:
345 sgodin 5377 case SentUpdate:
346     case SentUpdateGlare:
347     case SentReinviteGlare:
348 jason 4010 {
349     // !jf! do we need to store the BYE somewhere?
350     sendBye();
351     transition(Terminated);
352     handler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
353     break;
354     }
355    
356     case SentReinvite:
357     transition(WaitingToTerminate);
358     break;
359    
360 sgodin 5377 case Answered:
361     case WaitingToOffer:
362     case ReceivedReinviteSentOffer:
363     transition(WaitingToHangup);
364     break;
365    
366 jason 4010 case ReceivedUpdate:
367     case ReceivedReinvite:
368     case ReceivedReinviteNoOffer:
369     {
370     SipMessage response;
371     mDialog.makeResponse(response, mLastSessionModification, 488);
372     InfoLog (<< "Sending " << response.brief());
373 daniel 5505 send(response);
374 jason 4010
375     sendBye();
376     transition(Terminated);
377     handler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
378     break;
379     }
380    
381 sgodin 5377 case WaitingToTerminate: // ?slg? Why is this here?
382 jason 4010 {
383     sendBye();
384     transition(Terminated);
385     handler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
386     break;
387     }
388    
389     case Terminated:
390     // no-op.
391     break;
392    
393     default:
394     assert(0);
395     break;
396     }
397 jason 2555 }
398    
399 jason 4010 void
400     InviteSession::reject(int statusCode, WarningCategory *warning)
401 jason 2555 {
402 jason 4010 switch (mState)
403     {
404     case ReceivedUpdate:
405     case ReceivedReinvite:
406     case ReceivedReinviteNoOffer:
407     {
408     transition(Connected);
409    
410     SipMessage response;
411     mDialog.makeResponse(response, mLastSessionModification, statusCode);
412     if(warning)
413     {
414     response.header(h_Warnings).push_back(*warning);
415     }
416     InfoLog (<< "Sending " << response.brief());
417 daniel 5505 send(response);
418 jason 4010 break;
419     }
420    
421     default:
422     assert(0);
423     break;
424     }
425 jason 2555 }
426 davidb 2575
427 jason 4010 void
428     InviteSession::targetRefresh(const NameAddr& localUri)
429 jason 2941 {
430 sgodin 5001 if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite?
431 jason 4010 {
432     // !jf! add interface to Dialog
433     //mDialog.setLocalContact(localUri);
434     provideOffer(*mCurrentLocalSdp);
435     }
436     else
437     {
438     WarningLog (<< "Can't targetRefresh before Connected");
439     assert(0);
440     throw UsageUseException("targetRefresh not allowed in this context", __FILE__, __LINE__);
441     }
442 jason 2941 }
443    
444 jason 2856 void
445 jason 4010 InviteSession::refer(const NameAddr& referTo)
446     {
447     if (mSentRefer)
448     {
449     throw UsageUseException("Attempted to send overlapping refer", __FILE__, __LINE__);
450     }
451    
452 sgodin 5001 if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite?
453 jason 4010 {
454     mSentRefer = true;
455     SipMessage refer;
456     mDialog.makeRequest(refer, REFER);
457     refer.header(h_ReferTo) = referTo;
458     refer.header(h_ReferredBy) = mDialog.mLocalContact; // !slg! is it ok to do this - should it be an option?
459 daniel 5505 send(refer);
460 jason 4010 }
461     else
462     {
463     WarningLog (<< "Can't refer before Connected");
464     assert(0);
465     throw UsageUseException("REFER not allowed in this context", __FILE__, __LINE__);
466     }
467     }
468    
469     void
470     InviteSession::refer(const NameAddr& referTo, InviteSessionHandle sessionToReplace)
471     {
472     if (!sessionToReplace.isValid())
473     {
474     throw UsageUseException("Attempted to make a refer w/ and invalid replacement target", __FILE__, __LINE__);
475     }
476    
477     if (mSentRefer)
478     {
479     throw UsageUseException("Attempted to send overlapping refer", __FILE__, __LINE__);
480     }
481    
482 sgodin 5001 if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite?
483 jason 4010 {
484     mSentRefer = true;
485     SipMessage refer;
486     mDialog.makeRequest(refer, REFER);
487    
488     refer.header(h_ReferTo) = referTo;
489 sgodin 5001 refer.header(h_ReferredBy) = mDialog.mLocalContact; // ?slg? is it ok to do this - should it be an option?
490 jason 4010 CallId replaces;
491     DialogId id = sessionToReplace->mDialog.getId();
492     replaces.value() = id.getCallId();
493     replaces.param(p_toTag) = id.getRemoteTag();
494     replaces.param(p_fromTag) = id.getLocalTag();
495    
496     refer.header(h_ReferTo).uri().embedded().header(h_Replaces) = replaces;
497 daniel 5505 send(refer);
498 jason 4010 }
499     else
500     {
501     WarningLog (<< "Can't refer before Connected");
502     assert(0);
503     throw UsageUseException("REFER not allowed in this context", __FILE__, __LINE__);
504     }
505     }
506    
507     void
508     InviteSession::info(const Contents& contents)
509     {
510     if (mNitState == NitComplete)
511     {
512 sgodin 5001 if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite?
513 jason 4010 {
514     mNitState = NitProceeding;
515     SipMessage info;
516     mDialog.makeRequest(info, INFO);
517     // !jf! handle multipart here
518     info.setContents(&contents);
519 daniel 5383 DumHelper::setOutgoingEncrptionLevel(info, mCurrentEncryptionLevel);
520 daniel 5505 send(info);
521 jason 4010 }
522     else
523     {
524     WarningLog (<< "Can't send INFO before Connected");
525     assert(0);
526     throw UsageUseException("Can't send INFO before Connected", __FILE__, __LINE__);
527     }
528     }
529     else
530     {
531     throw UsageUseException("Cannot start a non-invite transaction until the previous one has completed",
532     __FILE__, __LINE__);
533     }
534     }
535    
536     void
537 sgodin 5265 InviteSession::message(const Contents& contents)
538     {
539     if (mNitState == NitComplete)
540     {
541     if (isConnected()) // ?slg? likely not safe in any state except Connected - what should behaviour be if state is ReceivedReinvite?
542     {
543     mNitState = NitProceeding;
544     SipMessage message;
545     mDialog.makeRequest(message, MESSAGE);
546     // !jf! handle multipart here
547     message.setContents(&contents);
548 daniel 5383 DumHelper::setOutgoingEncrptionLevel(message, mCurrentEncryptionLevel);
549 daniel 5505 send(message);
550 sgodin 5265 InfoLog (<< "Trying to send MESSAGE: " << message);
551     }
552     else
553     {
554     WarningLog (<< "Can't send MESSAGE before Connected");
555     assert(0);
556     throw UsageUseException("Can't send MESSAGE before Connected", __FILE__, __LINE__);
557     }
558     }
559     else
560     {
561     throw UsageUseException("Cannot start a non-invite transaction until the previous one has completed",
562     __FILE__, __LINE__);
563     }
564     }
565    
566     void
567 jason 4010 InviteSession::dispatch(const SipMessage& msg)
568     {
569     // !jf! do we need to handle 3xx here or is it handled elsewhere?
570     switch (mState)
571     {
572     case Connected:
573     dispatchConnected(msg);
574     break;
575     case SentUpdate:
576     dispatchSentUpdate(msg);
577     break;
578     case SentReinvite:
579     dispatchSentReinvite(msg);
580     break;
581     case SentUpdateGlare:
582     case SentReinviteGlare:
583     // The behavior is the same except for timer which is handled in dispatch(Timer)
584     dispatchGlare(msg);
585     break;
586     case ReceivedUpdate:
587     case ReceivedReinvite:
588     case ReceivedReinviteNoOffer:
589     dispatchReceivedUpdateOrReinvite(msg);
590     break;
591 derek 5355 case ReceivedReinviteSentOffer:
592     dispatchReceivedReinviteSentOffer(msg);
593     break;
594 jason 4010 case Answered:
595     dispatchAnswered(msg);
596     break;
597     case WaitingToOffer:
598     dispatchWaitingToOffer(msg);
599     break;
600     case WaitingToTerminate:
601     dispatchWaitingToTerminate(msg);
602     break;
603 sgodin 5377 case WaitingToHangup:
604     dispatchWaitingToHangup(msg);
605     break;
606 jason 4010 case Terminated:
607     dispatchTerminated(msg);
608     break;
609     case Undefined:
610     default:
611     assert(0);
612     break;
613     }
614     }
615    
616     void
617 derek 2990 InviteSession::dispatch(const DumTimeout& timeout)
618     {
619 derek 3255 if (timeout.type() == DumTimeout::Retransmit200)
620 derek 2990 {
621 jason 4010 if (mCurrentRetransmit200)
622 derek 3255 {
623 jason 4010 InfoLog (<< "Retransmitting: " << endl << mInvite200);
624 daniel 5383 DumHelper::setOutgoingEncrptionLevel(mInvite200, mCurrentEncryptionLevel);
625 daniel 5505 send(mInvite200);
626 derek 3255 mCurrentRetransmit200 *= 2;
627     mDum.addTimerMs(DumTimeout::Retransmit200, resipMin(Timer::T2, mCurrentRetransmit200), getBaseHandle(), timeout.seq());
628     }
629 derek 2990 }
630 derek 3255 else if (timeout.type() == DumTimeout::WaitForAck)
631 derek 2990 {
632 jason 4010 if(mCurrentRetransmit200) // If retransmit200 timer is active then ACK is not received yet
633 derek 3255 {
634 jason 4010 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
635    
636     // this is so the app can decided to ignore this. default implementation
637     // will call end next
638     mDum.mInviteSessionHandler->onAckNotReceived(getSessionHandle());
639    
640     // If we are waiting for an Ack and it times out, then end with a BYE
641 sgodin 5377 if(mState == UAS_WaitingToHangup ||
642     mState == WaitingToHangup)
643 sgodin 3363 {
644 jason 4010 sendBye();
645     transition(Terminated);
646     mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
647 sgodin 3363 }
648 derek 5355 else if(mState == ReceivedReinviteSentOffer)
649     {
650     transition(Connected);
651     mProposedLocalSdp.release();
652     mProposedEncryptionLevel = DialogUsageManager::None;
653     //!dcm! -- should this be onIllegalNegotiation?
654     mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), 0);
655     }
656 sgodin 5377 else if(mState == WaitingToOffer)
657     {
658     assert(mProposedLocalSdp.get());
659     //!dcm! -- should this be onIllegalNegotiation?
660     mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), 0);
661     if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))
662     {
663     provideOffer( *(dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back())),
664     mProposedEncryptionLevel,
665     dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front()));
666     }
667     else
668     {
669     provideOffer(*(dynamic_cast<SdpContents*>(mProposedLocalSdp.get())), mProposedEncryptionLevel, 0);
670     }
671     }
672 derek 3255 }
673 derek 2990 }
674 jason 4010 else if (timeout.type() == DumTimeout::Glare)
675 derek 3255 {
676 jason 4010 if (mState == SentUpdateGlare)
677     {
678     transition(SentUpdate);
679    
680     InfoLog (<< "Retransmitting the UPDATE (glare condition timer)");
681 daniel 5505 send(mLastSessionModification);
682 jason 4010 }
683     else if (mState == SentReinviteGlare)
684     {
685     transition(SentReinvite);
686    
687     InfoLog (<< "Retransmitting the reINVITE (glare condition timer)");
688 daniel 5505 send(mLastSessionModification);
689 jason 4010 }
690 derek 3255 }
691 sgodin 3392 else if (timeout.type() == DumTimeout::SessionExpiration)
692     {
693     if(timeout.seq() == mSessionTimerSeq)
694     {
695 jason 4010 // this is so the app can decided to ignore this. default implementation
696     // will call end next
697     mDum.mInviteSessionHandler->onSessionExpired(getSessionHandle());
698 sgodin 3392 }
699     }
700     else if (timeout.type() == DumTimeout::SessionRefresh)
701     {
702 jason 4010 if(timeout.seq() == mSessionTimerSeq)
703 sgodin 3392 {
704 jason 4010 if(mState == Connected) // Note: If not connected then we must be issueing a reinvite/update or receiving one - in either case the session timer stuff will get reset/renegotiated - thus just ignore this referesh
705 sgodin 3392 {
706 sgodin 4369 sessionRefresh();
707 sgodin 3392 }
708     }
709     }
710 derek 2990 }
711    
712 jason 4010 void
713     InviteSession::dispatchConnected(const SipMessage& msg)
714 sgodin 3392 {
715 jason 4010 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
716     std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
717    
718     switch (toEvent(msg, sdp.get()))
719 sgodin 3392 {
720 jason 4010 case OnInvite:
721     case OnInviteReliable:
722     mLastSessionModification = msg;
723     transition(ReceivedReinviteNoOffer);
724     //handler->onDialogModified(getSessionHandle(), None, msg);
725     handler->onOfferRequired(getSessionHandle(), msg);
726     break;
727 sgodin 3392
728 jason 4010 case OnInviteOffer:
729     case OnInviteReliableOffer:
730     mLastSessionModification = msg;
731     transition(ReceivedReinvite);
732 daniel 5068 mCurrentEncryptionLevel = getEncryptionLevel(msg);
733 jason 4010 //handler->onDialogModified(getSessionHandle(), Offer, msg);
734     handler->onOffer(getSessionHandle(), msg, *sdp);
735     break;
736    
737     case On2xx:
738     case On2xxOffer:
739     case On2xxAnswer:
740     // retransmission of 200I
741     // !jf! Need to include the answer here.
742     sendAck();
743     break;
744    
745 sgodin 4369 case OnUpdateOffer:
746 jason 4010 transition(ReceivedUpdate);
747    
748     // !kh!
749     // Find out if it's an UPDATE requiring state change.
750     // See rfc3311 5.2, 4th paragraph.
751     mLastSessionModification = msg;
752 daniel 5068 mCurrentEncryptionLevel = getEncryptionLevel(msg);
753 jason 4010 handler->onOffer(getSessionHandle(), msg, *sdp);
754     break;
755    
756 sgodin 4369 case OnUpdate:
757     {
758 sgodin 5001 // ?slg? no sdp in update - just responsd immediately (likely session timer) - do we need a callback?
759 sgodin 4369 SipMessage response;
760     mLastSessionModification = msg;
761     mDialog.makeResponse(response, mLastSessionModification, 200);
762     handleSessionTimerRequest(response, mLastSessionModification);
763 daniel 5505 BaseUsage::send(response);
764 sgodin 4369 break;
765     }
766    
767 jason 4010 case OnUpdateRejected:
768     case On200Update:
769     WarningLog (<< "DUM delivered an UPDATE response in an incorrect state " << endl << msg);
770     assert(0);
771     break;
772    
773     case OnAck:
774     mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
775     break;
776    
777     default:
778     dispatchOthers(msg);
779     break;
780     }
781     }
782    
783     void
784     InviteSession::dispatchSentUpdate(const SipMessage& msg)
785     {
786     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
787     std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
788    
789     switch (toEvent(msg, sdp.get()))
790     {
791     case OnInvite:
792     case OnInviteReliable:
793     case OnInviteOffer:
794     case OnInviteReliableOffer:
795     case OnUpdate:
796 sgodin 4369 case OnUpdateOffer:
797 sgodin 3392 {
798 jason 4010 // glare
799     SipMessage response;
800     mDialog.makeResponse(response, msg, 491);
801 daniel 5505 BaseUsage::send(response);
802 jason 4010 break;
803     }
804    
805     case On200Update:
806     transition(Connected);
807     handleSessionTimerResponse(msg);
808     if (sdp.get())
809 sgodin 3392 {
810 daniel 5068 mCurrentEncryptionLevel = getEncryptionLevel(msg);
811     setCurrentLocalSdp(msg);
812 jason 4010 mCurrentRemoteSdp = InviteSession::makeSdp(*sdp);
813     handler->onAnswer(getSessionHandle(), msg, *sdp);
814 sgodin 3392 }
815 sgodin 4369 else if(mProposedLocalSdp.get())
816 sgodin 3392 {
817 sgodin 4369 // If we sent an offer in the Update Request and no answer is received
818 jason 4010 handler->onIllegalNegotiation(getSessionHandle(), msg);
819 sgodin 4369 mProposedLocalSdp.release();
820 daniel 5068 mProposedEncryptionLevel = DialogUsageManager::None;
821 jason 4010 }
822     break;
823    
824     case On491Update:
825 sgodin 4369 transition(SentUpdateGlare);
826 jason 4010 start491Timer();
827     break;
828    
829 daniel 5068 case On422Update: // session timer
830 sgodin 4394 if(msg.exists(h_MinSE))
831     {
832     // Change interval to min from 422 response
833     mSessionInterval = msg.header(h_MinSE).value();
834 sgodin 4691 mMinSE = mSessionInterval;
835 sgodin 4394 sessionRefresh();
836     }
837     else
838     {
839     // Response must contact Min_SE - if not - just ignore
840 sgodin 5001 // ?slg? callback?
841 sgodin 4394 transition(Connected);
842     mProposedLocalSdp.release();
843 daniel 5068 mProposedEncryptionLevel = DialogUsageManager::None;
844 sgodin 4394 }
845     break;
846    
847 jason 4010 case OnUpdateRejected:
848 sgodin 4369 // !jf! - callback?
849     mProposedLocalSdp.release();
850 daniel 5068 mProposedEncryptionLevel = DialogUsageManager::None;
851 sgodin 4369 transition(Connected);
852 jason 4010 break;
853    
854     case OnGeneralFailure:
855     sendBye();
856     transition(Terminated);
857     handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
858     break;
859    
860     default:
861     dispatchOthers(msg);
862     break;
863     }
864     }
865    
866     void
867     InviteSession::dispatchSentReinvite(const SipMessage& msg)
868     {
869     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
870     std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
871    
872     switch (toEvent(msg, sdp.get()))
873     {
874     case OnInvite:
875     case OnInviteReliable:
876     case OnInviteOffer:
877     case OnInviteReliableOffer:
878     case OnUpdate:
879 sgodin 4369 case OnUpdateOffer:
880 jason 4010 {
881     SipMessage response;
882     mDialog.makeResponse(response, msg, 491);
883 daniel 5505 BaseUsage::send(response);
884 jason 4010 break;
885 sgodin 3392 }
886 jason 4010
887     case On1xx:
888     case On1xxEarly:
889 sgodin 5001 // Some UA's send a 100 response to a ReInvite - just ignore it
890 jason 4010 break;
891    
892     case On2xxAnswer:
893     case On2xxOffer:
894 sgodin 3392 {
895 jason 4010 transition(Connected);
896     handleSessionTimerResponse(msg);
897 daniel 5068 setCurrentLocalSdp(msg);
898 jason 4010 mCurrentRemoteSdp = InviteSession::makeSdp(*sdp);
899 daniel 5068 mCurrentEncryptionLevel = getEncryptionLevel(msg);
900 jason 4010 // !jf! I need to potentially include an answer in the ACK here
901     sendAck();
902     handler->onAnswer(getSessionHandle(), msg, *sdp);
903    
904    
905     // !jf! do I need to allow a reINVITE overlapping the retransmission of
906     // the ACK when a 200I is received? If yes, then I need to store all
907     // ACK messages for 64*T1
908     break;
909     }
910     case On2xx:
911     sendAck();
912     transition(Connected);
913     handleSessionTimerResponse(msg);
914     handler->onIllegalNegotiation(getSessionHandle(), msg);
915 sgodin 4369 mProposedLocalSdp.release();
916 daniel 5068 mProposedEncryptionLevel = DialogUsageManager::None;
917 jason 4010 break;
918    
919 sgodin 4394 case On422Invite:
920     if(msg.exists(h_MinSE))
921     {
922     // Change interval to min from 422 response
923     mSessionInterval = msg.header(h_MinSE).value();
924 sgodin 4691 mMinSE = mSessionInterval;
925 sgodin 4394 sessionRefresh();
926     }
927     else
928     {
929     // Response must contact Min_SE - if not - just ignore
930 sgodin 5001 // ?slg? callback?
931 sgodin 4394 transition(Connected);
932     mProposedLocalSdp.release();
933 daniel 5068 mProposedEncryptionLevel = DialogUsageManager::None;
934 sgodin 4394 }
935     break;
936    
937 jason 4010 case On491Invite:
938 sgodin 4369 transition(SentReinviteGlare);
939 jason 4010 start491Timer();
940     break;
941    
942     case OnGeneralFailure:
943     sendBye();
944     transition(Terminated);
945     handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
946     break;
947    
948     case OnInviteFailure:
949 sgodin 5130 case On487Invite:
950     case On489Invite:
951 jason 4010 transition(Connected);
952 sgodin 4369 mProposedLocalSdp.release();
953 derek 5355 handler->onOfferRejected(getSessionHandle(), &msg);
954 jason 4010 break;
955    
956     default:
957     dispatchOthers(msg);
958     break;
959     }
960     }
961    
962 derek 5355 void InviteSession::dispatchReceivedReinviteSentOffer(const SipMessage& msg)
963     {
964     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
965     std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
966    
967     switch (toEvent(msg, sdp.get()))
968     {
969     case OnInvite:
970     case OnInviteReliable:
971     case OnInviteOffer:
972     case OnInviteReliableOffer:
973     case OnUpdate:
974     case OnUpdateOffer:
975     {
976     SipMessage response;
977     mDialog.makeResponse(response, msg, 491);
978 daniel 5505 BaseUsage::send(response);
979 derek 5355 break;
980     }
981     case OnAckAnswer:
982     transition(Connected);
983     setCurrentLocalSdp(msg);
984     mCurrentRemoteSdp = InviteSession::makeSdp(*sdp);
985     mCurrentEncryptionLevel = getEncryptionLevel(msg);
986     mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
987     handler->onAnswer(getSessionHandle(), msg, *sdp);
988     break;
989     case OnAck:
990     transition(Connected);
991     mProposedLocalSdp.release();
992     mProposedEncryptionLevel = DialogUsageManager::None;
993     mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
994     //!dcm! -- should this be onIllegalNegotiation?
995     handler->onOfferRejected(getSessionHandle(), &msg);
996     break;
997     default:
998     dispatchOthers(msg);
999     break;
1000     }
1001     }
1002    
1003 jason 4010 void
1004     InviteSession::dispatchGlare(const SipMessage& msg)
1005     {
1006     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1007     MethodTypes method = msg.header(h_CSeq).method();
1008     if (method == INVITE && msg.isRequest())
1009     {
1010     // Received inbound reinvite, when waiting to resend outbound reinvite or update
1011     transition(ReceivedReinvite);
1012 derek 5355 handler->onOfferRejected(getSessionHandle(), &msg);
1013 jason 4010 }
1014     else if (method == UPDATE && msg.isRequest())
1015     {
1016     // Received inbound update, when waiting to resend outbound reinvite or update
1017     transition(ReceivedUpdate);
1018 derek 5355 handler->onOfferRejected(getSessionHandle(), &msg);
1019 jason 4010 }
1020     else
1021     {
1022     dispatchOthers(msg);
1023     }
1024     }
1025    
1026     void
1027     InviteSession::dispatchReceivedUpdateOrReinvite(const SipMessage& msg)
1028     {
1029     MethodTypes method = msg.header(h_CSeq).method();
1030     if (method == INVITE || method == UPDATE)
1031     {
1032     // Means that the UAC has sent us a second reINVITE or UPDATE before we
1033     // responded to the first one. Bastard!
1034     SipMessage response;
1035     mDialog.makeResponse(response, msg, 500);
1036     response.header(h_RetryAfter).value() = Random::getRandom() % 10;
1037 daniel 5505 send(response);
1038 jason 4010 }
1039     else
1040     {
1041     dispatchOthers(msg);
1042     }
1043     }
1044    
1045    
1046     void
1047     InviteSession::dispatchAnswered(const SipMessage& msg)
1048     {
1049     if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK)
1050     {
1051     mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1052     transition(Connected);
1053     }
1054     else
1055     {
1056     dispatchOthers(msg);
1057     }
1058     }
1059    
1060     void
1061     InviteSession::dispatchWaitingToOffer(const SipMessage& msg)
1062     {
1063     if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK)
1064     {
1065 daniel 5068 assert(mProposedLocalSdp.get());
1066 jason 4010 mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1067 daniel 5068 if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))
1068     {
1069     provideOffer( *(dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back())),
1070     mProposedEncryptionLevel,
1071     dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front()));
1072     }
1073     else
1074     {
1075     provideOffer(*(dynamic_cast<SdpContents*>(mProposedLocalSdp.get())), mProposedEncryptionLevel, 0);
1076     }
1077 jason 4010 }
1078     else
1079     {
1080     dispatchOthers(msg);
1081     }
1082     }
1083    
1084     void
1085     InviteSession::dispatchWaitingToTerminate(const SipMessage& msg)
1086     {
1087     if (msg.isResponse() &&
1088     msg.header(h_CSeq).method() == INVITE)
1089     {
1090     if(msg.header(h_StatusLine).statusCode() / 200 == 1) // Note: stack ACK's non-2xx final responses only
1091     {
1092     // !jf! Need to include the answer here.
1093     sendAck();
1094     }
1095     sendBye();
1096     transition(Terminated);
1097     mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
1098     }
1099     }
1100    
1101     void
1102 sgodin 5377 InviteSession::dispatchWaitingToHangup(const SipMessage& msg)
1103     {
1104     std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
1105    
1106     switch (toEvent(msg, sdp.get()))
1107     {
1108     case OnAck:
1109     case OnAckAnswer:
1110     {
1111     mCurrentRetransmit200 = 0; // stop the 200 retransmit timer
1112    
1113     sendBye();
1114     transition(Terminated);
1115     mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
1116     break;
1117     }
1118    
1119     default:
1120     break;
1121     }
1122     }
1123    
1124     void
1125 jason 4010 InviteSession::dispatchTerminated(const SipMessage& msg)
1126     {
1127     InfoLog (<< "InviteSession::dispatchTerminated " << msg.brief());
1128    
1129     if (msg.isRequest())
1130     {
1131     SipMessage response;
1132     mDialog.makeResponse(response, msg, 481);
1133 daniel 5505 send(response);
1134 jason 4010
1135     // !jf! means the peer sent BYE while we are waiting for response to BYE
1136     //mDum.destroy(this);
1137     }
1138     else
1139     {
1140     mDum.destroy(this);
1141     }
1142     }
1143    
1144     void
1145     InviteSession::dispatchOthers(const SipMessage& msg)
1146     {
1147     // handle OnGeneralFailure
1148     // handle OnRedirect
1149    
1150     switch (msg.header(h_CSeq).method())
1151     {
1152     case PRACK:
1153     dispatchPrack(msg);
1154     break;
1155     case CANCEL:
1156     dispatchCancel(msg);
1157     break;
1158     case BYE:
1159     dispatchBye(msg);
1160     break;
1161     case INFO:
1162     dispatchInfo(msg);
1163     break;
1164 sgodin 5265 case MESSAGE:
1165     dispatchMessage(msg);
1166     break;
1167 jason 4010 case ACK:
1168     // Ignore duplicate ACKs from 2xx reTransmissions
1169     break;
1170     default:
1171     // handled in Dialog
1172     WarningLog (<< "DUM delivered a "
1173     << msg.header(h_CSeq).unknownMethodName()
1174     << " to the InviteSession "
1175     << endl
1176     << msg);
1177     assert(0);
1178     break;
1179     }
1180     }
1181    
1182     void
1183     InviteSession::dispatchUnhandledInvite(const SipMessage& msg)
1184     {
1185     assert(msg.isRequest());
1186     assert(msg.header(h_CSeq).method() == INVITE);
1187    
1188     // If we get an INVITE request from the wire and we are not in
1189     // Connected state, reject the request and send a BYE
1190     SipMessage response;
1191     mDialog.makeResponse(response, msg, 400); // !jf! what code to use?
1192     InfoLog (<< "Sending " << response.brief());
1193 daniel 5505 send(response);
1194 jason 4010
1195     sendBye();
1196     transition(Terminated);
1197     mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1198     }
1199    
1200     void
1201     InviteSession::dispatchPrack(const SipMessage& msg)
1202     {
1203     assert(msg.header(h_CSeq).method() == PRACK);
1204     if(msg.isRequest())
1205     {
1206     SipMessage rsp;
1207     mDialog.makeResponse(rsp, msg, 481);
1208 daniel 5505 send(rsp);
1209 jason 4010
1210     sendBye();
1211     // !jf! should we make some other callback here
1212     transition(Terminated);
1213     mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1214     }
1215     else
1216     {
1217     // ignore. could be PRACK/200
1218     }
1219     }
1220    
1221     void
1222     InviteSession::dispatchCancel(const SipMessage& msg)
1223     {
1224     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1225     assert(msg.header(h_CSeq).method() == CANCEL);
1226     if(msg.isRequest())
1227     {
1228     SipMessage rsp;
1229     mDialog.makeResponse(rsp, msg, 200);
1230 daniel 5505 send(rsp);
1231 jason 4010
1232     sendBye();
1233     // !jf! should we make some other callback here
1234     transition(Terminated);
1235     handler->onTerminated(getSessionHandle(), InviteSessionHandler::PeerEnded, &msg);
1236     }
1237     else
1238     {
1239     WarningLog (<< "DUM let me send a CANCEL at an incorrect state " << endl << msg);
1240     assert(0);
1241     }
1242     }
1243    
1244     void
1245     InviteSession::dispatchBye(const SipMessage& msg)
1246     {
1247     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1248    
1249     if (msg.isRequest())
1250     {
1251    
1252     SipMessage rsp;
1253     InfoLog (<< "Received " << msg.brief());
1254     mDialog.makeResponse(rsp, msg, 200);
1255 daniel 5505 send(rsp);
1256 jason 4010
1257     // !jf! should we make some other callback here
1258     transition(Terminated);
1259     handler->onTerminated(getSessionHandle(), InviteSessionHandler::PeerEnded, &msg);
1260     mDum.destroy(this);
1261     }
1262     else
1263     {
1264     WarningLog (<< "DUM let me send a BYE at an incorrect state " << endl << msg);
1265     assert(0);
1266     }
1267     }
1268    
1269     void
1270     InviteSession::dispatchInfo(const SipMessage& msg)
1271     {
1272     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1273     if (msg.isRequest())
1274     {
1275     InfoLog (<< "Received " << msg.brief());
1276     mDialog.makeResponse(mLastNitResponse, msg, 200);
1277     handler->onInfo(getSessionHandle(), msg);
1278     }
1279     else
1280     {
1281     assert(mNitState == NitProceeding);
1282     mNitState = NitComplete;
1283     //!dcm! -- toss away 1xx to an info?
1284     if (msg.header(h_StatusLine).statusCode() >= 300)
1285     {
1286     handler->onInfoFailure(getSessionHandle(), msg);
1287     }
1288     else if (msg.header(h_StatusLine).statusCode() >= 200)
1289     {
1290     handler->onInfoSuccess(getSessionHandle(), msg);
1291     }
1292     }
1293     }
1294    
1295     void
1296 sgodin 5265 InviteSession::acceptNIT(int statusCode)
1297 jason 4010 {
1298     if (statusCode / 100 != 2)
1299     {
1300     throw UsageUseException("Must accept with a 2xx", __FILE__, __LINE__);
1301     }
1302    
1303     mLastNitResponse.header(h_StatusLine).statusCode() = statusCode;
1304 sgodin 5415 Helper::getResponseCodeReason(statusCode, mLastNitResponse.header(h_StatusLine).reason());
1305 daniel 5505 BaseUsage::send(mLastNitResponse);
1306 jason 4010 }
1307    
1308     void
1309 sgodin 5265 InviteSession::rejectNIT(int statusCode)
1310 jason 4010 {
1311     if (statusCode < 400)
1312     {
1313     throw UsageUseException("Must reject with a >= 4xx", __FILE__, __LINE__);
1314     }
1315 sgodin 5415 mLastNitResponse.header(h_StatusLine).statusCode() = statusCode;
1316     Helper::getResponseCodeReason(statusCode, mLastNitResponse.header(h_StatusLine).reason());
1317 daniel 5505 BaseUsage::send(mLastNitResponse);
1318 jason 4010 }
1319    
1320     void
1321 sgodin 5265 InviteSession::dispatchMessage(const SipMessage& msg)
1322     {
1323     InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1324     if (msg.isRequest())
1325     {
1326     InfoLog (<< "Received " << msg.brief());
1327     mDialog.makeResponse(mLastNitResponse, msg, 200);
1328 sgodin 5415 mLastNitResponse.header(h_Contacts).clear();
1329 sgodin 5265 handler->onMessage(getSessionHandle(), msg);
1330     }
1331     else
1332     {
1333     assert(mNitState == NitProceeding);
1334     mNitState = NitComplete;
1335     //!dcm! -- toss away 1xx to an message?
1336     if (msg.header(h_StatusLine).statusCode() >= 300)
1337     {
1338     handler->onMessageFailure(getSessionHandle(), msg);
1339     }
1340     else if (msg.header(h_StatusLine).statusCode() >= 200)
1341     {
1342     handler->onMessageSuccess(getSessionHandle(), msg);
1343     }
1344     }
1345     }
1346    
1347     void
1348 jason 4010 InviteSession::startRetransmit200Timer()
1349     {
1350     mCurrentRetransmit200 = Timer::T1;
1351     int seq = mLastSessionModification.header(h_CSeq).sequence();
1352     mDum.addTimerMs(DumTimeout::Retransmit200, mCurrentRetransmit200, getBaseHandle(), seq);
1353     mDum.addTimerMs(DumTimeout::WaitForAck, Timer::TH, getBaseHandle(), seq);
1354     }
1355    
1356     void
1357     InviteSession::start491Timer()
1358     {
1359     int seq = mLastSessionModification.header(h_CSeq).sequence();
1360     int timer = Random::getRandom() % 4000;
1361     mDum.addTimerMs(DumTimeout::Glare, timer, getBaseHandle(), seq);
1362     }
1363    
1364 sgodin 4369 void
1365     InviteSession::setSessionTimerHeaders(SipMessage &msg)
1366     {
1367     if(mSessionInterval >= 90) // If mSessionInterval is 0 then SessionTimers are considered disabled
1368     {
1369     msg.header(h_SessionExpires).value() = mSessionInterval;
1370 sgodin 4691 if(msg.isRequest())
1371     {
1372     msg.header(h_SessionExpires).param(p_refresher) = Data(mSessionRefresher ? "uac" : "uas");
1373     }
1374     else
1375     {
1376     msg.header(h_SessionExpires).param(p_refresher) = Data(mSessionRefresher ? "uas" : "uac");
1377     }
1378     msg.header(h_MinSE).value() = mMinSE;
1379 sgodin 4369 }
1380     else
1381     {
1382     msg.remove(h_SessionExpires);
1383     msg.remove(h_MinSE);
1384     }
1385     }
1386    
1387 jason 4010 void
1388 sgodin 4369 InviteSession::sessionRefresh()
1389     {
1390     if (updateMethodSupported())
1391     {
1392     transition(SentUpdate);
1393     mDialog.makeRequest(mLastSessionModification, UPDATE);
1394     mLastSessionModification.releaseContents(); // Don't send SDP
1395     }
1396     else
1397     {
1398     transition(SentReinvite);
1399     mDialog.makeRequest(mLastSessionModification, INVITE);
1400 daniel 5068 InviteSession::setSdp(mLastSessionModification, mCurrentLocalSdp.get());
1401     mProposedLocalSdp = InviteSession::makeSdp(*mCurrentLocalSdp.get(), 0);
1402 sgodin 4369 }
1403 sgodin 5499 mLastSessionModification.remove(h_ProxyAuthorizations); // remove remote credentials.
1404 sgodin 4369 setSessionTimerHeaders(mLastSessionModification);
1405    
1406 sgodin 4691 InfoLog (<< "sessionRefresh: Sending " << mLastSessionModification.brief());
1407 daniel 5383 DumHelper::setOutgoingEncrptionLevel(mLastSessionModification, mCurrentEncryptionLevel);
1408 daniel 5505 send(mLastSessionModification);
1409 sgodin 4369 }
1410    
1411     void
1412 sgodin 4691 InviteSession::setSessionTimerPreferences()
1413     {
1414     mSessionInterval = mDialog.mDialogSet.getUserProfile()->getDefaultSessionTime(); // Used only if remote doesn't request a time
1415     if(mSessionInterval != 0)
1416     {
1417     // If session timers are no disabled then ensure interval is greater than or equal to MinSE
1418     mSessionInterval = resipMax(mMinSE, mSessionInterval);
1419     }
1420     switch(mDialog.mDialogSet.getUserProfile()->getDefaultSessionTimerMode())
1421     {
1422     case Profile::PreferLocalRefreshes:
1423     mSessionRefresher = true; // Default refresher is Local
1424     break;
1425     case Profile::PreferRemoteRefreshes:
1426     mSessionRefresher = false; // Default refresher is Remote
1427     break;
1428     case Profile::PreferUASRefreshes:
1429     mSessionRefresher = dynamic_cast<ServerInviteSession*>(this) != NULL; // Default refresher is UAS (for the session) - callee
1430     break;
1431     case Profile::PreferUACRefreshes:
1432     mSessionRefresher = dynamic_cast<ClientInviteSession*>(this) != NULL; // Default refresher is UAC (for the session) - caller
1433     break;
1434     }
1435     }
1436    
1437     void
1438     InviteSession::startSessionTimer()
1439     {
1440     if(mSessionInterval >= 90) // 90 is the absolute minimum - RFC4028
1441     {
1442     // Check if we are the refresher
1443     if(mSessionRefresher)
1444     {
1445     // Start Session-Refresh Timer to mSessionInterval / 2 (recommended by RFC4028)
1446     mDum.addTimer(DumTimeout::SessionRefresh, mSessionInterval / 2, getBaseHandle(), ++mSessionTimerSeq);
1447     }
1448     else
1449     {
1450     // Start Session-Expiration Timer to mSessionInterval - BYE should be sent a minimum of 32 and one third of the SessionInterval, seconds before the session expires (recommended by RFC4028)
1451     mDum.addTimer(DumTimeout::SessionExpiration, mSessionInterval - resipMin(32,mSessionInterval/3), getBaseHandle(), ++mSessionTimerSeq);
1452     }
1453     }
1454     else // Session Interval less than 90 - consider timers disabled
1455     {
1456     ++mSessionTimerSeq; // increment seq, incase old timers are running and now session timers are disabled
1457     }
1458     }
1459    
1460     void
1461 jason 4010 InviteSession::handleSessionTimerResponse(const SipMessage& msg)
1462     {
1463     assert(msg.header(h_CSeq).method() == INVITE || msg.header(h_CSeq).method() == UPDATE);
1464    
1465     // If session timers are locally supported then handle response
1466     if(mDum.getMasterProfile()->getSupportedOptionTags().find(Token(Symbols::Timer)))
1467     {
1468 sgodin 4691 setSessionTimerPreferences();
1469 jason 4010
1470     if(msg.exists(h_Requires) && msg.header(h_Requires).find(Token(Symbols::Timer))
1471     && !msg.exists(h_SessionExpires))
1472     {
1473     // If no Session Expires in response and Requires header is present then session timer is to be 'turned off'
1474     mSessionInterval = 0;
1475     }
1476     // Process Session Timer headers
1477     else if(msg.exists(h_SessionExpires))
1478     {
1479 sgodin 3392 mSessionInterval = msg.header(h_SessionExpires).value();
1480     if(msg.header(h_SessionExpires).exists(p_refresher))
1481     {
1482 jason 4010 // Remote end specified refresher preference
1483 sgodin 4691 mSessionRefresher = (msg.header(h_SessionExpires).param(p_refresher) == Data("uac"));
1484 sgodin 3392 }
1485     }
1486 jason 4010 else
1487     {
1488     // Note: If no Requires or Session-Expires, then UAS does not support Session Timers
1489     // - we are free to use our SessionInterval settings (set above as a default)
1490     // If far end doesn't support then refresher must be local
1491 sgodin 4691 mSessionRefresher = true;
1492 jason 4010 }
1493 sgodin 3392
1494 sgodin 4691 // Update MinSE if specified and longer than current value
1495     if(msg.exists(h_MinSE))
1496 sgodin 3392 {
1497 sgodin 4691 mMinSE = resipMax(mMinSE, msg.header(h_MinSE).value());
1498 sgodin 3392 }
1499 sgodin 4691
1500     startSessionTimer();
1501 sgodin 3392 }
1502     }
1503    
1504 jason 4010 void
1505     InviteSession::handleSessionTimerRequest(SipMessage &response, const SipMessage& request)
1506 sgodin 3392 {
1507 jason 4010 assert(request.header(h_CSeq).method() == INVITE || request.header(h_CSeq).method() == UPDATE);
1508    
1509 sgodin 3392 // If session timers are locally supported then add necessary headers to response
1510 jason 4010 if(mDum.getMasterProfile()->getSupportedOptionTags().find(Token(Symbols::Timer)))
1511 sgodin 3392 {
1512 sgodin 4691 setSessionTimerPreferences();
1513 sgodin 3392
1514     // Check if far-end supports
1515     bool farEndSupportsTimer = false;
1516     if(request.exists(h_Supporteds) && request.header(h_Supporteds).find(Token(Symbols::Timer)))
1517     {
1518     farEndSupportsTimer = true;
1519     if(request.exists(h_SessionExpires))
1520     {
1521 jason 4010 // Use Session Interval requested by remote - if none then use local settings
1522 sgodin 3392 mSessionInterval = request.header(h_SessionExpires).value();
1523     if(request.header(h_SessionExpires).exists(p_refresher))
1524     {
1525 sgodin 4691 mSessionRefresher = (request.header(h_SessionExpires).param(p_refresher) == Data("uas"));
1526 sgodin 3392 }
1527     }
1528 sgodin 4691
1529     // Update MinSE if specified and longer than current value
1530     if(request.exists(h_MinSE))
1531     {
1532     mMinSE = resipMax(mMinSE, request.header(h_MinSE).value());
1533     }
1534 sgodin 3392 }
1535 jason 4010 else
1536     {
1537     // If far end doesn't support then refresher must be local
1538 sgodin 4691 mSessionRefresher = true;
1539 jason 4010 }
1540 sgodin 3392
1541 jason 4010 // Add Session-Expires to response if required
1542 sgodin 3392 if(mSessionInterval >= 90)
1543     {
1544 jason 4010 if(farEndSupportsTimer)
1545 sgodin 3392 {
1546 jason 4010 // If far end supports session-timer then require it, if not already present
1547     if(!response.header(h_Requires).find(Token(Symbols::Timer)))
1548     {
1549     response.header(h_Requires).push_back(Token(Symbols::Timer));
1550     }
1551 sgodin 3392 }
1552 sgodin 4691 setSessionTimerHeaders(response);
1553     }
1554 sgodin 3392
1555 sgodin 4691 startSessionTimer();
1556 sgodin 3392 }
1557     }
1558    
1559 jason 4010 Data
1560     InviteSession::toData(State state)
1561 jason 2856 {
1562 jason 4010 switch (state)
1563 derek 3255 {
1564 jason 4010 case Undefined:
1565     return "InviteSession::Undefined";
1566     case Connected:
1567     return "InviteSession::Connected";
1568     case SentUpdate:
1569     return "InviteSession::SentUpdate";
1570     case SentUpdateGlare:
1571     return "InviteSession::SentUpdateGlare";
1572     case SentReinvite:
1573     return "InviteSession::SentReinvite";
1574     case SentReinviteGlare:
1575     return "InviteSession::SentReinviteGlare";
1576     case ReceivedUpdate:
1577     return "InviteSession::ReceivedUpdate";
1578     case ReceivedReinvite:
1579     return "InviteSession::ReceivedReinvite";
1580     case ReceivedReinviteNoOffer:
1581     return "InviteSession::ReceivedReinviteNoOffer";
1582 derek 5355 case ReceivedReinviteSentOffer:
1583     return "InviteSession::ReceivedReinviteSentOffer";
1584 jason 4010 case Answered:
1585     return "InviteSession::Answered";
1586     case WaitingToOffer:
1587     return "InviteSession::WaitingToOffer";
1588     case WaitingToTerminate:
1589     return "InviteSession::WaitingToTerminate";
1590 sgodin 5377 case WaitingToHangup:
1591     return "InviteSession::WaitingToHangup";
1592 derek 2961 case Terminated:
1593 jason 4010 return "InviteSession::Terminated";
1594 jason 2856
1595 jason 4010 case UAC_Start:
1596     return "UAC_Start";
1597     case UAS_Offer:
1598     return "UAS_Offer";
1599     case UAS_OfferProvidedAnswer:
1600     return "UAS_OfferProvidedAnswer";
1601     case UAS_EarlyOffer:
1602     return "UAS_EarlyOffer";
1603     case UAS_EarlyProvidedAnswer:
1604     return "UAS_EarlyProvidedAnswer";
1605     case UAS_NoOffer:
1606     return "UAS_NoOffer";
1607     case UAS_ProvidedOffer:
1608     return "UAS_ProvidedOffer";
1609     case UAS_EarlyNoOffer:
1610     return "UAS_EarlyNoOffer";
1611     case UAS_EarlyProvidedOffer:
1612     return "UAS_EarlyProvidedOffer";
1613     case UAS_Accepted:
1614     return "UAS_Accepted";
1615     case UAS_WaitingToOffer:
1616     return "UAS_WaitingToOffer";
1617     case UAS_AcceptedWaitingAnswer:
1618     return "UAS_AcceptedWaitingAnswer";
1619     case UAC_Early:
1620     return "UAC_Early";
1621     case UAC_EarlyWithOffer:
1622     return "UAC_EarlyWithOffer";
1623     case UAC_EarlyWithAnswer:
1624     return "UAC_EarlyWithAnswer";
1625     case UAC_Answered:
1626     return "UAC_Answered";
1627     case UAC_SentUpdateEarly:
1628     return "UAC_SentUpdateEarly";
1629     case UAC_SentUpdateConnected:
1630     return "UAC_SentUpdateConnected";
1631     case UAC_ReceivedUpdateEarly:
1632     return "UAC_ReceivedUpdateEarly";
1633     case UAC_SentAnswer:
1634     return "UAC_SentAnswer";
1635     case UAC_QueuedUpdate:
1636     return "UAC_QueuedUpdate";
1637     case UAC_Cancelled:
1638     return "UAC_Cancelled";
1639 sgodin 3332
1640 jason 4010 case UAS_Start:
1641     return "UAS_Start";
1642     case UAS_OfferReliable:
1643     return "UAS_OfferReliable";
1644     case UAS_NoOfferReliable:
1645     return "UAS_NoOfferReliable";
1646     case UAS_FirstSentOfferReliable:
1647     return "UAS_FirstSentOfferReliable";
1648     case UAS_FirstEarlyReliable:
1649     return "UAS_FirstEarlyReliable";
1650     case UAS_EarlyReliable:
1651     return "UAS_EarlyReliable";
1652     case UAS_SentUpdate:
1653     return "UAS_SentUpdate";
1654     case UAS_SentUpdateAccepted:
1655     return "UAS_SentUpdateAccepted";
1656     case UAS_ReceivedUpdate:
1657     return "UAS_ReceivedUpdate";
1658     case UAS_ReceivedUpdateWaitingAnswer:
1659     return "UAS_ReceivedUpdateWaitingAnswer";
1660     case UAS_WaitingToTerminate:
1661     return "UAS_WaitingToTerminate";
1662     case UAS_WaitingToHangup:
1663     return "UAS_WaitingToHangup";
1664     }
1665     assert(0);
1666     return "Undefined";
1667     }
1668 sgodin 3392
1669    
1670 jason 4010 void
1671     InviteSession::transition(State target)
1672     {
1673     InfoLog (<< "Transition " << toData(mState) << " -> " << toData(target));
1674     mState = target;
1675     }
1676 sgodin 3392
1677 jason 4010 bool
1678     InviteSession::isReliable(const SipMessage& msg)
1679     {
1680     // Ensure supported both locally and remotely
1681     return msg.exists(h_Supporteds) && msg.header(h_Supporteds).find(Token(Symbols::C100rel)) &&
1682     mDum.getMasterProfile()->getSupportedOptionTags().find(Token(Symbols::C100rel));
1683 jason 2856 }
1684    
1685 jason 4010 std::auto_ptr<SdpContents>
1686     InviteSession::getSdp(const SipMessage& msg)
1687 derek 3255 {
1688 jason 4010 // !jf! this code doesn't yet work - definitely if USE_SSL=false
1689     //Helper::ContentsSecAttrs attrs = Helper::extractFromPkcs7(msg, mDum.getSecurity());
1690     //return std::auto_ptr<SdpContents>(dynamic_cast<SdpContents*>(attrs.mContents.get()));
1691     SdpContents* sdp = dynamic_cast<SdpContents*>(msg.getContents());
1692     if (sdp)
1693 derek 3255 {
1694 jason 4010 SdpContents* cloned = static_cast<SdpContents*>(sdp->clone());
1695     return std::auto_ptr<SdpContents>(cloned);
1696 derek 3255 }
1697 jason 4010 else
1698     {
1699     static std::auto_ptr<SdpContents> empty;
1700     return empty;
1701     }
1702 derek 3255 }
1703    
1704 jason 4010 std::auto_ptr<SdpContents>
1705     InviteSession::makeSdp(const SdpContents& sdp)
1706 derek 2955 {
1707 jason 4010 return std::auto_ptr<SdpContents>(static_cast<SdpContents*>(sdp.clone()));
1708 derek 2955 }
1709 jason 2856
1710 daniel 5068 auto_ptr<Contents>
1711     InviteSession::makeSdp(const SdpContents& sdp,
1712     const SdpContents* alternative)
1713     {
1714     if (alternative)
1715     {
1716     MultipartAlternativeContents* mac = new MultipartAlternativeContents;
1717     mac->parts().push_back(alternative->clone());
1718     mac->parts().push_back(sdp.clone());
1719     return auto_ptr<Contents>(mac);
1720     }
1721     else
1722     {
1723     return auto_ptr<Contents>(sdp.clone());
1724     }
1725     }
1726    
1727 jason 4010 void
1728 daniel 5068 InviteSession::setSdp(SipMessage& msg, const SdpContents& sdp, const SdpContents* alternative)
1729 derek 3112 {
1730 jason 4010 // !jf! should deal with multipart here
1731 derek 3112
1732 jason 4010 // This will clone the sdp since the InviteSession also wants to keep its own
1733     // copy of the sdp around for the application to access
1734 daniel 5068 if (alternative)
1735     {
1736     MultipartAlternativeContents* mac = new MultipartAlternativeContents;
1737     mac->parts().push_back(alternative->clone());
1738     mac->parts().push_back(sdp.clone());
1739     msg.setContents(auto_ptr<Contents>(mac));
1740     }
1741     else
1742     {
1743     msg.setContents(&sdp);
1744     }
1745 derek 3112 }
1746    
1747 daniel 5068 void
1748     InviteSession::setSdp(SipMessage& msg, const Contents* sdp)
1749     {
1750     assert(sdp);
1751     msg.setContents(sdp);
1752     }
1753    
1754 jason 4010 InviteSession::Event
1755     InviteSession::toEvent(const SipMessage& msg, const SdpContents* sdp)
1756 jason 2621 {
1757 jason 4010 MethodTypes method = msg.header(h_CSeq).method();
1758     int code = msg.isResponse() ? msg.header(h_StatusLine).statusCode() : 0;
1759     bool reliable = isReliable(msg);
1760     bool sentOffer = mProposedLocalSdp.get();
1761    
1762     if (code == 481 || code == 408)
1763 derek 2961 {
1764 jason 4010 return OnGeneralFailure;
1765     }
1766     else if (code >= 300 && code <= 399)
1767     {
1768     return OnRedirect;
1769     }
1770     else if (method == INVITE && code == 0)
1771     {
1772     if (sdp)
1773     {
1774     if (reliable)
1775 sgodin 3363 {
1776 jason 4010 return OnInviteReliableOffer;
1777     }
1778     else
1779     {
1780     return OnInviteOffer;
1781     }
1782     }
1783     else
1784     {
1785     if (reliable)
1786     {
1787     return OnInviteReliable;
1788     }
1789     else
1790     {
1791     return OnInvite;
1792     }
1793     }
1794     }
1795     else if (method == INVITE && code > 100 && code < 200) // !kh! 100 is handled by transaction layer.
1796     {
1797     if (reliable)
1798     {
1799     if (sdp)
1800     {
1801     if (sentOffer)
1802 sgodin 3363 {
1803 jason 4010 return On1xxAnswer;
1804 sgodin 3363 }
1805     else
1806     {
1807 jason 4010 return On1xxOffer;
1808 sgodin 3363 }
1809     }
1810     else
1811     {
1812 jason 4010 return On1xx;
1813 sgodin 3363 }
1814 jason 4010 }
1815     else
1816     {
1817     if (sdp)
1818 sgodin 3363 {
1819 jason 4010 return On1xxEarly;
1820 sgodin 3363 }
1821     else
1822     {
1823 jason 4010 return On1xx;
1824 sgodin 3363 }
1825 jason 4010 }
1826 derek 2961 }
1827 jason 4010 else if (method == INVITE && code >= 200 && code < 300)
1828 jason 2809 {
1829 jason 4010 if (sdp)
1830     {
1831     if (sentOffer)
1832 jason 2809 {
1833 jason 4010 return On2xxAnswer;
1834 jason 2809 }
1835     else
1836     {
1837 jason 4010 return On2xxOffer;
1838 jason 2809 }
1839 jason 4010 }
1840     else
1841     {
1842     return On2xx;
1843     }
1844 jason 2809 }
1845 sgodin 4394 else if (method == INVITE && code == 422)
1846     {
1847     return On422Invite;
1848     }
1849 jason 4010 else if (method == INVITE && code == 487)
1850 derek 3293 {
1851 jason 4010 return On487Invite;
1852 derek 3293 }
1853 jason 4010 else if (method == INVITE && code == 489)
1854 derek 3276 {
1855 jason 4010 return On489Invite;
1856 derek 3276 }
1857 jason 4010 else if (method == INVITE && code == 491)
1858 derek 2965 {
1859 jason 4010 return On491Invite;
1860 derek 2965 }
1861 jason 4010 else if (method == INVITE && code >= 400)
1862 derek 2965 {
1863 jason 4010 return OnInviteFailure;
1864     }
1865     else if (method == ACK)
1866     {
1867     if (sdp)
1868 derek 2965 {
1869 jason 4010 return OnAckAnswer;
1870 derek 2965 }
1871 derek 2978 else
1872     {
1873 jason 4010 return OnAck;
1874 derek 2978 }
1875 jason 4010 }
1876     else if (method == CANCEL && code == 0)
1877 jason 2809 {
1878 jason 4010 return OnCancel;
1879 jason 2809 }
1880 jason 4010 else if (method == CANCEL && code / 200 == 1)
1881 sgodin 3338 {
1882 jason 4010 return On200Cancel;
1883 sgodin 3338 }
1884 jason 4010 else if (method == CANCEL && code >= 400)
1885 sgodin 3338 {
1886 jason 4010 return OnCancelFailure;
1887 sgodin 3338 }
1888 jason 4010 else if (method == BYE && code == 0)
1889 jason 2846 {
1890 jason 4010 return OnBye;
1891 jason 2846 }
1892 jason 4010 else if (method == BYE && code / 200 == 1)
1893 derek 3101 {
1894 jason 4010 return On200Bye;
1895 derek 3101 }
1896 jason 4010 else if (method == PRACK && code == 0)
1897     {
1898     return OnPrack;
1899     }
1900     else if (method == PRACK && code / 200 == 1)
1901     {
1902     return On200Prack;
1903     }
1904     else if (method == UPDATE && code == 0)
1905     {
1906 sgodin 4369 if (sdp)
1907     {
1908     return OnUpdateOffer;
1909     }
1910     else
1911     {
1912     return OnUpdate;
1913     }
1914 jason 4010 }
1915     else if (method == UPDATE && code / 200 == 1)
1916     {
1917     return On200Update;
1918     }
1919 sgodin 4394 else if (method == UPDATE && code == 422)
1920     {
1921     return On422Update;
1922     }
1923 jason 4010 else if (method == UPDATE && code == 489)
1924     {
1925     return On489Update;
1926     }
1927     else if (method == UPDATE && code == 491)
1928     {
1929     return On491Update;
1930     }
1931     else if (method == UPDATE && code >= 400)
1932     {
1933     return OnUpdateRejected;
1934     }
1935     else
1936     {
1937 sgodin 5012 //assert(0); // dispatchOthers will throw if the message type is really unknown
1938 jason 4010 return Unknown;
1939     }
1940 derek 2965 }
1941    
1942 jason 4010 void InviteSession::sendAck(const SdpContents *sdp)
1943 derek 2955 {
1944 jason 4010 SipMessage ack;
1945     mDialog.makeRequest(ack, ACK);
1946     if(sdp != 0)
1947 derek 3255 {
1948 jason 4010 setSdp(ack, *sdp);
1949 derek 3255 }
1950 jason 4010 InfoLog (<< "Sending " << ack.brief());
1951 daniel 5505 send(ack);
1952 derek 2981 }
1953    
1954 jason 4010 void InviteSession::sendBye()
1955 derek 2849 {
1956 jason 4010 SipMessage bye;
1957     mDialog.makeRequest(bye, BYE);
1958     InfoLog (<< "Sending " << bye.brief());
1959 daniel 5505 send(bye);
1960 jason 4010 }
1961 derek 2992
1962 daniel 5068 DialogUsageManager::EncryptionLevel InviteSession::getEncryptionLevel(const SipMessage& msg)
1963     {
1964     DialogUsageManager::EncryptionLevel level = DialogUsageManager::None;
1965     const SecurityAttributes* secAttr = msg.getSecurityAttributes();
1966     if (secAttr)
1967     {
1968     SignatureStatus sig = secAttr->getSignatureStatus();
1969     bool sign = (SignatureTrusted == sig || SignatureCATrusted == sig || SignatureSelfSigned == sig);
1970     bool encrypted = secAttr->isEncrypted();
1971     if (encrypted && sign ) level = DialogUsageManager::SignAndEncrypt;
1972     else if (encrypted) level = DialogUsageManager::Encrypt;
1973     else if (sign) level = DialogUsageManager::Sign;
1974     }
1975     return level;
1976     }
1977 derek 2992
1978 daniel 5068 void InviteSession::setCurrentLocalSdp(const SipMessage& msg)
1979     {
1980     assert(mProposedLocalSdp.get());
1981     if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))
1982     {
1983     if (DialogUsageManager::Encrypt == getEncryptionLevel(msg) || DialogUsageManager::SignAndEncrypt == getEncryptionLevel(msg))
1984     {
1985     mCurrentLocalSdp = auto_ptr<SdpContents>(static_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back()->clone()));
1986     }
1987     else
1988     {
1989     mCurrentLocalSdp = auto_ptr<SdpContents>(static_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front()->clone()));
1990     }
1991     }
1992     else
1993     {
1994     mCurrentLocalSdp = auto_ptr<SdpContents>(static_cast<SdpContents*>(mProposedLocalSdp.get()->clone()));
1995     }
1996     mProposedLocalSdp.release();
1997     }
1998    
1999 daniel 5505 void InviteSession::onReadyToSend(SipMessage& msg)
2000     {
2001     mDum.mInviteSessionHandler->onReadyToSend(getSessionHandle(), msg);
2002     }
2003 daniel 5068
2004 daniel 5505 void InviteSession::send(SipMessage& msg)
2005     {
2006     if (msg.isRequest())
2007     {
2008     // give app an chance to adorn the message.
2009     onReadyToSend(msg);
2010     }
2011    
2012     mDialog.send(msg);
2013     }
2014    
2015    
2016 davidb 2575 /* ====================================================================
2017 jason 4010 * The Vovida Software License, Version 1.0
2018     *
2019 davidb 2575 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
2020 jason 4010 *
2021 davidb 2575 * Redistribution and use in source and binary forms, with or without
2022     * modification, are permitted provided that the following conditions
2023     * are met:
2024 jason 4010 *
2025 davidb 2575 * 1. Redistributions of source code must retain the above copyright
2026     * notice, this list of conditions and the following disclaimer.
2027 jason 4010 *
2028 davidb 2575 * 2. Redistributions in binary form must reproduce the above copyright
2029     * notice, this list of conditions and the following disclaimer in
2030     * the documentation and/or other materials provided with the
2031    
2032     * distribution.
2033 jason 4010 *
2034 davidb 2575 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2035     * and "Vovida Open Communication Application Library (VOCAL)" must
2036     * not be used to endorse or promote products derived from this
2037     * software without prior written permission. For written
2038     * permission, please contact vocal@vovida.org.
2039     *
2040     * 4. Products derived from this software may not be called "VOCAL", nor
2041     * may "VOCAL" appear in their name, without prior written
2042     * permission of Vovida Networks, Inc.
2043 jason 4010 *
2044 davidb 2575 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2045     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2046     * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2047     * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2048     * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2049     * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2050     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2051     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2052     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2053     * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2054     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2055     * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2056     * DAMAGE.
2057 jason 4010 *
2058 davidb 2575 * ====================================================================
2059 jason 4010 *
2060 davidb 2575 * This software consists of voluntary contributions made by Vovida
2061     * Networks, Inc. and many individuals on behalf of Vovida Networks,
2062     * Inc. For more information on Vovida Networks, Inc., please see
2063     * <http://www.vovida.org/>.
2064     *
2065     */
2066 jason 5459

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27