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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Sep 2 15:25:13 CDT 2011


branch "client-registration" has been updated
       via  49654083b0cd285e5744419d25b977fd7480abe1 (commit)
       via  bf7a9fe072438dfde54e155631e4514446276ff5 (commit)
       via  f4b439dbb49bd1fc6b0aead292b2723048b6e9b9 (commit)
      from  081f82acfed7cc21734b83c470e521b0fadf652a (commit)

Summary of changes:
 src/CMakeLists.txt            |    2 +
 src/SipClientRegistration.cpp |  274 +++++++++++++++++++++++++++++++++++++++++
 src/SipClientRegistration.h   |   30 ++++-
 3 files changed, 301 insertions(+), 5 deletions(-)
 create mode 100644 src/SipClientRegistration.cpp


- Log -----------------------------------------------------------------
commit 49654083b0cd285e5744419d25b977fd7480abe1
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 bf7a9fe072438dfde54e155631e4514446276ff5
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 f4b439dbb49bd1fc6b0aead292b2723048b6e9b9
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;
 };
 
 }

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list