reSIProcate/DialogUsageManager  9680
ClientInviteSession.cxx
Go to the documentation of this file.
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  */