[asterisk-scf-commits] asterisk-scf/release/sip.git branch "authexten" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Feb 14 16:57:35 CST 2011


branch "authexten" has been updated
       via  f3343d7b5205f981b8d4002991f233a4e4e9645e (commit)
       via  53a20db873d9eb943ec65f9a6f10da125108ae94 (commit)
       via  7651845251617268572d954cc1cc94d1c609f7f7 (commit)
       via  529b6387bda5b3287a20d5166638d0ea08901e4d (commit)
       via  a90a0ae0e000a0679619e1dd2d0c065baaa5fb8c (commit)
       via  1e847b293c9f7ec3e6b2f051768f59a07d66f7d7 (commit)
       via  d479d28083104c2f4ec3aa74f232c46a1ad2e231 (commit)
      from  6913f102979144b1203fd032d1afffcf7cd8d09c (commit)

Summary of changes:
 src/AuthHelper.cpp                     |  229 -------------------
 src/AuthHelper.h                       |   52 -----
 src/AuthManager.cpp                    |  392 ++++++++++++++++++++++++++++++++
 src/AuthManager.h                      |  210 +++++++++++++++++
 src/CMakeLists.txt                     |    4 +-
 src/PJSipModule.cpp                    |   15 +-
 src/PJSipModule.h                      |   25 +--
 src/PJSipSessionModule.cpp             |   89 +++-----
 src/PJSipSessionModule.h               |    2 +
 src/PJSipSessionModuleConstruction.cpp |    7 +
 10 files changed, 651 insertions(+), 374 deletions(-)
 delete mode 100644 src/AuthHelper.cpp
 delete mode 100644 src/AuthHelper.h
 create mode 100644 src/AuthManager.cpp
 create mode 100644 src/AuthManager.h


- Log -----------------------------------------------------------------
commit f3343d7b5205f981b8d4002991f233a4e4e9645e
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 16:57:13 2011 -0600

    Pimplify the AuthManager and add some documentation to AuthManager.h

diff --git a/src/AuthManager.cpp b/src/AuthManager.cpp
index 9d9ef6f..23c733d 100644
--- a/src/AuthManager.cpp
+++ b/src/AuthManager.cpp
@@ -270,23 +270,38 @@ pj_timer_entry *AuthInstance::getTimerEntry()
     return &mImpl->entry;
 }
 
-AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
-    : mEndpoint(endpt),
-    mPool(pjsip_endpt_create_pool(endpt, "auth%p", 1200, 512)),
-    mLogger(logger)
+class AuthManagerPriv
 {
-}
+public:
+    AuthManagerPriv(pjsip_endpoint *endpt, Logger &logger)
+        : mPool(pjsip_endpt_create_pool(endpt, "auth%p", 1200, 512)),
+        mLogger(logger) { }
+
+    ~AuthManagerPriv()
+    {
+        mAuthInstances.erase(mAuthInstances.begin(), mAuthInstances.end());
+        pjsip_endpt_release_pool(mEndpoint, mPool);
+    }
+
+    std::vector<boost::shared_ptr<AuthInstance> > mAuthInstances;
+    pjsip_endpoint *mEndpoint;
+    pj_pool_t *mPool;
+    moduleHookVector mRegisteredHooks;
+    Logger mLogger;
+    int mCounter;
+};
+
+AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
+    : mImpl(new AuthManagerPriv(endpt, logger)) { }
 
 AuthManager::~AuthManager()
 {
-    pjsip_endpt_release_pool(mEndpoint, mPool);
-    mAuthInstances.erase(mAuthInstances.begin(), mAuthInstances.end());
 }
 
 boost::shared_ptr<AuthInstance> AuthManager::createAuthInstance(pjsip_rx_data *rdata, RequestType type)
 {
-    boost::shared_ptr<AuthInstance> instance(new AuthInstance(rdata, mRegisteredHooks, type, mPool, mLogger));
-    mAuthInstances.push_back(instance);
+    boost::shared_ptr<AuthInstance> instance(new AuthInstance(rdata, mImpl->mRegisteredHooks, type, mImpl->mPool, mImpl->mLogger));
+    mImpl->mAuthInstances.push_back(instance);
     return instance;
 }
 
@@ -295,7 +310,8 @@ bool AuthManager::authenticate(pjsip_rx_data *rdata)
     std::string fromTag(pj_strbuf(&rdata->msg_info.from->tag), pj_strlen(&rdata->msg_info.from->tag));
     std::string callId(pj_strbuf(&rdata->msg_info.cid->id), pj_strlen(&rdata->msg_info.cid->id));
     boost::shared_ptr<AuthInstance> instance;
-    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++iter)
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mImpl->mAuthInstances.begin();
+            iter != mImpl->mAuthInstances.end(); ++iter)
     {
         if (fromTag == (*iter)->getFromTag() && callId == (*iter)->getCallId())
         {
@@ -303,8 +319,8 @@ bool AuthManager::authenticate(pjsip_rx_data *rdata)
             {
                 //If authentication has succeeded, then we can remove this AuthInstance
                 //from our list, and we need to cancel the scheduled task
-                pjsip_endpt_cancel_timer(mEndpoint, (*iter)->getTimerEntry());
-                mAuthInstances.erase(iter);
+                pjsip_endpt_cancel_timer(mImpl->mEndpoint, (*iter)->getTimerEntry());
+                mImpl->mAuthInstances.erase(iter);
                 return true;
             }
             break;
@@ -315,11 +331,12 @@ bool AuthManager::authenticate(pjsip_rx_data *rdata)
 
 void AuthManager::destroyAuthInstance(const boost::shared_ptr<AuthInstance> &instance)
 {
-    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++ iter)
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mImpl->mAuthInstances.begin();
+            iter != mImpl->mAuthInstances.end(); ++ iter)
     {
         if (*iter == instance)
         {
-            mAuthInstances.erase(iter);
+            mImpl->mAuthInstances.erase(iter);
             break;
         }
     }
@@ -328,36 +345,39 @@ void AuthManager::destroyAuthInstance(const boost::shared_ptr<AuthInstance> &ins
 void AuthManager::scheduleAuthDestruction(const boost::shared_ptr<AuthInstance> &instance)
 {
     const pj_time_val time = {60, 0};
-    pj_timer_entry *entry = instance->createTimerEntry(mCounter++);
-    pjsip_endpt_schedule_timer(mEndpoint, entry, &time);
+    pj_timer_entry *entry = instance->createTimerEntry(mImpl->mCounter++);
+    pjsip_endpt_schedule_timer(mImpl->mEndpoint, entry, &time);
 }
 
 void AuthManager::authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry)
 {
-    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++iter)
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mImpl->mAuthInstances.begin();
+            iter != mImpl->mAuthInstances.end(); ++iter)
     {
         if (entry->id == (*iter)->getTimerEntry()->id)
         {
-            mAuthInstances.erase(iter);
+            mImpl->mAuthInstances.erase(iter);
             return;
         }
     }
 }
 
-void AuthManager::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
+void AuthManager::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook,
+        int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
 {
     boost::shared_ptr<AuthHookData> hookData(new AuthHookData(priority, hook, types));
-    mRegisteredHooks.push_back(hookData);
-    std::stable_sort(mRegisteredHooks.begin(), mRegisteredHooks.end());
+    mImpl->mRegisteredHooks.push_back(hookData);
+    std::stable_sort(mImpl->mRegisteredHooks.begin(), mImpl->mRegisteredHooks.end());
 }
 
 void AuthManager::removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook)
 {
-    for (moduleHookVector::iterator iter = mRegisteredHooks.begin(); iter != mRegisteredHooks.end(); ++iter)
+    for (moduleHookVector::iterator iter = mImpl->mRegisteredHooks.begin();
+            iter != mImpl->mRegisteredHooks.end(); ++iter)
     {
         if ((*iter)->getHook() == hook)
         {
-            mRegisteredHooks.erase(iter);
+            mImpl->mRegisteredHooks.erase(iter);
             break;
         }
     }
@@ -365,7 +385,7 @@ void AuthManager::removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookP
 
 void AuthManager::clearAuthHooks()
 {
-    mRegisteredHooks.clear();
+    mImpl->mRegisteredHooks.clear();
 }
 
 };
diff --git a/src/AuthManager.h b/src/AuthManager.h
index 2455527..6dc696c 100644
--- a/src/AuthManager.h
+++ b/src/AuthManager.h
@@ -30,8 +30,6 @@ namespace AsteriskSCF
 namespace SipSessionManager
 {
 
-class AuthInstancePriv;
-
 class AuthHookData
 {
 public:
@@ -57,6 +55,13 @@ typedef std::vector<boost::shared_ptr<AuthHookData> > moduleHookVector;
 
 void sessionAuthTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
 
+class AuthInstancePriv;
+
+/**
+ * An AuthInstance represents a single attempt of us
+ * as the authentication server to authenticate a
+ * SIP requester.
+ */
 class AuthInstance
 {
 public:
@@ -65,38 +70,140 @@ public:
             AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type,
             pj_pool_t *pool,
             const AsteriskSCF::System::Logging::Logger &logger);
+    /**
+     * The AuthInstance is able to distill all of the registered hooks
+     * down to a smaller list based on the request types that the hooks
+     * service. This is a helper function to get the distilled
+     * list of hooks.
+     */
     std::vector<AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx> getHooks();
+    /**
+     * This function is a convenience function to fill in the common
+     * data elements of a RequestInfo class given incoming request
+     * data.
+     */
     void fillInRequestInfo(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestInfoPtr info);
+    /**
+     * Add digest information to an outgoing response
+     */
     void addDigests(pjsip_tx_data *tdata, AsteriskSCF::SIP::ExtensionPoint::V1::DigestChallengeSeq digests);
+    /**
+     * Attempt to authenticate an incoming request.
+     *
+     * It's not necessary to call this function directly since
+     * the AuthManager will take care of it for you. The method needs
+     * to be public so that the AuthManager is capable of calling it.
+     */
     bool authenticate(pjsip_rx_data *rdata);
+    /**
+     * Create a pj_timer_entry with the given id.
+     * For more information about our interaction with
+     * PJLIB's scheduler, see AuthManager::scheduleAuthDestruction.
+     *
+     * It's not necessary to call this function directly since
+     * the AuthManager will take care of it for you. The method needs
+     * to be public so that the AuthManager is capable of calling it.
+     */
     pj_timer_entry *createTimerEntry(int id);
+    /**
+     * Get the From tag from the original unauthenticated request.
+     *
+     * It's likely you'll never need to use this function yourself.
+     * The method needs to be public so that the AuthManager is
+     * capable of calling it
+     */
     std::string getFromTag();
+    /**
+     * Get the Call-id from the original unauthenticated request.
+     *
+     * It's likely you'll never need to use this function yourself.
+     * The method needs to be public so that the AuthManager is
+     * capable of calling it
+     */
     std::string getCallId();
+    /**
+     * Get the pj_timer_entry that was created using
+     * createTimerEntry().
+     *
+     * It's likely you'll never need to use this function yourself.
+     * The method needs to be public so that the AuthManager is
+     * capable of calling it
+     */
     pj_timer_entry *getTimerEntry();
 private:
     boost::shared_ptr<AuthInstancePriv> mImpl;
 };
 
+class AuthManagerPriv;
+
+/**
+ * The AuthManager contains all AuthInstances
+ * for a given PJSIP module. It also contains
+ * all of a PJSIP module's registered authentication
+ * hooks.
+ */
 class AuthManager
 {
 public:
     AuthManager(pjsip_endpoint *endpt, AsteriskSCF::System::Logging::Logger& logger);
     ~AuthManager();
-    boost::shared_ptr<AuthInstance> createAuthInstance(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    /**
+     * Attempt to authenticate a request
+     *
+     * This will search through the AuthManager's AuthInstances to
+     * attempt to authenticate the request.
+     * XXX Note that since the current task at hand is just to set
+     * up the extension point for authentication and not to actually
+     * authenticate, this doesn't actually do anything useful.
+     */
     bool authenticate(pjsip_rx_data *rdata);
+    /**
+     * Create a new AuthInstance
+     *
+     * If a PJSIP module decides wants to challenge a requester, then
+     * it must create an AuthInstance in order to do so. Do not
+     * construct AuthInstances directly, but rather use this function
+     * so that the AuthManager will have a reference to the AuthInstance
+     * for later.
+     */
+    boost::shared_ptr<AuthInstance> createAuthInstance(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    /**
+     * Schedule the destruction of an AuthInstance
+     *
+     * After challenging a requester for authentication information,
+     * a PJSIP module should call this method. This will ensure that if
+     * the requester does not attempt to authenticate or never succeeds
+     * in authenticating, the AuthInstance will eventually be destroyed.
+     */
     void scheduleAuthDestruction(const boost::shared_ptr<AuthInstance> &instance);
+    /**
+     * Destroy an AuthInstance
+     * 
+     * This method is handy for destroying an AuthInstance if one has been created,
+     * but a failure condition occurs before a challenge can be sent to the
+     * requesting UA.
+     */
     void destroyAuthInstance(const boost::shared_ptr<AuthInstance> &instance);
+    /**
+     * This is the callback that scheduleAuthDestruction sets up.
+     *
+     * Do not call this method directly.
+     */
     void authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
+    /**
+     * Register a new authentication hook with the AuthManager
+     */
     void addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types);
+    /**
+     * Remove a registered authentication hook from the AuthManager
+     */
     void removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook);
+    /**
+     * Remove all registered authentication hooks from the AuthManager
+     */
     void clearAuthHooks();
 private:
-    std::vector<boost::shared_ptr<AuthInstance> > mAuthInstances;
-    pjsip_endpoint *mEndpoint;
-    pj_pool_t *mPool;
-    moduleHookVector mRegisteredHooks;
-    AsteriskSCF::System::Logging::Logger mLogger;
-    int mCounter;
+    boost::shared_ptr<AuthManagerPriv> mImpl;
 };
 
 }; //end namespace SipSessionManager

commit 53a20db873d9eb943ec65f9a6f10da125108ae94
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 15:53:18 2011 -0600

    Add attempt to authenticate inside the PJSipSessionManager.

diff --git a/src/AuthManager.cpp b/src/AuthManager.cpp
index 827ea06..9d9ef6f 100644
--- a/src/AuthManager.cpp
+++ b/src/AuthManager.cpp
@@ -265,9 +265,9 @@ std::string AuthInstance::getCallId()
     return mImpl->callId;
 }
 
-int AuthInstance::getTimerEntryId()
+pj_timer_entry *AuthInstance::getTimerEntry()
 {
-    return mImpl->entry.id;
+    return &mImpl->entry;
 }
 
 AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
@@ -301,8 +301,13 @@ bool AuthManager::authenticate(pjsip_rx_data *rdata)
         {
             if ((*iter)->authenticate(rdata) == true)
             {
+                //If authentication has succeeded, then we can remove this AuthInstance
+                //from our list, and we need to cancel the scheduled task
+                pjsip_endpt_cancel_timer(mEndpoint, (*iter)->getTimerEntry());
+                mAuthInstances.erase(iter);
                 return true;
             }
+            break;
         }
     }
     return false;
@@ -331,9 +336,8 @@ void AuthManager::authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry
 {
     for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++iter)
     {
-        if (entry->id == (*iter)->getTimerEntryId())
+        if (entry->id == (*iter)->getTimerEntry()->id)
         {
-            pjsip_endpt_cancel_timer(mEndpoint, entry);
             mAuthInstances.erase(iter);
             return;
         }
diff --git a/src/AuthManager.h b/src/AuthManager.h
index 848ef35..2455527 100644
--- a/src/AuthManager.h
+++ b/src/AuthManager.h
@@ -72,7 +72,7 @@ public:
     pj_timer_entry *createTimerEntry(int id);
     std::string getFromTag();
     std::string getCallId();
-    int getTimerEntryId();
+    pj_timer_entry *getTimerEntry();
 private:
     boost::shared_ptr<AuthInstancePriv> mImpl;
 };
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 41f4950..5a37de0 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -432,6 +432,13 @@ pj_status_t PJSipSessionModule::unload()
 
 bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, RequestType type, pjsip_endpoint *endpt)
 {
+    //First, let's see if this message has some auth that we know about.
+    if (mAuthManager->authenticate(rdata) == true)
+    {
+        //Oh yeah! Authentication succeeded!
+        return false;
+    }
+
     boost::shared_ptr<AuthInstance> authInstance(mAuthManager->createAuthInstance(rdata, type));
     
     std::vector<AuthHookPrx> hooks = authInstance->getHooks();
@@ -447,8 +454,8 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
     //
     //XXX While this seems like something that could be taken care of in either the
     //AuthInstance or AuthManager class, there are some specific issues with this.
-    //For instance, in this case, we create the outgoing message via the inv_session,
-    //whereas other PJSIP modules will likely either access the base dialog directly
+    //For instance, in this case, we create the outgoing message using the inv_session,
+    //whereas other PJSIP modules will either access the base dialog directly
     //or have a different layer of indirection instead of the inv_session.
     for (std::vector<AuthHookPrx>::iterator iter = hooks.begin(); iter != hooks.end(); ++iter)
     {
@@ -459,7 +466,8 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
         {
             lg(Error) << "SIP Authentication hook reported a failure: " << result.info;
         }
-        else if (result.status == Succeeded) {
+        else if (result.status == Succeeded)
+        {
             if (digests.empty())
             {
                 //Hook says not to challenge. This AuthInstance

commit 7651845251617268572d954cc1cc94d1c609f7f7
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 15:24:35 2011 -0600

    Destroy AuthInstance if hook returns successful but has no digest challenges.

diff --git a/src/AuthManager.cpp b/src/AuthManager.cpp
index ea1cc70..827ea06 100644
--- a/src/AuthManager.cpp
+++ b/src/AuthManager.cpp
@@ -308,6 +308,18 @@ bool AuthManager::authenticate(pjsip_rx_data *rdata)
     return false;
 }
 
+void AuthManager::destroyAuthInstance(const boost::shared_ptr<AuthInstance> &instance)
+{
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++ iter)
+    {
+        if (*iter == instance)
+        {
+            mAuthInstances.erase(iter);
+            break;
+        }
+    }
+}
+
 void AuthManager::scheduleAuthDestruction(const boost::shared_ptr<AuthInstance> &instance)
 {
     const pj_time_val time = {60, 0};
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 1422663..41f4950 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -444,6 +444,12 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
     authInstance->fillInRequestInfo(rdata, info);
 
     //We have our RequestInfo created. Now start calling out to any registered hooks
+    //
+    //XXX While this seems like something that could be taken care of in either the
+    //AuthInstance or AuthManager class, there are some specific issues with this.
+    //For instance, in this case, we create the outgoing message via the inv_session,
+    //whereas other PJSIP modules will likely either access the base dialog directly
+    //or have a different layer of indirection instead of the inv_session.
     for (std::vector<AuthHookPrx>::iterator iter = hooks.begin(); iter != hooks.end(); ++iter)
     {
         DigestChallengeSeq digests;
@@ -456,7 +462,9 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
         else if (result.status == Succeeded) {
             if (digests.empty())
             {
-                //Hook says not to challenge. Just return
+                //Hook says not to challenge. This AuthInstance
+                //is deader than dead.
+                mAuthManager->destroyAuthInstance(authInstance);
                 return false;
             }
 

commit 529b6387bda5b3287a20d5166638d0ea08901e4d
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 15:12:12 2011 -0600

    Add steps in to actually attempt authentication before trying to challenge.

diff --git a/src/AuthManager.cpp b/src/AuthManager.cpp
index 3e4e339..ea1cc70 100644
--- a/src/AuthManager.cpp
+++ b/src/AuthManager.cpp
@@ -29,8 +29,10 @@ namespace SipSessionManager
 class AuthInstancePriv
 {
 public:
-    AuthInstancePriv(moduleHookVector moduleHooks, RequestType type, pj_pool_t *pool, const Logger &logger)
-        : mPool(pool), mLogger(logger)
+    AuthInstancePriv(pjsip_rx_data *rdata, moduleHookVector moduleHooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+        : mPool(pool), mLogger(logger),
+        fromTag(pj_strbuf(&rdata->msg_info.from->tag), pj_strlen(&rdata->msg_info.from->tag)),
+        callId(pj_strbuf(&rdata->msg_info.cid->id), pj_strlen(&rdata->msg_info.cid->id))
     {
         if (moduleHooks.empty())
         {
@@ -91,11 +93,14 @@ public:
     std::vector<AuthHookPrx> hooks;
     std::vector<pjsip_auth_srv *> authServers;
     pj_pool_t *mPool;
+    pj_timer_entry entry;
     Logger mLogger;
+    std::string fromTag;
+    std::string callId;
 };
 
-AuthInstance::AuthInstance(moduleHookVector hooks, RequestType type, pj_pool_t *pool, const Logger &logger)
-        : mImpl(new AuthInstancePriv(hooks, type, pool, logger)) { }
+AuthInstance::AuthInstance(pjsip_rx_data *rdata, moduleHookVector hooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+        : mImpl(new AuthInstancePriv(rdata, hooks, type, pool, logger)) { }
 
 std::vector<AuthHookPrx> AuthInstance::getHooks()
 {
@@ -121,6 +126,37 @@ static pj_status_t lookup_cred(pj_pool_t *pool, const pj_str_t *realm, const pj_
     return !PJ_SUCCESS;
 }
 
+bool AuthInstance::authenticate(pjsip_rx_data *rdata)
+{
+    //For each server auth, we need to call pjsip_auth_srv_verify(), which will then
+    //annoyingly call into the lookup function we created for pjsip. That's where the
+    //real fun begins :(
+    for (std::vector<pjsip_auth_srv *>::iterator iter = mImpl->authServers.begin(); iter != mImpl->authServers.end(); ++iter)
+    {
+        int status_code;
+        pj_status_t status = pjsip_auth_srv_verify(*iter, rdata, &status_code);
+        switch (status)
+        {
+        case PJ_SUCCESS:
+            return true;
+        case PJSIP_EAUTHNOAUTH:
+        case PJSIP_EAUTHACCNOTFOUND:
+        case PJSIP_EAUTHACCDISABLED:
+        case PJSIP_EAUTHINVALIDREALM:
+        case PJSIP_EAUTHINVALIDDIGEST:
+        default:
+            mImpl->mLogger(Warning) << "Could not auth";
+        }
+    }
+    return false;
+}
+
+pj_timer_entry *AuthInstance::createTimerEntry(int id)
+{
+    pj_timer_entry_init(&mImpl->entry, id, this, sessionAuthTimeout);
+    return &mImpl->entry;
+}
+
 void AuthInstance::addDigests(pjsip_tx_data *tdata, DigestChallengeSeq digests)
 {
     static char qop[] = "auth";
@@ -219,6 +255,21 @@ void AuthInstance::fillInRequestInfo(pjsip_rx_data *rdata, RequestInfoPtr info)
     }
 }
 
+std::string AuthInstance::getFromTag()
+{
+    return mImpl->fromTag;
+}
+
+std::string AuthInstance::getCallId()
+{
+    return mImpl->callId;
+}
+
+int AuthInstance::getTimerEntryId()
+{
+    return mImpl->entry.id;
+}
+
 AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
     : mEndpoint(endpt),
     mPool(pjsip_endpt_create_pool(endpt, "auth%p", 1200, 512)),
@@ -229,15 +280,54 @@ AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
 AuthManager::~AuthManager()
 {
     pjsip_endpt_release_pool(mEndpoint, mPool);
+    mAuthInstances.erase(mAuthInstances.begin(), mAuthInstances.end());
 }
 
-boost::shared_ptr<AuthInstance> AuthManager::createAuthInstance(RequestType type)
+boost::shared_ptr<AuthInstance> AuthManager::createAuthInstance(pjsip_rx_data *rdata, RequestType type)
 {
-    boost::shared_ptr<AuthInstance> instance(new AuthInstance(mRegisteredHooks, type, mPool, mLogger));
+    boost::shared_ptr<AuthInstance> instance(new AuthInstance(rdata, mRegisteredHooks, type, mPool, mLogger));
     mAuthInstances.push_back(instance);
     return instance;
 }
 
+bool AuthManager::authenticate(pjsip_rx_data *rdata)
+{
+    std::string fromTag(pj_strbuf(&rdata->msg_info.from->tag), pj_strlen(&rdata->msg_info.from->tag));
+    std::string callId(pj_strbuf(&rdata->msg_info.cid->id), pj_strlen(&rdata->msg_info.cid->id));
+    boost::shared_ptr<AuthInstance> instance;
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++iter)
+    {
+        if (fromTag == (*iter)->getFromTag() && callId == (*iter)->getCallId())
+        {
+            if ((*iter)->authenticate(rdata) == true)
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void AuthManager::scheduleAuthDestruction(const boost::shared_ptr<AuthInstance> &instance)
+{
+    const pj_time_val time = {60, 0};
+    pj_timer_entry *entry = instance->createTimerEntry(mCounter++);
+    pjsip_endpt_schedule_timer(mEndpoint, entry, &time);
+}
+
+void AuthManager::authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry)
+{
+    for (std::vector<boost::shared_ptr<AuthInstance> >::iterator iter = mAuthInstances.begin(); iter != mAuthInstances.end(); ++iter)
+    {
+        if (entry->id == (*iter)->getTimerEntryId())
+        {
+            pjsip_endpt_cancel_timer(mEndpoint, entry);
+            mAuthInstances.erase(iter);
+            return;
+        }
+    }
+}
+
 void AuthManager::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
 {
     boost::shared_ptr<AuthHookData> hookData(new AuthHookData(priority, hook, types));
diff --git a/src/AuthManager.h b/src/AuthManager.h
index 3630113..848ef35 100644
--- a/src/AuthManager.h
+++ b/src/AuthManager.h
@@ -55,16 +55,24 @@ private:
 
 typedef std::vector<boost::shared_ptr<AuthHookData> > moduleHookVector;
 
+void sessionAuthTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
+
 class AuthInstance
 {
 public:
-    AuthInstance(moduleHookVector hooks,
+    AuthInstance(pjsip_rx_data *rdata,
+            moduleHookVector hooks,
             AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type,
             pj_pool_t *pool,
             const AsteriskSCF::System::Logging::Logger &logger);
     std::vector<AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx> getHooks();
     void fillInRequestInfo(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestInfoPtr info);
     void addDigests(pjsip_tx_data *tdata, AsteriskSCF::SIP::ExtensionPoint::V1::DigestChallengeSeq digests);
+    bool authenticate(pjsip_rx_data *rdata);
+    pj_timer_entry *createTimerEntry(int id);
+    std::string getFromTag();
+    std::string getCallId();
+    int getTimerEntryId();
 private:
     boost::shared_ptr<AuthInstancePriv> mImpl;
 };
@@ -74,7 +82,11 @@ class AuthManager
 public:
     AuthManager(pjsip_endpoint *endpt, AsteriskSCF::System::Logging::Logger& logger);
     ~AuthManager();
-    boost::shared_ptr<AuthInstance> createAuthInstance(AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    boost::shared_ptr<AuthInstance> createAuthInstance(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    bool authenticate(pjsip_rx_data *rdata);
+    void scheduleAuthDestruction(const boost::shared_ptr<AuthInstance> &instance);
+    void destroyAuthInstance(const boost::shared_ptr<AuthInstance> &instance);
+    void authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
     void addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types);
     void removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook);
     void clearAuthHooks();
@@ -84,6 +96,7 @@ private:
     pj_pool_t *mPool;
     moduleHookVector mRegisteredHooks;
     AsteriskSCF::System::Logging::Logger mLogger;
+    int mCounter;
 };
 
 }; //end namespace SipSessionManager
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 50d54c6..1422663 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -432,7 +432,7 @@ pj_status_t PJSipSessionModule::unload()
 
 bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, RequestType type, pjsip_endpoint *endpt)
 {
-    boost::shared_ptr<AuthInstance> authInstance(mAuthManager->createAuthInstance(type));
+    boost::shared_ptr<AuthInstance> authInstance(mAuthManager->createAuthInstance(rdata, type));
     
     std::vector<AuthHookPrx> hooks = authInstance->getHooks();
     if (hooks.empty())
@@ -467,55 +467,7 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
 
             pjsip_inv_send_msg(inv, tdata);
 
-            // So here's the part that truly sucks about all this. Authentication
-            // is something whose lifetime is not governed by the lifetime of any other
-            // SIP element. The current transaction, dialog, and inv_session all end
-            // when we receive the ACK for the 401 we send. This means we can't stuff
-            // the AuthInstance into any of these structures. Instead, we have to store
-            // this in a container local to the module itself.
-            //
-            // Now, that leads to two further issues: identification and lifetime.
-            //
-            // When a new message comes in, how are we supposed to match up the new incoming
-            // request with our stored AuthInstance? If you read RFC 3261, it implies that
-            // a requester should regenerate his original request with auth info added and
-            // the CSeq incremented. So we SHOULD be able to use the call-id and from tag
-            // to figure out which AuthInstance to retrieve. Experimentation will be required
-            // to determine if this actually works in all cases.
-            //
-            // The lifetime of an AuthInstance is a bit hard to grasp. Let's say we send a 401
-            // response and then either a) never receive an ACK or b) receive an ACK but never
-            // receive a new request with proper auth info. In either case, we will never
-            // receive any sort of message that indicates to us that we should destroy the
-            // AuthInstance. Instead, what we have to do is periodically check to see if we
-            // have held onto an AuthInstance for longer than some prescribed period. While I'd
-            // think that a few seconds would be long enough to hold on, in practice this may
-            // cause issues. If we have to retransmit the 401 3 times and then the other endpoint
-            // has to retransmit its ACK 4 times, then the INVITE with the auth info has to
-            // be retransmitted 3 times, then that's a lot of time between when we created the
-            // AuthInstance and when we finally see auth info. So this means we have to wait
-            // a minute or two before we can safely claim that an AuthInstance isn't going to
-            // be used for anything.
-            //
-            // One thing we can be assured of is that the AuthInstance definitely only pertains
-            // to this particular PJSIP module. So it seems we can add a container to the PJSIP
-            // module and store our AuthInstances in there. We can get away with using a vector
-            // pretty easily. So first, we need to modify the AuthInstance class to store the
-            // call-id and from tag of the request so that we can identify which to use when
-            // authenticating. We can modify the AuthInstance's constructor to take the pjsip_rdata
-            // to fill in these values. We can even be slick and define an operator== so that
-            // we can use std::find to find an appropriate match, but that's not entirely
-            // necessary atm.
-            //
-            // So how about the lifetime issue? Well PJSIP offers a handy function called
-            // pjsip_endpt_schedule_timer. We can schedule a callback to be called in the future,
-            // presumably when the AuthInstance can be determined to be no longer useful. This callback
-            // can find and remove the AuthInstance from the vector. Now of course, if we receive
-            // authentication from the requester, then we can destroy the AuthInstance and cancel
-            // the scheduled callback. This will require adding the pj_timer_entry to the AuthInstance.
-            // Unfortunately we can't schedule the operation from within a method of AuthInstance because
-            // the vector of AuthInstances lives here in the module, not the AuthInstance. So instead, we'll
-            // need a method in the PJSipModule to schedule the operation instead. Easy-peasy.
+            mAuthManager->scheduleAuthDestruction(authInstance);
             return true;
         }
     }
@@ -1265,5 +1217,10 @@ pjsip_dialog *PJSipSessionModule::uaOnDialogForked(pjsip_dialog *first_set, pjsi
     return NULL;
 }
 
+void PJSipSessionModule::authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry)
+{
+    mAuthManager->authTimeout(timer_heap, entry);
+}
+
 }; //end namespace SipSessionManager
 }; //end namespace AsteriskSCF
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 9ac956a..a5a613a 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -80,6 +80,7 @@ public:
     pjsip_redirect_op invOnRedirected(pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e);
     pjsip_dialog *uaOnDialogForked(pjsip_dialog *first_set, pjsip_rx_data *rdata);
     // Missing onsendack for now
+    void authTimeout(pj_timer_heap_t *timer_heap, pj_timer_entry *entry);
     void replicateState(PJSipDialogModInfo *dlgInfo, PJSipTransactionModInfo *tsxInfo,
         PJSipSessionModInfo *sessionInfo);
 private:
diff --git a/src/PJSipSessionModuleConstruction.cpp b/src/PJSipSessionModuleConstruction.cpp
index b4ca3bc..905f35d 100644
--- a/src/PJSipSessionModuleConstruction.cpp
+++ b/src/PJSipSessionModuleConstruction.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "PJSipSessionModule.h"
+#include "AuthManager.h"
 
 namespace AsteriskSCF
 {
@@ -91,6 +92,11 @@ static pjsip_dialog *uaOnDialogForked(pjsip_dialog *first_set, pjsip_rx_data *rd
     return sessionModule->uaOnDialogForked(first_set, rdata);
 }
 
+void sessionAuthTimeout(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
+{
+    return sessionModule->authTimeout(timer_heap, entry);
+}
+
 PJSipSessionModule::PJSipSessionModule(pjsip_endpoint *endpt,
     boost::shared_ptr<SipEndpointFactory> endpointFactoryPtr,
     AsteriskSCF::SmartProxy::SmartProxy<AsteriskSCF::SessionCommunications::V1::SessionRouterPrx> sessionRouter,

commit a90a0ae0e000a0679619e1dd2d0c065baaa5fb8c
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 10:45:12 2011 -0600

    Rename AuthHelper to AuthManager

diff --git a/src/AuthHelper.cpp b/src/AuthManager.cpp
similarity index 91%
rename from src/AuthHelper.cpp
rename to src/AuthManager.cpp
index d3ca98f..3e4e339 100644
--- a/src/AuthHelper.cpp
+++ b/src/AuthManager.cpp
@@ -14,7 +14,7 @@
  * at the top of the source tree.
  */
 
-#include "AuthHelper.h"
+#include "AuthManager.h"
 
 using namespace AsteriskSCF::SIP::ExtensionPoint::V1;
 using namespace AsteriskSCF::System::Hook::V1;
@@ -26,10 +26,10 @@ namespace AsteriskSCF
 namespace SipSessionManager
 {
 
-class AuthHelperPriv
+class AuthInstancePriv
 {
 public:
-    AuthHelperPriv(moduleHookVector moduleHooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+    AuthInstancePriv(moduleHookVector moduleHooks, RequestType type, pj_pool_t *pool, const Logger &logger)
         : mPool(pool), mLogger(logger)
     {
         if (moduleHooks.empty())
@@ -94,10 +94,10 @@ public:
     Logger mLogger;
 };
 
-AuthHelper::AuthHelper(moduleHookVector hooks, RequestType type, pj_pool_t *pool, const Logger &logger)
-        : mImpl(new AuthHelperPriv(hooks, type, pool, logger)) { }
+AuthInstance::AuthInstance(moduleHookVector hooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+        : mImpl(new AuthInstancePriv(hooks, type, pool, logger)) { }
 
-std::vector<AuthHookPrx> AuthHelper::getHooks()
+std::vector<AuthHookPrx> AuthInstance::getHooks()
 {
     return mImpl->hooks;
 }
@@ -121,7 +121,7 @@ static pj_status_t lookup_cred(pj_pool_t *pool, const pj_str_t *realm, const pj_
     return !PJ_SUCCESS;
 }
 
-void AuthHelper::addDigests(pjsip_tx_data *tdata, DigestChallengeSeq digests)
+void AuthInstance::addDigests(pjsip_tx_data *tdata, DigestChallengeSeq digests)
 {
     static char qop[] = "auth";
     pj_str_t pjqop = pj_str(qop);
@@ -147,7 +147,7 @@ void AuthHelper::addDigests(pjsip_tx_data *tdata, DigestChallengeSeq digests)
     }
 }
 
-void AuthHelper::fillInRequestInfo(pjsip_rx_data *rdata, RequestInfoPtr info)
+void AuthInstance::fillInRequestInfo(pjsip_rx_data *rdata, RequestInfoPtr info)
 {
     char buf[512];
     size_t pos;
@@ -231,11 +231,11 @@ AuthManager::~AuthManager()
     pjsip_endpt_release_pool(mEndpoint, mPool);
 }
 
-boost::shared_ptr<AuthHelper> AuthManager::createAuthHelper(RequestType type)
+boost::shared_ptr<AuthInstance> AuthManager::createAuthInstance(RequestType type)
 {
-    boost::shared_ptr<AuthHelper> helper(new AuthHelper(mRegisteredHooks, type, mPool, mLogger));
-    mAuthInstances.push_back(helper);
-    return helper;
+    boost::shared_ptr<AuthInstance> instance(new AuthInstance(mRegisteredHooks, type, mPool, mLogger));
+    mAuthInstances.push_back(instance);
+    return instance;
 }
 
 void AuthManager::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
diff --git a/src/AuthHelper.h b/src/AuthManager.h
similarity index 89%
rename from src/AuthHelper.h
rename to src/AuthManager.h
index 0bd8228..3630113 100644
--- a/src/AuthHelper.h
+++ b/src/AuthManager.h
@@ -30,7 +30,7 @@ namespace AsteriskSCF
 namespace SipSessionManager
 {
 
-class AuthHelperPriv;
+class AuthInstancePriv;
 
 class AuthHookData
 {
@@ -55,10 +55,10 @@ private:
 
 typedef std::vector<boost::shared_ptr<AuthHookData> > moduleHookVector;
 
-class AuthHelper
+class AuthInstance
 {
 public:
-    AuthHelper(moduleHookVector hooks,
+    AuthInstance(moduleHookVector hooks,
             AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type,
             pj_pool_t *pool,
             const AsteriskSCF::System::Logging::Logger &logger);
@@ -66,7 +66,7 @@ public:
     void fillInRequestInfo(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestInfoPtr info);
     void addDigests(pjsip_tx_data *tdata, AsteriskSCF::SIP::ExtensionPoint::V1::DigestChallengeSeq digests);
 private:
-    boost::shared_ptr<AuthHelperPriv> mImpl;
+    boost::shared_ptr<AuthInstancePriv> mImpl;
 };
 
 class AuthManager
@@ -74,12 +74,12 @@ class AuthManager
 public:
     AuthManager(pjsip_endpoint *endpt, AsteriskSCF::System::Logging::Logger& logger);
     ~AuthManager();
-    boost::shared_ptr<AuthHelper> createAuthHelper(AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    boost::shared_ptr<AuthInstance> createAuthInstance(AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
     void addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types);
     void removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook);
     void clearAuthHooks();
 private:
-    std::vector<boost::shared_ptr<AuthHelper> > mAuthInstances;
+    std::vector<boost::shared_ptr<AuthInstance> > mAuthInstances;
     pjsip_endpoint *mEndpoint;
     pj_pool_t *mPool;
     moduleHookVector mRegisteredHooks;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 99e9240..93a8dbb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,8 +27,8 @@ asterisk_scf_component_add_file(SipSessionManager PJSipSessionModule.h)
 asterisk_scf_component_add_file(SipSessionManager PJSipLoggingModule.cpp)
 asterisk_scf_component_add_file(SipSessionManager PJSipLoggingModuleConstruction.cpp)
 asterisk_scf_component_add_file(SipSessionManager PJSipLoggingModule.h)
-asterisk_scf_component_add_file(SipSessionManager AuthHelper.cpp)
-asterisk_scf_component_add_file(SipSessionManager AuthHelper.h)
+asterisk_scf_component_add_file(SipSessionManager AuthManager.cpp)
+asterisk_scf_component_add_file(SipSessionManager AuthManager.h)
 asterisk_scf_component_add_file(SipSessionManager SipStateReplicatorListener.cpp)
 asterisk_scf_component_add_file(SipSessionManager SipStateReplicator.h)
 asterisk_scf_component_add_slice(SipSessionManager ../local-slice/SipIf.ice)
diff --git a/src/PJSipModule.h b/src/PJSipModule.h
index cb648bf..076ce6f 100644
--- a/src/PJSipModule.h
+++ b/src/PJSipModule.h
@@ -26,7 +26,7 @@
 #include <SipStateReplicationIf.h>
 #include <AsteriskSCF/System/Hook/HookIf.h>
 #include <AsteriskSCF/SIP/SIPExtensionPointIf.h>
-#include "AuthHelper.h"
+#include "AuthManager.h"
 
 namespace AsteriskSCF
 {
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 2c2bb26..50d54c6 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -27,7 +27,6 @@
 #include "SipSession.h"
 #include "PJSipManager.h"
 #include "SipStateReplicator.h"
-#include "AuthHelper.h"
 
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::SIP::ExtensionPoint::V1;
@@ -433,16 +432,16 @@ pj_status_t PJSipSessionModule::unload()
 
 bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, RequestType type, pjsip_endpoint *endpt)
 {
-    boost::shared_ptr<AuthHelper> authHelper(mAuthManager->createAuthHelper(type));
+    boost::shared_ptr<AuthInstance> authInstance(mAuthManager->createAuthInstance(type));
     
-    std::vector<AuthHookPrx> hooks = authHelper->getHooks();
+    std::vector<AuthHookPrx> hooks = authInstance->getHooks();
     if (hooks.empty())
     {
         return false;
     }
 
     RequestInfoPtr info(new InviteRequestInfo);
-    authHelper->fillInRequestInfo(rdata, info);
+    authInstance->fillInRequestInfo(rdata, info);
 
     //We have our RequestInfo created. Now start calling out to any registered hooks
     for (std::vector<AuthHookPrx>::iterator iter = hooks.begin(); iter != hooks.end(); ++iter)
@@ -464,7 +463,7 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
             pjsip_tx_data *tdata;
             pjsip_inv_end_session(inv, 401, NULL, &tdata);
 
-            authHelper->addDigests(tdata, digests);
+            authInstance->addDigests(tdata, digests);
 
             pjsip_inv_send_msg(inv, tdata);
 
@@ -472,50 +471,50 @@ bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv,
             // is something whose lifetime is not governed by the lifetime of any other
             // SIP element. The current transaction, dialog, and inv_session all end
             // when we receive the ACK for the 401 we send. This means we can't stuff
-            // the AuthHelper into any of these structures. Instead, we have to store
+            // the AuthInstance into any of these structures. Instead, we have to store
             // this in a container local to the module itself.
             //
             // Now, that leads to two further issues: identification and lifetime.
             //
             // When a new message comes in, how are we supposed to match up the new incoming
-            // request with our stored AuthHelper? If you read RFC 3261, it implies that
+            // request with our stored AuthInstance? If you read RFC 3261, it implies that
             // a requester should regenerate his original request with auth info added and
             // the CSeq incremented. So we SHOULD be able to use the call-id and from tag
-            // to figure out which AuthHelper to retrieve. Experimentation will be required
+            // to figure out which AuthInstance to retrieve. Experimentation will be required
             // to determine if this actually works in all cases.
             //
-            // The lifetime of an AuthHelper is a bit hard to grasp. Let's say we send a 401
+            // The lifetime of an AuthInstance is a bit hard to grasp. Let's say we send a 401
             // response and then either a) never receive an ACK or b) receive an ACK but never
             // receive a new request with proper auth info. In either case, we will never
             // receive any sort of message that indicates to us that we should destroy the
-            // AuthHelper. Instead, what we have to do is periodically check to see if we
-            // have held onto an AuthHelper for longer than some prescribed period. While I'd
+            // AuthInstance. Instead, what we have to do is periodically check to see if we
+            // have held onto an AuthInstance for longer than some prescribed period. While I'd
             // think that a few seconds would be long enough to hold on, in practice this may
             // cause issues. If we have to retransmit the 401 3 times and then the other endpoint
             // has to retransmit its ACK 4 times, then the INVITE with the auth info has to
             // be retransmitted 3 times, then that's a lot of time between when we created the
-            // AuthHelper and when we finally see auth info. So this means we have to wait
-            // a minute or two before we can safely claim that an AuthHelper isn't going to
+            // AuthInstance and when we finally see auth info. So this means we have to wait
+            // a minute or two before we can safely claim that an AuthInstance isn't going to
             // be used for anything.
             //
-            // One thing we can be assured of is that the AuthHelper definitely only pertains
+            // One thing we can be assured of is that the AuthInstance definitely only pertains
             // to this particular PJSIP module. So it seems we can add a container to the PJSIP
-            // module and store our AuthHelpers in there. We can get away with using a vector
-            // pretty easily. So first, we need to modify the AuthHelper class to store the
+            // module and store our AuthInstances in there. We can get away with using a vector
+            // pretty easily. So first, we need to modify the AuthInstance class to store the
             // call-id and from tag of the request so that we can identify which to use when
-            // authenticating. We can modify the AuthHelper's constructor to take the pjsip_rdata
+            // authenticating. We can modify the AuthInstance's constructor to take the pjsip_rdata
             // to fill in these values. We can even be slick and define an operator== so that
             // we can use std::find to find an appropriate match, but that's not entirely
             // necessary atm.
             //
             // So how about the lifetime issue? Well PJSIP offers a handy function called
             // pjsip_endpt_schedule_timer. We can schedule a callback to be called in the future,
-            // presumably when the AuthHelper can be determined to be no longer useful. This callback
-            // can find and remove the AuthHelper from the vector. Now of course, if we receive
-            // authentication from the requester, then we can destroy the AuthHelper and cancel
-            // the scheduled callback. This will require adding the pj_timer_entry to the AuthHelper.
-            // Unfortunately we can't schedule the operation from within a method of AuthHelper because
-            // the vector of AuthHelpers lives here in the module, not the AuthHelper. So instead, we'll
+            // presumably when the AuthInstance can be determined to be no longer useful. This callback
+            // can find and remove the AuthInstance from the vector. Now of course, if we receive
+            // authentication from the requester, then we can destroy the AuthInstance and cancel
+            // the scheduled callback. This will require adding the pj_timer_entry to the AuthInstance.
+            // Unfortunately we can't schedule the operation from within a method of AuthInstance because
+            // the vector of AuthInstances lives here in the module, not the AuthInstance. So instead, we'll
             // need a method in the PJSipModule to schedule the operation instead. Easy-peasy.
             return true;
         }

commit 1e847b293c9f7ec3e6b2f051768f59a07d66f7d7
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 10:32:25 2011 -0600

    Actually construct an AuthManager in the PJSipSessionModule

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index aa01701..2c2bb26 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -275,6 +275,11 @@ InviteSessionState PJSipSessionModInfo::inviteStateTranslate(pjsip_inv_state sta
     return retState;
 }
 
+void PJSipSessionModule::createAuthManager(pjsip_endpoint *endpt)
+{
+    mAuthManager.reset(new AuthManager(endpt, lg));
+}
+
 void PJSipSessionModule::replicateState(PJSipDialogModInfo *dlgInfo, PJSipTransactionModInfo *tsxInfo,
     PJSipSessionModInfo *sessionInfo)
 {
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 068703f..9ac956a 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -88,6 +88,7 @@ private:
     void handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdata);
     bool checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type, pjsip_endpoint *endpt);
     void getURIParams(pjsip_uri *uri, AsteriskSCF::SIP::ExtensionPoint::V1::ParamDict &params);
+    void createAuthManager(pjsip_endpoint *endpt);
     pjsip_inv_callback mInvCallback;
     pjsip_ua_init_param mUaParam;
     const std::string mName;
diff --git a/src/PJSipSessionModuleConstruction.cpp b/src/PJSipSessionModuleConstruction.cpp
index e6cebaf..b4ca3bc 100644
--- a/src/PJSipSessionModuleConstruction.cpp
+++ b/src/PJSipSessionModuleConstruction.cpp
@@ -141,6 +141,7 @@ PJSipSessionModule::PJSipSessionModule(pjsip_endpoint *endpt,
     pjsip_xfer_init_module(endpt);
     pjsip_replaces_init_module(endpt);
     pjsip_endpt_register_module(endpt, &mModule);
+    createAuthManager(endpt);
 }
 
 }; //end namespace SipSessionManager

commit d479d28083104c2f4ec3aa74f232c46a1ad2e231
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon Feb 14 10:15:52 2011 -0600

    Add an AuthManager class.
    
    All PJSIP modules will have an AuthManager that manages the
    creation of AuthHelpers (to be renamed soon), manages the
    registered authentication hooks, and will soon also be managing
    the scheduled callbacks with PJSIP as well.

diff --git a/src/AuthHelper.cpp b/src/AuthHelper.cpp
index c657dab..d3ca98f 100644
--- a/src/AuthHelper.cpp
+++ b/src/AuthHelper.cpp
@@ -29,8 +29,8 @@ namespace SipSessionManager
 class AuthHelperPriv
 {
 public:
-    AuthHelperPriv(moduleHookVector moduleHooks, RequestType type, pjsip_endpoint *endpt, const Logger &logger)
-        : mEndpoint(endpt), pool(pjsip_endpt_create_pool(endpt, "auth%p", 1200, 512)), mLogger(logger)
+    AuthHelperPriv(moduleHookVector moduleHooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+        : mPool(pool), mLogger(logger)
     {
         if (moduleHooks.empty())
         {
@@ -51,11 +51,6 @@ public:
         }
     }
 
-    ~AuthHelperPriv()
-    {
-        pjsip_endpt_release_pool(mEndpoint, pool);
-    }
-
     void getURIParams(pjsip_uri *uri, ParamDict &params)
     {
         pjsip_sip_uri *sipURI = (pjsip_sip_uri *) pjsip_uri_get_uri(uri);
@@ -95,13 +90,12 @@ public:
 
     std::vector<AuthHookPrx> hooks;
     std::vector<pjsip_auth_srv *> authServers;
-    pjsip_endpoint *mEndpoint;
-    pj_pool_t *pool;
+    pj_pool_t *mPool;
     Logger mLogger;
 };
 
-AuthHelper::AuthHelper(moduleHookVector hooks, RequestType type, pjsip_endpoint *endpt, const Logger &logger)
-        : mImpl(new AuthHelperPriv(hooks, type, endpt, logger)) { }
+AuthHelper::AuthHelper(moduleHookVector hooks, RequestType type, pj_pool_t *pool, const Logger &logger)
+        : mImpl(new AuthHelperPriv(hooks, type, pool, logger)) { }
 
 std::vector<AuthHookPrx> AuthHelper::getHooks()
 {
@@ -133,10 +127,10 @@ void AuthHelper::addDigests(pjsip_tx_data *tdata, DigestChallengeSeq digests)
     pj_str_t pjqop = pj_str(qop);
     for (DigestChallengeSeq::iterator digest = digests.begin(); digest != digests.end(); ++digest)
     {
-        pjsip_auth_srv *authServer = PJ_POOL_ZALLOC_T(mImpl->pool, pjsip_auth_srv);
+        pjsip_auth_srv *authServer = PJ_POOL_ZALLOC_T(mImpl->mPool, pjsip_auth_srv);
         pj_str_t realm;
         pj_cstr(&realm, (*digest)->realm.c_str());
-        pjsip_auth_srv_init(mImpl->pool, authServer, &realm, lookup_cred, 0);
+        pjsip_auth_srv_init(mImpl->mPool, authServer, &realm, lookup_cred, 0);
         pj_str_t nonce, opaque, *noncePtr = NULL, *opaquePtr = NULL;
         if (!(*digest)->opaque.empty())
         {
@@ -225,5 +219,48 @@ void AuthHelper::fillInRequestInfo(pjsip_rx_data *rdata, RequestInfoPtr info)
     }
 }
 
+AuthManager::AuthManager(pjsip_endpoint *endpt, Logger &logger)
+    : mEndpoint(endpt),
+    mPool(pjsip_endpt_create_pool(endpt, "auth%p", 1200, 512)),
+    mLogger(logger)
+{
+}
+
+AuthManager::~AuthManager()
+{
+    pjsip_endpt_release_pool(mEndpoint, mPool);
+}
+
+boost::shared_ptr<AuthHelper> AuthManager::createAuthHelper(RequestType type)
+{
+    boost::shared_ptr<AuthHelper> helper(new AuthHelper(mRegisteredHooks, type, mPool, mLogger));
+    mAuthInstances.push_back(helper);
+    return helper;
+}
+
+void AuthManager::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
+{
+    boost::shared_ptr<AuthHookData> hookData(new AuthHookData(priority, hook, types));
+    mRegisteredHooks.push_back(hookData);
+    std::stable_sort(mRegisteredHooks.begin(), mRegisteredHooks.end());
+}
+
+void AuthManager::removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook)
+{
+    for (moduleHookVector::iterator iter = mRegisteredHooks.begin(); iter != mRegisteredHooks.end(); ++iter)
+    {
+        if ((*iter)->getHook() == hook)
+        {
+            mRegisteredHooks.erase(iter);
+            break;
+        }
+    }
+}
+
+void AuthManager::clearAuthHooks()
+{
+    mRegisteredHooks.clear();
+}
+
 };
 };
diff --git a/src/AuthHelper.h b/src/AuthHelper.h
index 9d87494..0bd8228 100644
--- a/src/AuthHelper.h
+++ b/src/AuthHelper.h
@@ -24,8 +24,6 @@
 #include <AsteriskSCF/SIP/SIPExtensionPointIf.h>
 #include <AsteriskSCF/logger.h>
 
-#include "PJSipModule.h"
-
 namespace AsteriskSCF
 {
 
@@ -34,12 +32,35 @@ namespace SipSessionManager
 
 class AuthHelperPriv;
 
+class AuthHookData
+{
+public:
+    AuthHookData(int priority, AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
+        : mPriority(priority), mHook(hook), mTypes(types) { }
+
+    int getPriority() const { return mPriority; }
+    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx getHook() const { return mHook; }
+    AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq getRequestTypes() const { return mTypes; }
+
+    bool operator< (const AuthHookData &rhs) const
+    {
+        return getPriority() < rhs.getPriority();
+    }
+
+private:
+    int mPriority;
+    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx mHook;
+    AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq mTypes;
+};
+
+typedef std::vector<boost::shared_ptr<AuthHookData> > moduleHookVector;
+
 class AuthHelper
 {
 public:
     AuthHelper(moduleHookVector hooks,
             AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type,
-            pjsip_endpoint *endpt,
+            pj_pool_t *pool,
             const AsteriskSCF::System::Logging::Logger &logger);
     std::vector<AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx> getHooks();
     void fillInRequestInfo(pjsip_rx_data *rdata, AsteriskSCF::SIP::ExtensionPoint::V1::RequestInfoPtr info);
@@ -48,5 +69,22 @@ private:
     boost::shared_ptr<AuthHelperPriv> mImpl;
 };
 
+class AuthManager
+{
+public:
+    AuthManager(pjsip_endpoint *endpt, AsteriskSCF::System::Logging::Logger& logger);
+    ~AuthManager();
+    boost::shared_ptr<AuthHelper> createAuthHelper(AsteriskSCF::SIP::ExtensionPoint::V1::RequestType type);
+    void addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types);
+    void removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook);
+    void clearAuthHooks();
+private:
+    std::vector<boost::shared_ptr<AuthHelper> > mAuthInstances;
+    pjsip_endpoint *mEndpoint;
+    pj_pool_t *mPool;
+    moduleHookVector mRegisteredHooks;
+    AsteriskSCF::System::Logging::Logger mLogger;
+};
+
 }; //end namespace SipSessionManager
 }; //end namespace AsteriskSCF
diff --git a/src/PJSipModule.cpp b/src/PJSipModule.cpp
index a2e9535..2e837ee 100644
--- a/src/PJSipModule.cpp
+++ b/src/PJSipModule.cpp
@@ -156,26 +156,17 @@ TransactionState PJSipTransactionModInfo::transactionStateTranslate(pjsip_tsx_st
 
 void PJSipModule::addAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, int priority, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
 {
-    boost::shared_ptr<AuthHookData> hookData(new AuthHookData(priority, hook, types));
-    mAuthHooks.push_back(hookData);
-    std::stable_sort(mAuthHooks.begin(), mAuthHooks.end());
+    mAuthManager->addAuthHook(hook, priority, types);
 }
 
 void PJSipModule::removeAuthHook(AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook)
 {
-    for (moduleHookVector::iterator iter = mAuthHooks.begin(); iter != mAuthHooks.end(); ++iter)
-    {
-        if ((*iter)->getHook() == hook)
-        {
-            mAuthHooks.erase(iter);
-            break;
-        }
-    }
+    mAuthManager->removeAuthHook(hook);
 }
 
 void PJSipModule::clearAuthHooks()
 {
-    mAuthHooks.clear();
+    mAuthManager->clearAuthHooks();
 }
 
 };
diff --git a/src/PJSipModule.h b/src/PJSipModule.h
index 6d8ac76..cb648bf 100644
--- a/src/PJSipModule.h
+++ b/src/PJSipModule.h
@@ -26,6 +26,7 @@
 #include <SipStateReplicationIf.h>
 #include <AsteriskSCF/System/Hook/HookIf.h>
 #include <AsteriskSCF/SIP/SIPExtensionPointIf.h>
+#include "AuthHelper.h"
 
 namespace AsteriskSCF
 {
@@ -35,28 +36,6 @@ namespace SipSessionManager
 
 using namespace AsteriskSCF::SIP::V1;
 
-class AuthHookData
-{
-public:
-    AuthHookData(int priority, AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx hook, AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq types)
-        : mPriority(priority), mHook(hook), mTypes(types) { }
-
-    int getPriority() const { return mPriority; }
-    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx getHook() const { return mHook; }
-    AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq getRequestTypes() const { return mTypes; }
-
-    bool operator< (const AuthHookData &rhs) const
-    {
-        return getPriority() < rhs.getPriority();
-    }
-
-private:
-    int mPriority;
-    AsteriskSCF::SIP::ExtensionPoint::V1::AuthHookPrx mHook;
-    AsteriskSCF::SIP::ExtensionPoint::V1::RequestTypeSeq mTypes;
-};
-
-typedef std::vector<boost::shared_ptr<AuthHookData> > moduleHookVector;
 class PJSipModule
 {
 public:
@@ -77,7 +56,7 @@ protected:
     PJSipModule() { }
     virtual ~PJSipModule() { }
     pjsip_module mModule;
-    moduleHookVector mAuthHooks;
+    boost::shared_ptr<AuthManager> mAuthManager;
 private:
     const std::string mName;
 };
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 4375c83..aa01701 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -428,7 +428,7 @@ pj_status_t PJSipSessionModule::unload()
 
 bool PJSipSessionModule::checkAuth(pjsip_rx_data *rdata, pjsip_inv_session *inv, RequestType type, pjsip_endpoint *endpt)
 {
-    boost::shared_ptr<AuthHelper> authHelper(new AuthHelper(mAuthHooks, type, endpt, lg));
+    boost::shared_ptr<AuthHelper> authHelper(mAuthManager->createAuthHelper(type));
     
     std::vector<AuthHookPrx> hooks = authHelper->getHooks();
     if (hooks.empty())

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


-- 
asterisk-scf/release/sip.git



More information about the asterisk-scf-commits mailing list