[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