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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5645 - (show annotations) (download)
Tue Nov 15 05:20:40 2005 UTC (14 years, 2 months ago) by derek
File size: 35280 byte(s)
fixup endreason

1 #include "resip/stack/SdpContents.hxx"
2 #include "resip/dum/ClientInviteSession.hxx"
3 #include "resip/dum/Dialog.hxx"
4 #include "resip/dum/DialogUsageManager.hxx"
5 #include "resip/dum/InviteSessionHandler.hxx"
6 #include "resip/dum/DumTimeout.hxx"
7 #include "resip/dum/MasterProfile.hxx"
8 #include "resip/dum/ServerInviteSession.hxx"
9 #include "resip/dum/ServerSubscription.hxx"
10 #include "resip/dum/UsageUseException.hxx"
11 #include "resip/dum/DumHelper.hxx"
12 #include "resip/stack/SipFrag.hxx"
13 #include "rutil/Logger.hxx"
14 #include "rutil/Random.hxx"
15 #include "rutil/compat.hxx"
16 #include "rutil/WinLeakCheck.hxx"
17
18 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM
19
20 using namespace resip;
21 using namespace std;
22
23 ClientInviteSession::ClientInviteSession(DialogUsageManager& dum,
24 Dialog& dialog,
25 const SipMessage& request,
26 const Contents* initialOffer,
27 DialogUsageManager::EncryptionLevel level,
28 ServerSubscriptionHandle serverSub) :
29 InviteSession(dum, dialog),
30 mLastReceivedRSeq(-1),
31 mStaleCallTimerSeq(1),
32 mCancelledTimerSeq(1),
33 mServerSub(serverSub)
34 {
35 assert(request.isRequest());
36 if(initialOffer)
37 {
38 mProposedLocalSdp = auto_ptr<Contents>(initialOffer->clone());
39 mProposedEncryptionLevel = level;
40 }
41 mInvite = request;
42
43 mState=UAC_Start;
44 }
45
46 ClientInviteSessionHandle
47 ClientInviteSession::getHandle()
48 {
49 return ClientInviteSessionHandle(mDum, getBaseHandle().getId());
50 }
51
52 const SdpContents&
53 ClientInviteSession::getEarlyMedia() const
54 {
55 return *mEarlyMedia;
56 }
57
58 void
59 ClientInviteSession::provideOffer(const SdpContents& offer, DialogUsageManager::EncryptionLevel level, const SdpContents* alternative)
60 {
61 InfoLog (<< toData(mState) << ": provideOffer");
62
63 switch(mState)
64 {
65 case UAC_EarlyWithAnswer:
66 {
67 transition(UAC_SentUpdateEarly);
68
69 // Creates an UPDATE request with application supplied offer.
70 mDialog.makeRequest(mLastSessionModification, UPDATE);
71 InviteSession::setSdp(mLastSessionModification, offer);
72
73 // Remember proposed local SDP.
74 mProposedLocalSdp = InviteSession::makeSdp(offer, alternative);
75 mProposedEncryptionLevel = level;
76
77 // Send the req and do state transition.
78 DumHelper::setOutgoingEncryptionLevel(mLastSessionModification, mProposedEncryptionLevel);
79 send(mLastSessionModification);
80 break;
81 }
82
83 case UAC_SentAnswer:
84 // just queue it for later
85 transition(UAC_QueuedUpdate);
86 mProposedLocalSdp = InviteSession::makeSdp(offer, alternative);
87 mProposedEncryptionLevel = level;
88 break;
89
90 case UAC_Start:
91 case UAC_Early:
92 case UAC_EarlyWithOffer:
93 case UAC_Answered:
94 case UAC_SentUpdateEarly:
95 case UAC_SentUpdateConnected:
96 case UAC_ReceivedUpdateEarly:
97 case UAC_Cancelled:
98 case UAC_QueuedUpdate:
99 case Terminated:
100 assert(0);
101 break;
102
103 default:
104 InviteSession::provideOffer(offer, level, alternative);
105 break;
106 }
107 }
108
109 void
110 ClientInviteSession::provideOffer (const SdpContents& offer)
111 {
112 this->provideOffer(offer, mCurrentEncryptionLevel, 0);
113 }
114
115 void
116 ClientInviteSession::provideAnswer (const SdpContents& answer)
117 {
118 InfoLog (<< toData(mState) << ": provideAnswer");
119
120 switch(mState)
121 {
122 case UAC_EarlyWithOffer:
123 {
124 transition(UAC_SentAnswer);
125
126 // Remember proposed local SDP.
127 mCurrentRemoteSdp = mProposedRemoteSdp;
128 mCurrentLocalSdp = InviteSession::makeSdp(answer);
129
130 // Creates an PRACK request with application supplied offer.
131 sendPrack(answer);
132 break;
133 }
134
135 case UAC_Answered:
136 {
137 transition(Connected);
138 sendAck(mInvite, &answer);
139
140 mCurrentRemoteSdp = mProposedRemoteSdp;
141 mCurrentLocalSdp = InviteSession::makeSdp(answer);
142 // mLastSessionModification = ack; // ?slg? is this needed?
143 break;
144 }
145
146 case UAC_Start:
147 case UAC_Early:
148 case UAC_EarlyWithAnswer:
149 case UAC_SentUpdateEarly:
150 case UAC_SentUpdateConnected:
151 case UAC_ReceivedUpdateEarly:
152 case UAC_SentAnswer:
153 case UAC_Cancelled:
154 case UAC_QueuedUpdate:
155 case Terminated:
156 assert(0);
157 break;
158
159 default:
160 InviteSession::provideAnswer(answer);
161 break;
162 }
163 }
164
165 void
166 ClientInviteSession::end()
167 {
168 end(NotSpecified);
169 }
170
171 void
172 ClientInviteSession::end(EndReason reason)
173 {
174 InfoLog (<< toData(mState) << ": end");
175 if (mEndReason == NotSpecified)
176 {
177 mEndReason = reason;
178 }
179
180 switch(mState)
181 {
182 case UAC_Early:
183 case UAC_EarlyWithOffer:
184 case UAC_EarlyWithAnswer:
185 case UAC_Answered:
186 case UAC_SentUpdateEarly:
187 case UAC_ReceivedUpdateEarly:
188 case UAC_SentAnswer:
189 case UAC_QueuedUpdate:
190 case UAC_Cancelled: // !jf! possibly incorrect to always BYE in UAC_Cancelled
191 {
192 sendBye();
193 transition(Terminated);
194 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Ended);
195 break;
196 }
197
198 case UAC_Start:
199 WarningLog (<< "Try to end when in state=" << toData(mState));
200 assert(0);
201 break;
202
203 case Terminated:
204 assert(0);
205 break;
206
207 default:
208 InviteSession::end(reason);
209 break;
210 }
211 }
212
213 void
214 ClientInviteSession::reject (int statusCode, WarningCategory *warning)
215 {
216 InfoLog (<< toData(mState) << ": reject(" << statusCode << ")");
217
218 switch(mState)
219 {
220 case UAC_ReceivedUpdateEarly:
221 {
222 // Creates an PRACK request with application supplied status code.
223 // !kh! hopefully 488....
224 SipMessage req;
225 mDialog.makeRequest(req, PRACK);
226 req.header(h_StatusLine).statusCode() = statusCode;
227 if(warning)
228 {
229 req.header(h_Warnings).push_back(*warning);
230 }
231
232 // Send the req and do state transition.
233 send(req);
234 transition(UAC_EarlyWithAnswer);
235 break;
236 }
237
238 case UAC_Start:
239 case UAC_Early:
240 case UAC_EarlyWithOffer:
241 case UAC_EarlyWithAnswer:
242 case UAC_Answered:
243 case UAC_SentUpdateEarly:
244 case UAC_SentAnswer:
245 case UAC_Cancelled:
246 WarningLog (<< "Try to reject when in state=" << toData(mState));
247 assert(0);
248 break;
249
250 default:
251 InviteSession::reject(statusCode);
252 break;
253 }
254 }
255
256 void
257 ClientInviteSession::cancel()
258 {
259 switch(mState)
260 {
261 case UAC_Early:
262 case UAC_EarlyWithOffer:
263 case UAC_EarlyWithAnswer:
264 case UAC_SentUpdateEarly:
265 case UAC_ReceivedUpdateEarly:
266 case UAC_SentAnswer:
267 InfoLog (<< toData(mState) << ": cancel");
268 startCancelTimer();
269 transition(UAC_Cancelled);
270 break;
271
272 case UAC_Cancelled:
273 // !jf!
274 // assert(0);
275 break;
276
277 default:
278 assert(0);
279 break;
280 }
281 }
282
283 void
284 ClientInviteSession::onForkAccepted()
285 {
286 switch(mState)
287 {
288 case UAC_Early:
289 case UAC_EarlyWithOffer:
290 case UAC_EarlyWithAnswer:
291 case UAC_SentUpdateEarly:
292 case UAC_ReceivedUpdateEarly:
293 InfoLog (<< toData(mState) << ": onForkAccepted");
294 // !jf! should we avoid creating another timer here? I don't think it
295 // matters. Default timer is for 32secs. This is here to handle the
296 // cleanup on forked INVITEs that have sent a provisional response but
297 // don't ever receive a final response.
298 mDum.addTimerMs(DumTimeout::WaitingForForked2xx, Timer::TH, getBaseHandle(), 1);
299 break;
300 default:
301 // If the dialog is already set up (or cancelled) we disregard.
302 break;
303 }
304 }
305
306 void
307 ClientInviteSession::startCancelTimer()
308 {
309 InfoLog (<< toData(mState) << ": startCancelTimer");
310 mDum.addTimerMs(DumTimeout::Cancelled, Timer::TH, getBaseHandle(), ++mCancelledTimerSeq);
311 }
312
313 void
314 ClientInviteSession::startStaleCallTimer()
315 {
316 InfoLog (<< toData(mState) << ": startStaleCallTimer");
317 unsigned long when = mDialog.mDialogSet.getUserProfile()->getDefaultStaleCallTime();
318 when += Random::getRandom() % 120;
319
320 mDum.addTimer(DumTimeout::StaleCall,
321 when,
322 getBaseHandle(),
323 ++mStaleCallTimerSeq);
324 }
325
326 void
327 ClientInviteSession::sendSipFrag(const SipMessage& msg)
328 {
329 if (mServerSub.isValid())
330 {
331 if (msg.isResponse() && mState >= UAC_Start && mState <= UAC_Cancelled)
332 {
333 int code = msg.header(h_StatusLine).statusCode();
334 if (code > 100)
335 {
336 SipFrag contents;
337 contents.message().header(h_StatusLine) = msg.header(h_StatusLine);
338 if (code < 200)
339 {
340 mServerSub->send(mServerSub->update(&contents));
341 }
342 else
343 {
344 mServerSub->end(NoResource, &contents);
345 }
346 }
347 }
348 }
349 }
350
351 void
352 ClientInviteSession::dispatch(const SipMessage& msg)
353 {
354 try
355 {
356 sendSipFrag(msg);
357 switch(mState)
358 {
359 case UAC_Start:
360 dispatchStart(msg);
361 break;
362 case UAC_Early:
363 dispatchEarly(msg);
364 break;
365 case UAC_EarlyWithOffer:
366 dispatchEarlyWithOffer(msg);
367 break;
368 case UAC_EarlyWithAnswer:
369 dispatchEarlyWithAnswer(msg);
370 break;
371 case UAC_Answered:
372 dispatchAnswered(msg);
373 break;
374 case UAC_SentUpdateEarly:
375 dispatchSentUpdateEarly(msg);
376 break;
377 case UAC_SentUpdateConnected:
378 dispatchSentUpdateConnected(msg);
379 break;
380 case UAC_ReceivedUpdateEarly:
381 dispatchReceivedUpdateEarly(msg);
382 break;
383 case UAC_SentAnswer:
384 dispatchSentAnswer(msg);
385 break;
386 case UAC_QueuedUpdate:
387 dispatchQueuedUpdate(msg);
388 break;
389 case UAC_Cancelled:
390 dispatchCancelled(msg);
391 break;
392 default:
393 InviteSession::dispatch(msg);
394 break;
395 }
396 }
397 catch (BaseException& e)
398 {
399 WarningLog (<< "Caught: " << e);
400 mDum.mInviteSessionHandler->onFailure(getHandle(), msg);
401 end();
402 }
403 }
404
405 void
406 ClientInviteSession::dispatch(const DumTimeout& timer)
407 {
408 if (timer.type() == DumTimeout::Cancelled)
409 {
410 if(timer.seq() == mCancelledTimerSeq)
411 {
412 if (mServerSub.isValid())
413 {
414 SipMessage response;
415 mDialog.makeResponse(response, mInvite, 487);
416 sendSipFrag(response);
417 }
418 transition(Terminated);
419 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::Cancelled);
420 mDum.destroy(this);
421 }
422 }
423 else if (timer.type() == DumTimeout::StaleCall)
424 {
425 if(timer.seq() == mStaleCallTimerSeq)
426 {
427 mDum.mInviteSessionHandler->onStaleCallTimeout(getHandle());
428 mDum.mInviteSessionHandler->terminate(getHandle());
429 }
430 }
431 else if (timer.type() == DumTimeout::WaitingForForked2xx)
432 {
433 transition(Terminated);
434 mDum.mInviteSessionHandler->onForkDestroyed(getHandle());
435 mDum.destroy(this);
436 }
437 else
438 {
439 InviteSession::dispatch(timer);
440 }
441 }
442
443 void
444 ClientInviteSession::handleRedirect (const SipMessage& msg)
445 {
446 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
447 transition(Terminated);
448 handler->onRedirected(getHandle(), msg);
449 mDum.destroy(this);
450 }
451
452 void
453 ClientInviteSession::handleProvisional(const SipMessage& msg)
454 {
455 assert(msg.isResponse());
456 assert(msg.header(h_StatusLine).statusCode() < 200);
457 assert(msg.header(h_StatusLine).statusCode() > 100);
458
459 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
460
461 // must match
462 if (msg.header(h_CSeq).sequence() != mInvite.header(h_CSeq).sequence())
463 {
464 InfoLog (<< "Failure: CSeq doesn't match invite: " << msg.brief());
465 handler->onFailure(getHandle(), msg);
466 end();
467 }
468 else if (isReliable(msg))
469 {
470 if (!msg.exists(h_RSeq))
471 {
472 InfoLog (<< "Failure: No RSeq in 1xx: " << msg.brief());
473 handler->onFailure(getHandle(), msg);
474 end();
475 }
476 else
477 {
478 // store state about the provisional if reliable, so we can detect retransmissions
479 int rseq = msg.header(h_RSeq).value();
480 if ( (mLastReceivedRSeq == -1) || (rseq == mLastReceivedRSeq+1))
481 {
482 startStaleCallTimer();
483 mLastReceivedRSeq = rseq;
484 InfoLog (<< "Got a reliable 1xx with rseq = " << rseq);
485 handler->onProvisional(getHandle(), msg);
486 }
487 else
488 {
489 InfoLog (<< "Got an out of order reliable 1xx with rseq = " << rseq << " dropping");
490 }
491 }
492 }
493 else
494 {
495 startStaleCallTimer();
496 handler->onProvisional(getHandle(), msg);
497 }
498 }
499
500 void
501 ClientInviteSession::handleFinalResponse(const SipMessage& msg)
502 {
503 assert(msg.isResponse());
504 assert(msg.header(h_StatusLine).statusCode() >= 200);
505 assert(msg.header(h_StatusLine).statusCode() < 300);
506
507 handleSessionTimerResponse(msg);
508 storePeerCapabilities(msg);
509 ++mStaleCallTimerSeq; // disable stale call timer
510 }
511
512 void
513 ClientInviteSession::handleOffer (const SipMessage& msg, const SdpContents& sdp)
514 {
515 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
516
517 handleProvisional(msg);
518 mProposedRemoteSdp = InviteSession::makeSdp(sdp);
519 mCurrentEncryptionLevel = getEncryptionLevel(msg);
520 handler->onOffer(getSessionHandle(), msg, sdp);
521 }
522
523 void
524 ClientInviteSession::handleAnswer (const SipMessage& msg, const SdpContents& sdp)
525 {
526 //mCurrentLocalSdp = mProposedLocalSdp;
527 setCurrentLocalSdp(msg);
528 mCurrentEncryptionLevel = getEncryptionLevel(msg);
529 mCurrentRemoteSdp = InviteSession::makeSdp(sdp);
530
531 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
532 handleProvisional(msg);
533 handler->onAnswer(getSessionHandle(), msg, sdp);
534
535 sendPrackIfNeeded(msg);
536 }
537
538 // will not include SDP (this is a subsequent 1xx)
539 void
540 ClientInviteSession::sendPrackIfNeeded(const SipMessage& msg)
541 {
542 if ( isReliable(msg) &&
543 (mLastReceivedRSeq == -1 || msg.header(h_RSeq).value() == mLastReceivedRSeq+1))
544 {
545 SipMessage prack;
546 mDialog.makeRequest(prack, PRACK);
547 prack.header(h_RSeq) = msg.header(h_RSeq);
548 send(prack);
549 }
550 }
551
552 // This version is used to send an answer to the UAS in PRACK
553 // from EarlyWithOffer state. Assumes that it is the first PRACK. Subsequent
554 // PRACK will not have SDP
555 void
556 ClientInviteSession::sendPrack(const SdpContents& sdp)
557 {
558 SipMessage prack;
559 mDialog.makeRequest(prack, PRACK);
560 prack.header(h_RSeq).value() = mLastReceivedRSeq;
561 InviteSession::setSdp(prack, sdp);
562
563 // Remember last session modification.
564 // mLastSessionModification = prack; // ?slg? is this needed?
565
566 DumHelper::setOutgoingEncryptionLevel(prack, mCurrentEncryptionLevel);
567 send(prack);
568 }
569
570
571 /*
572 bool
573 ClientInviteSession::isNextProvisional(const SipMessage& msg)
574 {
575 }
576
577 bool
578 ClientInviteSession::isRetransmission(const SipMessage& msg)
579 {
580 if ( mLastReceivedRSeq == -1 ||
581 msg.header(h_RSeq).value() <= mLastReceivedRSeq)
582 {
583 return false;
584 }
585 else
586 {
587 return true;
588 }
589 }
590 */
591
592 void
593 ClientInviteSession::dispatchStart (const SipMessage& msg)
594 {
595 assert(msg.isResponse());
596 assert(msg.header(h_StatusLine).statusCode() > 100);
597 assert(msg.header(h_CSeq).method() == INVITE);
598
599 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
600 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
601
602 InviteSession::Event event = toEvent(msg, sdp.get());
603 switch (event)
604 {
605 case On1xx:
606 transition(UAC_Early);
607 handler->onNewSession(getHandle(), None, msg);
608 if(!isTerminated())
609 {
610 handleProvisional(msg);
611 }
612 break;
613
614 case On1xxEarly:
615 // !jf! Assumed that if UAS supports 100rel, the first 1xx must contain an
616 // offer or an answer.
617 transition(UAC_Early);
618 mEarlyMedia = InviteSession::makeSdp(*sdp);
619 handler->onNewSession(getHandle(), None, msg);
620 if(!isTerminated())
621 {
622 handleProvisional(msg);
623 if(!isTerminated())
624 {
625 handler->onEarlyMedia(getHandle(), msg, *sdp);
626 }
627 }
628 break;
629
630 case On1xxOffer:
631 transition(UAC_EarlyWithOffer);
632 handler->onNewSession(getHandle(), Offer, msg);
633 if(!isTerminated())
634 {
635 handleOffer(msg, *sdp);
636 }
637 break;
638
639 case On1xxAnswer:
640 transition(UAC_EarlyWithAnswer);
641 handler->onNewSession(getHandle(), Answer, msg);
642 if(!isTerminated())
643 {
644 handleAnswer(msg, *sdp);
645 }
646 break;
647
648 case On2xxOffer:
649 transition(UAC_Answered);
650 handleFinalResponse(msg);
651 mProposedRemoteSdp = InviteSession::makeSdp(*sdp);
652 handler->onNewSession(getHandle(), Offer, msg);
653 assert(mProposedLocalSdp.get() == 0);
654 mCurrentEncryptionLevel = getEncryptionLevel(msg);
655 if(!isTerminated())
656 {
657 handler->onOffer(getSessionHandle(), msg, *sdp);
658 if(!isTerminated())
659 {
660 handler->onConnected(getHandle(), msg);
661 }
662 }
663 break;
664
665 case On2xxAnswer:
666 transition(Connected);
667 sendAck(mInvite);
668 handleFinalResponse(msg);
669 //mCurrentLocalSdp = mProposedLocalSdp;
670 setCurrentLocalSdp(msg);
671 mCurrentEncryptionLevel = getEncryptionLevel(msg);
672 mCurrentRemoteSdp = InviteSession::makeSdp(*sdp);
673 handler->onNewSession(getHandle(), Answer, msg);
674 if(!isTerminated()) // onNewSession callback may call end() or reject()
675 {
676 handler->onAnswer(getSessionHandle(), msg, *sdp);
677 if(!isTerminated()) // onAnswer callback may call end() or reject()
678 {
679 handler->onConnected(getHandle(), msg);
680 }
681 }
682 break;
683
684 case On2xx:
685 {
686 sendAck(mInvite);
687 sendBye();
688 InfoLog (<< "Failure: 2xx with no answer: " << msg.brief());
689 transition(Terminated);
690 handler->onFailure(getHandle(), msg);
691 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
692 break;
693 }
694
695 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
696 case OnInviteFailure:
697 case OnGeneralFailure:
698 case On422Invite:
699 case On487Invite:
700 case On489Invite:
701 case On491Invite:
702 InfoLog (<< "Failure: error response: " << msg.brief());
703 transition(Terminated);
704 handler->onFailure(getHandle(), msg);
705 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
706 mDum.destroy(this);
707 break;
708
709 default:
710 // !kh!
711 // should not assert here for peer sent us garbage.
712 //assert(0);
713 WarningLog (<< "Don't know what this is : " << msg);
714 break;
715 }
716 }
717
718 void
719 ClientInviteSession::dispatchEarly (const SipMessage& msg)
720 {
721 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
722 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
723
724 switch (toEvent(msg, sdp.get()))
725 {
726 case On1xx:
727 transition(UAC_Early);
728 handleProvisional(msg);
729 break;
730
731 case On1xxEarly: // only unreliable
732 transition(UAC_Early);
733 handleProvisional(msg);
734 if(!isTerminated())
735 {
736 mEarlyMedia = InviteSession::makeSdp(*sdp);
737 handler->onEarlyMedia(getHandle(), msg, *sdp);
738 }
739 break;
740
741 case On1xxOffer:
742 transition(UAC_EarlyWithOffer);
743 handleOffer(msg, *sdp);
744 break;
745
746 case On1xxAnswer:
747 transition(UAC_EarlyWithAnswer);
748 handleAnswer(msg, *sdp);
749 break;
750
751 case On2xxOffer:
752 transition(UAC_Answered);
753 handleFinalResponse(msg);
754
755 assert(mProposedLocalSdp.get() == 0);
756 mCurrentEncryptionLevel = getEncryptionLevel(msg);
757 mProposedRemoteSdp = InviteSession::makeSdp(*sdp);
758
759 handler->onOffer(getSessionHandle(), msg, *sdp);
760 if(!isTerminated())
761 {
762 handler->onConnected(getHandle(), msg);
763 }
764 break;
765
766 case On2xxAnswer:
767 transition(Connected);
768 sendAck(mInvite);
769 handleFinalResponse(msg);
770 //mCurrentLocalSdp = mProposedLocalSdp;
771 setCurrentLocalSdp(msg);
772 mCurrentEncryptionLevel = getEncryptionLevel(msg);
773 mCurrentRemoteSdp = InviteSession::makeSdp(*sdp);
774 handler->onAnswer(getSessionHandle(), msg, *sdp);
775 if(!isTerminated()) // onNewSession callback may call end() or reject()
776 {
777 handler->onConnected(getHandle(), msg);
778 }
779 break;
780
781 case On2xx:
782 {
783 sendAck(mInvite);
784 sendBye();
785 InfoLog (<< "Failure: 2xx with no answer: " << msg.brief());
786 transition(Terminated);
787 handler->onFailure(getHandle(), msg);
788 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
789 break;
790 }
791
792 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
793 case OnInviteFailure:
794 case OnGeneralFailure:
795 case On422Invite:
796 case On487Invite:
797 case On489Invite:
798 case On491Invite:
799 InfoLog (<< "Failure: error response: " << msg.brief());
800 transition(Terminated);
801 handler->onFailure(getHandle(), msg);
802 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
803 mDum.destroy(this);
804 break;
805
806 default:
807 // !kh!
808 // should not assert here for peer sent us garbage.
809 //assert(0);
810 WarningLog (<< "Don't know what this is : " << msg);
811 break;
812 }
813 }
814
815 void
816 ClientInviteSession::dispatchAnswered (const SipMessage& msg)
817 {
818 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
819 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
820
821 switch (toEvent(msg, sdp.get()))
822 {
823 case On1xx:
824 case On1xxEarly:
825 case On1xxOffer:
826 // late, so ignore
827 break;
828
829 case On2xxOffer:
830 case On2xx:
831 case On2xxAnswer:
832 // retransmission
833 break;
834
835 case OnRedirect:
836 // too late
837 break;
838
839 // !slg! This probably doesn't even make sense (after a 2xx)
840 case OnGeneralFailure:
841 case On422Invite:
842 {
843 sendBye();
844 InfoLog (<< "Failure: error response: " << msg.brief());
845 transition(Terminated);
846 handler->onFailure(getHandle(), msg);
847 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
848 mDum.destroy(this);
849 break;
850 }
851
852 default:
853 // !kh!
854 // should not assert here for peer sent us garbage.
855 //assert(0);
856 WarningLog (<< "Don't know what this is : " << msg);
857 break;
858 }
859
860 }
861
862 void
863 ClientInviteSession::dispatchEarlyWithOffer (const SipMessage& msg)
864 {
865 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
866 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
867
868 switch (toEvent(msg, sdp.get()))
869 {
870 case On1xx: // must be reliable
871 handleProvisional(msg);
872 sendPrackIfNeeded(msg);
873 break;
874
875 case On2xx:
876 case On2xxAnswer:
877 sendAck(mInvite);
878 sendBye();
879 InfoLog (<< "Failure: no answer sent: " << msg.brief());
880 transition(Terminated);
881 handler->onFailure(getHandle(), msg);
882 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
883 break;
884
885 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
886 case OnInviteFailure:
887 case OnGeneralFailure:
888 case On422Invite:
889 case On487Invite:
890 case On489Invite:
891 case On491Invite:
892 InfoLog (<< "Failure: error response: " << msg.brief());
893 transition(Terminated);
894 handler->onFailure(getHandle(), msg);
895 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
896 mDum.destroy(this);
897 break;
898
899 default:
900 // !kh!
901 // should not assert here for peer sent us garbage.
902 //assert(0);
903 WarningLog (<< "Don't know what this is : " << msg);
904 break;
905 }
906 }
907
908 void
909 ClientInviteSession::dispatchSentAnswer (const SipMessage& msg)
910 {
911 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
912 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
913
914 switch (toEvent(msg, sdp.get()))
915 {
916 case On200Prack:
917 transition(UAC_EarlyWithAnswer);
918 break;
919
920 case On2xx:
921 transition(Connected);
922 sendAck(mInvite);
923 handleFinalResponse(msg);
924 handler->onConnected(getHandle(), msg);
925 break;
926
927 case On2xxAnswer:
928 case On2xxOffer:
929 case On1xxAnswer:
930 case On1xxOffer:
931 sendAck(mInvite);
932 sendBye();
933 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief());
934 transition(Terminated);
935 handler->onFailure(getHandle(), msg);
936 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
937 break;
938
939 case On1xx:
940 handleProvisional(msg);
941 sendPrackIfNeeded(msg);
942 break;
943
944 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
945 case OnInviteFailure:
946 case OnGeneralFailure:
947 case On422Invite:
948 case On487Invite:
949 case On489Invite:
950 case On491Invite:
951 InfoLog (<< "Failure: error response: " << msg.brief());
952 transition(Terminated);
953 handler->onFailure(getHandle(), msg);
954 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
955 mDum.destroy(this);
956 break;
957
958 default:
959 // !kh!
960 // should not assert here for peer sent us garbage.
961 //assert(0);
962 WarningLog (<< "Don't know what this is : " << msg);
963 break;
964 }
965 }
966
967 void
968 ClientInviteSession::dispatchQueuedUpdate (const SipMessage& msg)
969 {
970 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
971 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
972
973 switch (toEvent(msg, sdp.get()))
974 {
975 case On200Prack:
976 transition(UAC_SentUpdateEarly);
977 {
978 mDialog.makeRequest(mLastSessionModification, UPDATE);
979 InviteSession::setSdp(mLastSessionModification, mProposedLocalSdp.get());
980
981 DumHelper::setOutgoingEncryptionLevel(mLastSessionModification, mProposedEncryptionLevel);
982 send(mLastSessionModification);
983 }
984 break;
985
986 case On2xx:
987 transition(SentUpdate);
988 {
989 sendAck(mInvite);
990
991 SipMessage update;
992 mDialog.makeRequest(update, UPDATE);
993 InviteSession::setSdp(update, mProposedLocalSdp.get());
994 DumHelper::setOutgoingEncryptionLevel(update, mProposedEncryptionLevel);
995 send(update);
996 }
997 handleFinalResponse(msg);
998 handler->onConnected(getHandle(), msg);
999 break;
1000
1001 case On2xxAnswer:
1002 case On2xxOffer:
1003 case On1xxAnswer:
1004 case On1xxOffer:
1005 sendAck(mInvite);
1006 sendBye();
1007 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief());
1008 transition(Terminated);
1009 handler->onFailure(getHandle(), msg);
1010 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1011 break;
1012
1013 case On1xx:
1014 handleProvisional(msg);
1015 sendPrackIfNeeded(msg);
1016 break;
1017
1018 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
1019 case OnInviteFailure:
1020 case OnGeneralFailure:
1021 case On422Invite:
1022 case On487Invite:
1023 case On489Invite:
1024 case On491Invite:
1025 InfoLog (<< "Failure: error response: " << msg.brief());
1026 transition(Terminated);
1027 handler->onFailure(getHandle(), msg);
1028 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1029 mDum.destroy(this);
1030 break;
1031
1032 default:
1033 // !kh!
1034 // should not assert here for peer sent us garbage.
1035 //assert(0);
1036 WarningLog (<< "Don't know what this is : " << msg);
1037 break;
1038 }
1039 }
1040
1041
1042
1043 void
1044 ClientInviteSession::dispatchEarlyWithAnswer (const SipMessage& msg)
1045 {
1046 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1047 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
1048
1049 switch (toEvent(msg, sdp.get()))
1050 {
1051 case On1xx:
1052 handleProvisional(msg);
1053 sendPrackIfNeeded(msg);
1054 break;
1055
1056 case On2xx:
1057 transition(Connected);
1058 sendAck(mInvite);
1059 handleFinalResponse(msg);
1060 handler->onConnected(getHandle(), msg);
1061 break;
1062
1063 case On2xxAnswer:
1064 case On2xxOffer:
1065 sendAck(mInvite);
1066 sendBye();
1067 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief());
1068 transition(Terminated);
1069 handler->onFailure(getHandle(), msg);
1070 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1071 break;
1072
1073 case OnUpdateOffer:
1074 transition(UAC_ReceivedUpdateEarly);
1075 mCurrentEncryptionLevel = getEncryptionLevel(msg);
1076 mProposedRemoteSdp = InviteSession::makeSdp(*sdp);
1077 handler->onOffer(getSessionHandle(), msg, *sdp);
1078 break;
1079
1080 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets here then it's because the redirect was intentionaly not handled and should be treated as an INVITE failure
1081 case OnInviteFailure:
1082 case OnGeneralFailure:
1083 case On422Invite:
1084 case On487Invite:
1085 case On489Invite:
1086 case On491Invite:
1087 InfoLog (<< "Failure: error response: " << msg.brief());
1088 transition(Terminated);
1089 handler->onFailure(getHandle(), msg);
1090 handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg);
1091 mDum.destroy(this);
1092 break;
1093
1094 default:
1095 // !kh!
1096 // should not assert here for peer sent us garbage.
1097 //assert(0);
1098 WarningLog (<< "Don't know what this is : " << msg);
1099 break;
1100 }
1101 }
1102
1103 void
1104 ClientInviteSession::dispatchSentUpdateEarly (const SipMessage& msg)
1105 {
1106 assert(0);
1107 }
1108
1109 void
1110 ClientInviteSession::dispatchSentUpdateConnected (const SipMessage& msg)
1111 {
1112 assert(0);
1113 }
1114
1115 void
1116 ClientInviteSession::dispatchReceivedUpdateEarly (const SipMessage& msg)
1117 {
1118 assert(0);
1119 }
1120
1121 void
1122 ClientInviteSession::dispatchCancelled (const SipMessage& msg)
1123 {
1124 InviteSessionHandler* handler = mDum.mInviteSessionHandler;
1125 std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg);
1126
1127 switch (toEvent(msg, sdp.get()))
1128 {
1129 case OnGeneralFailure:
1130 case OnCancelFailure:
1131 case On487Invite:
1132 case OnRedirect:
1133 case On422Invite:
1134 transition(Terminated);
1135 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Cancelled, &msg);
1136 mDum.destroy(this);
1137 break;
1138
1139 case On2xx:
1140 case On2xxOffer:
1141 case On2xxAnswer:
1142 {
1143 // this is the 2xx crossing the CANCEL case
1144 sendAck(mInvite);
1145 sendBye();
1146 transition(Terminated);
1147 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Cancelled, &msg);
1148 mCancelledTimerSeq++;
1149 break;
1150 }
1151
1152 default:
1153 break;
1154 }
1155 }
1156
1157 /* ====================================================================
1158 * The Vovida Software License, Version 1.0
1159 *
1160 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1161 *
1162 * Redistribution and use in source and binary forms, with or without
1163 * modification, are permitted provided that the following conditions
1164 * are met:
1165 *
1166 * 1. Redistributions of source code must retain the above copyright
1167 * notice, this list of conditions and the following disclaimer.
1168 *
1169 * 2. Redistributions in binary form must reproduce the above copyright
1170 * notice, this list of conditions and the following disclaimer in
1171 * the documentation and/or other materials provided with the
1172
1173 * distribution.
1174 *
1175 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1176 * and "Vovida Open Communication Application Library (VOCAL)" must
1177 * not be used to endorse or promote products derived from this
1178 * software without prior written permission. For written
1179 * permission, please contact vocal@vovida.org.
1180 *
1181 * 4. Products derived from this software may not be called "VOCAL", nor
1182 * may "VOCAL" appear in their name, without prior written
1183 * permission of Vovida Networks, Inc.
1184 *
1185 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1186 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1187 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1188 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1189 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1190 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1191 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1192 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1193 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1194 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1195 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1196 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1197 * DAMAGE.
1198 *
1199 * ====================================================================
1200 *
1201 * This software consists of voluntary contributions made by Vovida
1202 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1203 * Inc. For more information on Vovida Networks, Inc., please see
1204 * <http://www.vovida.org/>.
1205 *
1206 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27