[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