reSIProcate/DialogUsageManager  9694
Public Member Functions | Static Public Member Functions | Protected Member Functions | Private Types | Private Member Functions | Private Attributes | Friends
resip::ClientRegistration Class Reference

dcm! -- shutdown/deletion API -- end? More...

#include <ClientRegistration.hxx>

Inheritance diagram for resip::ClientRegistration:
Inheritance graph
[legend]
Collaboration diagram for resip::ClientRegistration:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 ClientRegistration (DialogUsageManager &dum, DialogSet &dialog, SharedPtr< SipMessage > req)
ClientRegistrationHandle getHandle ()
void addBinding (const NameAddr &contact)
 Adds a registration binding, using the registration from the UserProfile.
void addBinding (const NameAddr &contact, UInt32 registrationTime)
 Adds a registration binding, using the specified registration time.
void removeBinding (const NameAddr &contact)
 Removes one particular binding.
void removeAll (bool stopRegisteringWhenDone=false)
 Removes all bindings associated with the AOR - even those that may have been by a another UA.
void removeMyBindings (bool stopRegisteringWhenDone=false)
 Removes all bindings added by addBinding.
void requestRefresh (UInt32 expires=0)
 Request a manual refresh of the registration.
void stopRegistering ()
 kills the usgage, does not unregister, call removeMyBindings to unregister
const NameAddrsmyContacts ()
 returns a list of contacts added by addBinding
const NameAddrsallContacts ()
 returns a list of all contacts for this AOR - may include those added by other UA's
UInt32 whenExpires () const
 returns the number of seconds until the registration expires - relative
virtual void end ()
 Calls removeMyBindings and ends usage when complete.
void removeMyBindingsCommand (bool stopRegisteringWhenDone=false)
 Provide asynchronous method access by using command.
virtual void endCommand ()
virtual void dispatch (const SipMessage &msg)
virtual void dispatch (const DumTimeout &timer)
virtual EncodeStreamdump (EncodeStream &strm) const

Static Public Member Functions

static void tagContact (NameAddr &contact, DialogUsageManager &dum, SharedPtr< UserProfile > &userProfile)

Protected Member Functions

virtual ~ClientRegistration ()

Private Types

enum  State {
  Querying, Adding, Refreshing, Registered,
  Removing, RetryAdding, RetryRefreshing, None
}

Private Member Functions

SharedPtr< SipMessagetryModification (ClientRegistration::State state)
void internalRequestRefresh (UInt32 expires=0)
unsigned int checkProfileRetry (const SipMessage &msg)
void tagContact (NameAddr &contact) const
unsigned long calculateExpiry (const SipMessage &reg200) const
bool contactIsMine (const NameAddr &contact) const
bool rinstanceIsMine (const Data &rinstance) const
bool searchByUri (const Uri &cUri) const
void flowTerminated ()
 ClientRegistration (const ClientRegistration &)
ClientRegistrationoperator= (const ClientRegistration &)

Private Attributes

SharedPtr< SipMessagemLastRequest
NameAddrs mMyContacts
NameAddrs mAllContacts
unsigned int mTimerSeq
State mState
bool mEndWhenDone
bool mUserRefresh
UInt32 mRegistrationTime
UInt64 mExpires
State mQueuedState
SharedPtr< SipMessagemQueuedRequest
NetworkAssociation mNetworkAssociation

Friends

class DialogSet

Detailed Description

dcm! -- shutdown/deletion API -- end?

Definition at line 16 of file ClientRegistration.hxx.


Member Enumeration Documentation

Enumerator:
Querying 
Adding 
Refreshing 
Registered 
Removing 
RetryAdding 
RetryRefreshing 
None 

Definition at line 80 of file ClientRegistration.hxx.

      {
         Querying,
         Adding,
         Refreshing,
         Registered,
         Removing,
         RetryAdding,    // Waiting to retry an add
         RetryRefreshing, // Waiting to retry a refresh
         None // for queued only
      } State;

Constructor & Destructor Documentation

ClientRegistration::ClientRegistration ( DialogUsageManager dum,
DialogSet dialog,
SharedPtr< SipMessage req 
)

Definition at line 29 of file ClientRegistration.cxx.

References mLastRequest, mMyContacts, mNetworkAssociation, mRegistrationTime, None, and resip::NetworkAssociation::setDum().

   : NonDialogUsage(dum, dialogSet),
     mLastRequest(request),
     mTimerSeq(0),
     mState(mLastRequest->exists(h_Contacts) ? Adding : Querying),
     mEndWhenDone(false),
     mUserRefresh(false),
     mRegistrationTime(mDialogSet.mUserProfile->getDefaultRegistrationTime()),
     mExpires(0),
     mQueuedState(None),
     mQueuedRequest(new SipMessage)
{
   // If no Contacts header, this is a query
   if (mLastRequest->exists(h_Contacts))
   {
      mMyContacts = mLastRequest->header(h_Contacts);
   }

   if(mLastRequest->exists(h_Expires) && 
      mLastRequest->header(h_Expires).isWellFormed())
   {
      mRegistrationTime = mLastRequest->header(h_Expires).value();
   }

   mNetworkAssociation.setDum(&dum);
}

Here is the call graph for this function:

ClientRegistration::~ClientRegistration ( ) [protected, virtual]

Definition at line 58 of file ClientRegistration.cxx.

References DebugLog, resip::DialogSet::mClientRegistration, resip::NonDialogUsage::mDialogSet, and resip::DialogSet::mUserProfile.

{
   DebugLog ( << "ClientRegistration::~ClientRegistration" );
   mDialogSet.mClientRegistration = 0;

   // !dcm! Will not interact well with multiple registrations from the same AOR
   mDialogSet.mUserProfile->setServiceRoute(NameAddrs());
}
resip::ClientRegistration::ClientRegistration ( const ClientRegistration ) [private]

Member Function Documentation

void ClientRegistration::addBinding ( const NameAddr contact)

Adds a registration binding, using the registration from the UserProfile.

Definition at line 68 of file ClientRegistration.cxx.

References resip::NonDialogUsage::mDialogSet, and resip::DialogSet::mUserProfile.

{
   addBinding(contact, mDialogSet.mUserProfile->getDefaultRegistrationTime());
}
void ClientRegistration::addBinding ( const NameAddr contact,
UInt32  registrationTime 
)

Adds a registration binding, using the specified registration time.

Definition at line 104 of file ClientRegistration.cxx.

References Adding, resip::ParserContainer< T >::back(), mMyContacts, mQueuedState, mRegistrationTime, None, resip::ParserContainer< T >::push_back(), resip::NonDialogUsage::send(), tagContact(), and tryModification().

{
   SharedPtr<SipMessage> next = tryModification(Adding);
   mMyContacts.push_back(contact);
   tagContact(mMyContacts.back());

   next->header(h_Contacts) = mMyContacts;
   mRegistrationTime = registrationTime;
   next->header(h_Expires).value() = mRegistrationTime;
   next->header(h_CSeq).sequence()++;
   // caller prefs

   if (mQueuedState == None)
   {
      send(next);
   }
}

Here is the call graph for this function:

const NameAddrs & ClientRegistration::allContacts ( )

returns a list of all contacts for this AOR - may include those added by other UA's

Definition at line 303 of file ClientRegistration.cxx.

References mAllContacts.

{
   return mAllContacts;
}
unsigned long ClientRegistration::calculateExpiry ( const SipMessage reg200) const [private]

Definition at line 751 of file ClientRegistration.cxx.

References contactIsMine(), resip::SipMessage::exists(), resip::SipMessage::header(), resip::LazyParser::isWellFormed(), and mRegistrationTime.

Referenced by dispatch().

{
   unsigned long expiry=mRegistrationTime;
   if(reg200.exists(h_Expires) &&
      reg200.header(h_Expires).isWellFormed() &&
      reg200.header(h_Expires).value() < expiry)
   {
      expiry=reg200.header(h_Expires).value();
   }

   if(!reg200.exists(h_Contacts))
   {
      return expiry;
   }

   const NameAddrs& contacts(reg200.header(h_Contacts));

   for(NameAddrs::const_iterator c=contacts.begin();c!=contacts.end();++c)
   {
      // Our expiry is never going to increase if we find one of our contacts, 
      // so if the expiry is not lower, we just ignore it. For registrars that
      // leave our requested expiry alone, this code ends up being pretty quick,
      // especially if there aren't contacts from other endpoints laying around.
      if(c->isWellFormed() &&
         c->exists(p_expires) && 
         c->param(p_expires) < expiry &&
         contactIsMine(*c))
      {
         expiry=c->param(p_expires);
      }
   }
   return expiry;
}

Here is the call graph for this function:

unsigned int ClientRegistration::checkProfileRetry ( const SipMessage msg) [private]

Definition at line 842 of file ClientRegistration.cxx.

References Adding, resip::DialogUsageManager::addTimer(), resip::SipMessage::exists(), resip::BaseUsage::getBaseHandle(), resip::SipMessage::header(), resip::DialogUsageManager::mClientAuthManager, resip::NonDialogUsage::mDialogSet, resip::BaseUsage::mDum, mEndWhenDone, mExpires, mLastRequest, mState, mTimerSeq, resip::DialogSet::mUserProfile, Refreshing, resip::DumTimeout::RegistrationRetry, RetryAdding, and RetryRefreshing.

Referenced by dispatch().

{
   unsigned int retryInterval = mDialogSet.mUserProfile->getDefaultRegistrationRetryTime();
   if (retryInterval > 0 &&
      (mState == Adding || mState == Refreshing) &&
      !mEndWhenDone)
   {
      if (msg.exists(h_RetryAfter) && msg.header(h_RetryAfter).value() > 0)
      {
         // Use retry interval from error response
         retryInterval = msg.header(h_RetryAfter).value();
      }
      mExpires = 0;
      switch(mState)
      {
      case Adding:
         mState = RetryAdding;
         break;
      case Refreshing:
         mState = RetryRefreshing;
         break;
      default:
         assert(false);
         break;
      }

      if(mDum.mClientAuthManager.get()) mDum.mClientAuthManager.get()->clearAuthenticationState(DialogSetId(*mLastRequest));
      mDum.addTimer(DumTimeout::RegistrationRetry,
         retryInterval,
         getBaseHandle(),
         ++mTimerSeq);
      return retryInterval;
   }
   return 0;
}

Here is the call graph for this function:

bool ClientRegistration::contactIsMine ( const NameAddr contact) const [private]

Definition at line 786 of file ClientRegistration.cxx.

References resip::NameAddr::exists(), resip::Uri::exists(), resip::NonDialogUsage::mDialogSet, resip::DialogSet::mUserProfile, resip::ParserCategory::param(), rinstanceIsMine(), searchByUri(), and resip::NameAddr::uri().

Referenced by calculateExpiry().

{
   // Try to find this contact in mMyContacts
   if(mDialogSet.mUserProfile->hasInstanceId() && 
      contact.exists(p_Instance))
   {
      return contact.param(p_Instance)==mDialogSet.mUserProfile->getInstanceId();
   }
   else if(mDialogSet.mUserProfile->getRinstanceEnabled() &&
            contact.uri().exists(p_rinstance))
   {
      return rinstanceIsMine(contact.uri().param(p_rinstance));
   }
   else
   {
      return searchByUri(contact.uri());
   }
}

Here is the call graph for this function:

void ClientRegistration::dispatch ( const SipMessage msg) [virtual]

Implements resip::BaseUsage.

Definition at line 359 of file ClientRegistration.cxx.

References resip::Helper::aBitSmallerThan(), Adding, resip::DialogUsageManager::addTimer(), calculateExpiry(), checkProfileRetry(), resip::ParserContainerBase::clear(), DebugLog, resip::SipMessage::empty(), end(), ErrLog, resip::SipMessage::exists(), resip::Uri::exists(), resip::BaseUsage::getBaseHandle(), getHandle(), resip::BaseException::getMessage(), resip::SipMessage::getReceivedTransport(), resip::SipMessage::getSource(), resip::Timer::getTimeSecs(), resip::NonDialogUsage::getUserProfile(), h_StatusLine, resip::SipMessage::header(), InfoLog, resip::Inserter(), resip::SipMessage::isExternal(), resip::SipMessage::isResponse(), mAllContacts, resip::DialogUsageManager::mClientAuthManager, resip::DialogUsageManager::mClientRegistrationHandler, resip::NonDialogUsage::mDialogSet, resip::BaseUsage::mDum, mEndWhenDone, mExpires, mLastRequest, mNetworkAssociation, mQueuedRequest, mQueuedState, mRegistrationTime, mState, mTimerSeq, resip::DialogSet::mUserProfile, mUserRefresh, None, resip::ClientRegistrationHandler::onFailure(), resip::ClientRegistrationHandler::onRemoved(), resip::ClientRegistrationHandler::onRequestRetry(), resip::ClientRegistrationHandler::onSuccess(), resip::Symbols::Outbound, Querying, Refreshing, Registered, resip::DumTimeout::Registration, resip::DumTimeout::RegistrationRetry, Removing, RetryAdding, RetryRefreshing, resip::Symbols::SCTP, resip::NonDialogUsage::send(), stopRegistering(), resip::Symbols::TCP, resip::Symbols::TLS, resip::NetworkAssociation::update(), resip::RequestLine::uri(), and WarningLog.

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

{
   try
   {
      // !jf! there may be repairable errors that we can handle here
      assert(msg.isResponse());
      const int& code = msg.header(h_StatusLine).statusCode();
      bool nextHopSupportsOutbound = false;
      int keepAliveTime = 0;

      // If registration was successful - look for next hop indicating support for outbound
      if(mDialogSet.mUserProfile->clientOutboundEnabled() && msg.isExternal() && code >= 200 && code < 300)
      {
         // If ClientOutbound support is enabled and the registration response contains 
         // Requires: outbound or a Path with outbound then outbound is supported by the 
         // server, so store the flow key in the UserProfile 
         // and use it for sending all messages (DialogUsageManager::sendUsingOutboundIfAppropriate)
         try
         {
            if((!msg.empty(h_Paths) && msg.header(h_Paths).back().uri().exists(p_ob)) ||
               (!msg.empty(h_Requires) && msg.header(h_Requires).find(Token(Symbols::Outbound))))
            {
               mDialogSet.mUserProfile->mClientOutboundFlowTuple = msg.getSource();
               mDialogSet.mUserProfile->mClientOutboundFlowTuple.onlyUseExistingConnection = true;
               nextHopSupportsOutbound = true;
               if(!msg.empty(h_FlowTimer))
               {
                  keepAliveTime = msg.header(h_FlowTimer).value();
               }
            }
         }
         catch(BaseException&e)
         {
            ErrLog(<<"Error parsing Path or Requires:" << e);
         }
      }

      if(msg.isExternal())
      {
         const Data& receivedTransport = msg.header(h_Vias).front().transport();
         if(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, nextHopSupportsOutbound);
         }
      }

      if (code < 200)
      {
         // throw it away
         return;
      }
      else if (code < 300) // success
      {
         try
         {
            if (msg.exists(h_ServiceRoutes))
            {
               InfoLog(<< "Updating service route: " << Inserter(msg.header(h_ServiceRoutes)));
               mDialogSet.mUserProfile->setServiceRoute(msg.header(h_ServiceRoutes));
            }
            else
            {
               DebugLog(<< "Clearing service route (" << Inserter(getUserProfile()->getServiceRoute()) << ")");
               mDialogSet.mUserProfile->setServiceRoute(NameAddrs());
            }
         }
         catch(BaseException &e)
         {
            ErrLog(<< "Error Parsing Service Route:" << e);
         }    

         //gruu update, should be optimized
         try
         {
            if(mDialogSet.mUserProfile->gruuEnabled() && msg.exists(h_Contacts))
            {
               for (NameAddrs::const_iterator it = msg.header(h_Contacts).begin(); 
                    it != msg.header(h_Contacts).end(); it++)
               {
                  if (it->exists(p_Instance) && it->param(p_Instance) == mDialogSet.mUserProfile->getInstanceId())
                  {
                     if(it->exists(p_pubGruu))
                     {
                        mDialogSet.mUserProfile->setPublicGruu(Uri(it->param(p_pubGruu)));
                     }
                     if(it->exists(p_tempGruu))
                     {
                        mDialogSet.mUserProfile->setTempGruu(Uri(it->param(p_tempGruu)));
                     }
                     break;
                   }
               }
            }
         }
         catch(BaseException&e)
         {
            ErrLog(<<"Error parsing GRUU:" << e);
         }
         
         // !jf! consider what to do if no contacts
         // !ah! take list of ctcs and push into mMy or mOther as required.

         // make timers to re-register
         UInt32 expiry = calculateExpiry(msg);
         if(msg.exists(h_Contacts))
         {
            mAllContacts = msg.header(h_Contacts);
         }
         else
         {
            mAllContacts.clear();
         }

         if (expiry != 0 && expiry != UINT_MAX)
         {
            if(expiry>=7)
            {
               int exp = Helper::aBitSmallerThan(expiry);
               mExpires = exp + Timer::getTimeSecs();
               mDum.addTimer(DumTimeout::Registration,
                             exp,
                             getBaseHandle(),
                             ++mTimerSeq);
            }
            else
            {
               WarningLog(<< "Server is using an unreasonably low expiry: " 
                           << expiry 
                           << " We're just going to end this registration.");
               end();
               return;
            }
         }

         switch (mState)
         {
            case Querying:
            case Adding:
               if(expiry != 0)
               {
                  mState = Registered;
                  mDum.mClientRegistrationHandler->onSuccess(getHandle(), msg);
               }
               else
               {
                  mDum.mClientRegistrationHandler->onRemoved(getHandle(), msg);
                  checkProfileRetry(msg);
               }
               break;

            case Removing:
               //mDum.mClientRegistrationHandler->onSuccess(getHandle(), msg);
               mDum.mClientRegistrationHandler->onRemoved(getHandle(), msg);
               InfoLog (<< "Finished removing registration " << *this << " mEndWhenDone=" << mEndWhenDone);
               if (mEndWhenDone)
               {
                  // !kh!
                  // stopRegistering() deletes 'this'
                  // furthur processing makes no sense
                  //assert(mQueuedState == None);
                  stopRegistering();
                  return;
               }
               break;

            case Registered:
            case Refreshing:
               mState = Registered;
               if(expiry != 0)
               {
                  if(mUserRefresh)
                  {
                      mUserRefresh = false;
                      mDum.mClientRegistrationHandler->onSuccess(getHandle(), msg);
                  }
               }
               else
               {
                  mDum.mClientRegistrationHandler->onRemoved(getHandle(), msg);
                  checkProfileRetry(msg);
               }
               break;

            default:
               break;
         }

         if (mQueuedState != None)
         {
            InfoLog (<< "Sending queued request: " << *mQueuedRequest);
            mState = mQueuedState;
            mQueuedState = None;
            *mLastRequest = *mQueuedRequest;
            send(mLastRequest);
         }
      }
      else
      {
         if((mState == Adding || mState == Refreshing) && !mEndWhenDone)
         {
            if (code == 423) // interval too short
            {
               UInt32 maxRegistrationTime = mDialogSet.mUserProfile->getDefaultMaxRegistrationTime();
               if (msg.exists(h_MinExpires) && 
                   (maxRegistrationTime == 0 || msg.header(h_MinExpires).value() < maxRegistrationTime)) // If maxRegistrationTime is enabled, then check it
               {
                  mRegistrationTime = msg.header(h_MinExpires).value();
                  mLastRequest->header(h_Expires).value() = mRegistrationTime;
                  mLastRequest->header(h_CSeq).sequence()++;
                  send(mLastRequest);
                  return;
               }
            }
            else if (code == 408 || (code == 503 && msg.getReceivedTransport() == 0))
            {
               int retry = mDum.mClientRegistrationHandler->onRequestRetry(getHandle(), 0, msg);
            
               if (retry < 0)
               {
                  DebugLog(<< "Application requested failure on Retry-After");
               }
               else if (retry == 0)
               {
                  DebugLog(<< "Application requested immediate retry on 408 or internal 503");
               
                  mLastRequest->header(h_CSeq).sequence()++;
                  send(mLastRequest);
                  mUserRefresh = true;  // Reset this flag, so that the onSuccess callback will be called if we are successful when re-trying
                  return;
               }
               else
               {
                  DebugLog(<< "Application requested delayed retry on 408 or internal 503: " << retry);
                  mExpires = 0;
                  switch(mState)
                  {
                  case Adding:
                     mState = RetryAdding;
                     break;
                  case Refreshing:
                     mState = RetryRefreshing;
                     break;
                  default:
                     assert(false);
                     break;
                  }
                  if(mDum.mClientAuthManager.get()) mDum.mClientAuthManager.get()->clearAuthenticationState(DialogSetId(*mLastRequest));
                  mDum.addTimer(DumTimeout::RegistrationRetry, 
                                retry, 
                                getBaseHandle(),
                                ++mTimerSeq);       
                  mUserRefresh = true;  // Reset this flag, so that the onSuccess callback will be called if we are successful when re-trying
                  return;
               }
            }
         }
         
         mDum.mClientRegistrationHandler->onFailure(getHandle(), msg);
         mUserRefresh = true;  // Reset this flag, so that the onSuccess callback will be called if we are successful when re-trying

         // Retry if Profile setting is set
         unsigned int retryInterval = checkProfileRetry(msg);
         if(retryInterval > 0)
         {
            InfoLog( << "Registration error " << code << " for " << msg.header(h_To) << ", retrying in " << retryInterval << " seconds.");
            return;
         }

         // assume that if a failure occurred, the bindings are gone
         if (mEndWhenDone)
         {
            mDum.mClientRegistrationHandler->onRemoved(getHandle(), msg);
         }
         delete this;
      }
   }
   catch(BaseException& e)
   {
      InfoLog( << "Exception in ClientRegistration::dispatch: "  <<  e.getMessage());
      mDum.mClientRegistrationHandler->onFailure(getHandle(), msg);
      delete this;
   }
}

Here is the call graph for this function:

void ClientRegistration::dispatch ( const DumTimeout timer) [virtual]

Implements resip::BaseUsage.

Definition at line 879 of file ClientRegistration.cxx.

References Adding, resip::ParserContainerBase::empty(), internalRequestRefresh(), mLastRequest, mMyContacts, mState, mTimerSeq, Refreshing, Registered, resip::DumTimeout::Registration, resip::DumTimeout::RegistrationRetry, RetryAdding, RetryRefreshing, resip::NonDialogUsage::send(), resip::DumTimeout::seq(), and resip::DumTimeout::type().

{
   switch(timer.type())
   {
      case DumTimeout::Registration:
         // If you happen to be Adding/Updating when the timer goes off, you should just ignore
         // it since a new timer will get added when the 2xx is received.
         if (timer.seq() == mTimerSeq && mState == Registered)
         {
            if (!mMyContacts.empty())
            {
               internalRequestRefresh();
            }
         }
         break;

      case DumTimeout::RegistrationRetry:
         if (timer.seq() == mTimerSeq)
         {
            switch(mState)
            {
            case RetryAdding:
               mState = Adding;
               break;
            case RetryRefreshing:
               mState = Refreshing;
               break;
            default:
              assert(false);
              break;
            }

            // Resend last request
            mLastRequest->header(h_CSeq).sequence()++;
            mLastRequest->remove(h_ProxyAuthorizations);
            mLastRequest->remove(h_Authorizations); 
            send(mLastRequest);
         }
         break;
      default:
         break;
   }
}

Here is the call graph for this function:

EncodeStream & ClientRegistration::dump ( EncodeStream strm) const [virtual]

Implements resip::BaseUsage.

Definition at line 352 of file ClientRegistration.cxx.

References mLastRequest.

{
   strm << "ClientRegistration " << mLastRequest->header(h_From).uri();
   return strm;
}
void ClientRegistration::end ( ) [virtual]

Calls removeMyBindings and ends usage when complete.

Implements resip::BaseUsage.

Definition at line 318 of file ClientRegistration.cxx.

References removeMyBindings().

Referenced by dispatch().

{
   removeMyBindings(true);
}

Here is the call graph for this function:

void ClientRegistration::endCommand ( ) [virtual]

Definition at line 346 of file ClientRegistration.cxx.

References resip::BaseUsage::mDum, and resip::TransactionUser::post().

Here is the call graph for this function:

void ClientRegistration::flowTerminated ( ) [private]

Definition at line 924 of file ClientRegistration.cxx.

References resip::NetworkAssociation::clear(), getHandle(), resip::DialogUsageManager::mClientRegistrationHandler, resip::BaseUsage::mDum, mNetworkAssociation, and resip::ClientRegistrationHandler::onFlowTerminated().

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

{
   // Clear the network association
   mNetworkAssociation.clear();

   // Notify application - not default handler implementation is to immediately attempt
   // a re-registration in order to form a new flow
   mDum.mClientRegistrationHandler->onFlowTerminated(getHandle());
}

Here is the call graph for this function:

ClientRegistrationHandle ClientRegistration::getHandle ( )

Definition at line 24 of file ClientRegistration.cxx.

References resip::BaseUsage::getBaseHandle(), and resip::BaseUsage::mDum.

Referenced by dispatch(), flowTerminated(), and resip::DialogSet::getClientRegistration().

Here is the call graph for this function:

void ClientRegistration::internalRequestRefresh ( UInt32  expires = 0) [private]

Definition at line 269 of file ClientRegistration.cxx.

References InfoLog, mLastRequest, mMyContacts, mRegistrationTime, mState, mTimerSeq, Refreshing, Registered, RetryAdding, RetryRefreshing, and resip::NonDialogUsage::send().

Referenced by dispatch(), and requestRefresh().

{
   if(mState == RetryAdding && mState == RetryRefreshing)
   {
      // disable retry time and try refresh immediately
      ++mTimerSeq;
   }
   else if (mState != Registered)
   {
      InfoLog (<< "a request is already in progress, no need to refresh " << *this);
      return;
   }

   InfoLog (<< "requesting refresh of " << *this);
   
   mState = Refreshing;
   mLastRequest->header(h_CSeq).sequence()++;
   mLastRequest->header(h_Contacts)=mMyContacts;
   if(expires > 0)
   {
      mRegistrationTime = expires;
   }
   mLastRequest->header(h_Expires).value()=mRegistrationTime;

   send(mLastRequest);
}

Here is the call graph for this function:

const NameAddrs & ClientRegistration::myContacts ( )

returns a list of contacts added by addBinding

Definition at line 297 of file ClientRegistration.cxx.

References mMyContacts.

Referenced by removeMyBindings().

{
   return mMyContacts;
}
ClientRegistration& resip::ClientRegistration::operator= ( const ClientRegistration ) [private]
void ClientRegistration::removeAll ( bool  stopRegisteringWhenDone = false)

Removes all bindings associated with the AOR - even those that may have been by a another UA.

Note: Set's contact header to '*'. Set flag to true to end the usage when complete.

Definition at line 156 of file ClientRegistration.cxx.

References resip::ParserContainerBase::clear(), mAllContacts, mEndWhenDone, mMyContacts, mQueuedState, mState, None, Removing, resip::NonDialogUsage::send(), resip::NameAddr::setAllContacts(), tryModification(), and WarningLog.

{
   if (mState == Removing)
   {
      WarningLog (<< "Already removing a binding");
      throw UsageUseException("Can't remove binding when already removing registration bindings", __FILE__,__LINE__);
   }

   SharedPtr<SipMessage> next = tryModification(Removing);

   mAllContacts.clear();
   mMyContacts.clear();

   NameAddr all;
   all.setAllContacts();
   next->header(h_Contacts).clear();
   next->header(h_Contacts).push_back(all);
   next->header(h_Expires).value() = 0;
   next->header(h_CSeq).sequence()++;
   mEndWhenDone = stopRegisteringWhenDone;

   if (mQueuedState == None)
   {
      send(next);
   }
}

Here is the call graph for this function:

void ClientRegistration::removeBinding ( const NameAddr contact)

Removes one particular binding.

Definition at line 123 of file ClientRegistration.cxx.

References resip::ParserContainer< T >::begin(), resip::ParserContainer< T >::end(), resip::ParserContainer< T >::erase(), mMyContacts, mQueuedState, mState, None, Removing, resip::NonDialogUsage::send(), tryModification(), resip::NameAddr::uri(), and WarningLog.

{
   if (mState == Removing)
   {
      WarningLog (<< "Already removing a binding");
      throw UsageUseException("Can't remove binding when already removing registration bindings", __FILE__,__LINE__);
   }

   SharedPtr<SipMessage> next = tryModification(Removing);
   for (NameAddrs::iterator i=mMyContacts.begin(); i != mMyContacts.end(); i++)
   {
      if (i->uri() == contact.uri())
      {
         next->header(h_Contacts).clear();
         next->header(h_Contacts).push_back(*i);
         next->header(h_Expires).value() = 0;
         next->header(h_CSeq).sequence()++;

         if (mQueuedState == None)
         {
            send(next);
         }

         mMyContacts.erase(i);
         return;
      }
   }

   // !jf! What state are we left in now?
   throw Exception("No such binding", __FILE__, __LINE__);
}

Here is the call graph for this function:

void ClientRegistration::removeMyBindings ( bool  stopRegisteringWhenDone = false)

Removes all bindings added by addBinding.

Set flag to true to end the usage when complete

Definition at line 184 of file ClientRegistration.cxx.

References resip::ParserContainer< T >::begin(), resip::ParserContainerBase::clear(), resip::ParserContainerBase::empty(), resip::ParserContainer< T >::end(), InfoLog, mEndWhenDone, mMyContacts, mQueuedState, mState, myContacts(), None, Removing, resip::NonDialogUsage::send(), tryModification(), and WarningLog.

Referenced by end().

{
   InfoLog (<< "Removing binding");

   if (mState == Removing)
   {
      WarningLog (<< "Already removing a binding");
      throw UsageUseException("Can't remove binding when already removing registration bindings", __FILE__,__LINE__);
   }

   if (mMyContacts.empty())
   {
      WarningLog (<< "No bindings to remove");
      throw UsageUseException("No bindings to remove", __FILE__,__LINE__);
   }

   SharedPtr<SipMessage> next = tryModification(Removing);

   next->header(h_Contacts) = mMyContacts;
   mMyContacts.clear();

   NameAddrs& myContacts = next->header(h_Contacts);

   for (NameAddrs::iterator i=myContacts.begin(); i != myContacts.end(); i++)
   {
      i->param(p_expires) = 0;
   }

   next->remove(h_Expires);
   next->header(h_CSeq).sequence()++;

   // !jf! is this ok if queued
   mEndWhenDone = stopRegisteringWhenDone;

   if (mQueuedState == None)
   {
      send(next);
   }
}

Here is the call graph for this function:

void ClientRegistration::removeMyBindingsCommand ( bool  stopRegisteringWhenDone = false)

Provide asynchronous method access by using command.

Definition at line 248 of file ClientRegistration.cxx.

References resip::BaseUsage::mDum, and resip::TransactionUser::post().

{
   mDum.post(new ClientRegistrationRemoveMyBindings(*this, stopRegisteringWhenDone));
}

Here is the call graph for this function:

void ClientRegistration::requestRefresh ( UInt32  expires = 0)

Request a manual refresh of the registration.

If 0 then default to using original expires value (to remove use removeXXX() instead)

Definition at line 261 of file ClientRegistration.cxx.

References internalRequestRefresh(), and mUserRefresh.

{
    // Set flag so that handlers get called for success/failure
    mUserRefresh = true;
    internalRequestRefresh(expires);
}

Here is the call graph for this function:

bool ClientRegistration::rinstanceIsMine ( const Data rinstance) const [private]

Definition at line 806 of file ClientRegistration.cxx.

References resip::ParserContainer< T >::begin(), resip::ParserContainer< T >::end(), and mMyContacts.

Referenced by contactIsMine().

{
   // !bwc! This could be made faster if we used a single rinstance...
   for(NameAddrs::const_iterator m=mMyContacts.begin(); m!=mMyContacts.end(); ++m)
   {
      if(m->uri().exists(p_rinstance) && m->uri().param(p_rinstance)==rinstance)
      {
         return true;
      }
   }
   return false;
}

Here is the call graph for this function:

bool ClientRegistration::searchByUri ( const Uri cUri) const [private]

Definition at line 820 of file ClientRegistration.cxx.

References resip::ParserContainer< T >::begin(), resip::ParserContainer< T >::end(), resip::DialogUsageManager::getSipStack(), resip::Uri::host(), resip::SipStack::isMyDomain(), resip::BaseUsage::mDum, mMyContacts, resip::Uri::port(), resip::Uri::scheme(), and resip::Uri::user().

Referenced by contactIsMine().

{
   for(NameAddrs::const_iterator m=mMyContacts.begin(); m!=mMyContacts.end(); ++m)
   {
      if(m->uri()==cUri)
      {
         return true;
      }
      else if(m->uri().host().empty() && 
               m->uri().user()==cUri.user() &&
               m->uri().scheme()==cUri.scheme() &&
               mDum.getSipStack().isMyDomain(cUri.host(), cUri.port()))
      {
         // Empty host-part in our contact; this means we're relying on the 
         // stack to fill out this Contact header. Also, the user-part matches.
         return true;
      }
   }
   return false;
}

Here is the call graph for this function:

void ClientRegistration::stopRegistering ( )

kills the usgage, does not unregister, call removeMyBindings to unregister

Definition at line 254 of file ClientRegistration.cxx.

Referenced by dispatch().

{
   //timers aren't a concern, as DUM checks for Handle validity before firing.
   delete this;
}
void ClientRegistration::tagContact ( NameAddr contact,
DialogUsageManager dum,
SharedPtr< UserProfile > &  userProfile 
) [static]

Definition at line 664 of file ClientRegistration.cxx.

References resip::Data::empty(), ErrLog, resip::Random::getCryptoRandomHex(), resip::DialogUsageManager::getMasterProfile(), resip::DialogUsageManager::getSipStack(), resip::Uri::host(), InfoLog, resip::SipStack::isMyDomain(), resip::ParserCategory::param(), resip::Uri::port(), resip::NameAddr::uri(), resip::Uri::user(), and WarningLog.

Referenced by addBinding(), resip::RegistrationCreator::RegistrationCreator(), and tagContact().

{
   if(contact.uri().host().empty() || 
      dum.getSipStack().isMyDomain(contact.uri().host(), contact.uri().port()))
   {
      // Contact points at us; it is appropriate to add a +sip.instance to 
      // this Contact. We don't need to have full gruu support enabled to add
      // a +sip.instance either...
      if(userProfile->hasInstanceId())
      {
         contact.param(p_Instance) = userProfile->getInstanceId();
         if(userProfile->getRegId() != 0)
         {
            contact.param(p_regid) = userProfile->getRegId();
         }
      }
      else if(userProfile->getRinstanceEnabled())
      {
         // !slg! poor mans instance id so that we can tell which contacts 
         // are ours - to be replaced by gruu someday.
         InfoLog(<< "You really should consider setting an instance id in"
                     " the UserProfile (see UserProfile::setInstanceId())."
                     " This is really easy, and makes this class much less "
                     "likely to clash with another endpoint registering at "
                     "the same AOR.");
         contact.uri().param(p_rinstance) = Random::getCryptoRandomHex(8);  
      }
      else if(!contact.uri().user().empty())
      {
         WarningLog(<< "Ok, not only have you not specified an instance id, "
                  "you have disabled the rinstance hack (ie; resip's \"poor"
                  " man's +sip.instance\"). We will try to match Contacts"
                  " based on what you've put in the user-part of your "
                  "Contact, but this can be dicey, especially if you've put"
                  " something there that another endpoint is likely to "
                  "use.");
      }
      else
      {
         ErrLog(<< "Ok, not only have you not specified an instance id, "
                  "you have disabled the rinstance hack (ie; resip's \"poor"
                  " man's +sip.instance\"), _and_ you haven't put anything"
                  " in the user-part of your Contact. This is asking for "
                  "confusion later. We'll do our best to try to match things"
                  " up later when the response comes in...");
      }
   }
   else
   {
      // Looks like a third-party registration. +sip.instance is out of the 
      // question, but we can still use rinstance.
      if(userProfile->getRinstanceEnabled())
      {
         // !slg! poor mans instance id so that we can tell which contacts 
         // are ours - to be replaced by gruu someday.
         contact.uri().param(p_rinstance) = Random::getCryptoRandomHex(8);  
      }
      else if(!contact.uri().user().empty())
      {
         WarningLog(<< "You're trying to do a third-party registration, but "
                  "you have disabled the rinstance hack (ie; resip's \"poor"
                  " man's +sip.instance\"). We will try to match Contacts"
                  " based on what you've put in the user-part of your "
                  "Contact, but this can be dicey, especially if you've put"
                  " something there that another endpoint is likely to "
                  "use.");
      }
      else
      {
         ErrLog(<< "You're trying to do a third-party registration,  and "
                  "not only have you disabled the rinstance hack (ie; "
                  "resip's \"poor man's +sip.instance\"), you haven't"
                  " put anything in the user-part of your Contact. This is "
                  "asking for confusion later. We'll do our best to try to "
                  "match things up later when the response comes in...");
      }
   }
   
   if (userProfile->getMethodsParamEnabled())
   {
      contact.param(p_methods) = dum.getMasterProfile()->getAllowedMethodsData();
   }

   // ?bwc? Host and port override?
}

Here is the call graph for this function:

void ClientRegistration::tagContact ( NameAddr contact) const [private]

Definition at line 658 of file ClientRegistration.cxx.

References resip::NonDialogUsage::mDialogSet, resip::BaseUsage::mDum, resip::DialogSet::mUserProfile, and tagContact().

Here is the call graph for this function:

SharedPtr< SipMessage > ClientRegistration::tryModification ( ClientRegistration::State  state) [private]

Definition at line 74 of file ClientRegistration.cxx.

References mLastRequest, mQueuedRequest, mQueuedState, mState, mTimerSeq, None, Registered, RetryAdding, RetryRefreshing, and WarningLog.

Referenced by addBinding(), removeAll(), removeBinding(), and removeMyBindings().

{
   if (mState != Registered)
   {
      if(mState != RetryAdding && mState != RetryRefreshing)
      {
         if (mQueuedState != None)
         {
            WarningLog (<< "Trying to modify bindings when another request is already queued");
            throw UsageUseException("Queuing multiple requests for Registration Bindings", __FILE__,__LINE__);
         }

         *mQueuedRequest = *mLastRequest;
         mQueuedState = state;

         return mQueuedRequest;
      }
      else
      {
          ++mTimerSeq;  // disable retry timer
      }
   }

   assert(mQueuedState == None);
   mState = state;

   return mLastRequest;
}
UInt32 ClientRegistration::whenExpires ( ) const

returns the number of seconds until the registration expires - relative

Definition at line 309 of file ClientRegistration.cxx.

References resip::Timer::getTimeSecs(), and mExpires.

{
// !cj! - TODO - I'm supisious these time are getting confused on what units they are in 
   UInt64 now = Timer::getTimeSecs();
   UInt64 ret = mExpires - now;
   return (UInt32)ret;
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class DialogSet [friend]

Definition at line 101 of file ClientRegistration.hxx.


Member Data Documentation

Definition at line 107 of file ClientRegistration.hxx.

Referenced by allContacts(), dispatch(), and removeAll().

Definition at line 111 of file ClientRegistration.hxx.

Referenced by checkProfileRetry(), dispatch(), removeAll(), and removeMyBindings().

Definition at line 114 of file ClientRegistration.hxx.

Referenced by checkProfileRetry(), dispatch(), and whenExpires().

Definition at line 118 of file ClientRegistration.hxx.

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

Definition at line 116 of file ClientRegistration.hxx.

Referenced by dispatch(), and tryModification().

unsigned int resip::ClientRegistration::mTimerSeq [private]

Definition at line 112 of file ClientRegistration.hxx.

Referenced by dispatch(), and requestRefresh().


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