[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "client-registration" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Sep 8 10:06:04 CDT 2011


branch "client-registration" has been created
        at  7654c9134f255423b8e94e4b88accb878796e4a7 (commit)

- Log -----------------------------------------------------------------
commit 7654c9134f255423b8e94e4b88accb878796e4a7
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Sep 7 18:04:59 2011 -0500

    Give access to the auth hooks in the registration client.

diff --git a/src/PJSipManager.cpp b/src/PJSipManager.cpp
index a73ee76..d2d67c1 100644
--- a/src/PJSipManager.cpp
+++ b/src/PJSipManager.cpp
@@ -59,6 +59,7 @@ void PJSipManager::addAuthHook(const AuthHookPrx &hook, int priority, const Requ
     {
         mLoggingModule->addAuthHook(hook, priority, types);
     }
+    mClientRegistrationManager->addAuthHook(hook);
 }
 
 void PJSipManager::removeAuthHook(const AuthHookPrx &hook)
@@ -71,6 +72,7 @@ void PJSipManager::removeAuthHook(const AuthHookPrx &hook)
     {
         mLoggingModule->removeAuthHook(hook);
     }
+    mClientRegistrationManager->removeAuthHook(hook);
 }
 
 void PJSipManager::clearAuthHooks()
@@ -83,6 +85,7 @@ void PJSipManager::clearAuthHooks()
     {
         mLoggingModule->clearAuthHooks();
     }
+    mClientRegistrationManager->clearAuthHooks();
 }
 
 static void *monitorThread(void *endpt)
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index dcd4385..47c7f27 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -130,9 +130,31 @@ Ice::StringSeq SipRegistrationClientManager::getSupported()
     return mSupported;
 }
 
+void SipRegistrationClientManager::addAuthHook(const AuthHookPrx& hook)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    if (std::find(mAuthHooks.begin(), mAuthHooks.end(), hook) == mAuthHooks.end())
+    {
+        mAuthHooks.push_back(hook);
+    }
+}
+
+void SipRegistrationClientManager::removeAuthHook(const AuthHookPrx& hook)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    mAuthHooks.erase(std::remove(mAuthHooks.begin(), mAuthHooks.end(), hook), mAuthHooks.end());
+}
+
+void SipRegistrationClientManager::clearAuthHooks()
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    mAuthHooks.clear();
+}
+
 AuthHookSeq SipRegistrationClientManager::getAuthHooks()
 {
-    return AuthHookSeq();
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    return mAuthHooks;
 }
 
 SipRegistrationClient::SipRegistrationClient(
@@ -248,9 +270,7 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
     case 407:
     {
         //We must authenticate!
-        lg(Debug) << "Hi!";
         authenticate(param->rdata);
-        lg(Debug) << "Bye!";
         break;
     }
     default:
@@ -265,11 +285,21 @@ Ice::StringSeq SipRegistrationClient::getRealms(pjsip_rx_data *rdata)
 {
     Ice::StringSeq realms;
 
-    pjsip_proxy_authenticate_hdr *authHeader = NULL;
+    pjsip_proxy_authenticate_hdr *authHeader = (pjsip_proxy_authenticate_hdr*) &rdata->msg_info.msg->hdr;
 
-    while ((authHeader = (pjsip_proxy_authenticate_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_PROXY_AUTHENTICATE, authHeader)))
+    while ((authHeader = (pjsip_proxy_authenticate_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_WWW_AUTHENTICATE, authHeader->next)))
     {
-        realms.push_back(std::string(pj_strbuf(&authHeader->challenge.digest.realm), pj_strlen(&authHeader->challenge.digest.realm)));
+        std::string realm(pj_strbuf(&authHeader->challenge.digest.realm), pj_strlen(&authHeader->challenge.digest.realm));
+        lg(Debug) << "Found the realm " << realm;
+        realms.push_back(realm);
+    }
+
+    authHeader = (pjsip_proxy_authenticate_hdr*) &rdata->msg_info.msg->hdr;
+
+    while ((authHeader = (pjsip_proxy_authenticate_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_PROXY_AUTHENTICATE, authHeader->next)))
+    {
+        std::string realm(pj_strbuf(&authHeader->challenge.digest.realm), pj_strlen(&authHeader->challenge.digest.realm));
+        realms.push_back(realm);
     }
 
     return realms;
@@ -287,6 +317,7 @@ void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
     {
         ClientAuthSeq auths;
         Ice::StringSeq realms = getRealms(rdata);
+
         HookResult result = (*iter)->getCredentials(mEndpointName, realms, auths);
         if (result.status == Succeeded)
         {
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 601d41b..e72e15e 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -54,9 +54,14 @@ public:
 
     AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookSeq getAuthHooks();
 
+    void addAuthHook(const AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx& hook);
+    void removeAuthHook(const AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx& hook);
+    void clearAuthHooks();
+    
 private:
     Ice::StringSeq mAllow;
     Ice::StringSeq mSupported;
+    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookSeq mAuthHooks;
     boost::shared_mutex mLock;
 };
 

commit f5a0c2e9133a8b3df35a3f4ac081409a1d9b81a5
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Sep 7 16:46:39 2011 -0500

    Add additional information to client registration constructor.
    
    I can now properly register with an Asterisk server...unauthenticated.
    Trying one where authentication is required now.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index dbf05d1..dcd4385 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -136,7 +136,7 @@ AuthHookSeq SipRegistrationClientManager::getAuthHooks()
 }
 
 SipRegistrationClient::SipRegistrationClient(
-        const ContactInfoSeq& contacts,
+        const SipClientRegistrationItemPtr& confItem,
         pjsip_endpoint* pjEndpoint,
         const SipEndpointPtr& sipEndpoint,
         const SipRegistrationClientManagerPtr manager)
@@ -145,7 +145,7 @@ SipRegistrationClient::SipRegistrationClient(
     pjsip_regc_create(pjEndpoint, this, regCallback, &mReg);
 
     std::vector<pj_str_t> pjContacts;
-    std::transform(contacts.begin(), contacts.end(), std::back_inserter(pjContacts), MakeContact(mReg));
+    std::transform(confItem->contacts.begin(), confItem->contacts.end(), std::back_inserter(pjContacts), MakeContact(mReg));
 
     SipEndpointConfig& config = sipEndpoint->getConfig();
     std::stringstream server;
@@ -159,10 +159,8 @@ SipRegistrationClient::SipRegistrationClient(
     pj_str_t fromURL;
     pj_strdup2(pjsip_regc_get_pool(mReg), &fromURL, from.str().c_str());
 
-    std::stringstream to;
-    to << "<sip:" << mEndpointName << "@" << config.transportConfig.address << ">";
     pj_str_t toURL;
-    pj_strdup2(pjsip_regc_get_pool(mReg), &toURL, to.str().c_str());
+    pj_strdup2(pjsip_regc_get_pool(mReg), &toURL, confItem->aor.c_str());
 
     pjsip_regc_init(
             mReg,
@@ -171,10 +169,10 @@ SipRegistrationClient::SipRegistrationClient(
             &toURL,
             pjContacts.size(),
             &pjContacts.front(),
-            PJSIP_REGC_EXPIRATION_NOT_SPECIFIED
+            confItem->defaultExpiration
             );
 
-    addContacts(contacts);
+    addContacts(confItem->contacts);
 }
 
 SipRegistrationClient::~SipRegistrationClient()
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 9903966..601d41b 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -71,7 +71,7 @@ class SipRegistrationClient : public IceUtil::Shared
 {
 public:
     SipRegistrationClient(
-            const AsteriskSCF::Configuration::SipSessionManager::V1::ContactInfoSeq& contacts,
+            const AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemPtr& confItem,
             pjsip_endpoint* pjEndpoint,
             const SipEndpointPtr& sipEndpoint,
             const SipRegistrationClientManagerPtr manager);
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index e2d9124..b39fcc7 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -331,7 +331,7 @@ void SipEndpoint::updateClientRegistrations(SipClientRegistrationItemSeq& items)
         {
             //New one!
             mImplPriv->mClientRegistrations[(*item)->aor] =
-                new SipRegistrationClient((*item)->contacts, mImplPriv->mManager->getEndpoint(), this, mImplPriv->mManager->getClientRegistrationManager());
+                new SipRegistrationClient(*item, mImplPriv->mManager->getEndpoint(), this, mImplPriv->mManager->getClientRegistrationManager());
         }
     }
 }

commit ed015861dae9dbf07fa1795d6babb1e1fd0b205f
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Sep 7 15:44:11 2011 -0500

    Make sure that the SipRegistrationClientManager is populated properly.
    
    This fixes segfaults I was seeing earlier.

diff --git a/src/PJSipManager.cpp b/src/PJSipManager.cpp
index 4d60459..a73ee76 100644
--- a/src/PJSipManager.cpp
+++ b/src/PJSipManager.cpp
@@ -257,12 +257,18 @@ pj_pool_t* PJSipManager::getMemoryPool()
     return mMemoryPool;
 }
 
+SipRegistrationClientManagerPtr PJSipManager::getClientRegistrationManager() const
+{
+    return mClientRegistrationManager;
+}
+
 PJSipManager::PJSipManager() :
     mEndpoint(0),
     mSessionModule(0),
     mLoggingModule(0),
     mPjThread(0),
-    mMemoryPool(0)
+    mMemoryPool(0),
+    mClientRegistrationManager(new SipRegistrationClientManager)
 {
     memset(&mCachingPool, 0, sizeof(mCachingPool));
 
diff --git a/src/PJSipManager.h b/src/PJSipManager.h
index fe25567..d485c14 100644
--- a/src/PJSipManager.h
+++ b/src/PJSipManager.h
@@ -36,6 +36,7 @@
 #include "SipModule.h"
 #include "PJSipRegistrarModule.h"
 #include "SipReplicationContext.h"
+#include "SipClientRegistration.h"
 
 namespace AsteriskSCF
 {
@@ -130,6 +131,8 @@ public:
 
     void handleEvents();
 
+    SipRegistrationClientManagerPtr getClientRegistrationManager() const;
+
 private:
     pjsip_endpoint *mEndpoint;
     PJSipSessionModulePtr mSessionModule;
@@ -143,6 +146,8 @@ private:
     SipModuleMap mModules;
     std::map<std::string, TransportPtr> mTransports;
 
+    SipRegistrationClientManagerPtr mClientRegistrationManager;
+
     PJSipManager();
 };
 
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index 529f388..dbf05d1 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -138,8 +138,9 @@ AuthHookSeq SipRegistrationClientManager::getAuthHooks()
 SipRegistrationClient::SipRegistrationClient(
         const ContactInfoSeq& contacts,
         pjsip_endpoint* pjEndpoint,
-        const SipEndpointPtr& sipEndpoint)
-    : mEndpointName(sipEndpoint->getName())
+        const SipEndpointPtr& sipEndpoint,
+        const SipRegistrationClientManagerPtr manager)
+    : mEndpointName(sipEndpoint->getName()), mManager(manager)
 {
     pjsip_regc_create(pjEndpoint, this, regCallback, &mReg);
 
@@ -217,7 +218,6 @@ void SipRegistrationClient::sendRegister()
     //Then we can simply call pjsip_regc_update_contact, then pjsip_regc_register,
     //and then pjsip_regc_send. Simple-dimple.
 
-#if 0
     Ice::StringSeq allow = mManager->getAllow();
     Ice::StringSeq supported = mManager->getSupported();
 
@@ -225,7 +225,6 @@ void SipRegistrationClient::sendRegister()
     //we have registration messages being sent out properly.
     (void) allow;
     (void) supported;
-#endif
 
     std::vector<pj_str_t> contacts;
     std::transform(mContacts.begin(), mContacts.end(), std::back_inserter(contacts), MakeContact(mReg));
@@ -251,7 +250,9 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
     case 407:
     {
         //We must authenticate!
+        lg(Debug) << "Hi!";
         authenticate(param->rdata);
+        lg(Debug) << "Bye!";
         break;
     }
     default:
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 8c62e44..9903966 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -73,7 +73,8 @@ public:
     SipRegistrationClient(
             const AsteriskSCF::Configuration::SipSessionManager::V1::ContactInfoSeq& contacts,
             pjsip_endpoint* pjEndpoint,
-            const SipEndpointPtr& sipEndpoint);
+            const SipEndpointPtr& sipEndpoint,
+            const SipRegistrationClientManagerPtr manager);
 
     ~SipRegistrationClient();
 
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 26ec264..e2d9124 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -331,7 +331,7 @@ void SipEndpoint::updateClientRegistrations(SipClientRegistrationItemSeq& items)
         {
             //New one!
             mImplPriv->mClientRegistrations[(*item)->aor] =
-                new SipRegistrationClient((*item)->contacts, mImplPriv->mManager->getEndpoint(), this);
+                new SipRegistrationClient((*item)->contacts, mImplPriv->mManager->getEndpoint(), this, mImplPriv->mManager->getClientRegistrationManager());
         }
     }
 }

commit 57946244283425c9a3c698634d4cb69355ecab50
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Sep 7 15:05:43 2011 -0500

    A number of bug fixes found while testing registration:
    
    1) Added post-config processing to configuration. This clears up an
    issue where we referred to a seemingly nonexistent registration group
    in an endpoint's config.
    
    2) Use dynamic allocation for pj strings. This was definitely necessary
    for contacts, but I went ahead and used it elsewhere because I felt like
    it.
    
    3) Fixed a logic error where square brackets were being added to IPv4
    addresses due to a faulty understanding of std::string::find()
    
    Current problems include:
    1) Not enough data is passed to the client registration constructor so
    the default expiration and correct AOR are not present.
    2) I experienced a crash when a 401 was returned from the registrar.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 12d71ba..623b975 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -102,8 +102,6 @@ class SipSectionVisitors(Configurator.SectionVisitors):
 
         self.groups.append(group)
 
-    def visit_registration_contacts(self, section, option):
-            
     def visit_registration(self, config, section):
 
         class RegistrationContactHandler:
@@ -117,7 +115,7 @@ class SipSectionVisitors(Configurator.SectionVisitors):
                 for contact in contacts:
                     uri, slash, expiration = contact.partition('/')
                     info = AsteriskSCF.Configuration.SipSessionManager.V1.ContactInfo()
-                    info.contactUri = uri
+                    info.contactURI = uri
                     info.expiration = int(expiration)
                     ret.append(info)
 
@@ -132,7 +130,7 @@ class SipSectionVisitors(Configurator.SectionVisitors):
         item = AsteriskSCF.Configuration.SipSessionManager.V1.SipClientRegistrationItem()
 
         mapper.map('aor', item, 'aor', 'registration', config.get, None)
-        mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, None)
+        mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, AsteriskSCF.Configuration.SipSessionManager.V1.DefaultExpiration)
         handler = RegistrationContactHandler(config)
         mapper.map('contacts', item, 'contacts', 'registration', handler.get, None)
 
@@ -283,6 +281,16 @@ class SipSectionVisitors(Configurator.SectionVisitors):
         except:
             print 'No configured formats for endpoint ' + section
 
+        try:
+            registrations = config.get(section, 'registrations')
+            registrationList = registrations.split(',')
+            for reg in registrationList:
+                item = AsteriskSCF.Configuration.SipSessionManager.V1.SipRegistrationGroupRef()
+                item.registrationGroupName = reg
+                group.configurationItems[reg] = item
+        except:
+            pass
+
         self.groups.append(group)
 
     def visit_unsupported(self, config, section):
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index a7b9d83..529f388 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -16,9 +16,13 @@
 
 #include "SipClientRegistration.h"
 
+using namespace AsteriskSCF::System::Logging;
+
 namespace
 {
 
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.SipSessionManager");
+
 using namespace AsteriskSCF::SipSessionManager;
 using namespace AsteriskSCF::System::Hook::V1;
 using namespace AsteriskSCF::Configuration::SipSessionManager::V1;
@@ -55,13 +59,23 @@ struct EqualContacts
     const std::string mContact;
 };
 
-pj_str_t makeContact(const ContactInfo& info)
+
+struct MakeContact
 {
-    std::stringstream str;
-    str << info.contactURI << ";expires=" << info.expiration;
-    pj_str_t ret;
-    pj_cstr(&ret, str.str().c_str());
-    return ret;
+    MakeContact(pjsip_regc * reg)
+        : mReg(reg) { }
+
+    pj_str_t operator() (const ContactInfo& info)
+    {
+        lg(Debug) << "Making contact from " << info.contactURI << " and " << info.expiration;
+        std::stringstream str;
+        str << info.contactURI << ";expires=" << info.expiration;
+        pj_str_t ret;
+        pj_strdup2(pjsip_regc_get_pool(mReg), &ret, str.str().c_str());
+        return ret;
+    };
+
+    pjsip_regc *mReg;
 };
 
 /**
@@ -130,24 +144,24 @@ SipRegistrationClient::SipRegistrationClient(
     pjsip_regc_create(pjEndpoint, this, regCallback, &mReg);
 
     std::vector<pj_str_t> pjContacts;
-    std::transform(contacts.begin(), contacts.end(), std::back_inserter(pjContacts), makeContact);
+    std::transform(contacts.begin(), contacts.end(), std::back_inserter(pjContacts), MakeContact(mReg));
 
     SipEndpointConfig& config = sipEndpoint->getConfig();
     std::stringstream server;
     server << "sip:" << config.transportConfig.address;
 
     pj_str_t serverURL;
-    pj_cstr(&serverURL, server.str().c_str());
+    pj_strdup2(pjsip_regc_get_pool(mReg), &serverURL, server.str().c_str());
 
     std::stringstream from;
     from << "\"" << mEndpointName << "\" <sip:" << mEndpointName << "@" << config.transportConfig.address <<  ">";
     pj_str_t fromURL;
-    pj_cstr(&fromURL, from.str().c_str());
+    pj_strdup2(pjsip_regc_get_pool(mReg), &fromURL, from.str().c_str());
 
     std::stringstream to;
     to << "<sip:" << mEndpointName << "@" << config.transportConfig.address << ">";
     pj_str_t toURL;
-    pj_cstr(&toURL, to.str().c_str());
+    pj_strdup2(pjsip_regc_get_pool(mReg), &toURL, to.str().c_str());
 
     pjsip_regc_init(
             mReg,
@@ -203,6 +217,7 @@ void SipRegistrationClient::sendRegister()
     //Then we can simply call pjsip_regc_update_contact, then pjsip_regc_register,
     //and then pjsip_regc_send. Simple-dimple.
 
+#if 0
     Ice::StringSeq allow = mManager->getAllow();
     Ice::StringSeq supported = mManager->getSupported();
 
@@ -210,9 +225,10 @@ void SipRegistrationClient::sendRegister()
     //we have registration messages being sent out properly.
     (void) allow;
     (void) supported;
+#endif
 
     std::vector<pj_str_t> contacts;
-    std::transform(mContacts.begin(), mContacts.end(), std::back_inserter(contacts), makeContact);
+    std::transform(mContacts.begin(), mContacts.end(), std::back_inserter(contacts), MakeContact(mReg));
 
     pjsip_regc_update_contact(mReg, contacts.size(), &contacts.front());
 
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index d669f8c..047c7f5 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -137,6 +137,8 @@ static void performSerialCheck(const ConfigurationItemDict& changedItems, const
 typedef boost::function<void()> UpdateCommand;
 typedef vector<UpdateCommand> UpdateCommandList;
 
+UpdateCommandList postProcesses;
+
 class ConfigBase
 {
 public:
@@ -296,6 +298,8 @@ class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfi
         };
         void visitSipRegistrationGroupRef(const SipRegistrationGroupRefPtr& registration)
         {
+            //Since this refers to a group that may not have been processed yet,
+            //we defer it until later.
             mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateRegistration, mConfig, registration));
         }
 
@@ -411,24 +415,38 @@ public:
 
     void updateRegistration(const SipRegistrationGroupRefPtr& registration)
     {
-        RegistrationConfigMap::const_iterator entry =
-            mRegistrationConfigMap.find(registration->registrationGroupName);
+        mClientRegistrations.push_back(registration->registrationGroupName);
+    }
 
-        if (entry == mRegistrationConfigMap.end())
+    void postUpdateRegistration(const Ice::StringSeq& regs)
+    {
+        SipClientRegistrationItemSeq regItems;
+        for (Ice::StringSeq::const_iterator strIter = regs.begin();
+                strIter != regs.end(); ++strIter)
         {
-            //Group doesn't exist.
-            return;
-        }
+            RegistrationConfigMap::const_iterator entry =
+                mRegistrationConfigMap.find(*strIter);
 
-        SipClientRegistrationItemPtr item = entry->second->getClientRegistrationItem();
+            if (entry == mRegistrationConfigMap.end())
+            {
+                //Group doesn't exist.
+                return;
+            }
+
+            SipClientRegistrationItemPtr item = entry->second->getClientRegistrationItem();
+
+            if (item == 0)
+            {
+                //Group doesn't have a configuration item.
+                return;
+            }
 
-        if (item == 0)
+            regItems.push_back(item);
+        }
+        if (!regItems.empty())
         {
-            //Group doesn't have a configuration item.
-            return;
+            mEndpoint->updateClientRegistrations(regItems);
         }
-
-        mClientRegistrations.push_back(item);
     }
 
     void updated(const UpdateCommandList& updates)
@@ -451,7 +469,7 @@ public:
             }
             if (!mClientRegistrations.empty())
             {
-                mEndpoint->updateClientRegistrations(mClientRegistrations);
+                postProcesses.push_back(boost::bind(&EndpointConfigHelper::postUpdateRegistration, shared_from_this(), mClientRegistrations));
             }
             if (updateSystem)
             {
@@ -470,7 +488,7 @@ private:
     boost::shared_ptr<SipEndpointFactory> mFactory;
     LocatorRegistrySmartPrx mRegistry;
     string mRoutingId;
-    SipClientRegistrationItemSeq mClientRegistrations;
+    Ice::StringSeq mClientRegistrations;
 };
 
 /**
@@ -1607,6 +1625,16 @@ static void genericSet(const ConfigurationDataPtr& config, const T& group)
     }
 }
 
+static void runPostProcessing()
+{
+    for (UpdateCommandList::iterator iter = postProcesses.begin();
+            iter != postProcesses.end(); ++iter)
+    {
+        UpdateCommand command = *iter;
+        command();
+    }
+}
+
 void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Configuration::V1::ConfigurationGroupSeq& groups,
         const Ice::Current&)
 {
@@ -1665,10 +1693,13 @@ void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Confi
     
     SipConfigurationGroupVisitorPtr v = new GroupsVisitor(this);
     
+    postProcesses.clear();
     for (ConfigurationGroupSeq::const_iterator group = groups.begin(); group != groups.end(); ++group)
     {
 	(*group)->visit(v);
     }
+
+    runPostProcessing();
 }
 
 void ConfigurationServiceImpl::removeConfigurationItems(
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 128a928..26ec264 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -286,7 +286,7 @@ void SipEndpoint::setTargetAddress(std::string address, int port)
     char target[64];
     //If we're dealing with an IPv6 address that is not surrounded by square
     //brackets, we need to adjust for that.
-    if (address.find(':') && 
+    if (address.find(':') != std::string::npos && 
             (address.at(0) != '[' && address.at(address.length() - 1) != ']'))
     {
         pj_ansi_snprintf(target, sizeof(target), "[%s]:%d", address.c_str(), port);
@@ -315,6 +315,7 @@ void SipEndpoint::setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V
 
 void SipEndpoint::updateClientRegistrations(SipClientRegistrationItemSeq& items)
 {
+    lg(Debug) << "Updating client registrations for endpoint " << mImplPriv->mName;
     for (SipClientRegistrationItemSeq::iterator item = items.begin();
             item != items.end(); ++item)
     {

commit f5e26ad62bc18858e6e12a5c6e1addf1eb709a8a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Sep 6 18:41:44 2011 -0500

    Allow for multiple client registrations to be added to an endpoint.

diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index c93aa22..c972cf5 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -550,6 +550,8 @@ class SipClientRegistrationItem extends SipConfigurationItem
     int defaultExpiration;
 };
 
+sequence<SipClientRegistrationItem> SipClientRegistrationItemSeq;
+
 class SipRegistrationGroupRef extends SipConfigurationItem
 {
     string registrationGroupName;
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index de2b10f..d669f8c 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -428,7 +428,7 @@ public:
             return;
         }
 
-        mEndpoint->updateClientRegistration(item);
+        mClientRegistrations.push_back(item);
     }
 
     void updated(const UpdateCommandList& updates)
@@ -449,6 +449,10 @@ public:
                 UpdateCommand command = *op;
                 command();
             }
+            if (!mClientRegistrations.empty())
+            {
+                mEndpoint->updateClientRegistrations(mClientRegistrations);
+            }
             if (updateSystem)
             {
                 mFactory->generateRoutingDestinations(destinations);
@@ -466,6 +470,7 @@ private:
     boost::shared_ptr<SipEndpointFactory> mFactory;
     LocatorRegistrySmartPrx mRegistry;
     string mRoutingId;
+    SipClientRegistrationItemSeq mClientRegistrations;
 };
 
 /**
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index d98bb01..128a928 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -37,6 +37,7 @@ using namespace AsteriskSCF::Core::Discovery::V1;
 using namespace AsteriskSCF::SessionCommunications::V1;
 using namespace AsteriskSCF::Replication::SipSessionManager::V1;
 using namespace AsteriskSCF::Discovery;
+using namespace AsteriskSCF::Configuration::SipSessionManager::V1;
 
 namespace
 {
@@ -312,21 +313,25 @@ void SipEndpoint::setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V
     mImplPriv->mConfig.sessionConfig.dtmf = dtmf;
 }
 
-void SipEndpoint::updateClientRegistration(AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemPtr& item)
+void SipEndpoint::updateClientRegistrations(SipClientRegistrationItemSeq& items)
 {
-    std::map<std::string, SipRegistrationClientPtr>::iterator iter =
-        mImplPriv->mClientRegistrations.find(item->aor);
-
-    if (iter != mImplPriv->mClientRegistrations.end())
+    for (SipClientRegistrationItemSeq::iterator item = items.begin();
+            item != items.end(); ++item)
     {
-        //Updating one that exists
-        iter->second->addContacts(item->contacts);
-    }
-    else
-    {
-        //New one!
-        mImplPriv->mClientRegistrations[item->aor] =
-            new SipRegistrationClient(item->contacts, mImplPriv->mManager->getEndpoint(), this);
+        std::map<std::string, SipRegistrationClientPtr>::iterator iter =
+            mImplPriv->mClientRegistrations.find((*item)->aor);
+
+        if (iter != mImplPriv->mClientRegistrations.end())
+        {
+            //Updating one that exists
+            iter->second->addContacts((*item)->contacts);
+        }
+        else
+        {
+            //New one!
+            mImplPriv->mClientRegistrations[(*item)->aor] =
+                new SipRegistrationClient((*item)->contacts, mImplPriv->mManager->getEndpoint(), this);
+        }
     }
 }
 
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index f0a3e33..9ee243f 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -355,7 +355,7 @@ public:
     AsteriskSCF::Media::V1::StreamInformationDict getStreamTopology();
     void setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf);
 
-    void updateClientRegistration(AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemPtr& item);
+    void updateClientRegistrations(AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemSeq& items);
 
     void addDefaultSessionCookie(
         const AsteriskSCF::SessionCommunications::V1::SessionCookiePtr& cookie);

commit a87f0035311d0650068152e5ef476d18c83603b4
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Sep 6 18:15:49 2011 -0500

    Add the rest of the configuration operations.

diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index 7eed40e..de2b10f 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -892,6 +892,7 @@ public:
         mRoutingId(routingId), 
         mRoutingServiceLocatorRegistry(registry) 
     {
+        mRegistrationConfigMap.clear();
     }
 
     /**
@@ -1038,6 +1039,20 @@ public:
         }
     }
 
+    void remove(const SipRegistrationGroupPtr& group)
+    {
+        RegistrationConfigPtr config;
+        {
+            boost::unique_lock<boost::shared_mutex> lock(mLock);
+            RegistrationConfigMap::iterator i = mRegistrationConfigMap.find(group->name);
+            if (i != mRegistrationConfigMap.end())
+            {
+                config = i->second;
+                mRegistrationConfigMap.erase(i);
+            }
+        }
+    }
+
     SipGeneralGroupPtr getGroupFor(const SipGeneralGroupPtr&)
     {
         return mGroup;
@@ -1466,6 +1481,11 @@ ConfigurationGroupSeq ConfigurationServiceImpl::getConfiguration(
             getGeneric<SipEndpointGroupPtr>(mImpl->getData(), group, mGroups);
 	};
 
+    void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
+    {
+        getGeneric<SipRegistrationGroupPtr>(mImpl->getData(), group, mGroups);
+    }
+
 	ConfigurationServiceImplPtr mImpl;
 	ConfigurationGroupSeq& mGroups;
     };
@@ -1539,6 +1559,11 @@ ConfigurationGroupSeq ConfigurationServiceImpl::getConfigurationAll(
             genericGetAll<SipEndpointGroupPtr>(mImpl->getData(), group, mGroups);
 	};
 
+    void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
+    {
+        genericGetAll<SipRegistrationGroupPtr>(mImpl->getData(), group, mGroups);
+    }
+
 	ConfigurationServiceImplPtr mImpl;
 	ConfigurationGroupSeq& mGroups;
     };
@@ -1686,6 +1711,11 @@ void ConfigurationServiceImpl::removeConfigurationItems(
         {
             mImpl->getData()->removeFromGroup(group);
         };
+
+        void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
+        {
+            mImpl->getData()->removeFromGroup(group);
+        }
     private:
 	ConfigurationServiceImplPtr mImpl;
     };
@@ -1742,6 +1772,11 @@ void ConfigurationServiceImpl::removeConfigurationGroups(
             mImpl->getData()->remove(group);
         };
 
+        void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
+        {
+            mImpl->getData()->remove(group);
+        }
+
 	ConfigurationServiceImplPtr mImpl;
     };
     

commit f0afa67a194945ba8f9054c74efbc91d6502c72e
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Sep 6 17:59:30 2011 -0500

    Add code to be able to configure new client registrations for an endpoint.
    
    Next step is to add configuration code so things can be removed.

diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 3dba430..c93aa22 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -525,7 +525,7 @@ struct ContactInfo
      * Expiration for this contact in seconds
      */
     int expiration;
-}
+};
 
 sequence<ContactInfo> ContactInfoSeq;
 
@@ -550,6 +550,11 @@ class SipClientRegistrationItem extends SipConfigurationItem
     int defaultExpiration;
 };
 
+class SipRegistrationGroupRef extends SipConfigurationItem
+{
+    string registrationGroupName;
+};
+
 }; /* module V1 */
 
 }; /* module SipSessionManager */
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index cadc360..a7b9d83 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -21,6 +21,7 @@ namespace
 
 using namespace AsteriskSCF::SipSessionManager;
 using namespace AsteriskSCF::System::Hook::V1;
+using namespace AsteriskSCF::Configuration::SipSessionManager::V1;
 
 void regCallback(struct pjsip_regc_cbparam *param)
 {
@@ -31,14 +32,14 @@ void regCallback(struct pjsip_regc_cbparam *param)
     client->handleRegisterResponse(param);
 }
 
-bool operator< (const RegPair& lhs, const RegPair& rhs)
+bool operator< (const ContactInfo& lhs, const ContactInfo& rhs)
 {
-    return lhs.first < rhs.first;
+    return lhs.contactURI < rhs.contactURI;
 }
 
-bool operator== (const RegPair& lhs, const RegPair& rhs)
+bool operator== (const ContactInfo& lhs, const ContactInfo& rhs)
 {
-    return lhs.first == rhs.first;
+    return lhs.contactURI == rhs.contactURI;
 }
 
 struct EqualContacts
@@ -46,18 +47,18 @@ struct EqualContacts
     EqualContacts(const std::string& str)
         :mContact(str) { }
 
-    bool operator()(const RegPair& pair) 
+    bool operator()(const ContactInfo& info) 
     {
-        return pair.first == mContact;
+        return info.contactURI == mContact;
     }
 
     const std::string mContact;
 };
 
-pj_str_t makeContact(const RegPair& pair)
+pj_str_t makeContact(const ContactInfo& info)
 {
     std::stringstream str;
-    str << pair.first << ";expires=" << pair.second;
+    str << info.contactURI << ";expires=" << info.expiration;
     pj_str_t ret;
     pj_cstr(&ret, str.str().c_str());
     return ret;
@@ -121,7 +122,7 @@ AuthHookSeq SipRegistrationClientManager::getAuthHooks()
 }
 
 SipRegistrationClient::SipRegistrationClient(
-        const RegPairSeq& contacts,
+        const ContactInfoSeq& contacts,
         pjsip_endpoint* pjEndpoint,
         const SipEndpointPtr& sipEndpoint)
     : mEndpointName(sipEndpoint->getName())
@@ -166,7 +167,7 @@ SipRegistrationClient::~SipRegistrationClient()
     pjsip_regc_destroy(mReg);
 }
 
-void SipRegistrationClient::addContacts(const RegPairSeq& contacts)
+void SipRegistrationClient::addContacts(const ContactInfoSeq& contacts)
 {
     unique_add(mContacts, contacts);
 
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 4e40ae1..8c62e44 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -19,6 +19,8 @@
 #include <boost/thread.hpp>
 #include <pjsip_ua.h>
 
+#include <AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.h>
+
 #include "SipEndpoint.h"
 #include "AuthManager.h"
 
@@ -60,26 +62,22 @@ private:
 
 typedef IceUtil::Handle<SipRegistrationClientManager> SipRegistrationClientManagerPtr;
 
-
-typedef std::pair<std::string, int> RegPair;
-typedef std::vector<RegPair> RegPairSeq;
-
 /**
  * One of these exists per endpoint.
  * This takes care of sending REGISTER
  * to the configured endpoint.
  */
-class SipRegistrationClient
+class SipRegistrationClient : public IceUtil::Shared
 {
 public:
     SipRegistrationClient(
-            const RegPairSeq& contacts,
+            const AsteriskSCF::Configuration::SipSessionManager::V1::ContactInfoSeq& contacts,
             pjsip_endpoint* pjEndpoint,
             const SipEndpointPtr& sipEndpoint);
 
     ~SipRegistrationClient();
 
-    void addContacts(const RegPairSeq& contacts);
+    void addContacts(const AsteriskSCF::Configuration::SipSessionManager::V1::ContactInfoSeq& contacts);
 
     void removeContacts(const Ice::StringSeq& contacts);
 
@@ -92,10 +90,12 @@ private:
     void authenticate(pjsip_rx_data *rdata);
 
     const std::string mEndpointName;
-    RegPairSeq mContacts;
+    AsteriskSCF::Configuration::SipSessionManager::V1::ContactInfoSeq mContacts;
     SipRegistrationClientManagerPtr mManager;
     pjsip_regc* mReg;
 };
 
+typedef IceUtil::Handle<SipRegistrationClient> SipRegistrationClientPtr;
+
 }
 }
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index d6a342a..7eed40e 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -137,6 +137,72 @@ static void performSerialCheck(const ConfigurationItemDict& changedItems, const
 typedef boost::function<void()> UpdateCommand;
 typedef vector<UpdateCommand> UpdateCommandList;
 
+class ConfigBase
+{
+public:
+    virtual ~ConfigBase() {}
+
+    virtual SipConfigurationItemVisitorPtr getVisitor() { return 0; }
+};
+typedef boost::shared_ptr<ConfigBase> ConfigBasePtr;
+
+class RegistrationConfig : public ConfigBase, public boost::enable_shared_from_this<RegistrationConfig>
+{
+    class Visitor : public SipConfigurationItemVisitor
+    {
+    public:
+        Visitor(const boost::shared_ptr<RegistrationConfig>& config)
+            : mConfig(config) { }
+
+        void visitSipClientRegistrationItem(const SipClientRegistrationItemPtr& item)
+        {
+            mConfig->update(item);
+        }
+    private:
+        boost::shared_ptr<RegistrationConfig> mConfig;
+    };
+
+public:
+
+    RegistrationConfig(const SipRegistrationGroupPtr& group)
+        : mGroup(group) { }
+
+    SipConfigurationItemVisitorPtr getVisitor()
+    {
+        return new Visitor(shared_from_this());
+    }
+
+    void update(const SipClientRegistrationItemPtr& item)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+        mItem = item;
+    }
+
+    SipRegistrationGroupPtr getTypedGroup() const
+    {
+        return mGroup;
+    }
+
+    SipClientRegistrationItemPtr getClientRegistrationItem()
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        return mItem;
+    }
+
+private:
+
+    boost::shared_mutex mLock;
+
+    SipClientRegistrationItemPtr mItem;
+
+    mutable SipRegistrationGroupPtr mGroup;
+};
+
+typedef boost::shared_ptr<RegistrationConfig> RegistrationConfigPtr;
+typedef std::map<std::string, RegistrationConfigPtr> RegistrationConfigMap;
+
+RegistrationConfigMap mRegistrationConfigMap;
+
 /**
  * A helper class and visitor for propogating configuration changes to the SIPEndPoint implementation.
  **/
@@ -228,6 +294,10 @@ class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfi
         {
             mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDTMF, mConfig, dtmf));
         };
+        void visitSipRegistrationGroupRef(const SipRegistrationGroupRefPtr& registration)
+        {
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateRegistration, mConfig, registration));
+        }
 
     private:
 
@@ -333,11 +403,34 @@ public:
     {
         mEndpoint->setSignalingNATOptions(item->stun);
     }
+
     void updateDTMF(const SipDTMFItemPtr& dtmf)
     {
         mEndpoint->setDTMFMethod(dtmf->dtmf);
     }
 
+    void updateRegistration(const SipRegistrationGroupRefPtr& registration)
+    {
+        RegistrationConfigMap::const_iterator entry =
+            mRegistrationConfigMap.find(registration->registrationGroupName);
+
+        if (entry == mRegistrationConfigMap.end())
+        {
+            //Group doesn't exist.
+            return;
+        }
+
+        SipClientRegistrationItemPtr item = entry->second->getClientRegistrationItem();
+
+        if (item == 0)
+        {
+            //Group doesn't have a configuration item.
+            return;
+        }
+
+        mEndpoint->updateClientRegistration(item);
+    }
+
     void updated(const UpdateCommandList& updates)
     {
         //
@@ -375,15 +468,6 @@ private:
     string mRoutingId;
 };
 
-class ConfigBase
-{
-public:
-    virtual ~ConfigBase() {}
-
-    virtual SipConfigurationItemVisitorPtr getVisitor() { return 0; }
-};
-typedef boost::shared_ptr<ConfigBase> ConfigBasePtr;
-
 /**
  * The Transport specializations take care of any transport specific configuration and
  * initialization. The UDP and TCP transports are so similar that they could probably
@@ -1035,6 +1119,16 @@ public:
         return 0;
     }
 
+    const SipRegistrationGroupPtr getGroupFor(const SipRegistrationGroupPtr& group)
+    {
+        RegistrationConfigMap::const_iterator i;
+        if (getItem(mRegistrationConfigMap, i, group->name))
+        {
+            return i->second->getTypedGroup();
+        }
+        return 0;
+    }
+
 private:
 
     boost::shared_mutex mLock;
@@ -1217,6 +1311,23 @@ private:
         return transport->getVisitor();
     }
 
+    SipConfigurationItemVisitorPtr updateGroup(const SipRegistrationGroupPtr& group)
+    {
+        RegistrationConfigMap::const_iterator i;
+        RegistrationConfigPtr registrationConfig;
+        if (!getItem(mRegistrationConfigMap, i, group->name))
+        {
+            registrationConfig.reset(new RegistrationConfig(group));
+            mRegistrationConfigMap.insert(make_pair(group->name, registrationConfig));
+        }
+        else
+        {
+            registrationConfig = i->second;
+        }
+
+        return registrationConfig->getVisitor();
+    }
+
     template <class T>
     void copyTemplates(ConfigurationGroupSeq& groups, const T& items)
     {
@@ -1513,6 +1624,11 @@ void ConfigurationServiceImpl::setConfiguration(const AsteriskSCF::System::Confi
         {
             genericSet<SipEndpointGroupPtr>(mImpl->getData(), group);
         };
+
+        void visitSipRegistrationGroup(const SipRegistrationGroupPtr& group)
+        {
+            genericSet<SipRegistrationGroupPtr>(mImpl->getData(), group);
+        }
 	
 	ConfigurationServiceImplPtr mImpl;
     };
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index f88691b..d98bb01 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -16,6 +16,7 @@
 #include "PJSipManager.h"
 #include "SipEndpointFactory.h"
 #include "SipSession.h"
+#include "SipClientRegistration.h"
 #include <Ice/Ice.h>
 #include <IceUtil/UUID.h>
 
@@ -238,6 +239,8 @@ public:
     SipReplicationContextPtr mReplicationContext;
     AsteriskSCF::Collections::ProxySet<SessionListenerPrx>::SetPtr mDefaultListeners;
     AsteriskSCF::Collections::HandleSet<SessionCookiePtr>::SetPtr mDefaultSessionCookies;
+
+    std::map<std::string, SipRegistrationClientPtr> mClientRegistrations;
 };
 
 SipEndpoint::SipEndpoint(const Ice::ObjectAdapterPtr& adapter, 
@@ -309,6 +312,24 @@ void SipEndpoint::setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V
     mImplPriv->mConfig.sessionConfig.dtmf = dtmf;
 }
 
+void SipEndpoint::updateClientRegistration(AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemPtr& item)
+{
+    std::map<std::string, SipRegistrationClientPtr>::iterator iter =
+        mImplPriv->mClientRegistrations.find(item->aor);
+
+    if (iter != mImplPriv->mClientRegistrations.end())
+    {
+        //Updating one that exists
+        iter->second->addContacts(item->contacts);
+    }
+    else
+    {
+        //New one!
+        mImplPriv->mClientRegistrations[item->aor] =
+            new SipRegistrationClient(item->contacts, mImplPriv->mManager->getEndpoint(), this);
+    }
+}
+
 void SipEndpoint::setRTPOverIPv6(bool enabled)
 {
     mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index 80b9e2e..f0a3e33 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -355,6 +355,8 @@ public:
     AsteriskSCF::Media::V1::StreamInformationDict getStreamTopology();
     void setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf);
 
+    void updateClientRegistration(AsteriskSCF::Configuration::SipSessionManager::V1::SipClientRegistrationItemPtr& item);
+
     void addDefaultSessionCookie(
         const AsteriskSCF::SessionCommunications::V1::SessionCookiePtr& cookie);
 

commit 560f85b3223a130f3b8602ddcc8c36e87d8f9f50
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Sep 6 15:37:23 2011 -0500

    Add configuration items and configurator code for client registration.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 88639a8..12d71ba 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -102,6 +102,46 @@ class SipSectionVisitors(Configurator.SectionVisitors):
 
         self.groups.append(group)
 
+    def visit_registration_contacts(self, section, option):
+            
+    def visit_registration(self, config, section):
+
+        class RegistrationContactHandler:
+            def __init__(self, config):
+                self.config = config
+            def get(self, section, option):
+                setting = config.get(section, option)
+                contacts = setting.split(',')
+                ret = []
+
+                for contact in contacts:
+                    uri, slash, expiration = contact.partition('/')
+                    info = AsteriskSCF.Configuration.SipSessionManager.V1.ContactInfo()
+                    info.contactUri = uri
+                    info.expiration = int(expiration)
+                    ret.append(info)
+
+                return ret
+
+        group = AsteriskSCF.Configuration.SipSessionManager.V1.SipRegistrationGroup()
+        group.name = section
+        group.configurationItems = {}
+
+        mapper = Configurator.OptionMapper()
+
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipClientRegistrationItem()
+
+        mapper.map('aor', item, 'aor', 'registration', config.get, None)
+        mapper.map('expiration', item, 'defaultExpiration', 'registration', config.getint, None)
+        handler = RegistrationContactHandler(config)
+        mapper.map('contacts', item, 'contacts', 'registration', handler.get, None)
+
+        for option in config.options(section):
+            mapper.execute(group, section, option)
+        mapper.finish(group)
+
+        self.groups.append(group)
+
     def visit_endpoint(self, config, section):
         group = AsteriskSCF.Configuration.SipSessionManager.V1.SipEndpointGroup()
         group.name = section
@@ -254,6 +294,8 @@ class SipSectionVisitors(Configurator.SectionVisitors):
             self.visit_transport_tls(config, section)
         elif config.get(section, 'type') == 'endpoint':
             self.visit_endpoint(config, section)
+        elif config.get(section, 'type') == 'registration':
+            self.visit_registration(config, section)
 
 # In order to do service locator based lookup we need to pass in a params object
 serviceLocatorParams = AsteriskSCF.Core.Discovery.V1.ServiceLocatorParams()
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 6bddae5..3dba430 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -96,6 +96,18 @@ class SipDomainGroup extends SipConfigurationGroup
 };
 
 /**
+ * SIP Client Registration group. Used to configure
+ * parameters relating to client registration
+ */
+class SipRegistrationGroup extends SipConfigurationGroup
+{
+    /**
+     * Name for this registration group
+     */
+    string name;
+};
+
+/**
  * Domain item for bindings
  */
 class SipBindingsItem extends SipConfigurationItem
@@ -491,6 +503,53 @@ class SipDTMFItem extends SipConfigurationItem
     SipDTMFOption dtmf = RFC4733;
 };
 
+/**
+ * Information pertaining to a 
+ * contact bound to a specific AOR
+ */
+struct ContactInfo
+{
+    /**
+     * The URI for the contact. This
+     * will be fed in directly to the
+     * client registration code. This
+     * must be formatted as a SIP or SIPs
+     * URI. It may contain a display name.
+     *
+     * Examples:
+     * "Bob" <sip:bob at example.org>
+     * <sip:alice at example.org>
+     */
+    string contactURI;
+    /**
+     * Expiration for this contact in seconds
+     */
+    int expiration;
+}
+
+sequence<ContactInfo> ContactInfoSeq;
+
+const int DefaultExpiration = 3600;
+
+class SipClientRegistrationItem extends SipConfigurationItem
+{
+    /**
+     * The AOR to which the contacts will
+     * be bound.
+     */
+    string aor;
+    /**
+     * The contacts to bind to the AOR
+     */
+    ContactInfoSeq contacts;
+    /**
+     * The expiration to use for any contacts
+     * with no explicit expiration set. Units
+     * for expiration are seconds.
+     */
+    int defaultExpiration;
+};
+
 }; /* module V1 */
 
 }; /* module SipSessionManager */
diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index 9543aa2..cadc360 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -282,7 +282,7 @@ void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
                 pjsip_cred_info info;
                 pj_cstr(&info.realm, authIter->realm.c_str());
                 pj_cstr(&info.scheme, "digest");
-                pj_cstr(&info.username, authIter->user.c_str());
+                pj_cstr(&info.username, authIter->username.c_str());
                 pj_cstr(&info.data, authIter->password.c_str());
                 info.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
                 creds.push_back(info);

commit 07dde091d16b917b8c85536d8e7bfaaff77c8c31
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Sep 6 10:40:37 2011 -0500

    Add authentication support to client registration.
    
    The next step in this mess is to mess with configuration.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index 0706d0d..9543aa2 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -233,19 +233,8 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
     case 401:
     case 407:
     {
-        AuthHookSeq hooks = mManager->getAuthHooks();
-        for (AuthHookSeq::iterator iter = hooks.begin();
-                iter != hooks.end(); ++iter)
-        {
-            ClientAuthSeq auths;
-            Ice::StringSeq realms = getRealms(param->rdata);
-            HookResult result = (*iter)->getCredentials(mEndpointName, realms, auths);
-            if (result.status == Succeeded)
-            {
-                //Cool. So now we need to update the auth info on mReg
-            }
-        }
         //We must authenticate!
+        authenticate(param->rdata);
         break;
     }
     default:
@@ -270,5 +259,42 @@ Ice::StringSeq SipRegistrationClient::getRealms(pjsip_rx_data *rdata)
     return realms;
 }
 
+//XXX This function seems like it may fit better into AuthManager
+//or some more central place since it could be useful for authentication
+//responses for any type of request. This is not REGISTER-specific, in
+//other words.
+void SipRegistrationClient::authenticate(pjsip_rx_data *rdata)
+{
+    AuthHookSeq hooks = mManager->getAuthHooks();
+    for (AuthHookSeq::iterator iter = hooks.begin();
+            iter != hooks.end(); ++iter)
+    {
+        ClientAuthSeq auths;
+        Ice::StringSeq realms = getRealms(rdata);
+        HookResult result = (*iter)->getCredentials(mEndpointName, realms, auths);
+        if (result.status == Succeeded)
+        {
+            std::vector<pjsip_cred_info> creds;
+            //Cool. So now we need to update the auth info on mReg
+            for (ClientAuthSeq::iterator authIter = auths.begin();
+                    authIter != auths.end(); ++authIter)
+            {
+                pjsip_cred_info info;
+                pj_cstr(&info.realm, authIter->realm.c_str());
+                pj_cstr(&info.scheme, "digest");
+                pj_cstr(&info.username, authIter->user.c_str());
+                pj_cstr(&info.data, authIter->password.c_str());
+                info.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
+                creds.push_back(info);
+            }
+            if (creds.size() != 0)
+            {
+                pjsip_regc_set_credentials(mReg, creds.size(), &creds.front());
+                sendRegister();
+            }
+        }
+    }
+}
+
 }
 }
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 4e68ce5..4e40ae1 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -89,6 +89,8 @@ private:
 
     Ice::StringSeq getRealms(pjsip_rx_data *rdata);
 
+    void authenticate(pjsip_rx_data *rdata);
+
     const std::string mEndpointName;
     RegPairSeq mContacts;
     SipRegistrationClientManagerPtr mManager;

commit 9b2ad86fa457265c641ed3f68f8824fccc49fbdb
Author: Mark Michelson <mmichelson at digium.com>
Date:   Fri Sep 2 15:26:02 2011 -0500

    Add method to grab realms from the REGISTER response.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
index 6a07a1e..0706d0d 100644
--- a/src/SipClientRegistration.cpp
+++ b/src/SipClientRegistration.cpp
@@ -238,8 +238,8 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
                 iter != hooks.end(); ++iter)
         {
             ClientAuthSeq auths;
-            //XXX We need to extract the realms from the param->rdata.
-            HookResult result = (*iter)->getCredentials(mEndpointName, Ice::StringSeq(), auths);
+            Ice::StringSeq realms = getRealms(param->rdata);
+            HookResult result = (*iter)->getCredentials(mEndpointName, realms, auths);
             if (result.status == Succeeded)
             {
                 //Cool. So now we need to update the auth info on mReg
@@ -256,5 +256,19 @@ void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
     }
 }
 
+Ice::StringSeq SipRegistrationClient::getRealms(pjsip_rx_data *rdata)
+{
+    Ice::StringSeq realms;
+
+    pjsip_proxy_authenticate_hdr *authHeader = NULL;
+
+    while ((authHeader = (pjsip_proxy_authenticate_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_PROXY_AUTHENTICATE, authHeader)))
+    {
+        realms.push_back(std::string(pj_strbuf(&authHeader->challenge.digest.realm), pj_strlen(&authHeader->challenge.digest.realm)));
+    }
+
+    return realms;
+}
+
 }
 }
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index d1ac100..4e68ce5 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -87,6 +87,8 @@ public:
 private:
     void sendRegister();
 
+    Ice::StringSeq getRealms(pjsip_rx_data *rdata);
+
     const std::string mEndpointName;
     RegPairSeq mContacts;
     SipRegistrationClientManagerPtr mManager;

commit a7318e778be043b164a8d16c4bb7835811543f6a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Fri Sep 2 15:06:26 2011 -0500

    Add a skeleton for some response handling.

diff --git a/src/SipClientRegistration.cpp b/src/SipClientRegistration.cpp
new file mode 100644
index 0000000..6a07a1e
--- /dev/null
+++ b/src/SipClientRegistration.cpp
@@ -0,0 +1,260 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "SipClientRegistration.h"
+
+namespace
+{
+
+using namespace AsteriskSCF::SipSessionManager;
+using namespace AsteriskSCF::System::Hook::V1;
+
+void regCallback(struct pjsip_regc_cbparam *param)
+{
+    //I'd much rather be able to control things within the confines of my
+    //class thank you very much.
+
+    SipRegistrationClient *client = static_cast<SipRegistrationClient*>(param->token);
+    client->handleRegisterResponse(param);
+}
+
+bool operator< (const RegPair& lhs, const RegPair& rhs)
+{
+    return lhs.first < rhs.first;
+}
+
+bool operator== (const RegPair& lhs, const RegPair& rhs)
+{
+    return lhs.first == rhs.first;
+}
+
+struct EqualContacts
+{
+    EqualContacts(const std::string& str)
+        :mContact(str) { }
+
+    bool operator()(const RegPair& pair) 
+    {
+        return pair.first == mContact;
+    }
+
+    const std::string mContact;
+};
+
+pj_str_t makeContact(const RegPair& pair)
+{
+    std::stringstream str;
+    str << pair.first << ";expires=" << pair.second;
+    pj_str_t ret;
+    pj_cstr(&ret, str.str().c_str());
+    return ret;
+};
+
+/**
+ * Add new items to a vector, and remove duplicates.
+ * This is formulated so that if duplicates are added,
+ * the newer version will replace the old version in
+ * the vector
+ */
+template <class T>
+void unique_add(std::vector<T>& container, const std::vector<T>& stuffToAdd)
+{
+    container.insert(container.begin(), stuffToAdd.begin(), stuffToAdd.end());
+    std::stable_sort(container.begin(), container.end());
+    container.erase(std::unique(container.begin(), container.end()), container.end());
+}
+
+} // end anonymous namespace
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+using namespace AsteriskSCF::SIP::ExtensionPoint::V1;
+
+SipRegistrationClientManager::SipRegistrationClientManager()
+{
+}
+
+void SipRegistrationClientManager::addAllow(const Ice::StringSeq& allows)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    unique_add(mAllow, allows);
+}
+
+Ice::StringSeq SipRegistrationClientManager::getAllow()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    return mAllow;
+}
+
+void SipRegistrationClientManager::addSupported(const Ice::StringSeq& supporteds)
+{
+    boost::unique_lock<boost::shared_mutex> lock(mLock);
+    unique_add(mSupported, supporteds);
+}
+
+Ice::StringSeq SipRegistrationClientManager::getSupported()
+{
+    boost::shared_lock<boost::shared_mutex> lock(mLock);
+    return mSupported;
+}
+
+AuthHookSeq SipRegistrationClientManager::getAuthHooks()
+{
+    return AuthHookSeq();
+}
+
+SipRegistrationClient::SipRegistrationClient(
+        const RegPairSeq& contacts,
+        pjsip_endpoint* pjEndpoint,
+        const SipEndpointPtr& sipEndpoint)
+    : mEndpointName(sipEndpoint->getName())
+{
+    pjsip_regc_create(pjEndpoint, this, regCallback, &mReg);
+
+    std::vector<pj_str_t> pjContacts;
+    std::transform(contacts.begin(), contacts.end(), std::back_inserter(pjContacts), makeContact);
+
+    SipEndpointConfig& config = sipEndpoint->getConfig();
+    std::stringstream server;
+    server << "sip:" << config.transportConfig.address;
+
+    pj_str_t serverURL;
+    pj_cstr(&serverURL, server.str().c_str());
+
+    std::stringstream from;
+    from << "\"" << mEndpointName << "\" <sip:" << mEndpointName << "@" << config.transportConfig.address <<  ">";
+    pj_str_t fromURL;
+    pj_cstr(&fromURL, from.str().c_str());
+
+    std::stringstream to;
+    to << "<sip:" << mEndpointName << "@" << config.transportConfig.address << ">";
+    pj_str_t toURL;
+    pj_cstr(&toURL, to.str().c_str());
+
+    pjsip_regc_init(
+            mReg,
+            &serverURL,
+            &fromURL,
+            &toURL,
+            pjContacts.size(),
+            &pjContacts.front(),
+            PJSIP_REGC_EXPIRATION_NOT_SPECIFIED
+            );
+
+    addContacts(contacts);
+}
+
+SipRegistrationClient::~SipRegistrationClient()
+{
+    pjsip_regc_destroy(mReg);
+}
+
+void SipRegistrationClient::addContacts(const RegPairSeq& contacts)
+{
+    unique_add(mContacts, contacts);
+
+    sendRegister();
+}
+
+void SipRegistrationClient::removeContacts(const Ice::StringSeq& contacts)
+{
+    for (Ice::StringSeq::const_iterator iter = contacts.begin();
+            iter != contacts.end(); ++iter)
+    {
+        mContacts.erase(std::find_if(mContacts.begin(), mContacts.end(), EqualContacts(*iter)));
+    }
+
+    sendRegister();
+}
+
+void SipRegistrationClient::sendRegister()
+{
+    //The idea here is to send a REGISTER with all the info we know.
+    //
+    //What we do is create a contact array that pjsip can handle. PJSIP
+    //expects the contact URIs to just be strings. It will do the parsing
+    //for us.
+    //
+    //So what we need to do is to ask the SipRegistrationClientManager
+    //for what methods are allowed. We will add an Allow header with these
+    //methods.
+    //
+    //Then we need to ask the SipRegistrationClientManager for what stuff
+    //is supported and add that as a Supported: header.
+    //
+    //Then we can simply call pjsip_regc_update_contact, then pjsip_regc_register,
+    //and then pjsip_regc_send. Simple-dimple.
+
+    Ice::StringSeq allow = mManager->getAllow();
+    Ice::StringSeq supported = mManager->getSupported();
+
+    //For now don't worry about this stuff. We can add these headers in once
+    //we have registration messages being sent out properly.
+    (void) allow;
+    (void) supported;
+
+    std::vector<pj_str_t> contacts;
+    std::transform(mContacts.begin(), mContacts.end(), std::back_inserter(contacts), makeContact);
+
+    pjsip_regc_update_contact(mReg, contacts.size(), &contacts.front());
+
+    pjsip_tx_data *tdata;
+    pjsip_regc_register(mReg, PJ_TRUE, &tdata);
+    pjsip_regc_send(mReg, tdata);
+}
+
+void SipRegistrationClient::handleRegisterResponse(pjsip_regc_cbparam *param)
+{
+    switch (param->code)
+    {
+    case 100:
+        //Nobody cares
+        break;
+    case 200:
+        //This is a success!
+        break;
+    case 401:
+    case 407:
+    {
+        AuthHookSeq hooks = mManager->getAuthHooks();
+        for (AuthHookSeq::iterator iter = hooks.begin();
+                iter != hooks.end(); ++iter)
+        {
+            ClientAuthSeq auths;
+            //XXX We need to extract the realms from the param->rdata.
+            HookResult result = (*iter)->getCredentials(mEndpointName, Ice::StringSeq(), auths);
+            if (result.status == Succeeded)
+            {
+                //Cool. So now we need to update the auth info on mReg
+            }
+        }
+        //We must authenticate!
+        break;
+    }
+    default:
+        //The rest of these are failure cases. It may be possible to look
+        //at Retry-After headers, and on a 423, it may be possible to try again
+        //with modified expirations.
+        break;
+    }
+}
+
+}
+}
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index c36ff10..d1ac100 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -82,9 +82,12 @@ public:
     void addContacts(const RegPairSeq& contacts);
 
     void removeContacts(const Ice::StringSeq& contacts);
+
+    void handleRegisterResponse(pjsip_regc_cbparam *param);
 private:
     void sendRegister();
 
+    const std::string mEndpointName;
     RegPairSeq mContacts;
     SipRegistrationClientManagerPtr mManager;
     pjsip_regc* mReg;

commit 185177314c92bf0ff843f150f7634759ec45f138
Author: Mark Michelson <mmichelson at digium.com>
Date:   Fri Sep 2 14:13:02 2011 -0500

    We've now got the ability to send a REGISTER on startup and when
    the contacts are updated.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 58861aa..a90808d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -47,6 +47,8 @@ astscf_component_add_files(SipSessionManager PJSipLoggingModule.h)
 astscf_component_add_files(SipSessionManager PJSipRegistrarModule.cpp)
 astscf_component_add_files(SipSessionManager PJSipRegistrarModuleConstruction.cpp)
 astscf_component_add_files(SipSessionManager PJSipRegistrarModule.h)
+astscf_component_add_files(SipSessionManager SipClientRegistration.cpp)
+astscf_component_add_files(SipSessionManager SipClientRegistration.h)
 astscf_component_add_files(SipSessionManager AuthManager.cpp)
 astscf_component_add_files(SipSessionManager AuthManager.h)
 astscf_component_add_files(SipSessionManager SipConfiguration.cpp)
diff --git a/src/SipClientRegistration.h b/src/SipClientRegistration.h
index 9fce858..c36ff10 100644
--- a/src/SipClientRegistration.h
+++ b/src/SipClientRegistration.h
@@ -16,6 +16,10 @@
 
 #pragma once
 
+#include <boost/thread.hpp>
+#include <pjsip_ua.h>
+
+#include "SipEndpoint.h"
 #include "AuthManager.h"
 
 namespace AsteriskSCF
@@ -33,7 +37,7 @@ namespace SipSessionManager
  * The client registrations themselves will then use
  * accessors in order to get the necessary information.
  */
-class SipRegistrationClientManager 
+class SipRegistrationClientManager : public IceUtil::Shared
 {
 public:
     SipRegistrationClientManager();
@@ -46,14 +50,17 @@ public:
 
     Ice::StringSeq getSupported();
 
-    AsteriskSCF::SIP::ExtensionPoint::V1::AuthClientHookSeq getAuthClientHooks();
+    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookSeq getAuthHooks();
 
 private:
     Ice::StringSeq mAllow;
     Ice::StringSeq mSupported;
-    boost::shared_lock mLock;
+    boost::shared_mutex mLock;
 };
 
+typedef IceUtil::Handle<SipRegistrationClientManager> SipRegistrationClientManagerPtr;
+
+
 typedef std::pair<std::string, int> RegPair;
 typedef std::vector<RegPair> RegPairSeq;
 
@@ -65,14 +72,22 @@ typedef std::vector<RegPair> RegPairSeq;
 class SipRegistrationClient
 {
 public:
-    SipRegistrationClient(const std::string& aor, const RegPairSeq& contacts);
+    SipRegistrationClient(
+            const RegPairSeq& contacts,
+            pjsip_endpoint* pjEndpoint,
+            const SipEndpointPtr& sipEndpoint);
+
+    ~SipRegistrationClient();
 
     void addContacts(const RegPairSeq& contacts);
 
     void removeContacts(const Ice::StringSeq& contacts);
 private:
+    void sendRegister();
+
     RegPairSeq mContacts;
-    SipRegistrationClientManager mManager;
+    SipRegistrationClientManagerPtr mManager;
+    pjsip_regc* mReg;
 };
 
 }

commit fbea8a4d8f438cb0585814d88f4e664112196809
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Sep 1 18:31:57 2011 -0500

    Adjust for slice changes to combine both hooks.

diff --git a/src/AuthManager.h b/src/AuthManager.h
index 6b63ebf..96884ae 100644
--- a/src/AuthManager.h
+++ b/src/AuthManager.h
@@ -179,18 +179,6 @@ public:
      * Remove all registered authentication hooks from the AuthManager
      */
     void clearAuthHooks();
-    /**
-     * Register a new authentication client hook with the AuthManager
-     */
-    void addAuthClientHook(const AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx &hook, int priority, const AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq &types);
-    /**
-     * Remove a registered authentication client hook from the AuthManager
-     */
-    void removeAuthClientHook(const AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx &hook);
-    /**
-     * Remove all registered authentication client hooks from the AuthManager
-     */
-    void clearAuthClientHooks();
 
 private:
     boost::shared_ptr<AuthManagerPriv> mImpl;
diff --git a/src/Component.cpp b/src/Component.cpp
index 12ff379..ca64fe9 100644
--- a/src/Component.cpp
+++ b/src/Component.cpp
@@ -104,38 +104,6 @@ private:
 
 typedef IceUtil::Handle<SipAuthExtensionPoint> SipAuthExtensionPointPtr;
 
... 292 lines suppressed ...


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list