|
reSIProcate/DialogUsageManager
9680
|
00001 00002 #include "resip/stack/Contents.hxx" 00003 #include "resip/dum/ClientInviteSession.hxx" 00004 #include "resip/dum/Dialog.hxx" 00005 #include "resip/dum/DialogEventStateManager.hxx" 00006 #include "resip/dum/DialogUsageManager.hxx" 00007 #include "resip/dum/InviteSessionHandler.hxx" 00008 #include "resip/dum/DumTimeout.hxx" 00009 #include "resip/dum/MasterProfile.hxx" 00010 #include "resip/dum/ServerInviteSession.hxx" 00011 #include "resip/dum/ServerSubscription.hxx" 00012 #include "resip/dum/UsageUseException.hxx" 00013 #include "resip/dum/DumHelper.hxx" 00014 #include "resip/stack/SipFrag.hxx" 00015 #include "rutil/Logger.hxx" 00016 #include "rutil/Random.hxx" 00017 #include "rutil/compat.hxx" 00018 #include "rutil/WinLeakCheck.hxx" 00019 00020 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00021 00022 using namespace resip; 00023 using namespace std; 00024 00025 ClientInviteSession::ClientInviteSession(DialogUsageManager& dum, 00026 Dialog& dialog, 00027 SharedPtr<SipMessage> request, 00028 const Contents* initialOffer, 00029 DialogUsageManager::EncryptionLevel level, 00030 ServerSubscriptionHandle serverSub) : 00031 InviteSession(dum, dialog), 00032 mStaleCallTimerSeq(1), 00033 mCancelledTimerSeq(1), 00034 mServerSub(serverSub) 00035 { 00036 assert(request->isRequest()); 00037 if(initialOffer) 00038 { 00039 mProposedLocalOfferAnswer = auto_ptr<Contents>(initialOffer->clone()); 00040 mProposedEncryptionLevel = level; 00041 } 00042 *mLastLocalSessionModification = *request; // Copy message, so that modifications to mLastLocalSessionModification don't effect creator->getLastRequest 00043 00044 mState=UAC_Start; 00045 } 00046 00047 ClientInviteSessionHandle 00048 ClientInviteSession::getHandle() 00049 { 00050 return ClientInviteSessionHandle(mDum, getBaseHandle().getId()); 00051 } 00052 00053 const Contents& 00054 ClientInviteSession::getEarlyMedia() const 00055 { 00056 return *mEarlyMedia; 00057 } 00058 00059 void 00060 ClientInviteSession::provideOffer(const Contents& offer, DialogUsageManager::EncryptionLevel level, const Contents* alternative) 00061 { 00062 InfoLog (<< toData(mState) << ": provideOffer"); 00063 00064 switch(mState) 00065 { 00066 case UAC_EarlyWithAnswer: 00067 { 00068 transition(UAC_SentUpdateEarly); 00069 00070 // Creates an UPDATE request with application supplied offer. 00071 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); 00072 InviteSession::setOfferAnswer(*mLastLocalSessionModification, offer); 00073 00074 // Remember proposed local offferAnswer. 00075 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative); 00076 mProposedEncryptionLevel = level; 00077 00078 // Send the req and do state transition. 00079 DumHelper::setOutgoingEncryptionLevel(*mLastLocalSessionModification, mProposedEncryptionLevel); 00080 send(mLastLocalSessionModification); 00081 break; 00082 } 00083 00084 case UAC_SentAnswer: 00085 // just queue it for later 00086 transition(UAC_QueuedUpdate); 00087 mProposedLocalOfferAnswer = InviteSession::makeOfferAnswer(offer, alternative); 00088 mProposedEncryptionLevel = level; 00089 break; 00090 00091 case UAC_Start: 00092 case UAC_Early: 00093 case UAC_EarlyWithOffer: 00094 case UAC_Answered: 00095 case UAC_SentUpdateEarly: 00096 case UAC_ReceivedUpdateEarly: 00097 case UAC_Cancelled: 00098 case UAC_QueuedUpdate: 00099 case Terminated: 00100 assert(0); 00101 break; 00102 00103 default: 00104 InviteSession::provideOffer(offer, level, alternative); 00105 break; 00106 } 00107 } 00108 00109 void 00110 ClientInviteSession::provideOffer (const Contents& offer) 00111 { 00112 this->provideOffer(offer, mCurrentEncryptionLevel, 0); 00113 } 00114 00115 void 00116 ClientInviteSession::provideAnswer (const Contents& answer) 00117 { 00118 InfoLog (<< toData(mState) << ": provideAnswer"); 00119 00120 switch(mState) 00121 { 00122 case UAC_EarlyWithOffer: 00123 { 00124 transition(UAC_SentAnswer); 00125 00126 // Remember proposed local offerAnswer. 00127 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer; 00128 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer); 00129 00130 // Creates an PRACK request with application supplied offer. 00131 sendPrack(answer); 00132 break; 00133 } 00134 00135 case UAC_Answered: 00136 { 00137 transition(Connected); 00138 sendAck(&answer); 00139 00140 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer; 00141 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer); 00142 // mLastSessionModification = ack; // ?slg? is this needed? 00143 break; 00144 } 00145 case UAC_ReceivedUpdateEarly: 00146 { 00147 transition(UAC_EarlyWithAnswer); //.dcm. earlyWithAnwer is a strange 00148 //name...maybe earlyEstablished? 00149 //this sequence is repeated in many places...due for refactoring. 00150 //see ReceivedUpdate handling in InviteSession. 00151 //?dcm? are session timers allowed in the early dialog? 00152 00153 SharedPtr<SipMessage> response(new SipMessage); 00154 mDialog.makeResponse(*response, *mLastRemoteSessionModification, 200); 00155 InviteSession::setOfferAnswer(*response, answer, 0); 00156 mCurrentLocalOfferAnswer = InviteSession::makeOfferAnswer(answer); 00157 mCurrentRemoteOfferAnswer = mProposedRemoteOfferAnswer; 00158 InfoLog (<< "Sending " << response->brief()); 00159 DumHelper::setOutgoingEncryptionLevel(*response, mCurrentEncryptionLevel); 00160 send(response); 00161 break; 00162 } 00163 00164 case UAC_Start: 00165 case UAC_Early: 00166 case UAC_EarlyWithAnswer: 00167 case UAC_SentUpdateEarly: 00168 case UAC_SentAnswer: 00169 case UAC_Cancelled: 00170 case UAC_QueuedUpdate: 00171 case Terminated: 00172 assert(0); 00173 break; 00174 00175 default: 00176 InviteSession::provideAnswer(answer); 00177 break; 00178 } 00179 } 00180 00181 void 00182 ClientInviteSession::end() 00183 { 00184 end(NotSpecified); 00185 } 00186 00187 void 00188 ClientInviteSession::end(const Data& userReason) 00189 { 00190 mUserEndReason = userReason; 00191 end(InviteSession::UserSpecified); 00192 } 00193 00194 void 00195 ClientInviteSession::end(EndReason reason) 00196 { 00197 InfoLog (<< toData(mState) << ": end"); 00198 if (mEndReason == NotSpecified) 00199 { 00200 mEndReason = reason; 00201 } 00202 00203 switch(mState) 00204 { 00205 case UAC_Early: 00206 case UAC_EarlyWithOffer: 00207 case UAC_EarlyWithAnswer: 00208 case UAC_Answered: 00209 case UAC_SentUpdateEarly: 00210 case UAC_ReceivedUpdateEarly: 00211 case UAC_SentAnswer: 00212 case UAC_QueuedUpdate: 00213 case UAC_Cancelled: // !jf! possibly incorrect to always BYE in UAC_Cancelled 00214 { 00215 SharedPtr<SipMessage> msg = sendBye(); 00216 transition(Terminated); 00217 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get()); 00218 break; 00219 } 00220 00221 case UAC_Start: 00222 WarningLog (<< "Try to end when in state=" << toData(mState)); 00223 assert(0); 00224 break; 00225 00226 case Terminated: 00227 // no-op 00228 break; 00229 00230 default: 00231 InviteSession::end(reason); 00232 break; 00233 } 00234 } 00235 00236 void 00237 ClientInviteSession::reject (int statusCode, WarningCategory *warning) 00238 { 00239 InfoLog (<< toData(mState) << ": reject(" << statusCode << ")"); 00240 00241 switch(mState) 00242 { 00243 case UAC_ReceivedUpdateEarly: 00244 { 00245 SharedPtr<SipMessage> response(new SipMessage); 00246 mDialog.makeResponse(*response, *mLastRemoteSessionModification, statusCode); 00247 if(warning) 00248 { 00249 response->header(h_Warnings).push_back(*warning); 00250 } 00251 00252 // Send the req and do state transition. 00253 send(response); 00254 transition(UAC_EarlyWithAnswer); 00255 break; 00256 } 00257 00258 case UAC_Answered:{ 00259 // We received an offer in a 2xx response, and we want to reject it 00260 // ACK with no body, then send bye 00261 sendAck(); 00262 SharedPtr<SipMessage> msg = sendBye(); 00263 transition(Terminated); 00264 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalBye, msg.get()); 00265 break; 00266 } 00267 00268 case UAC_Start: 00269 case UAC_Early: 00270 case UAC_EarlyWithOffer: 00271 case UAC_EarlyWithAnswer: 00272 case UAC_SentUpdateEarly: 00273 case UAC_SentAnswer: 00274 case UAC_Cancelled: 00275 WarningLog (<< "Try to reject when in state=" << toData(mState)); 00276 assert(0); 00277 break; 00278 00279 default: 00280 InviteSession::reject(statusCode, warning); 00281 break; 00282 } 00283 } 00284 00285 void 00286 ClientInviteSession::cancel() 00287 { 00288 switch(mState) 00289 { 00290 case UAC_Early: 00291 case UAC_EarlyWithOffer: 00292 case UAC_EarlyWithAnswer: 00293 case UAC_SentUpdateEarly: 00294 case UAC_ReceivedUpdateEarly: 00295 case UAC_SentAnswer: 00296 InfoLog (<< toData(mState) << ": cancel"); 00297 startCancelTimer(); 00298 transition(UAC_Cancelled); 00299 break; 00300 00301 case UAC_Cancelled: 00302 case Terminated: 00303 // no-op already cancelled or ended 00304 break; 00305 00306 default: 00307 assert(0); 00308 break; 00309 } 00310 } 00311 00312 void 00313 ClientInviteSession::onForkAccepted() 00314 { 00315 switch(mState) 00316 { 00317 case UAC_Early: 00318 case UAC_EarlyWithOffer: 00319 case UAC_EarlyWithAnswer: 00320 case UAC_SentUpdateEarly: 00321 case UAC_ReceivedUpdateEarly: 00322 InfoLog (<< toData(mState) << ": onForkAccepted"); 00323 // !jf! should we avoid creating another timer here? I don't think it 00324 // matters. Default timer is for 32secs. This is here to handle the 00325 // cleanup on forked INVITEs that have sent a provisional response but 00326 // don't ever receive a final response. 00327 mDum.addTimerMs(DumTimeout::WaitingForForked2xx, Timer::TH, getBaseHandle(), 1); 00328 break; 00329 default: 00330 // If the dialog is already set up (or cancelled) we disregard. 00331 break; 00332 } 00333 } 00334 00335 void 00336 ClientInviteSession::startCancelTimer() 00337 { 00338 InfoLog (<< toData(mState) << ": startCancelTimer"); 00339 mDum.addTimerMs(DumTimeout::Cancelled, Timer::TH, getBaseHandle(), ++mCancelledTimerSeq); 00340 } 00341 00342 void 00343 ClientInviteSession::startStaleCallTimer() 00344 { 00345 InfoLog (<< toData(mState) << ": startStaleCallTimer"); 00346 unsigned long when = mDialog.mDialogSet.getUserProfile()->getDefaultStaleCallTime(); 00347 when += Random::getRandom() % 120; 00348 00349 mDum.addTimer(DumTimeout::StaleCall, 00350 when, 00351 getBaseHandle(), 00352 ++mStaleCallTimerSeq); 00353 } 00354 00355 void 00356 ClientInviteSession::sendSipFrag(const SipMessage& msg) 00357 { 00358 if (mServerSub.isValid()) 00359 { 00360 if (msg.isResponse() && mState >= UAC_Start && mState <= UAC_Cancelled) 00361 { 00362 int code = msg.header(h_StatusLine).statusCode(); 00363 if (code > 100) 00364 { 00365 SipFrag contents; 00366 contents.message().header(h_StatusLine) = msg.header(h_StatusLine); 00367 if(mDialog.mDialogSet.getUserProfile()->getExtraHeadersInReferNotifySipFragEnabled()) 00368 { 00369 contents.message().header(h_Vias) = msg.header(h_Vias); 00370 contents.message().header(h_From) = msg.header(h_From); 00371 contents.message().header(h_To) = msg.header(h_To); 00372 contents.message().header(h_CallId) = msg.header(h_CallId); 00373 contents.message().header(h_CSeq) = msg.header(h_CSeq); 00374 contents.message().header(h_Contacts) = msg.header(h_Contacts); 00375 } 00376 if (code < 200) 00377 { 00378 mServerSub->send(mServerSub->update(&contents)); 00379 } 00380 else 00381 { 00382 mServerSub->end(NoResource, &contents); 00383 } 00384 } 00385 } 00386 } 00387 } 00388 00389 void 00390 ClientInviteSession::dispatch(const SipMessage& msg) 00391 { 00392 try 00393 { 00394 if (msg.isRequest()) 00395 { 00396 if (msg.header(h_RequestLine).method() == INFO) 00397 { 00398 InviteSession::dispatchInfo(msg); 00399 return; 00400 } 00401 if (msg.header(h_RequestLine).method() == MESSAGE) 00402 { 00403 InviteSession::dispatchMessage(msg); 00404 return; 00405 } 00406 } 00407 00408 if (checkRseq(msg)) 00409 { 00410 return; 00411 } 00412 00413 sendSipFrag(msg); 00414 switch(mState) 00415 { 00416 case UAC_Start: 00417 dispatchStart(msg); 00418 break; 00419 case UAC_Early: 00420 dispatchEarly(msg); 00421 break; 00422 case UAC_EarlyWithOffer: 00423 dispatchEarlyWithOffer(msg); 00424 break; 00425 case UAC_EarlyWithAnswer: 00426 dispatchEarlyWithAnswer(msg); 00427 break; 00428 case UAC_Answered: 00429 dispatchAnswered(msg); 00430 break; 00431 case UAC_SentUpdateEarly: 00432 dispatchSentUpdateEarly(msg); 00433 break; 00434 case UAC_SentUpdateEarlyGlare: 00435 dispatchSentUpdateEarlyGlare(msg); 00436 break; 00437 case UAC_ReceivedUpdateEarly: 00438 dispatchReceivedUpdateEarly(msg); 00439 break; 00440 case UAC_SentAnswer: 00441 dispatchSentAnswer(msg); 00442 break; 00443 case UAC_QueuedUpdate: 00444 dispatchQueuedUpdate(msg); 00445 break; 00446 case UAC_Cancelled: 00447 dispatchCancelled(msg); 00448 break; 00449 default: 00450 InviteSession::dispatch(msg); 00451 break; 00452 } 00453 } 00454 catch (BaseException& e) 00455 { 00456 WarningLog (<< "Caught: " << e); 00457 onFailureAspect(getHandle(), msg); 00458 end(NotSpecified); 00459 } 00460 } 00461 00462 void 00463 ClientInviteSession::dispatch(const DumTimeout& timer) 00464 { 00465 if (timer.type() == DumTimeout::Cancelled) 00466 { 00467 if(timer.seq() == mCancelledTimerSeq) 00468 { 00469 if (mServerSub.isValid()) 00470 { 00471 SipMessage response; 00472 mDialog.makeResponse(response, *mLastLocalSessionModification, 487); 00473 sendSipFrag(response); 00474 } 00475 transition(Terminated); 00476 mDum.mInviteSessionHandler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalCancel); 00477 mDum.destroy(this); 00478 } 00479 } 00480 else if (timer.type() == DumTimeout::StaleCall) 00481 { 00482 if(timer.seq() == mStaleCallTimerSeq) 00483 { 00484 mDum.mInviteSessionHandler->onStaleCallTimeout(getHandle()); 00485 mDum.mInviteSessionHandler->terminate(getHandle()); 00486 } 00487 } 00488 else if (timer.type() == DumTimeout::WaitingForForked2xx) 00489 { 00490 transition(Terminated); 00491 mDum.mInviteSessionHandler->onForkDestroyed(getHandle()); 00492 mDum.destroy(this); 00493 } 00494 else if (timer.type() == DumTimeout::Glare) 00495 { 00496 if (mState == UAC_SentUpdateEarlyGlare) 00497 { 00498 transition(UAC_SentUpdateEarly); 00499 InfoLog (<< "Retransmitting the UPDATE (glare condition timer)"); 00500 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); // increments CSeq 00501 send(mLastLocalSessionModification); 00502 } 00503 else 00504 { 00505 InviteSession::dispatch(timer); 00506 } 00507 } 00508 else 00509 { 00510 InviteSession::dispatch(timer); 00511 } 00512 } 00513 00514 void 00515 ClientInviteSession::handleRedirect (const SipMessage& msg) 00516 { 00517 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00518 transition(Terminated); 00519 00520 if (mDum.mDialogEventStateManager) 00521 { 00522 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, InviteSessionHandler::Rejected); 00523 } 00524 00525 handler->onRedirected(getHandle(), msg); 00526 mDum.destroy(this); 00527 } 00528 00529 void 00530 ClientInviteSession::handleProvisional(const SipMessage& msg) 00531 { 00532 assert(msg.isResponse()); 00533 assert(msg.header(h_StatusLine).statusCode() < 200); 00534 assert(msg.header(h_StatusLine).statusCode() > 100); 00535 00536 //.dcm. Kept the following checks here rather than discardMessage as the 00537 // state machine can be affected(termination). 00538 00539 // !dcm! should we really end the InviteSession or should be discard the 1xx instead? 00540 if (msg.header(h_CSeq).sequence() != mLastLocalSessionModification->header(h_CSeq).sequence()) 00541 { 00542 InfoLog (<< "Failure: CSeq doesn't match invite: " << msg.brief()); 00543 onFailureAspect(getHandle(), msg); 00544 end(NotSpecified); 00545 return; 00546 } 00547 else if (isReliable(msg)) 00548 { 00549 if (!msg.exists(h_RSeq)) 00550 { 00551 InfoLog (<< "Failure: No RSeq in 1xx: " << msg.brief()); 00552 onFailureAspect(getHandle(), msg); 00553 end(NotSpecified); 00554 return; 00555 } 00556 } 00557 00558 startStaleCallTimer(); 00559 onProvisionalAspect(getHandle(), msg); 00560 } 00561 00562 void 00563 ClientInviteSession::handleFinalResponse(const SipMessage& msg) 00564 { 00565 assert(msg.isResponse()); 00566 assert(msg.header(h_StatusLine).statusCode() >= 200); 00567 assert(msg.header(h_StatusLine).statusCode() < 300); 00568 00569 handleSessionTimerResponse(msg); 00570 storePeerCapabilities(msg); 00571 ++mStaleCallTimerSeq; // disable stale call timer 00572 } 00573 00574 void 00575 ClientInviteSession::handleOffer (const SipMessage& msg, const Contents& offer) 00576 { 00577 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00578 00579 handleProvisional(msg); 00580 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(offer); 00581 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00582 handler->onOffer(getSessionHandle(), msg, offer); 00583 } 00584 00585 void 00586 ClientInviteSession::handleAnswer(const SipMessage& msg, const Contents& answer) 00587 { 00588 //mCurrentLocalOfferAnswer = mProposedLocalOfferAnswer; 00589 setCurrentLocalOfferAnswer(msg); 00590 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00591 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(answer); 00592 00593 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00594 handleProvisional(msg); 00595 handler->onAnswer(getSessionHandle(), msg, answer); 00596 00597 sendPrackIfNeeded(msg); 00598 } 00599 00600 // will not include SDP (this is a subsequent 1xx) 00601 void 00602 ClientInviteSession::sendPrackIfNeeded(const SipMessage& msg) 00603 { 00604 assert(msg.isResponse()); 00605 assert(msg.header(h_StatusLine).statusCode() < 200); 00606 assert(msg.header(h_StatusLine).statusCode() > 100); 00607 00608 if (isReliable(msg)) 00609 { 00610 SharedPtr<SipMessage> prack(new SipMessage); 00611 mDialog.makeRequest(*prack, PRACK); 00612 prack->header(h_RAck) = mRelRespInfo; 00613 send(prack); 00614 } 00615 } 00616 00617 // This version is used to send an answer to the UAS in PRACK 00618 // from EarlyWithOffer state. Assumes that it is the first PRACK. Subsequent 00619 // PRACK will not have SDP 00620 void 00621 ClientInviteSession::sendPrack(const Contents& offerAnswer) 00622 { 00623 SharedPtr<SipMessage> prack(new SipMessage); 00624 mDialog.makeRequest(*prack, PRACK); 00625 prack->header(h_RAck)= mRelRespInfo; 00626 00627 InviteSession::setOfferAnswer(*prack, offerAnswer); 00628 00629 // Remember last session modification. 00630 // mLastSessionModification = prack; // ?slg? is this needed? 00631 00632 DumHelper::setOutgoingEncryptionLevel(*prack, mCurrentEncryptionLevel); 00633 send(prack); 00634 } 00635 00636 00637 /* 00638 bool 00639 ClientInviteSession::isNextProvisional(const SipMessage& msg) 00640 { 00641 } 00642 00643 bool 00644 ClientInviteSession::isRetransmission(const SipMessage& msg) 00645 { 00646 if ( mLastReceivedRSeq == 0 || 00647 msg.header(h_RSeq).value() <= mLastReceivedRSeq) 00648 { 00649 return false; 00650 } 00651 else 00652 { 00653 return true; 00654 } 00655 } 00656 */ 00657 00658 void 00659 ClientInviteSession::dispatchStart (const SipMessage& msg) 00660 { 00661 assert(msg.isResponse()); 00662 assert(msg.header(h_StatusLine).statusCode() > 100); 00663 assert(msg.header(h_CSeq).method() == INVITE); 00664 00665 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00666 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 00667 00668 InviteSession::Event event = toEvent(msg, offerAnswer.get()); 00669 00670 switch (event) 00671 { 00672 case On1xx: 00673 transition(UAC_Early); 00674 handler->onNewSession(getHandle(), InviteSession::None, msg); 00675 if(!isTerminated()) 00676 { 00677 handleProvisional(msg); 00678 sendPrackIfNeeded(msg); //may wish to move emprty PRACK handling 00679 //outside the state machine 00680 } 00681 break; 00682 00683 case On1xxEarly: 00685 // reliable 1xx followed by a reliable 1xx. Also, the intial 1xx 00686 // doesn't have to have an offer. However, DUM will only generate 00687 // reliabled 1xx responses when 100rel is available. 00688 00689 transition(UAC_Early); 00690 mEarlyMedia = InviteSession::makeOfferAnswer(*offerAnswer); 00691 handler->onNewSession(getHandle(), InviteSession::None, msg); 00692 if(!isTerminated()) 00693 { 00694 handleProvisional(msg); 00695 if(!isTerminated()) 00696 { 00697 handler->onEarlyMedia(getHandle(), msg, *offerAnswer); 00698 } 00699 } 00700 break; 00701 00702 case On1xxOffer: 00703 transition(UAC_EarlyWithOffer); 00704 handler->onNewSession(getHandle(), InviteSession::Offer, msg); 00705 if(!isTerminated()) 00706 { 00707 handleOffer(msg, *offerAnswer); 00708 } 00709 break; 00710 00711 case On1xxAnswer: 00712 transition(UAC_EarlyWithAnswer); 00713 handler->onNewSession(getHandle(), InviteSession::Answer, msg); 00714 if(!isTerminated()) 00715 { 00716 handleAnswer(msg, *offerAnswer); 00717 } 00718 break; 00719 00720 case On2xxOffer: 00721 transition(UAC_Answered); 00722 handleFinalResponse(msg); 00723 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 00724 handler->onNewSession(getHandle(), InviteSession::Offer, msg); 00725 assert(mProposedLocalOfferAnswer.get() == 0); 00726 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00727 if(!isTerminated()) 00728 { 00729 handler->onOffer(getSessionHandle(), msg, *offerAnswer); 00730 if(!isTerminated()) //?jf? can this be terminated here but not above? .slg. yes application can call end() 00731 { 00732 onConnectedAspect(getHandle(), msg); 00733 } 00734 } 00735 break; 00736 00737 case On2xxAnswer: 00738 transition(Connected); 00739 sendAck(); 00740 handleFinalResponse(msg); 00741 //mCurrentLocalOfferAnswer = mProposedLocalOfferAnswer; 00742 setCurrentLocalOfferAnswer(msg); 00743 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00744 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 00745 handler->onNewSession(getHandle(), InviteSession::Answer, msg); 00746 if(!isTerminated()) // onNewSession callback may call end() or reject() 00747 { 00748 handler->onAnswer(getSessionHandle(), msg, *offerAnswer); 00749 if(!isTerminated()) // onAnswer callback may call end() or reject() 00750 { 00751 onConnectedAspect(getHandle(), msg); 00752 } 00753 } 00754 break; 00755 00756 case On2xx: 00757 { 00758 sendAck(); 00759 sendBye(); 00760 InfoLog (<< "Failure: 2xx with no answer: " << msg.brief()); 00761 transition(Terminated); 00762 onFailureAspect(getHandle(), msg); 00763 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00764 break; 00765 } 00766 00767 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 00768 case OnInviteFailure: 00769 case OnGeneralFailure: 00770 case On422Invite: 00771 case On487Invite: 00772 case On491Invite: 00773 InfoLog (<< "Failure: error response: " << msg.brief()); 00774 transition(Terminated); 00775 onFailureAspect(getHandle(), msg); 00776 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00777 mDum.destroy(this); 00778 break; 00779 00780 case OnBye: 00781 dispatchBye(msg); 00782 break; 00783 00784 default: 00785 // !kh! 00786 // should not assert here for peer sent us garbage. 00787 WarningLog (<< "Don't know what this is : " << msg); 00788 break; 00789 } 00790 } 00791 00792 void 00793 ClientInviteSession::dispatchEarly (const SipMessage& msg) 00794 { 00795 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00796 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 00797 00798 switch (toEvent(msg, offerAnswer.get())) 00799 { 00800 case On1xx: 00801 transition(UAC_Early); 00802 handleProvisional(msg); 00803 break; 00804 00805 case On1xxEarly: // only unreliable 00806 transition(UAC_Early); 00807 handleProvisional(msg); 00808 if(!isTerminated()) 00809 { 00810 mEarlyMedia = InviteSession::makeOfferAnswer(*offerAnswer); 00811 handler->onEarlyMedia(getHandle(), msg, *offerAnswer); 00812 } 00813 break; 00814 00815 case On1xxOffer: 00816 transition(UAC_EarlyWithOffer); 00817 handleOffer(msg, *offerAnswer); 00818 break; 00819 00820 case On1xxAnswer: 00821 transition(UAC_EarlyWithAnswer); 00822 handleAnswer(msg, *offerAnswer); 00823 break; 00824 00825 case On2xxOffer: 00826 transition(UAC_Answered); 00827 handleFinalResponse(msg); 00828 00829 assert(mProposedLocalOfferAnswer.get() == 0); 00830 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00831 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 00832 00833 handler->onOffer(getSessionHandle(), msg, *offerAnswer); 00834 if(!isTerminated()) 00835 { 00836 onConnectedAspect(getHandle(), msg); 00837 } 00838 break; 00839 00840 case On2xxAnswer: 00841 transition(Connected); 00842 sendAck(); 00843 handleFinalResponse(msg); 00844 //mCurrentLocalOfferAnswer = mProposedLocalOfferAnswer; 00845 setCurrentLocalOfferAnswer(msg); 00846 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00847 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 00848 handler->onAnswer(getSessionHandle(), msg, *offerAnswer); 00849 if(!isTerminated()) // onNewSession callback may call end() or reject() 00850 { 00851 onConnectedAspect(getHandle(), msg); 00852 } 00853 break; 00854 00855 case On2xx: 00856 { 00857 sendAck(); 00858 sendBye(); 00859 InfoLog (<< "Failure: 2xx with no answer: " << msg.brief()); 00860 transition(Terminated); 00861 onFailureAspect(getHandle(), msg); 00862 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00863 break; 00864 } 00865 00866 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 00867 case OnInviteFailure: 00868 case OnGeneralFailure: 00869 case On422Invite: 00870 case On487Invite: 00871 InfoLog (<< "Failure: error response: " << msg.brief()); 00872 transition(Terminated); 00873 onFailureAspect(getHandle(), msg); 00874 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00875 mDum.destroy(this); 00876 break; 00877 00878 case OnBye: 00879 dispatchBye(msg); 00880 break; 00881 00882 case OnUpdateOffer: 00883 if(mProposedLocalOfferAnswer.get()) 00884 { 00885 WarningLog (<< "Invalid UPDATE with offer received in early state with pending offer: " << msg.brief()); 00886 SharedPtr<SipMessage> response(new SipMessage); 00887 mDialog.makeResponse(*response, msg, 500); // RFC3311 - section 5.2 00888 InfoLog (<< "Sending " << response->brief()); 00889 send(response); 00890 } 00891 else 00892 { 00893 *mLastRemoteSessionModification = msg; 00894 transition(UAC_ReceivedUpdateEarly); 00895 mCurrentEncryptionLevel = getEncryptionLevel(msg); 00896 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 00897 handler->onOffer(getSessionHandle(), msg, *offerAnswer); 00898 } 00899 break; 00900 00901 case OnUpdate: 00902 { 00903 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback? 00904 SharedPtr<SipMessage> response(new SipMessage); 00905 *mLastRemoteSessionModification = msg; 00906 mDialog.makeResponse(*response, msg, 200); 00907 send(response); 00908 break; 00909 } 00910 00911 default: 00912 // !kh! 00913 // should not assert here for peer sent us garbage. 00914 WarningLog (<< "Don't know what this is : " << msg); 00915 break; 00916 } 00917 } 00918 00919 void 00920 ClientInviteSession::dispatchAnswered (const SipMessage& msg) 00921 { 00922 //InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00923 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 00924 00925 switch (toEvent(msg, offerAnswer.get())) 00926 { 00927 case On1xx: 00928 case On1xxEarly: 00929 case On1xxOffer: 00930 // late, so ignore 00931 break; 00932 00933 case On2xxOffer: 00934 case On2xx: 00935 case On2xxAnswer: 00936 // retransmission 00937 break; 00938 00939 case OnRedirect: 00940 // too late 00941 break; 00942 00943 // .slg. This doesn't really make sense (after a 2xx) 00944 case OnGeneralFailure: 00945 case On422Invite: 00946 break; 00947 #if 0 // !jf! don't think this is right 00948 { 00949 sendBye(); 00950 InfoLog (<< "Failure: error response: " << msg.brief()); 00951 transition(Terminated); 00952 onFailureAspect(getHandle(), msg); 00953 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00954 mDum.destroy(this); 00955 break; 00956 } 00957 #endif 00958 case OnBye: 00959 dispatchBye(msg); 00960 break; 00961 00962 default: 00963 // !kh! 00964 // should not assert here for peer sent us garbage. 00965 WarningLog (<< "Don't know what this is : " << msg); 00966 break; 00967 } 00968 00969 } 00970 00971 void 00972 ClientInviteSession::dispatchEarlyWithOffer (const SipMessage& msg) 00973 { 00974 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 00975 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 00976 00977 switch (toEvent(msg, offerAnswer.get())) 00978 { 00979 case On1xx: // must be reliable 00980 handleProvisional(msg); 00981 sendPrackIfNeeded(msg); 00982 break; 00983 00984 case On2xx: 00985 case On2xxAnswer: 00986 sendAck(); 00987 sendBye(); 00988 InfoLog (<< "Failure: no answer sent: " << msg.brief()); 00989 transition(Terminated); 00990 onFailureAspect(getHandle(), msg); 00991 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 00992 break; 00993 00994 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 00995 case OnInviteFailure: 00996 case OnGeneralFailure: 00997 case On422Invite: 00998 case On487Invite: 00999 case On491Invite: 01000 InfoLog (<< "Failure: error response: " << msg.brief()); 01001 transition(Terminated); 01002 onFailureAspect(getHandle(), msg); 01003 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01004 mDum.destroy(this); 01005 break; 01006 01007 case OnBye: 01008 dispatchBye(msg); 01009 break; 01010 01011 case OnUpdateOffer: 01012 { 01013 WarningLog (<< "Invalid UPDATE with offer received in early state with pending offer: " << msg.brief()); 01014 SharedPtr<SipMessage> response(new SipMessage); 01015 mDialog.makeResponse(*response, msg, 500); // RFC3311 - section 5.2 01016 InfoLog (<< "Sending " << response->brief()); 01017 send(response); 01018 break; 01019 } 01020 01021 case OnUpdate: 01022 { 01023 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback? 01024 SharedPtr<SipMessage> response(new SipMessage); 01025 *mLastRemoteSessionModification = msg; 01026 mDialog.makeResponse(*response, msg, 200); 01027 send(response); 01028 break; 01029 } 01030 01031 default: 01032 // !kh! 01033 // should not assert here for peer sent us garbage. 01034 WarningLog (<< "Don't know what this is : " << msg); 01035 break; 01036 } 01037 } 01038 01039 void 01040 ClientInviteSession::dispatchSentAnswer (const SipMessage& msg) 01041 { 01042 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01043 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01044 01045 switch (toEvent(msg, offerAnswer.get())) 01046 { 01047 case On200Prack: 01048 transition(UAC_EarlyWithAnswer); 01049 break; 01050 01051 case On2xx: 01052 transition(Connected); 01053 sendAck(); 01054 handleFinalResponse(msg); 01055 onConnectedAspect(getHandle(), msg); 01056 break; 01057 01058 case On2xxAnswer: 01059 case On2xxOffer: 01060 case On1xxAnswer: 01061 case On1xxOffer: 01062 sendAck(); 01063 sendBye(); 01064 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief()); 01065 transition(Terminated); 01066 onFailureAspect(getHandle(), msg); 01067 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01068 break; 01069 01070 case On1xx: 01071 handleProvisional(msg); 01072 sendPrackIfNeeded(msg); 01073 break; 01074 01075 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 01076 case OnInviteFailure: 01077 case OnGeneralFailure: 01078 case On422Invite: 01079 case On487Invite: 01080 case On491Invite: 01081 InfoLog (<< "Failure: error response: " << msg.brief()); 01082 transition(Terminated); 01083 onFailureAspect(getHandle(), msg); 01084 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01085 mDum.destroy(this); 01086 break; 01087 01088 case OnBye: 01089 dispatchBye(msg); 01090 break; 01091 01092 default: 01093 // !kh! 01094 // should not assert here for peer sent us garbage. 01095 WarningLog (<< "Don't know what this is : " << msg); 01096 break; 01097 } 01098 } 01099 01100 void 01101 ClientInviteSession::dispatchQueuedUpdate (const SipMessage& msg) 01102 { 01103 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01104 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01105 01106 switch (toEvent(msg, offerAnswer.get())) 01107 { 01108 case On200Prack: 01109 transition(UAC_SentUpdateEarly); 01110 { 01111 mDialog.makeRequest(*mLastLocalSessionModification, UPDATE); 01112 InviteSession::setOfferAnswer(*mLastLocalSessionModification, mProposedLocalOfferAnswer.get()); 01113 01114 DumHelper::setOutgoingEncryptionLevel(*mLastLocalSessionModification, mProposedEncryptionLevel); 01115 send(mLastLocalSessionModification); 01116 } 01117 break; 01118 01119 case On2xx: 01120 transition(SentUpdate); 01121 { 01122 sendAck(); 01123 01124 SharedPtr<SipMessage> update(new SipMessage); 01125 mDialog.makeRequest(*update, UPDATE); 01126 InviteSession::setOfferAnswer(*update, mProposedLocalOfferAnswer.get()); 01127 DumHelper::setOutgoingEncryptionLevel(*update, mProposedEncryptionLevel); 01128 send(update); 01129 } 01130 handleFinalResponse(msg); 01131 onConnectedAspect(getHandle(), msg); 01132 break; 01133 01134 case On2xxAnswer: 01135 case On2xxOffer: 01136 case On1xxAnswer: 01137 case On1xxOffer: 01138 sendAck(); 01139 sendBye(); 01140 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief()); 01141 transition(Terminated); 01142 onFailureAspect(getHandle(), msg); 01143 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01144 break; 01145 01146 case On1xx: 01147 handleProvisional(msg); 01148 sendPrackIfNeeded(msg); 01149 break; 01150 01151 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 01152 case OnInviteFailure: 01153 case OnGeneralFailure: 01154 case On422Invite: 01155 case On487Invite: 01156 case On491Invite: 01157 InfoLog (<< "Failure: error response: " << msg.brief()); 01158 transition(Terminated); 01159 onFailureAspect(getHandle(), msg); 01160 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01161 mDum.destroy(this); 01162 break; 01163 01164 case OnBye: 01165 dispatchBye(msg); 01166 break; 01167 01168 default: 01169 // !kh! 01170 // should not assert here for peer sent us garbage. 01171 WarningLog (<< "Don't know what this is : " << msg); 01172 break; 01173 } 01174 } 01175 01176 01177 01178 void 01179 ClientInviteSession::dispatchEarlyWithAnswer (const SipMessage& msg) 01180 { 01181 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01182 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01183 01184 switch (toEvent(msg, offerAnswer.get())) 01185 { 01186 case On1xx: 01187 handleProvisional(msg); 01188 sendPrackIfNeeded(msg); 01189 break; 01190 case On1xxOffer: 01191 if(!isTerminated()) 01192 { 01193 transition(UAC_EarlyWithOffer); 01194 handleOffer(msg, *offerAnswer); 01195 } 01196 break; 01197 case On2xx: 01198 transition(Connected); 01199 sendAck(); 01200 handleFinalResponse(msg); 01201 onConnectedAspect(getHandle(), msg); 01202 break; 01203 01204 case On2xxAnswer: 01205 case On2xxOffer: 01206 sendAck(); 01207 sendBye(); 01208 InfoLog (<< "Failure: illegal offer/answer: " << msg.brief()); 01209 transition(Terminated); 01210 onFailureAspect(getHandle(), msg); 01211 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01212 break; 01213 01214 case OnUpdateOffer: 01215 *mLastRemoteSessionModification = msg; 01216 transition(UAC_ReceivedUpdateEarly); 01217 mCurrentEncryptionLevel = getEncryptionLevel(msg); 01218 mProposedRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 01219 handler->onOffer(getSessionHandle(), msg, *offerAnswer); 01220 break; 01221 01222 case OnUpdate: 01223 { 01224 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback? 01225 SharedPtr<SipMessage> response(new SipMessage); 01226 *mLastRemoteSessionModification = msg; 01227 mDialog.makeResponse(*response, msg, 200); 01228 send(response); 01229 break; 01230 } 01231 01232 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 01233 case OnInviteFailure: 01234 case OnGeneralFailure: 01235 case On422Invite: 01236 case On487Invite: 01237 case On491Invite: 01238 InfoLog (<< "Failure: error response: " << msg.brief()); 01239 transition(Terminated); 01240 onFailureAspect(getHandle(), msg); 01241 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01242 mDum.destroy(this); 01243 break; 01244 01245 case OnBye: 01246 dispatchBye(msg); 01247 break; 01248 01249 default: 01250 // !kh! 01251 // should not assert here for peer sent us garbage. 01252 WarningLog (<< "Don't know what this is : " << msg); 01253 break; 01254 } 01255 } 01256 01257 void 01258 ClientInviteSession::dispatchSentUpdateEarly (const SipMessage& msg) 01259 { 01260 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01261 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01262 01263 switch (toEvent(msg, offerAnswer.get())) 01264 { 01265 case On200Update: 01266 transition(UAC_EarlyWithAnswer); 01267 setCurrentLocalOfferAnswer(msg); 01268 mCurrentEncryptionLevel = getEncryptionLevel(msg); 01269 mCurrentRemoteOfferAnswer = InviteSession::makeOfferAnswer(*offerAnswer); 01270 handler->onAnswer(getSessionHandle(), msg, *offerAnswer); 01271 break; 01272 01273 case OnUpdateOffer: 01274 { 01275 SharedPtr<SipMessage> response(new SipMessage); 01276 mDialog.makeResponse(*response, msg, 491); 01277 send(response); 01278 } 01279 break; 01280 01281 case OnUpdate: 01282 { 01283 // ?slg? no offerAnswer in update - just respond immediately - do we need a callback? 01284 SharedPtr<SipMessage> response(new SipMessage); 01285 *mLastRemoteSessionModification = msg; 01286 mDialog.makeResponse(*response, msg, 200); 01287 send(response); 01288 break; 01289 } 01290 01291 case On491Update: 01292 transition(UAC_SentUpdateEarlyGlare); 01293 start491Timer(); 01294 break; 01295 01296 case On2xx: 01297 transition(SentUpdate); 01298 sendAck(); 01299 break; 01300 01301 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets 01302 // here then it's because the redirect was intentionaly 01303 // not handled and should be treated as an INVITE failure 01304 case OnInviteFailure: 01305 case OnGeneralFailure: 01306 case On422Invite: 01307 case On487Invite: 01308 InfoLog (<< "Failure: error response: " << msg.brief()); 01309 transition(Terminated); 01310 onFailureAspect(getHandle(), msg); 01311 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01312 mDum.destroy(this); 01313 break; 01314 01315 default: 01316 WarningLog (<< "Don't know what this is : " << msg); 01317 break; 01318 } 01319 } 01320 01321 void 01322 ClientInviteSession::dispatchSentUpdateEarlyGlare (const SipMessage& msg) 01323 { 01324 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01325 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01326 01327 switch (toEvent(msg, offerAnswer.get())) 01328 { 01329 case OnUpdateOffer: 01330 handler->onOfferRejected(getSessionHandle(), &msg); 01331 //will cause transition to UAC_ReceivedUpdateEarly 01332 dispatchEarlyWithAnswer(msg); 01333 break; 01334 01335 case On2xx: 01336 //transition to connected state machine 01337 transition(SentUpdateGlare); 01338 sendAck(); 01339 break; 01342 case OnRedirect: // Redirects are handled by the DialogSet - if a 3xx gets 01343 // here then it's because the redirect was intentionaly 01344 // not handled and should be treated as an INVITE failure 01345 case OnInviteFailure: 01346 case OnGeneralFailure: 01347 case On422Invite: 01348 case On487Invite: 01349 InfoLog (<< "Failure: error response: " << msg.brief()); 01350 transition(Terminated); 01351 onFailureAspect(getHandle(), msg); 01352 handler->onTerminated(getSessionHandle(), InviteSessionHandler::Error, &msg); 01353 mDum.destroy(this); 01354 break; 01355 01356 default: 01357 WarningLog (<< "Don't know what this is : " << msg); 01358 break; 01359 } 01360 } 01361 01362 void 01363 ClientInviteSession::dispatchReceivedUpdateEarly (const SipMessage& msg) 01364 { 01365 /* 01366 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01367 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01368 01369 switch (toEvent(msg, offerAnswer.get())) 01370 { 01371 default: 01372 // !kh! 01373 // should not assert here for peer sent us garbage. 01374 WarningLog (<< "Don't know what this is : " << msg); 01375 break; 01376 } 01377 */ 01378 WarningLog (<< "Ignoring message received in ReceivedUpdateEarly: " << msg); 01379 } 01380 01381 void 01382 ClientInviteSession::dispatchCancelled (const SipMessage& msg) 01383 { 01384 InviteSessionHandler* handler = mDum.mInviteSessionHandler; 01385 std::auto_ptr<Contents> offerAnswer = InviteSession::getOfferAnswer(msg); 01386 01387 switch (toEvent(msg, offerAnswer.get())) 01388 { 01389 case OnGeneralFailure: 01390 case OnCancelFailure: 01391 case On487Invite: 01392 case OnRedirect: 01393 case On422Invite: 01394 case On491Invite: 01395 case OnInviteFailure: 01396 transition(Terminated); 01397 handler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalCancel, &msg); 01398 mDum.destroy(this); 01399 break; 01400 01401 case On2xx: 01402 case On2xxOffer: 01403 case On2xxAnswer: 01404 { 01405 // this is the 2xx crossing the CANCEL case 01406 sendAck(); 01407 sendBye(); 01408 transition(Terminated); 01409 handler->onTerminated(getSessionHandle(), InviteSessionHandler::LocalCancel, &msg); 01410 mCancelledTimerSeq++; 01411 break; 01412 } 01413 01414 case OnBye: 01415 dispatchBye(msg); 01416 break; 01417 01418 default: 01419 break; 01420 } 01421 } 01422 01423 //true if 180rel should be ignored. Saves rseq as a side effect. 01424 bool 01425 ClientInviteSession::checkRseq(const SipMessage& msg) 01426 { 01427 int code = msg.isResponse() ? msg.header(h_StatusLine).statusCode() : 0; 01428 if (msg.method() == INVITE && code > 100 && code < 200) 01429 { 01430 if (msg.exists(h_RSeq)) 01431 { 01432 // store state about the provisional if reliable, so we can detect retransmissions 01433 unsigned int rseq = (unsigned int) msg.header(h_RSeq).value(); 01434 unsigned int lastRseq = (unsigned int) mRelRespInfo.rSequence(); 01435 01436 if (rseq == lastRseq) 01437 { 01438 DebugLog(<< "Discarding reliable 1xx retranmission with rseq " << rseq); 01439 return true; 01440 } 01441 else if (lastRseq != 0 && rseq > lastRseq + 1) 01442 { 01443 DebugLog(<< "Discarding out of order reliable 1xx with rseq " << rseq); 01444 return true; 01445 } 01446 mRelRespInfo.rSequence() = rseq; 01447 mRelRespInfo.cSequence() = msg.header(h_CSeq).sequence(); 01448 mRelRespInfo.method() = msg.header(h_CSeq).method(); 01449 } 01450 } 01451 return false; 01452 } 01453 01454 void 01455 ClientInviteSession::onConnectedAspect(ClientInviteSessionHandle c, const SipMessage& msg) 01456 { 01457 if (mDum.mDialogEventStateManager) 01458 { 01459 mDum.mDialogEventStateManager->onConfirmed(mDialog, getSessionHandle()); 01460 } 01461 mDum.mInviteSessionHandler->onConnected(c, msg); 01462 } 01463 01464 void 01465 ClientInviteSession::onProvisionalAspect(ClientInviteSessionHandle c, const SipMessage& msg) 01466 { 01467 if (mDum.mDialogEventStateManager) 01468 { 01469 mDum.mDialogEventStateManager->onEarly(mDialog, getSessionHandle()); 01470 } 01471 mDum.mInviteSessionHandler->onProvisional(c, msg); 01472 } 01473 01474 void 01475 ClientInviteSession::onFailureAspect(ClientInviteSessionHandle c, const SipMessage& msg) 01476 { 01477 if (mDum.mDialogEventStateManager) 01478 { 01479 InviteSessionHandler::TerminatedReason reason = InviteSessionHandler::Rejected; 01480 if (msg.isResponse()) 01481 { 01482 if (msg.header(h_StatusLine).responseCode() == 408) 01483 { 01484 reason = InviteSessionHandler::Timeout; 01485 } 01486 else if (msg.header(h_StatusLine).responseCode() / 100 == 5) 01487 { 01488 reason = InviteSessionHandler::Error; 01489 } 01490 } 01491 mDum.mDialogEventStateManager->onTerminated(mDialog, msg, reason); 01492 } 01493 mDum.mInviteSessionHandler->onFailure(c, msg); 01494 } 01495 01496 /* ==================================================================== 01497 * The Vovida Software License, Version 1.0 01498 * 01499 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 01500 * 01501 * Redistribution and use in source and binary forms, with or without 01502 * modification, are permitted provided that the following conditions 01503 * are met: 01504 * 01505 * 1. Redistributions of source code must retain the above copyright 01506 * notice, this list of conditions and the following disclaimer. 01507 * 01508 * 2. Redistributions in binary form must reproduce the above copyright 01509 * notice, this list of conditions and the following disclaimer in 01510 * the documentation and/or other materials provided with the 01511 01512 * distribution. 01513 * 01514 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 01515 * and "Vovida Open Communication Application Library (VOCAL)" must 01516 * not be used to endorse or promote products derived from this 01517 * software without prior written permission. For written 01518 * permission, please contact vocal@vovida.org. 01519 * 01520 * 4. Products derived from this software may not be called "VOCAL", nor 01521 * may "VOCAL" appear in their name, without prior written 01522 * permission of Vovida Networks, Inc. 01523 * 01524 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 01525 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 01526 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 01527 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 01528 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 01529 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 01530 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 01531 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 01532 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 01533 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 01534 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 01535 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 01536 * DAMAGE. 01537 * 01538 * ==================================================================== 01539 * 01540 * This software consists of voluntary contributions made by Vovida 01541 * Networks, Inc. and many individuals on behalf of Vovida Networks, 01542 * Inc. For more information on Vovida Networks, Inc., please see 01543 * <http://www.vovida.org/>. 01544 * 01545 */
1.7.5.1