reSIProcate/DialogUsageManager  9694
Classes | Public Member Functions | Private Types | Private Member Functions | Private Attributes | Friends
resip::Dialog Class Reference

dcm! -- kill typedef std::list<DialogId> DialogIdSet; More...

#include <Dialog.hxx>

Collaboration diagram for resip::Dialog:
Collaboration graph
[legend]

List of all members.

Classes

class  Exception

Public Member Functions

 Dialog (DialogUsageManager &dum, const SipMessage &msg, DialogSet &ds)
const DialogIdgetId () const
const NameAddrgetLocalNameAddr () const
const NameAddrgetLocalContact () const
const NameAddrgetRemoteNameAddr () const
const NameAddrgetRemoteTarget () const
const NameAddrsgetRouteSet () const
void send (SharedPtr< SipMessage > msg)
void makeRequest (SipMessage &request, MethodTypes method)
void makeResponse (SipMessage &response, const SipMessage &request, int responseCode)
std::vector
< ClientSubscriptionHandle
getClientSubscriptions ()
std::vector
< ClientSubscriptionHandle
findClientSubscriptions (const Data &event)
std::vector
< ServerSubscriptionHandle
getServerSubscriptions ()
std::vector
< ServerSubscriptionHandle
findServerSubscriptions (const Data &event)
InviteSessionHandle getInviteSession ()
void end ()
void dispatch (const SipMessage &msg)
void processNotify (const SipMessage &notify)
void redirected (const SipMessage &msg)
void onForkAccepted ()
void cancel ()
bool isDestroying ()

Private Types

enum  DialogType { Invitation, Subscription, Fake }
typedef std::map< int,
SharedPtr< SipMessage > > 
RequestMap

Private Member Functions

virtual ~Dialog ()
void possiblyDie ()
ClientSubscriptionfindMatchingClientSub (const SipMessage &msg)
ServerSubscriptionfindMatchingServerSub (const SipMessage &msg)
void addUsage (BaseUsage *usage)
ClientInviteSessionmakeClientInviteSession (const SipMessage &msg)
ClientSubscriptionmakeClientSubscription (const SipMessage &msg)
ServerInviteSessionmakeServerInviteSession (const SipMessage &msg)
ServerSubscriptionmakeServerSubscription (const SipMessage &msg)
bool matches (const SipMessage &msg)
void handleTargetRefresh (const SipMessage &msg)
void flowTerminated ()

Private Attributes

DialogUsageManagermDum
DialogSetmDialogSet
DialogId mId
std::list< ClientSubscription * > mClientSubscriptions
std::list< ServerSubscription * > mServerSubscriptions
InviteSessionmInviteSession
NetworkAssociation mNetworkAssociation
DialogType mType
NameAddrs mRouteSet
NameAddr mLocalContact
unsigned int mLocalCSeq
unsigned int mRemoteCSeq
NameAddr mRemoteTarget
NameAddr mLocalNameAddr
NameAddr mRemoteNameAddr
CallID mCallId
UInt32 mDefaultSubExpiration
RequestMap mRequests
AppDialogmAppDialog
bool mDestroying
bool mReUseDialogSet

Friends

class DialogUsage
class DialogSet
class DialogUsageManager
class DestroyUsage
class ClientSubscription
class InviteSession
class ClientInviteSession
class ServerInviteSession
class ServerSubscription
class ClientRegistration
class ServerRegistration
class ClientPublication
class ServerPublication
class ClientOutOfDialogReq
class ServerOutOfDialogReq
class AppDialog
EncodeStreamoperator<< (EncodeStream &strm, const Dialog &dialog)

Detailed Description

dcm! -- kill typedef std::list<DialogId> DialogIdSet;

Definition at line 28 of file Dialog.hxx.


Member Typedef Documentation

typedef std::map<int, SharedPtr<SipMessage> > resip::Dialog::RequestMap [private]

Definition at line 155 of file Dialog.hxx.


Member Enumeration Documentation

enum resip::Dialog::DialogType [private]
Enumerator:
Invitation 
Subscription 
Fake 

Definition at line 130 of file Dialog.hxx.

      {
         Invitation,   // INVITE dialog
         Subscription, // Created by a SUBSCRIBE / NOTIFY / REFER
         Fake          // Not really a dialog (e.g. created by a REGISTER)
      } DialogType;

Constructor & Destructor Documentation

Dialog::Dialog ( DialogUsageManager dum,
const SipMessage msg,
DialogSet ds 
)

dcm! -- event header check

Definition at line 27 of file Dialog.cxx.

References resip::DialogSet::addDialog(), DebugLog, resip::Data::empty(), resip::Data::Empty, ErrLog, resip::Uri::exists(), resip::SipMessage::exists(), Fake, resip::DialogSet::getCreator(), resip::DialogSet::getId(), resip::BaseCreator::getLastRequest(), h_RequestLine, h_StatusLine, resip::SipMessage::header(), InfoLog, Invitation, resip::isEqualNoCase(), resip::SipMessage::isExternal(), resip::SipMessage::isRequest(), resip::SipMessage::isResponse(), mDialogSet, resip::RequestLine::method(), mId, mLocalContact, mLocalCSeq, mLocalNameAddr, mNetworkAssociation, mRemoteCSeq, mRemoteNameAddr, mRemoteTarget, mRouteSet, mType, resip::DialogSet::mUserProfile, resip::ParserCategory::param(), resip::Uri::scheme(), resip::NetworkAssociation::setDum(), resip::Symbols::Sip, resip::Symbols::Sips, Subscription, resip::NameAddr::uri(), resip::RequestLine::uri(), and resip::Uri::user().

   : mDum(dum),
     mDialogSet(ds),
     mId("INVALID", "INVALID", "INVALID"),
     mClientSubscriptions(),
     mServerSubscriptions(),
     mInviteSession(0),
     mType(Fake),
     mRouteSet(),
     mLocalContact(),
     mLocalCSeq(0),
     mRemoteCSeq(0),
     mRemoteTarget(),
     mLocalNameAddr(),
     mRemoteNameAddr(),
     mCallId(msg.header(h_CallID)),
     mDefaultSubExpiration(0),
     mAppDialog(0),
     mDestroying(false),
     mReUseDialogSet(false)
{
   assert(msg.isExternal());

   assert(msg.header(h_CSeq).method() != MESSAGE);
   assert(msg.header(h_CSeq).method() != REGISTER);
   assert(msg.header(h_CSeq).method() != PUBLISH);

   mNetworkAssociation.setDum(&dum);

   if (msg.isRequest()) // UAS
   {
      const SipMessage& request = msg;

      switch (request.header(h_CSeq).method())
      {
         case INVITE:
            mType = Invitation;
            break;

         case SUBSCRIBE:
         case REFER:
         case NOTIFY:
            mType = Subscription;
            break;

         default:
            mType = Fake;
      }
      if (request.exists(h_RecordRoutes))
      {
         mRouteSet = request.header(h_RecordRoutes); 
      }

      switch (request.header(h_CSeq).method())
      {
         case INVITE:
         case SUBSCRIBE:
         case REFER:
         case NOTIFY:
            DebugLog ( << "UAS dialog ID creation, DS: " << ds.getId());
            mId = DialogId(ds.getId(), 
                           request.header(h_From).exists(p_tag) ? request.header(h_From).param(p_tag) : Data::Empty);            

            mRemoteNameAddr = request.header(h_From);
            mLocalNameAddr = request.header(h_To);
            mLocalNameAddr.param(p_tag) = mId.getLocalTag();
            if (request.exists(h_Contacts) && request.header(h_Contacts).size() == 1)
            {
               const NameAddr& contact = request.header(h_Contacts).front();
               if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
                   isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
               {
                  // Store Remote Target
                  mRemoteTarget = contact;
                  
                  // Create Local Contact
                  if(mDialogSet.mUserProfile->hasUserAgentCapabilities())
                  {
                     mLocalContact = mDialogSet.mUserProfile->getUserAgentCapabilities();
                  }
                  if(!mDialogSet.mUserProfile->isAnonymous() && mDialogSet.mUserProfile->hasPublicGruu())
                  {
                     mLocalContact.uri() = mDialogSet.mUserProfile->getPublicGruu();
                  }
                  else if(mDialogSet.mUserProfile->isAnonymous() && mDialogSet.mUserProfile->hasTempGruu())
                  {
                     mLocalContact.uri() = mDialogSet.mUserProfile->getTempGruu();
                  }
                  else
                  {
                     if (mDialogSet.mUserProfile->hasOverrideHostAndPort())
                     {
                        mLocalContact.uri() = mDialogSet.mUserProfile->getOverrideHostAndPort();
                     }
                     if(request.header(h_RequestLine).uri().user().empty())
                     {
                        mLocalContact.uri().user() = request.header(h_To).uri().user(); 
                     }
                     else
                     {
                        mLocalContact.uri().user() = request.header(h_RequestLine).uri().user(); 
                     }
                     const Data& instanceId = mDialogSet.mUserProfile->getInstanceId();
                     if (!contact.uri().exists(p_gr) && !instanceId.empty())
                     {
                        mLocalContact.param(p_Instance) = instanceId;
                     }
                  }
                  if(mDialogSet.mUserProfile->clientOutboundEnabled())
                  {
                     // Add ;ob parm to non-register requests - RFC5626 pg17
                     mLocalContact.uri().param(p_ob);
                  }
               }
               else
               {
                  InfoLog(<< "Got an INVITE or SUBSCRIBE with invalid scheme");
                  InfoLog(<< request);
                  throw Exception("Invalid scheme in request", __FILE__, __LINE__);
               }
            }
            else
            {
               InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
               InfoLog (<< request);
               throw Exception("Too many (or no contact) contacts in request", __FILE__, __LINE__);
            }
            break;
         default:
            break;
      }

      mRemoteCSeq = request.header(h_CSeq).sequence();
      mLocalCSeq = 1;

      DebugLog ( << "************** Created Dialog as UAS **************" );
      DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
      DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
      DebugLog ( << "mLocalContact: " << mLocalContact );
      DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
   }
   else if (msg.isResponse())
   {
      mId = DialogId(msg);
      const SipMessage& response = msg;
      mRemoteNameAddr = response.header(h_To);
      mLocalNameAddr = response.header(h_From);

      switch (msg.header(h_CSeq).method())
      {
         case INVITE:
            mType = Invitation;
            break;

         case SUBSCRIBE:
         case REFER:
            mType = Subscription;
            break;

         default:
            mType = Fake;
      }

      if (response.exists(h_RecordRoutes))
      {
         mRouteSet = response.header(h_RecordRoutes).reverse();
      }

      switch (response.header(h_CSeq).method())
      {
         case INVITE:
         case SUBSCRIBE:
         case REFER:
            if (response.header(h_StatusLine).statusCode() > 100 &&
                response.header(h_StatusLine).statusCode() < 300)
            {

               if  (response.exists(h_Contacts) && response.header(h_Contacts).size() == 1)
               {
                  const NameAddr& contact = response.header(h_Contacts).front();
                  if (isEqualNoCase(contact.uri().scheme(), Symbols::Sips) ||
                     isEqualNoCase(contact.uri().scheme(), Symbols::Sip))
                  {
                     BaseCreator* creator = mDialogSet.getCreator();                                     

                     if( 0 == creator )
                     {
                        ErrLog(<< "BaseCreator is null for DialogSet");
                        ErrLog(<< response);
                        throw Exception("BaseCreator is null for DialogSet", __FILE__, __LINE__);
                     }

                     SharedPtr<SipMessage> lastRequest(creator->getLastRequest());

                     if( 0 == lastRequest.get() ||
                        !lastRequest->exists(h_Contacts) ||
                        lastRequest->header(h_Contacts).empty())
                     {
                        InfoLog(<< "lastRequest does not contain a valid contact");                                             
                        InfoLog(<< response);
                        throw Exception("lastRequest does not contain a valid contact.", __FILE__, __LINE__);
                     }
                     mLocalContact = creator->getLastRequest()->header(h_Contacts).front();
                     mRemoteTarget = contact;
                  }
                  else
                  {
                     InfoLog (<< "Got an INVITE or SUBSCRIBE with invalid scheme");
                     DebugLog (<< response);
                     throw Exception("Bad scheme in contact in response", __FILE__, __LINE__);
                  }
               }
               else
               {
                  InfoLog (<< "Got an INVITE or SUBSCRIBE that doesn't have exactly one contact");
                  DebugLog (<< response);
                  throw Exception("Too many contacts (or no contact) in response", __FILE__, __LINE__);
               }
               break;
               default:
                  break;
            }
      }

      mLocalCSeq = response.header(h_CSeq).sequence();
      mRemoteCSeq = 0;
      DebugLog ( << "************** Created Dialog as UAC **************" );
      DebugLog ( << "mRemoteNameAddr: " << mRemoteNameAddr );
      DebugLog ( << "mLocalNameAddr: " << mLocalNameAddr );
      DebugLog ( << "mLocalContact: " << mLocalContact );
      DebugLog ( << "mRemoteTarget: " << mRemoteTarget );
   }
   mDialogSet.addDialog(this);
   DebugLog ( <<"Dialog::Dialog " << mId);
}

Here is the call graph for this function:

Dialog::~Dialog ( ) [private, virtual]

Definition at line 264 of file Dialog.cxx.

References DebugLog, getId(), mAppDialog, mClientSubscriptions, mDestroying, resip::DialogSet::mDialogs, mDialogSet, mInviteSession, mReUseDialogSet, mServerSubscriptions, and resip::DialogSet::possiblyDie().

{
   DebugLog ( <<"Dialog::~Dialog() ");

   mDestroying = true;

   while (!mClientSubscriptions.empty())
   {
      delete *mClientSubscriptions.begin();
   }

   while (!mServerSubscriptions.empty())
   {
      delete *mServerSubscriptions.begin();
   }

   delete mInviteSession;
   mDialogSet.mDialogs.erase(this->getId());
   delete mAppDialog;
   if(!mReUseDialogSet)
   {
      mDialogSet.possiblyDie();
   }
}

Here is the call graph for this function:


Member Function Documentation

void resip::Dialog::addUsage ( BaseUsage usage) [private]
void Dialog::cancel ( )

Definition at line 326 of file Dialog.cxx.

References resip::ClientInviteSession::cancel(), Invitation, mInviteSession, and mType.

{
   assert(mType == Invitation);
   ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
   assert (uac);
   uac->cancel();
}

Here is the call graph for this function:

void Dialog::dispatch ( const SipMessage msg)

dys! the OR condition below is not draft compliant.

dcm! -- can't subscribe in an existing Dialog, this is all

dcm! -- ick, write guard

Definition at line 388 of file Dialog.cxx.

References resip::Message::brief(), resip::DialogUsageManager::checkEventPackage(), resip::ParserContainerBase::clear(), client, DebugLog, resip::Helper::determineFailureMessageEffect(), resip::ClientSubscription::dialogDestroyed(), resip::ServerSubscription::dialogDestroyed(), resip::InviteSession::dialogDestroyed(), resip::Helper::DialogTermination, resip::ServerSubscription::dispatch(), resip::ClientSubscription::dispatch(), resip::InviteSession::dispatch(), ErrLog, resip::SipMessage::exists(), findMatchingClientSub(), findMatchingServerSub(), resip::DialogUsageManager::getClientSubscriptionHandler(), resip::DialogSet::getCreator(), resip::ServerSubscription::getHandle(), resip::ClientSubscription::getHandle(), resip::BaseCreator::getLastRequest(), resip::InviteSession::getSessionHandle(), h_RequestLine, h_StatusLine, handleTargetRefresh(), resip::SipMessage::header(), InfoLog, resip::SipMessage::isExternal(), resip::SipMessage::isRequest(), resip::SipMessage::isResponse(), resip::LazyParser::isWellFormed(), makeClientInviteSession(), makeClientSubscription(), makeResponse(), makeServerInviteSession(), makeServerSubscription(), resip::DialogUsageManager::mClientAuthManager, mClientSubscriptions, mDefaultSubExpiration, mDestroying, mDialogSet, mDum, resip::RequestLine::method(), mInviteSession, resip::DialogUsageManager::mInviteSessionHandler, mLocalCSeq, mNetworkAssociation, resip::InviteSession::mReferSub, mRequests, mRouteSet, mServerSubscriptions, resip::DialogSet::mUserProfile, resip::InviteSession::nitComplete(), resip::Handle< ClientSubscription >::NotValid(), resip::InviteSessionHandler::onRefer(), resip::InviteSessionHandler::onReferAccepted(), resip::InviteSessionHandler::onReferRejected(), possiblyDie(), resip::InviteSession::referNoSub(), resip::Symbols::SCTP, send(), resip::DialogUsageManager::sendResponse(), server, resip::Symbols::TCP, resip::Symbols::TLS, and resip::NetworkAssociation::update().

Referenced by resip::DialogSet::dispatch().

{
   // !jf! Should be checking for messages with out of order CSeq and rejecting

   DebugLog ( << "Dialog::dispatch: " << msg.brief());

   if(msg.isExternal())
   {
      const Data& receivedTransport = msg.header(h_Vias).front().transport();
      int keepAliveTime = 0;
      if(receivedTransport == Symbols::TCP ||
         receivedTransport == Symbols::TLS ||
         receivedTransport == Symbols::SCTP)
      {
         keepAliveTime = mDialogSet.mUserProfile->getKeepAliveTimeForStream();
      }
      else
      {
         keepAliveTime = mDialogSet.mUserProfile->getKeepAliveTimeForDatagram();
      }

      if(keepAliveTime > 0)
      {
         mNetworkAssociation.update(msg, keepAliveTime, false /* targetSupportsOutbound */); // target supports outbound is detected in registration responses only
      }
   }
   
   handleTargetRefresh(msg);
   if (msg.isRequest())
   {
      const SipMessage& request = msg;
      switch (request.header(h_CSeq).method())
      {
         case INVITE:  // new INVITE
            if (mInviteSession == 0)
            {
               DebugLog ( << "Dialog::dispatch  --  Created new server invite session" << msg.brief());
               mInviteSession = makeServerInviteSession(request);
            }
            mInviteSession->dispatch(request);
            break;
            //refactor, send bad request for BYE, INFO, CANCEL?
         case BYE:
            if (mInviteSession == 0)
            {
               InfoLog ( << "Spurious BYE" );
               return;
            }
            else
            {
               mInviteSession->dispatch(request);
            }
            break;
         case UPDATE:
            if (mInviteSession == 0)
            {
               InfoLog ( << "Spurious UPDATE" );
               return;
            }
            else
            {
               mInviteSession->dispatch(request);
            }
            break;
         case INFO:
            if (mInviteSession == 0)
            {
               InfoLog ( << "Spurious INFO" );
               return;
            }
            else
            {
               mInviteSession->dispatch(request);
            }
            break;
         case MESSAGE:
            if (mInviteSession == 0)
            {
               InfoLog ( << "Spurious MESSAGE" );
               return;
            }
            else
            {
               mInviteSession->dispatch(request);
            }
            break;
         case ACK:
         case CANCEL:
            if (mInviteSession == 0)
            {
               InfoLog (<< "Drop stray ACK or CANCEL in dialog on the floor");
               DebugLog (<< request);
            }
            else
            {
               mInviteSession->dispatch(request);
            }
            break;
         case SUBSCRIBE:
         {
            ServerSubscription* server = findMatchingServerSub(request);
            if (server)
            {
               server->dispatch(request);
            }
            else
            {
               if (request.exists(h_Event) && request.header(h_Event).value() == "refer")
               {
                  InfoLog (<< "Received a subscribe to a non-existent refer subscription: " << request.brief());
                  SipMessage failure;
                  makeResponse(failure, request, 403);
                  mDum.sendResponse(failure);
                  return;
               }
               else
               {
                  if (mDum.checkEventPackage(request))
                  {
                     server = makeServerSubscription(request);
                     mServerSubscriptions.push_back(server);
                     server->dispatch(request);
                  }
               }
            }
         }
         break;
         case REFER:
         {
//             if (mInviteSession == 0)
//             {
//                InfoLog (<< "Received an in dialog refer in a non-invite dialog: " << request.brief());
//                SipMessage failure;
//                makeResponse(failure, request, 603);
//                mDum.sendResponse(failure);
//                return;
//             }
//             else 

            if  (!request.exists(h_ReferTo))
            {
               InfoLog (<< "Received refer w/out a Refer-To: " << request.brief());
               SipMessage failure;
               makeResponse(failure, request, 400);
               mDum.sendResponse(failure);
               return;
            }
            else
            {
               if ((request.exists(h_ReferSub) && 
                     request.header(h_ReferSub).isWellFormed() &&
                     request.header(h_ReferSub).value()=="false") ||
                     (request.exists(h_Requires) &&
                     request.header(h_Requires).find(Token("norefersub"))))
               {
                  assert(mInviteSession);
                  mInviteSession->referNoSub(msg);
               }
               else
               {
                  ServerSubscription* server = findMatchingServerSub(request);
                  ServerSubscriptionHandle serverHandle;
                  if (server)
                  {
                     serverHandle = server->getHandle();
                     server->dispatch(request);
                  }
                  else
                  {
                     server = makeServerSubscription(request);
                     mServerSubscriptions.push_back(server);
                     serverHandle = server->getHandle();
                     server->dispatch(request);
                  }

                  if (mInviteSession)
                  {
                     mDum.mInviteSessionHandler->onRefer(mInviteSession->getSessionHandle(), serverHandle, msg);
                  }
                  
               }
            }
         }
         break;
         case NOTIFY:
            {
               ClientSubscription* client = findMatchingClientSub(request);
               if (client)
               {
                  client->dispatch(request);
               }
               else
               {
                  BaseCreator* creator = mDialogSet.getCreator();
                  if (creator && (creator->getLastRequest()->header(h_RequestLine).method() == SUBSCRIBE ||
                     creator->getLastRequest()->header(h_RequestLine).method() == REFER))  
                  {
                     DebugLog (<< "Making subscription (from creator) request: " << *creator->getLastRequest());
                     ClientSubscription* sub = makeClientSubscription(*creator->getLastRequest());
                     mClientSubscriptions.push_back(sub);
                     sub->dispatch(request);
                  }
                  else
                  {
                     if (mInviteSession != 0 && (!msg.exists(h_Event) || msg.header(h_Event).value() == "refer") && 
                         mDum.getClientSubscriptionHandler("refer")!=0) 
                     {
                        DebugLog (<< "Making subscription from NOTIFY: " << msg);
                        ClientSubscription* sub = makeClientSubscription(msg);
                        mClientSubscriptions.push_back(sub);
                        ClientSubscriptionHandle client = sub->getHandle();
                        mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), client, msg);                                 
                        sub->dispatch(request);
                     }
                     else
                     {
                        SharedPtr<SipMessage> response(new SipMessage);
                        makeResponse(*response, msg, 406);
                        send(response);
                     }
                  }
               }
            }
            break;
        default:
           assert(0);
           return;
      }
   }
   else if (msg.isResponse())
   {
      // !jf! There is a substantial change in how this works in teltel-branch
      // from how it worked in main branch pre merge.
      // If the response doesn't match a cseq for a request I've sent, ignore
      // the response
      {//scope 'r' as it is invalidated below
         RequestMap::iterator r = mRequests.find(msg.header(h_CSeq).sequence());
         if (r != mRequests.end())
         {         
            bool handledByAuth = false;
            if (mDum.mClientAuthManager.get() && 
                mDum.mClientAuthManager->handle(*mDialogSet.mUserProfile, *r->second, msg))
            {
               InfoLog( << "about to re-send request with digest credentials" << r->second->brief());

               assert (r->second->isRequest());

               mLocalCSeq++;
               send(r->second);
               handledByAuth = true;
            }
            mRequests.erase(r);
            if (handledByAuth) return;
         }
      }
      
      const SipMessage& response = msg;
      int code = response.header(h_StatusLine).statusCode();
      // If this is a 200 response to the initial request, then store the routeset (if present)
      BaseCreator* creator = mDialogSet.getCreator();
      if (creator && (creator->getLastRequest()->header(h_CSeq) == response.header(h_CSeq)) && code >=200 && code < 300)
      {
         if (response.exists(h_RecordRoutes))
         {
            mRouteSet = response.header(h_RecordRoutes).reverse();
         }
         else
         {
            // Ensure that if the route-set in the 200 is empty, then we overwrite any existing route-sets
            mRouteSet.clear();
         }
      }

      // !jf! should this only be for 2xx responses? !jf! Propose no as an
      // answer !dcm! what is he on?
      switch (response.header(h_CSeq).method())
      {
         case INVITE:
            if (mInviteSession == 0)
            {
               DebugLog ( << "Dialog::dispatch  --  Created new client invite session" << msg.brief());

               mInviteSession = makeClientInviteSession(response);
               if (mInviteSession)
               {
                  mInviteSession->dispatch(response);
               }
               else
               {
                  ErrLog( << "Dialog::dispatch  --  Unable to create invite session from response" << msg.brief());
               }
            }
            else
            {
               mInviteSession->dispatch(response);
            }
            break;
         case BYE:
         case ACK:
         case CANCEL:
         case INFO:
         case MESSAGE:
         case UPDATE:
            if (mInviteSession)
            {
               mInviteSession->dispatch(response);
            }
            // else drop on the floor
            break;       

                 case REFER:
            if(mInviteSession)
            {
               if (code >= 300)
               {
                  mDum.mInviteSessionHandler->onReferRejected(mInviteSession->getSessionHandle(), msg);
               }
               else
               {
                  if (!mInviteSession->mReferSub && 
                      ((msg.exists(h_ReferSub) && msg.header(h_ReferSub).value()=="false") || 
                       !msg.exists(h_ReferSub)))
                  {
                     DebugLog(<< "refer accepted with norefersub");
                     mDum.mInviteSessionHandler->onReferAccepted(mInviteSession->getSessionHandle(), ClientSubscriptionHandle::NotValid(), msg);
                  }
                  // else no need for action - first Notify will cause onReferAccepted to be called
               }
               mInviteSession->nitComplete();
               break;
            }
            // fall through, out of dialog refer was sent.

         case SUBSCRIBE:
         {
            int code = response.header(h_StatusLine).statusCode();
            ClientSubscription* client = findMatchingClientSub(response);
            if (client)
            {
               client->dispatch(response);
            }
            else if (code < 300)
            {
               /*
                  we're capturing the  value from the expires header off
                  the 2xx because the ClientSubscription is only created
                  after receiving the NOTIFY that comes (usually) after
                  this 2xx.  We really should be creating the
                  ClientSubscription at either the 2xx or the NOTIFY
                  whichever arrives first. .mjf.
                  Note: we're capturing a duration here (not the
                  absolute time because all the inputs to
                  ClientSubscription desling with the expiration are expecting
                  duration type values from the headers. .mjf.
                */
               if(response.exists(h_Expires))
               {
                  mDefaultSubExpiration = response.header(h_Expires).value();
               }
               else
               {
                  //?dcm? defaults to 3600 in ClientSubscription if no expires value
                  //is provided anywhere...should we assume the value from the
                  //sub in the basecreator if it exists?
                  mDefaultSubExpiration = 0;
               }               
               return;
            }
            else
            {
               //a bit of a hack; currently, spurious failure messages may cause callbacks
               BaseCreator* creator = mDialogSet.getCreator();
               if (!creator || !creator->getLastRequest()->exists(h_Event))
               {
                  return;
               }
               else
               {
                  ClientSubscriptionHandler* handler =
                     mDum.getClientSubscriptionHandler(creator->getLastRequest()->header(h_Event).value());
                  if (handler)
                  {
                     ClientSubscription* sub = makeClientSubscription(*creator->getLastRequest());
                     mClientSubscriptions.push_back(sub);
                     sub->dispatch(response);
                  }
               }
            }

         }
         break;
         case NOTIFY:
         {
            //2xx responses are treated as retransmission quenchers(handled by
            //the stack). Failures are dispatched to all ServerSubsscriptions,
            //which may not be correct.

            int code = msg.header(h_StatusLine).statusCode();
            if (code >= 300)
            {
               mDestroying = true;
               for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
                    it != mServerSubscriptions.end(); )
               {
                  ServerSubscription* s = *it;
                  it++;
                  s->dispatch(msg);
               }
               mDestroying = false;
               possiblyDie();
            }
//             ServerSubscription* server = findMatchingServerSub(response);
//             if (server)
//             {
//                server->dispatch(response);
//             }
         }
         break;
         default:
            assert(0);
            return;
      }

#if 0     // merged from head back to teltel-branch
      if (msg.header(h_StatusLine).statusCode() >= 400
          && Helper::determineFailureMessageEffect(msg) == Helper::DialogTermination)
      {
         //kill all usages
         mDestroying = true;

         for (list<ServerSubscription*>::iterator it = mServerSubscriptions.begin();
              it != mServerSubscriptions.end(); )
         {
            ServerSubscription* s = *it;
            it++;
            s->dialogDestroyed(msg);
         }

         for (list<ClientSubscription*>::iterator it = mClientSubscriptions.begin();
              it != mClientSubscriptions.end(); )
         {
            ClientSubscription* s = *it;
            it++;
            s->dialogDestroyed(msg);
         }
         if (mInviteSession)
         {
            mInviteSession->dialogDestroyed(msg);
         }
         mDestroying = false;
         possiblyDie(); //should aways result in destruction of this
         return;
      }
#endif
   }
}

Here is the call graph for this function:

void Dialog::end ( )

Definition at line 335 of file Dialog.cxx.

References resip::ClientSubscription::end(), resip::ServerSubscription::end(), resip::InviteSession::end(), mClientSubscriptions, mInviteSession, and mServerSubscriptions.

{
   if (mInviteSession)
   {
      mInviteSession->end();
   }

   // End Subscriptions
   // !jrm! WARN ClientSubscription and ServerSubscription have access to this dialog and will remove themselves
   // from the m<client|server>Subscriptions collections in the call to end().
   for (list<ClientSubscription*>::iterator it(mClientSubscriptions.begin());
        it != mClientSubscriptions.end();)
   {
           ClientSubscription* c = *it;
       it++;       
           c->end();
   }

   for (list<ServerSubscription*>::iterator it2(mServerSubscriptions.begin());
        it2 != mServerSubscriptions.end();)
   {
           ServerSubscription* s = *it2;
       it2++;       
           s->end();
   }
}

Here is the call graph for this function:

std::vector< ClientSubscriptionHandle > Dialog::findClientSubscriptions ( const Data event)

Definition at line 890 of file Dialog.cxx.

References mClientSubscriptions.

Referenced by resip::AppDialog::findClientSubscriptions().

{
   std::vector<ClientSubscriptionHandle> handles;

   for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
        i != mClientSubscriptions.end(); ++i)
   {
      if ( (*i)->getEventType() == event)
      {
         handles.push_back((*i)->getHandle());
      }
   }
   return handles;
}
ClientSubscription * Dialog::findMatchingClientSub ( const SipMessage msg) [private]

Definition at line 863 of file Dialog.cxx.

References mClientSubscriptions.

Referenced by dispatch().

{
   for (std::list<ClientSubscription*>::iterator i=mClientSubscriptions.begin();
        i != mClientSubscriptions.end(); ++i)
   {
      if ((*i)->matches(msg))
      {
         return *i;
      }
   }
   return 0;
}
ServerSubscription * Dialog::findMatchingServerSub ( const SipMessage msg) [private]

Definition at line 849 of file Dialog.cxx.

References mServerSubscriptions.

Referenced by dispatch().

{
   for (std::list<ServerSubscription*>::iterator i=mServerSubscriptions.begin();
        i != mServerSubscriptions.end(); ++i)
   {
      if ((*i)->matches(msg))
      {
         return *i;
      }
   }
   return 0;
}
std::vector< ServerSubscriptionHandle > Dialog::findServerSubscriptions ( const Data event)

Definition at line 906 of file Dialog.cxx.

References mServerSubscriptions.

Referenced by resip::AppDialog::findServerSubscriptions().

{
   std::vector<ServerSubscriptionHandle> handles;

   for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
        i != mServerSubscriptions.end(); ++i)
   {
      if ( (*i)->getEventType() == event)
      {
         handles.push_back((*i)->getHandle());
      }
   }
   return handles;
}
void Dialog::flowTerminated ( ) [private]

Definition at line 1183 of file Dialog.cxx.

References resip::NetworkAssociation::clear(), resip::InviteSession::flowTerminated(), mClientSubscriptions, mInviteSession, mNetworkAssociation, and mServerSubscriptions.

{
   // Clear the network association
   mNetworkAssociation.clear();
   
   // notify server subscirption dialogs
   std::list<ServerSubscription*> tempServerList = mServerSubscriptions;  // Create copy since subscription can be deleted
   for (std::list<ServerSubscription*>::iterator is=tempServerList.begin();
        is != tempServerList.end(); ++is)
   {
      (*is)->flowTerminated();
   }

   // notify client subscription dialogs
   std::list<ClientSubscription*> tempClientList = mClientSubscriptions;  // Create copy since subscription can be deleted
   for (std::list<ClientSubscription*>::iterator ic=tempClientList.begin();
        ic != tempClientList.end(); ++ic)
   {
      (*ic)->flowTerminated();
   }

   // notify invite session dialog
   if (mInviteSession)
   {
      mInviteSession->flowTerminated();
   }
}

Here is the call graph for this function:

std::vector< ClientSubscriptionHandle > Dialog::getClientSubscriptions ( )

Definition at line 922 of file Dialog.cxx.

References mClientSubscriptions.

Referenced by resip::AppDialog::getClientSubscriptions().

{
   std::vector<ClientSubscriptionHandle> handles;

   for (std::list<ClientSubscription*>::const_iterator i = mClientSubscriptions.begin();
        i != mClientSubscriptions.end(); ++i)
   {
      handles.push_back((*i)->getHandle());
   }

   return handles;
}
const DialogId & Dialog::getId ( ) const
InviteSessionHandle Dialog::getInviteSession ( )
const NameAddr & Dialog::getLocalContact ( ) const
const NameAddr & Dialog::getLocalNameAddr ( ) const

Definition at line 296 of file Dialog.cxx.

References mLocalNameAddr.

Referenced by resip::DialogEventStateManager::onTryingUas().

{
   return mLocalNameAddr;
}
const NameAddr & Dialog::getRemoteNameAddr ( ) const
const NameAddr & Dialog::getRemoteTarget ( ) const
const NameAddrs & Dialog::getRouteSet ( ) const
std::vector< ServerSubscriptionHandle > Dialog::getServerSubscriptions ( )

Definition at line 936 of file Dialog.cxx.

References mServerSubscriptions.

Referenced by resip::AppDialog::getServerSubscriptions().

{
   std::vector<ServerSubscriptionHandle> handles;

   for (std::list<ServerSubscription*>::const_iterator i = mServerSubscriptions.begin();
        i != mServerSubscriptions.end(); ++i)
   {
      handles.push_back((*i)->getHandle());
   }

   return handles;
}
void Dialog::handleTargetRefresh ( const SipMessage msg) [private]

Definition at line 363 of file Dialog.cxx.

References resip::SipMessage::exists(), h_StatusLine, resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::SipMessage::isResponse(), resip::RequestLine::method(), and mRemoteTarget.

Referenced by dispatch().

{
   switch(msg.header(h_CSeq).method())
   {
      case INVITE:
      case UPDATE:
         if (msg.isRequest() || (msg.isResponse() && msg.header(h_StatusLine).statusCode()/100 == 2))
         {
            //?dcm? modify local target; 12.2.2 of 3261 implies that the remote
            //target is immediately modified.  Should we wait until a 2xx class
            //reponse is sent to a re-invite(easy when all send requests go
            //through Dialog)
            if (msg.exists(h_Contacts))
            {
               //.dcm. replace or check then replace
               mRemoteTarget = msg.header(h_Contacts).front();
            }
         }
         break;
      default:
         return;
   }
}

Here is the call graph for this function:

bool resip::Dialog::isDestroying ( ) [inline]

Definition at line 79 of file Dialog.hxx.

References mDestroying.

Referenced by resip::DialogSet::dispatch().

{ return mDestroying; };
ClientInviteSession * Dialog::makeClientInviteSession ( const SipMessage msg) [private]

Definition at line 1107 of file Dialog.cxx.

References ClientInviteSession, resip::DialogSet::getCreator(), resip::InviteSessionCreator::getEncryptionLevel(), resip::InviteSessionCreator::getInitialOffer(), resip::BaseCreator::getLastRequest(), resip::InviteSessionCreator::getServerSubscription(), mDialogSet, and mDum.

Referenced by dispatch().

{
   InviteSessionCreator* creator = dynamic_cast<InviteSessionCreator*>(mDialogSet.getCreator());
   if (!creator)
   {
      assert(0); // !jf! this maybe can assert by evil UAS
      return 0;
   }
   //return mDum.createAppClientInviteSession(*this, *creator);
   return new ClientInviteSession(mDum, *this, creator->getLastRequest(),
                                  creator->getInitialOffer(), creator->getEncryptionLevel(), creator->getServerSubscription());
}

Here is the call graph for this function:

ClientSubscription * Dialog::makeClientSubscription ( const SipMessage msg) [private]

Definition at line 1123 of file Dialog.cxx.

References ClientSubscription, mDefaultSubExpiration, and mDum.

Referenced by dispatch().

{
   return new ClientSubscription(mDum, *this, request, mDefaultSubExpiration);
}
void Dialog::makeRequest ( SipMessage request,
MethodTypes  method 
)

dcm! -- all of this is rather messy

Definition at line 969 of file Dialog.cxx.

References DebugLog, resip::SipMessage::exists(), resip::DialogUsageManager::getMasterProfile(), h_AllowEvents, h_CallId, h_RequestLine, resip::SipMessage::header(), resip::Symbols::id, mCallId, mDialogSet, mDum, resip::RequestLine::method(), mLocalContact, mLocalCSeq, mLocalNameAddr, mRemoteNameAddr, mRemoteTarget, mRouteSet, resip::DialogSet::mUserProfile, resip::ParserCategory::param(), resip::SipMessage::remove(), resip::NameAddr::uri(), and resip::RequestLine::uri().

Referenced by resip::ClientSubscription::ClientSubscription(), resip::DialogSet::dispatch(), resip::ClientInviteSession::dispatch(), resip::InviteSession::dispatch(), resip::ClientInviteSession::dispatchQueuedUpdate(), resip::ClientSubscription::end(), resip::InviteSession::info(), resip::ServerSubscription::makeNotify(), resip::InviteSession::message(), resip::ClientInviteSession::provideOffer(), resip::InviteSession::provideOffer(), resip::InviteSession::refer(), resip::InviteSession::requestOffer(), resip::ClientSubscription::requestRefresh(), resip::InviteSession::sendAck(), resip::InviteSession::sendBye(), resip::ClientInviteSession::sendPrack(), resip::ClientInviteSession::sendPrackIfNeeded(), resip::ServerInviteSession::sendUpdate(), and resip::InviteSession::sessionRefresh().

{
   RequestLine rLine(method);

   rLine.uri() = mRemoteTarget.uri();

   request.header(h_RequestLine) = rLine;
   request.header(h_To) = mRemoteNameAddr;
//   request.header(h_To).param(p_tag) = mId.getRemoteTag();
   request.header(h_From) = mLocalNameAddr;
//   request.header(h_From).param(p_tag) = mId.getLocalTag();

   request.header(h_CallId) = mCallId;

   request.remove(h_RecordRoutes);  
   request.remove(h_Replaces);

   request.remove(h_Contacts);
   request.header(h_Contacts).push_front(mLocalContact);

   request.header(h_CSeq).method() = method;
   request.header(h_MaxForwards).value() = 70;

   //must keep old via for cancel
   if (method != CANCEL)
   {
      request.header(h_Routes) = mRouteSet;
      request.remove(h_Vias);
      Via via;
      via.param(p_branch); // will create the branch
      request.header(h_Vias).push_front(via);
   }
   else
   {
      assert(request.exists(h_Vias));
   }

   //don't increment CSeq for ACK or CANCEL
   if (method != ACK && method != CANCEL)
   {
      request.header(h_CSeq).sequence() = ++mLocalCSeq;
   }
   else
   {
      // ACK and cancel have a minimal header set
      request.remove(h_Accepts);
      request.remove(h_AcceptEncodings);
      request.remove(h_AcceptLanguages);
      request.remove(h_Allows);
      request.remove(h_Requires);
      request.remove(h_ProxyRequires);
      request.remove(h_Supporteds);
      // request.header(h_CSeq).sequence() = ?;  // Caller should provide original request, or modify CSeq to proper value after calling this method
   }

   // If method is INVITE then advertise required headers
   if(method == INVITE || method == UPDATE)
   {
      if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::Allow)) request.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
      if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AcceptEncoding)) request.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
      if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AcceptLanguage)) request.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
      if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AllowEvents)) request.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
      if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::Supported)) request.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
   }

   if (mDialogSet.mUserProfile->isAnonymous())
   {
      request.header(h_Privacys).push_back(PrivacyCategory(Symbols::id));
   }

   DebugLog ( << "Dialog::makeRequest: " << std::endl << std::endl << request );
}

Here is the call graph for this function:

void Dialog::makeResponse ( SipMessage response,
const SipMessage request,
int  responseCode 
)

Definition at line 1044 of file Dialog.cxx.

References DebugLog, resip::DialogId::getLocalTag(), resip::DialogUsageManager::getMasterProfile(), resip::RequestLine::getMethod(), h_AllowEvents, h_RequestLine, resip::SipMessage::header(), resip::SipMessage::isRequest(), mDialogSet, mDum, mId, mLocalContact, resip::DialogSet::mUserProfile, and resip::SipMessage::remove().

Referenced by resip::ServerSubscription::accept(), resip::ServerInviteSession::accept(), resip::InviteSession::acceptReferNoSub(), resip::ClientSubscription::acceptUpdate(), resip::ServerSubscription::dispatch(), resip::ClientInviteSession::dispatch(), dispatch(), resip::ServerInviteSession::dispatchAccepted(), resip::ServerInviteSession::dispatchAcceptedWaitingAnswer(), resip::ServerInviteSession::dispatchBye(), resip::InviteSession::dispatchBye(), resip::ServerInviteSession::dispatchCancel(), resip::InviteSession::dispatchCancel(), resip::InviteSession::dispatchConnected(), resip::ClientInviteSession::dispatchEarly(), resip::ClientInviteSession::dispatchEarlyWithAnswer(), resip::ClientInviteSession::dispatchEarlyWithOffer(), resip::InviteSession::dispatchInfo(), resip::InviteSession::dispatchMessage(), resip::InviteSession::dispatchPrack(), resip::InviteSession::dispatchReceivedReinviteSentOffer(), resip::InviteSession::dispatchReceivedUpdateOrReinvite(), resip::InviteSession::dispatchSentReinvite(), resip::InviteSession::dispatchSentReinviteNoOffer(), resip::InviteSession::dispatchSentUpdate(), resip::ClientInviteSession::dispatchSentUpdateEarly(), resip::InviteSession::dispatchTerminated(), resip::InviteSession::dispatchUnhandledInvite(), resip::ServerInviteSession::dispatchUnknown(), resip::ServerInviteSession::dispatchWaitingToOffer(), resip::ServerInviteSession::dispatchWaitingToRequestOffer(), resip::InviteSession::dispatchWaitingToTerminate(), resip::InviteSession::end(), resip::ClientSubscription::processNextNotify(), resip::ClientInviteSession::provideAnswer(), resip::InviteSession::provideAnswer(), resip::InviteSession::provideOffer(), resip::ServerInviteSession::redirect(), resip::ServerSubscription::reject(), resip::ClientInviteSession::reject(), resip::ServerInviteSession::reject(), resip::InviteSession::reject(), resip::InviteSession::rejectReferNoSub(), resip::ClientSubscription::rejectUpdate(), resip::ServerInviteSession::sendAccept(), and resip::ServerInviteSession::sendProvisional().

{
   assert( code >= 100 );
   response.remove(h_Contacts);
   if (code < 300 && code > 100)
   {
      assert(request.isRequest());
      assert(request.header(h_RequestLine).getMethod() == INVITE ||
             request.header(h_RequestLine).getMethod() == SUBSCRIBE ||
             request.header(h_RequestLine).getMethod() == BYE ||
             request.header(h_RequestLine).getMethod() == CANCEL ||
             request.header(h_RequestLine).getMethod() == REFER ||
             request.header(h_RequestLine).getMethod() == MESSAGE ||
             request.header(h_RequestLine).getMethod() == NOTIFY ||
             request.header(h_RequestLine).getMethod() == INFO ||
             request.header(h_RequestLine).getMethod() == OPTIONS ||
             request.header(h_RequestLine).getMethod() == UPDATE
             );

//      assert (request.header(h_RequestLine).getMethod() == CANCEL ||  // Contact header is not required for Requests that do not form a dialog
//                    request.header(h_RequestLine).getMethod() == BYE ||
//                    request.header(h_Contacts).size() == 1);
      Helper::makeResponse(response, request, code, mLocalContact);
      response.header(h_To).param(p_tag) = mId.getLocalTag();

      if((request.header(h_RequestLine).getMethod() == INVITE ||
          request.header(h_RequestLine).getMethod() == UPDATE)
         && code >= 200 && code < 300)
      {
         // Check if we should add our capabilites to the invite success response
         if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::Allow)) 
         {
            response.header(h_Allows) = mDum.getMasterProfile()->getAllowedMethods();
         }
         if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AcceptEncoding)) 
         {
            response.header(h_AcceptEncodings) = mDum.getMasterProfile()->getSupportedEncodings();
         }
         if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AcceptLanguage)) 
         {
            response.header(h_AcceptLanguages) = mDum.getMasterProfile()->getSupportedLanguages();
         }
         if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::AllowEvents)) 
         {
            response.header(h_AllowEvents) = mDum.getMasterProfile()->getAllowedEvents();
         }
         if(mDialogSet.mUserProfile->isAdvertisedCapability(Headers::Supported)) 
         {
            response.header(h_Supporteds) = mDum.getMasterProfile()->getSupportedOptionTags();
         }
      }
   }
   else
   {
      Helper::makeResponse(response, request, code);
      response.header(h_To).param(p_tag) = mId.getLocalTag();
   }

   DebugLog ( << "Dialog::makeResponse: " << std::endl << std::endl << response);
}

Here is the call graph for this function:

ServerInviteSession * Dialog::makeServerInviteSession ( const SipMessage msg) [private]

Definition at line 1130 of file Dialog.cxx.

References mDum, and ServerInviteSession.

Referenced by dispatch().

{
   return new ServerInviteSession(mDum, *this, request);
}
ServerSubscription * Dialog::makeServerSubscription ( const SipMessage msg) [private]

Definition at line 1136 of file Dialog.cxx.

References mDum, and ServerSubscription.

Referenced by dispatch().

{
   return new ServerSubscription(mDum, *this, request);
}
bool resip::Dialog::matches ( const SipMessage msg) [private]
void Dialog::onForkAccepted ( )

Definition at line 1158 of file Dialog.cxx.

References mInviteSession, and resip::ClientInviteSession::onForkAccepted().

{
   ClientInviteSession* uac = dynamic_cast<ClientInviteSession*>(mInviteSession);
   if (uac)
   {
      uac->onForkAccepted();
   }
}

Here is the call graph for this function:

void Dialog::possiblyDie ( ) [private]

Definition at line 1168 of file Dialog.cxx.

References resip::DialogUsageManager::destroy(), mClientSubscriptions, mDestroying, mDum, mInviteSession, and mServerSubscriptions.

Referenced by dispatch(), and resip::DialogUsage::~DialogUsage().

{
   if (!mDestroying)
   {
      if (mClientSubscriptions.empty() &&
          mServerSubscriptions.empty() &&
          !mInviteSession)
      {
         mDestroying = true;
         mDum.destroy(this);
      }
   }
}

Here is the call graph for this function:

void resip::Dialog::processNotify ( const SipMessage notify)
void Dialog::redirected ( const SipMessage msg)

Definition at line 950 of file Dialog.cxx.

References resip::ClientInviteSession::handleRedirect(), mClientSubscriptions, mInviteSession, mReUseDialogSet, and mServerSubscriptions.

{
   //Established dialogs are not destroyed by a redirect
   if (!mClientSubscriptions.empty() || !mServerSubscriptions.empty())
   {
      return;
   }
   if (mInviteSession)
   {
      ClientInviteSession* cInv = dynamic_cast<ClientInviteSession*>(mInviteSession);
      if (cInv)
      {
         cInv->handleRedirect(msg);
         mReUseDialogSet = true;  // Set flag so that DialogSet will not be destroyed and new Request can use it
      }
   }
}

Here is the call graph for this function:

void Dialog::send ( SharedPtr< SipMessage msg)

Definition at line 1148 of file Dialog.cxx.

References mDum, mRequests, and resip::DialogUsageManager::send().

Referenced by resip::DialogSet::dispatch(), dispatch(), and resip::DialogUsage::send().

{
   if (msg->isRequest() && msg->header(h_CSeq).method() != ACK)
   {
      mRequests[msg->header(h_CSeq).sequence()] = msg;
   }
   mDum.send(msg);
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class AppDialog [friend]

Definition at line 100 of file Dialog.hxx.

friend class ClientInviteSession [friend]

Definition at line 90 of file Dialog.hxx.

Referenced by makeClientInviteSession().

friend class ClientOutOfDialogReq [friend]

Definition at line 97 of file Dialog.hxx.

friend class ClientPublication [friend]

Definition at line 95 of file Dialog.hxx.

friend class ClientRegistration [friend]

Definition at line 93 of file Dialog.hxx.

friend class ClientSubscription [friend]

Definition at line 88 of file Dialog.hxx.

Referenced by makeClientSubscription().

friend class DestroyUsage [friend]

Definition at line 86 of file Dialog.hxx.

friend class DialogSet [friend]

Definition at line 84 of file Dialog.hxx.

friend class DialogUsage [friend]

Definition at line 83 of file Dialog.hxx.

friend class DialogUsageManager [friend]

Definition at line 85 of file Dialog.hxx.

friend class InviteSession [friend]

Definition at line 89 of file Dialog.hxx.

EncodeStream& operator<< ( EncodeStream strm,
const Dialog dialog 
) [friend]
friend class ServerInviteSession [friend]

Definition at line 91 of file Dialog.hxx.

Referenced by makeServerInviteSession().

friend class ServerOutOfDialogReq [friend]

Definition at line 98 of file Dialog.hxx.

friend class ServerPublication [friend]

Definition at line 96 of file Dialog.hxx.

friend class ServerRegistration [friend]

Definition at line 94 of file Dialog.hxx.

friend class ServerSubscription [friend]

Definition at line 92 of file Dialog.hxx.

Referenced by makeServerSubscription().


Member Data Documentation

Definition at line 147 of file Dialog.hxx.

Referenced by makeRequest().

Definition at line 150 of file Dialog.hxx.

Referenced by dispatch(), and makeClientSubscription().

Definition at line 160 of file Dialog.hxx.

Referenced by dispatch(), isDestroying(), possiblyDie(), and ~Dialog().

Definition at line 121 of file Dialog.hxx.

Referenced by Dialog(), resip::DialogSet::findDialog(), getId(), and makeResponse().

unsigned int resip::Dialog::mLocalCSeq [private]

Definition at line 142 of file Dialog.hxx.

Referenced by Dialog(), dispatch(), and makeRequest().

Definition at line 145 of file Dialog.hxx.

Referenced by Dialog(), getLocalNameAddr(), makeRequest(), and resip::DialogUsage::myAddr().

Definition at line 127 of file Dialog.hxx.

Referenced by Dialog(), dispatch(), and flowTerminated().

unsigned int resip::Dialog::mRemoteCSeq [private]

Definition at line 143 of file Dialog.hxx.

Referenced by Dialog().

Definition at line 156 of file Dialog.hxx.

Referenced by dispatch(), and send().

Definition at line 161 of file Dialog.hxx.

Referenced by redirected(), and ~Dialog().

Definition at line 138 of file Dialog.hxx.

Referenced by Dialog(), dispatch(), getRouteSet(), and makeRequest().

Definition at line 137 of file Dialog.hxx.

Referenced by cancel(), and Dialog().


The documentation for this class was generated from the following files: