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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon May 23 16:15:52 CDT 2011


branch "master" has been updated
       via  960d3916fcb553e42df35266060363a425972007 (commit)
       via  f233332d7f4039a7fb007a42c207eb988dd9c77e (commit)
       via  71753eef2f0662b2642b0f5beef628c07c891bba (commit)
       via  069e20776fc5e0d44dbe7d5e4963167d93e64d6a (commit)
       via  56969fd2d98b159e1695d77a689fb78ecbfb6ebf (commit)
       via  30f4658ce0ba340fd90667a5483714ada1e5097c (commit)
       via  c807bf56d40a56549bc37ea3a3e46d8f540821da (commit)
       via  7246f8002b621284be27c987248888c5f701b7de (commit)
       via  b04ec118712501b0512f7c231015dfba60d8d965 (commit)
       via  57d2734e77552204087bcddeb9fa183255a4d140 (commit)
       via  1580cf9ff932630cb695b181826263c7e293405c (commit)
       via  01e69f75a66763af70bca71aa0783e98169ffd72 (commit)
       via  33d9123112321a9aae36a9f021c1c00fb6b0c425 (commit)
       via  0c327d8e8c59536fda95b1e07f0c54f31b825fdd (commit)
       via  d64b6e6f37ba0048fd66948ae6caf0864af1b3a7 (commit)
       via  847e828ad8e207d2d16cbf6ade1b7004fb2426f2 (commit)
       via  7d0b2a500d2e8867bc3fe8db177e2f968d97a849 (commit)
       via  623654b3e60749219d9fa790649f6833200c708f (commit)
       via  d64aea41b53bc585a88fa155bffe6c02562f29af (commit)
       via  72aedeaee32c837c3978f8e91d35af258dd6c880 (commit)
       via  349e921f0cc58898d43db5330643fc3789b0e7bf (commit)
       via  e9d1aa434ba33120497c9dee97ef386f955753b3 (commit)
       via  080f90db10d408e73b4dc9e8eeea8f32c5c0fcb1 (commit)
       via  9353dd8149dd64b463bd207a9be0bc5bd02e1b8f (commit)
       via  673f9e8d81c71018e60c6e7117348528c679ac72 (commit)
       via  576ef02976be38ad1d9ce56a1d1a78145386acec (commit)
       via  8ca653bd739b1b898d408fc439c12cfd85fa1f81 (commit)
       via  e1847341cfa58fa1881760591e1b15c89a3b3d98 (commit)
       via  31f82419f61f057124629513bc58b08b0cbf3c0f (commit)
       via  9efb966a80d43d8472f1844e1960f7c3c4b26fc3 (commit)
       via  19dcde2cc6fabcf7abcfcc41a6987169910c70ee (commit)
       via  0aa8e7cbb655426867811936cf679d2add799d33 (commit)
       via  c7611f180ddcaab977b7c2450d1c2af7f5c30d22 (commit)
       via  275aecd899a44502b0a4f76eab747691bd92af5f (commit)
       via  78e5e7f41cc406ab6fd735cd3bc2684f2ededd38 (commit)
       via  851a92b67b53c0f75bc703da381c4371d7aa0c23 (commit)
       via  2e022453c47afd990d1f27e4403e813a45060e84 (commit)
       via  9f7b96df9ee33cb9469d21446a7cdde44c3ccb7a (commit)
       via  369e38a8e535a447a56e913dd3da63d857bc1ab0 (commit)
       via  1f9e8d9ff5e1fa75e0cd9f6be7699efc400dc796 (commit)
       via  556bf54a532d466b1b77c5872d01de211386ef15 (commit)
       via  bfbb0f9d2ced1b1ec12b1cf4c6b57625451bc47c (commit)
       via  8dd3dc0e1a319ae29aa0cfd7eb67955d26d79241 (commit)
       via  b2c9c8642fbde0022dd790f0a7fc4ccaa58071b1 (commit)
       via  76872d653fe255eb38335206d55eee31ad94f0c6 (commit)
       via  ee47a2ef8ac50751307755c71010d5c4b91effcc (commit)
       via  b917d36d4d91e0069678882fa6785a6ff78ce677 (commit)
       via  d395576d5663b58be0b3ac74609e735b5fa858d5 (commit)
       via  13f04bb0a3bc4098b7cc9b1a5f394e2876376292 (commit)
       via  5620383d390adef3a55d7a81234f1e1a8ff03430 (commit)
      from  ccfb81d546c08b540f175a65fc905123f430f4fc (commit)

Summary of changes:
 src/CMakeLists.txt                     |    2 +-
 src/PJSipManager.h                     |   61 ++
 src/PJSipModule.h                      |    2 +-
 src/PJSipSessionModule.cpp             | 1566 +++++++++++++++++++-------------
 src/PJSipSessionModule.h               |  203 ++++-
 src/PJSipSessionModuleConstruction.cpp |   12 +
 src/SipEndpoint.cpp                    |    9 +-
 src/SipSession.cpp                     |  822 ++++++++++++-----
 src/SipSession.h                       |   90 ++-
 src/SipSessionManagerApp.cpp           |   52 --
 src/SipStateReplicatorListener.cpp     |    3 +-
 11 files changed, 1877 insertions(+), 945 deletions(-)


- Log -----------------------------------------------------------------
commit 960d3916fcb553e42df35266060363a425972007
Merge: ccfb81d f233332
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 23 15:50:21 2011 -0500

    Merge branch 'threading'
    
    Conflicts:
    	src/SipEndpoint.cpp
    	src/SipSession.cpp
    	src/SipSession.h
    	src/SipSessionManagerApp.cpp

diff --cc src/SipEndpoint.cpp
index 07f1a25,889cbf8..3ff806f
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@@ -275,15 -267,16 +277,16 @@@ AsteriskSCF::SessionCommunications::V1:
      }
  
      SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
- 	mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6);
 -            mImplPriv->mServiceLocator, mImplPriv->mReplica, true);
++        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true);
      mImplPriv->mSessions.push_back(session);
+     std::cout << "And now we're returing a session proxy..." << std::endl;
      return session->getSessionProxy();
  }
  
  AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
  {
      SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
- 	mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6);
 -            mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
++        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false);
      mImplPriv->mSessions.push_back(session);
      return session;
  }
diff --cc src/SipSession.cpp
index 2731b02,b9564eb..baf2bf3
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@@ -160,20 -243,61 +243,72 @@@ public
      AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx mServiceLocator;
  
      AsteriskSCF::System::Component::V1::ReplicaPtr mReplica;
- 
-     /**
-      * Shared mutex lock which protects some of the session.
-      */
-     boost::shared_mutex mLock;
  };
  
+ void SipSession::initializePJSIPStructs()
+ {
+     pj_str_t local_uri, remote_uri;
+     SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
+     
++    std::string prefix;
++    if (config.transportConfig.secureTransport == OUTBOUND || config.transportConfig.secureTransport == BOTH)
++    {
++        prefix = "sips";
++    }
++    else
++    {
++        prefix = "sip";
++    }
++
+     char local[64];
 -    pj_ansi_sprintf(local, "sip:%s", config.sessionConfig.sourceAddress.c_str());
++    pj_ansi_sprintf(local, "%s:%s", prefix.c_str(), config.sessionConfig.sourceAddress.c_str());
+     local_uri = pj_str(local);
+     
+     char remote[64];
+     bool userDefined = mImplPriv->mDestination.size() != 0;
 -    pj_ansi_sprintf(remote, "sip:%s%s%s",
++    pj_ansi_sprintf(remote, "%s:%s%s%s",
++        prefix.c_str(),
+         userDefined ? mImplPriv->mDestination.c_str() : "",
+         userDefined ? "@" : "",
+         config.transportConfig.address.c_str());
+     remote_uri = pj_str(remote);
+ 
+     pjsip_dialog *dialog;
+     if ((pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, &local_uri, &remote_uri, &remote_uri, &dialog)) !=
+             PJ_SUCCESS)
+     {
+         // What should we do here? Throw an exception?
+         return;
+     }
+     mImplPriv->mDialog = dialog;
+     
+     pjsip_inv_session *inviteSession;
+     pjmedia_sdp_session *sdp = createSDPOffer();
+     if ((pjsip_inv_create_uac(dialog, sdp, 0, &inviteSession)) != PJ_SUCCESS)
+     {
+         pjsip_dlg_terminate(dialog);
+         // What should we do here? Throw an exception?
+         return;
+     }
+ 
+     pjsip_timer_setting session_timer_settings;
+     pjsip_timer_setting_default(&session_timer_settings);
+     pjsip_timer_init_session(inviteSession, &session_timer_settings);
+ 
+     SessionWorkPtr sessionWork(new SessionWork(mImplPriv->mManager->getSessionModule()->getThreadPoolQueue()));
+     PJSipSessionModInfo *session_mod_info(new PJSipSessionModInfo(inviteSession, this, sessionWork));
+     inviteSession->mod_data[mImplPriv->mManager->getSessionModule()->getModule().id] = (void*)session_mod_info;
+     pjsip_dlg_add_usage(dialog, &mImplPriv->mManager->getSessionModule()->getModule(), NULL);
+     mImplPriv->mInviteSession = inviteSession;
+ }
+ 
  /**
   * Default constructor.
   */
  SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
          const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
          PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-     const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool ipv6)
 -        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
++        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool ipv6, bool isUAC)
      : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
  {
      if (listener != 0)
@@@ -190,7 -314,12 +325,12 @@@
  
      // Get an RTP session capable of handling the formats we are going to offer
      AsteriskSCF::Media::V1::FormatSeq formats;
 -    requestRTPSessions(formats);
 +    requestRTPSessions(formats, ipv6);
+ 
+     if (isUAC)
+     {
+         initializePJSIPStructs();
+     }
  }
  
  /**
diff --cc src/SipSession.h
index e18c480,495cf81..2a60c76
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@@ -63,7 -97,7 +97,7 @@@ public
          const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, PJSipManager *manager,
          const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
          const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
- 	bool ipv6);
 -        bool isUAC);
++        bool ipv6, bool isUAC);
  
      SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&,
          const Ice::Identity&, const AsteriskSCF::Media::V1::SessionPrx&,
@@@ -133,9 -197,13 +197,13 @@@
      void setListeners(const AsteriskSCF::SIP::V1::SessionListenerSeq&);
  
      AsteriskSCF::Media::V1::SessionPrx getHiddenMediaSession();
+ 
+     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
  private:
 -    void requestRTPSessions(AsteriskSCF::Media::V1::FormatSeq& formats);
 +    void requestRTPSessions(AsteriskSCF::Media::V1::FormatSeq& formats, bool ipv6);
  
+     void initializePJSIPStructs();
+ 
      /**
       * Private implementation details.
       */
diff --cc src/SipSessionManagerApp.cpp
index 5500578,d37584d..678a3e8
--- a/src/SipSessionManagerApp.cpp
+++ b/src/SipSessionManagerApp.cpp
@@@ -234,80 -231,6 +234,28 @@@ private
  };
  
  /**
-  * Wrapper class around pj_thread_desc.
-  */
- class ThreadDescWrapper
- {
- public:
-     /**
-      * pjthread thread description information, must persist for the life of the thread
-      */
-     pj_thread_desc mDesc;
- };
- 
- /**
-  * Type definition used to create a smart pointer for the above.
-  */
- typedef boost::shared_ptr<ThreadDescWrapper> ThreadDescWrapperPtr;
- 
- /**
-  * Implementation of the Ice::ThreadNotification class.
-  */
- class pjlibHook : public Ice::ThreadNotification
- {
- public:
-     /**
-      * Implementation of the start function which is called when a thread starts.
-      */
-     void start()
-     {
-         ThreadDescWrapperPtr wrapper = ThreadDescWrapperPtr(new ThreadDescWrapper());
-         pj_thread_t *thread;
-         pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
-         pjThreads.insert(make_pair(thread, wrapper));
-     }
- 
-     /**
-      * Implementation of the stop function which is called when a thread stops.
-      */
-     void stop()
-     {
-         if (pj_thread_is_registered())
-         {
-             pjThreads.erase(pj_thread_this());
-         }
-     }
- 
- private:
-     /**
-      * A map containing thread lifetime persistent data.
-      */
-     map<pj_thread_t*, ThreadDescWrapperPtr> pjThreads;
- };
- 
- /**
 + * Comparator implementation for name based configuration service locating
 + */
 +class SipConfigurationCompare : public ServiceLocatorParamsCompare
 +{
 +public:
 +    SipConfigurationCompare(const string& name) : mName(name) {}
 +    bool isSupported(const ServiceLocatorParamsPtr &params, const Ice::Current &)
 +    {
 +        SipConfigurationParamsPtr configParams = SipConfigurationParamsPtr::dynamicCast(params);
 +        if (configParams->name == mName)
 +        {
 +            return true;
 +        }
 +        return false;
 +    }
 +private:
 +    string mName;
 +};
 +
 +typedef IceUtil::Handle<SipConfigurationCompare> SipConfigurationComparePtr;
 +
 +/**
   * Helper function to add some parameters to one of our registered interfaces in the ServiceLocator, so that
   * other components can look up our interfaces.
   */

commit f233332d7f4039a7fb007a42c207eb988dd9c77e
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 23 14:43:48 2011 -0500

    Change encapsulation of queued operation members.
    
    Specifically made members either protected or public in places where
    I could.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 3882704..3f75ca5 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -332,6 +332,7 @@ public:
             const std::string destination)
         : mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination) { }
 
+protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing SessionCreationOperation" << std::endl;
@@ -402,6 +403,7 @@ public:
         return Complete;
     }
 
+private:
     PJSipSessionModulePtr mSessionModule;
     SipEndpointPtr mCaller;
     AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx> mSessionRouter;
@@ -580,6 +582,7 @@ public:
         mTargetSipUri(target_sip_uri), mSession(session), mSessionRouter(sessionRouter),
         mModuleId(moduleId), mWasWithDestination(false) { }
 
+protected:
     /**
      * This is what is initially called when the operation is queued.
      *
@@ -774,6 +777,7 @@ public:
         return Complete;
     }
 
+private:
     /**
      * The INVITE session, which contains the dialog on which the
      * REFER was received.
@@ -923,6 +927,7 @@ public:
     HandleInviteResponseOperation(int respCode, const int invState, const SipSessionPtr& session)
         : mRespCode(respCode), mInvState(invState), mSession(session) { }
 
+protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing HandleInviteResponseOperation" << std::endl;
@@ -1020,7 +1025,7 @@ public:
         }
         return Complete;
     }
-   
+private:   
     int mRespCode;
     const int mInvState;
     SipSessionPtr mSession;
@@ -1055,6 +1060,7 @@ public:
             const int tsxState)
         : mSessionModule(module), mTsx(tsx), mInv(inv), mEventType(eventType), mTsxState(tsxState) { }
 
+protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         lg(Debug) << "Executing TransactionStateOperation";
@@ -1095,6 +1101,7 @@ public:
         return Complete;
     }
 
+private:
     PJSipSessionModulePtr mSessionModule;
     pjsip_transaction *mTsx;
     pjsip_inv_session *mInv;
@@ -1108,6 +1115,7 @@ public:
     InviteStateOperation(const PJSipSessionModulePtr& module, pjsip_inv_session* inv, const int eventType, const int invState, const std::string branch)
         : mSessionModule(module), mInv(inv), mEventType(eventType), mInvState(invState), mEventBranch(branch) { }
 
+protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         if (mInvState == PJSIP_INV_STATE_DISCONNECTED)
@@ -1203,6 +1211,7 @@ public:
         return Complete;
     }
 
+private:
     PJSipSessionModulePtr mSessionModule;
     pjsip_inv_session* mInv;
     const int mEventType;
@@ -1308,6 +1317,7 @@ public:
     HandleMediaUpdate(pjsip_inv_session *inv, const int moduleId, const ServiceLocatorPrx& serviceLocator)
         : mInv(inv), mModuleId(moduleId), mServiceLocator(serviceLocator) { }
 
+protected:
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         const pjmedia_sdp_session *remote_sdp;
@@ -1411,6 +1421,7 @@ public:
         return Complete;
     }
 
+private:
     pjsip_inv_session* mInv;
     const int mModuleId;
     ServiceLocatorPrx mServiceLocator;
@@ -1530,6 +1541,7 @@ public:
         mQueueListener->workResumable();
     }
 
+private:
     QueueListenerPtr mQueueListener;
 };
 
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 0a8a872..73fd186 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -184,6 +184,7 @@ public:
         return result;
     }
 
+protected:
     /**
      * All SipQueueableOperations are required to provide an overload
      * of this function. This is where initial processing takes place.
@@ -203,7 +204,7 @@ public:
     {
         return AsteriskSCF::System::WorkQueue::V1::Complete;
     }
-protected:
+
     enum states
     {
         /**
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index d3fad49..b9564eb 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -371,7 +371,7 @@ public:
         mCb->ice_response(sessionInfo);
         return Complete;
     }
-
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_addListenerPtr mCb;
     AsteriskSCF::SessionCommunications::V1::SessionListenerPrx mListener;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
@@ -449,6 +449,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_indicatePtr mCb;
     AsteriskSCF::SessionCommunications::V1::IndicationPtr mIndication;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
@@ -482,6 +483,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_getEndpointPtr mCb;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -515,6 +517,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr mCb;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -545,6 +548,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_getMediaSessionPtr mCb;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -583,7 +587,8 @@ public:
         mCb->ice_response(bridge);
         return Complete;
     }
-    
+
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_getBridgePtr mCb;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -620,6 +625,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_setBridgePtr mCb;
     SipSessionPtr mSession;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
@@ -680,6 +686,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::AMD_Session_removeBridgePtr mCb;
     SipSessionPtr mSession;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
@@ -713,6 +720,7 @@ public:
         mImplPriv->removeListener(mListener);
         return Complete;
     }
+private:
     AsteriskSCF::SessionCommunications::V1::SessionListenerPrx mListener;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -754,6 +762,7 @@ public:
         return Complete;
     }
 
+private:
     SipSessionPtr mSession;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
@@ -799,6 +808,7 @@ public:
         return Complete;
     }
 
+private:
     AsteriskSCF::SessionCommunications::V1::ResponseCodePtr mResponse;
     pjsip_inv_session *mInviteSession;
 };
@@ -848,6 +858,7 @@ public:
         return Complete;
     }
 
+private:
     SipSessionPtr mSession;
     boost::shared_ptr<SipSessionPriv> mSessionPriv;
 };

commit 71753eef2f0662b2642b0f5beef628c07c891bba
Author: Mark Michelson <mmichelson at digium.com>
Date:   Mon May 23 14:17:39 2011 -0500

    Protect the pjlibHook map with a mutex.

diff --git a/src/PJSipManager.h b/src/PJSipManager.h
index f36b0ac..ef7e457 100644
--- a/src/PJSipManager.h
+++ b/src/PJSipManager.h
@@ -24,6 +24,7 @@
 #include <Ice/Ice.h>
 
 #include <boost/shared_ptr.hpp>
+#include <boost/thread/locks.hpp>
 
 #include <AsteriskSCF/Discovery/SmartProxy.h>
 
@@ -142,7 +143,10 @@ public:
         ThreadDescWrapperPtr wrapper = ThreadDescWrapperPtr(new ThreadDescWrapper());
         pj_thread_t *thread;
         pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
-        pjThreads.insert(std::make_pair(thread, wrapper));
+        {
+            boost::lock_guard<boost::mutex> lock(mLock);
+            pjThreads.insert(std::make_pair(thread, wrapper));
+        }
     }
 
     /**
@@ -152,6 +156,7 @@ public:
     {
         if (pj_thread_is_registered())
         {
+            boost::lock_guard<boost::mutex> lock(mLock);
             pjThreads.erase(pj_thread_this());
         }
     }
@@ -161,6 +166,10 @@ private:
      * A map containing thread lifetime persistent data.
      */
     std::map<pj_thread_t*, ThreadDescWrapperPtr> pjThreads;
+    /**
+     * Mutex to protect the map
+     */
+    boost::mutex mLock;
 };
 
 }; //End namespace SipSessionManager

commit 069e20776fc5e0d44dbe7d5e4963167d93e64d6a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 19:10:20 2011 -0500

    Make debug messages consistent and actually use the logger.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 7229342..3882704 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -334,7 +334,7 @@ public:
 
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "SessionCreationOperation running. About to create a session!" << std::endl;
+        lg(Debug) << "Executing SessionCreationOperation" << std::endl;
         try
         {
             mSession = mCaller->createSession(mDestination);
@@ -476,7 +476,6 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
     pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
     PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(tsx);
     tsx->mod_data[mModule.id] = (void *)tsx_mod_info;
-    std::cout << "We put mod info into the tsx at address " << tsx << std::endl;
 
     //XXX The sdp argument is NULL for now, but can be changed if we
     //know what has been configured for this particular caller.
@@ -926,7 +925,7 @@ public:
 
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Handling response to an INVITE yo!" << std::endl;
+        lg(Debug) << "Executing HandleInviteResponseOperation" << std::endl;
         //Treat all 1XX messages we don't recognize the same as a 180
         if (mRespCode > 100 && mRespCode < 200 && mRespCode != 183)
         {
@@ -1058,7 +1057,7 @@ public:
 
     SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "The transaction has address " << mTsx << std::endl;
+        lg(Debug) << "Executing TransactionStateOperation";
         PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
         if (!tsx_mod_info)
         {
@@ -1161,7 +1160,6 @@ public:
             }
             lg(Debug) << "Replicating state on DISCONNECTED inv_state.";
             mSessionModule->replicateState(dlg_mod_info, NULL, session_mod_info);
-            std::cout << "Deleting session mod info on a session" << std::endl;
             delete session_mod_info;
             mInv->mod_data[mSessionModule->getModule().id] = 0;
             if (dlg_mod_info)
@@ -1285,7 +1283,7 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
         SipSessionPtr session = session_mod_info->getSessionPtr();
 
         std::string method(pj_strbuf(&tsx->method.name), pj_strlen(&tsx->method.name));
-        std::cout << "Queuing a Transaction state operation for transaction " << tsx  << " Method: " << method << std::endl;
+        lg(Debug) << "Queuing a Transaction state operation for transaction " << tsx  << " Method: " << method;
         enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state), inv);
     }
 }
@@ -1406,7 +1404,6 @@ public:
                 }
                 catch (...)
                 {
-                    std::cout << "EXCEPTION DURING MEDIA UPDATE????" << std::endl;
                     // If we get here the format just isn't supported...
                 }
             }
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 16930b6..d3fad49 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -364,7 +364,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Actually executing addListener logic" << std::endl;
+        lg(Debug) << "Executing addListener operation";
         mImplPriv->addListener(mListener);
         AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
             mImplPriv->getInfo();
@@ -382,7 +382,7 @@ void SipSession::addListener_async(
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
         const Ice::Current&)
 {
-    std::cout << "addListener called. Queueing operation..." << std::endl;
+    lg(Debug) << "Queueing addListener operation";
     enqueueSessionWork(new AddListenerOperation(cb, listener, mImplPriv));
 }
 
@@ -398,7 +398,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing indicate operation" << std::endl;
+        lg(Debug) << "Executing indicate operation";
         AsteriskSCF::SessionCommunications::V1::ConnectIndicationPtr Connect;
         AsteriskSCF::SessionCommunications::V1::FlashIndicationPtr Flash;
         AsteriskSCF::SessionCommunications::V1::HoldIndicationPtr Hold;
@@ -463,7 +463,7 @@ void SipSession::indicate_async(
         const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication,
         const Ice::Current&)
 {
-    std::cout << "Queuing an indicate operation" << std::endl;
+    lg(Debug) << "Queuing an indicate operation";
     enqueueSessionWork(new IndicateOperation(cb, indication, mImplPriv, this));
 }
 
@@ -477,7 +477,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing a getEndpoint Operation" << std::endl;
+        lg(Debug) << "Executing a getEndpoint Operation";
         mCb->ice_response(mImplPriv->mEndpoint->getEndpointProxy());
         return Complete;
     }
@@ -493,7 +493,7 @@ void SipSession::getEndpoint_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getEndpointPtr& cb,
         const Ice::Current&)
 {
-    std::cout << "Queuing a getEndpoint operation" << std::endl;
+    lg(Debug) << "Queuing a getEndpoint operation";
     enqueueSessionWork(new GetEndpointOperation(cb, mImplPriv));
 }
 
@@ -507,7 +507,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing a GetInfo operation" << std::endl;
+        lg(Debug) << "Executing a GetInfo operation";
         AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
             mImplPriv->getInfo();
 
@@ -526,7 +526,7 @@ void SipSession::getInfo_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr& cb,
         const Ice::Current&)
 {
-    std::cout << "queuing a getInfo operation" << std::endl;
+    lg(Debug) << "queuing a getInfo operation";
     enqueueSessionWork(new GetInfoOperation(cb, mImplPriv));
 }
 
@@ -540,7 +540,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing a GetMediaSession operation" << std::endl;
+        lg(Debug) << "Executing a GetMediaSession operation";
         mCb->ice_response(mImplPriv->mMediaSessionProxy);
         return Complete;
     }
@@ -556,7 +556,7 @@ void SipSession::getMediaSession_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getMediaSessionPtr& cb,
         const Ice::Current&)
 {
-    std::cout << "queuing a getMediaSession operation" << std::endl;
+    lg(Debug) << "queuing a getMediaSession operation";
     enqueueSessionWork(new GetMediaSessionOperation(cb, mImplPriv));
 }
 
@@ -569,7 +569,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing a GetBridge operation" << std::endl;
+        lg(Debug) << "Executing a GetBridge operation";
         AsteriskSCF::SessionCommunications::V1::BridgePrx bridge;
         try
         {
@@ -595,7 +595,7 @@ void SipSession::getBridge_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getBridgePtr& cb,
         const Ice::Current&)
 {
-    std::cout << "queuing a getBridge operation" << std::endl;
+    lg(Debug) << "queuing a getBridge operation";
     enqueueSessionWork(new GetBridgeOperation(cb, mImplPriv));
 }
 
@@ -613,7 +613,7 @@ public:
     
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Executing a SetBridge operation" << std::endl;
+        lg(Debug) << "Executing a SetBridge operation";
         mSession->setBridge(mBridge);
         mImplPriv->addListener(mListener);
         mCb->ice_response(mImplPriv->getInfo());
@@ -637,7 +637,7 @@ void SipSession::setBridge_async(
     const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
     const Ice::Current& current)
 {
-    std::cout << "queuing a setBridge operation" << std::endl;
+    lg(Debug) << "queuing a setBridge operation";
     enqueueSessionWork(new SetBridgeOperation(cb, this, mImplPriv, bridge, listener, current));
 }
 
@@ -695,7 +695,7 @@ void SipSession::removeBridge_async(
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
         const Ice::Current& current)
 {
-    std::cout << "queuing a removeBridge operation" << std::endl;
+    lg(Debug) << "queuing a removeBridge operation";
     enqueueSessionWork(new RemoveBridgeOperation(cb, this, mImplPriv, listener, current));
 }
 
@@ -709,7 +709,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
-        std::cout << "Actually removing listener" << std::endl;
+        lg(Debug) << "Actually removing listener";
         mImplPriv->removeListener(mListener);
         return Complete;
     }
@@ -722,7 +722,7 @@ public:
  */
 void SipSession::removeListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener, const Ice::Current&)
 {
-    std::cout << "removeListener called. Queuing operation" << std::endl;
+    lg(Debug) << "removeListener called. Queuing operation";
     enqueueSessionWork(new RemoveListenerOperation(listener, mImplPriv));
 }
 
@@ -764,7 +764,7 @@ public:
  */
 void SipSession::start(const Ice::Current&)
 {
-    std::cout << "We've been asked to start a session." << std::endl;
+    lg(Debug) << "We've been asked to start a session.";
     enqueueSessionWork(new StartOperation(this, mImplPriv));
 }
 
@@ -809,7 +809,7 @@ public:
  */
 void SipSession::stop(const AsteriskSCF::SessionCommunications::V1::ResponseCodePtr& response, const Ice::Current&)
 {
-    std::cout << "queuing a stop operation" << std::endl;
+    lg(Debug) << "queuing a stop operation";
     enqueueSessionWork(new StopOperation(response, mImplPriv->mInviteSession));
 }
 
@@ -857,7 +857,7 @@ public:
  */
 void SipSession::destroy()
 {
-    std::cout << "queuing a destroy operation" << std::endl;
+    lg(Debug) << "queuing a destroy operation";
     enqueueSessionWork(new DestroyOperation(this, mImplPriv));
 }
 
@@ -1075,7 +1075,7 @@ void SipSession::enqueueSessionWork(const SuspendableWorkPtr& task)
 {
     if (!mImplPriv->mInviteSession)
     {
-        std::cout << "No invite session yet. Unable to queue operation" << std::endl;
+        lg(Debug) << "No invite session yet. Unable to queue operation";
         return;
     }
     PJSipSessionModInfo *session_mod_info =

commit 56969fd2d98b159e1695d77a689fb78ecbfb6ebf
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 18:46:12 2011 -0500

    A bit of cleanup plus adding some helpful comments.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index c20ac28..7229342 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -330,23 +330,9 @@ public:
             pjsip_tx_data *tdata,
             pjsip_dialog *replacedDialog,
             const std::string destination)
-        : mState(Initial), mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination) { }
+        : mSessionModule(module), mCaller(caller), mSessionRouter(router), mInv(inv), mTdata(tdata), mReplacedDialog(replacedDialog), mDestination(destination) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        switch (mState)
-        {
-            case Initial:
-                return initial();
-            case CalledBack:
-                return calledBack();
-            default:
-                lg(Error) << "We're in a bad state here.";
-                return Complete;
-        }
-    }
-
-    SuspendableWorkResult initial()
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         std::cout << "SessionCreationOperation running. About to create a session!" << std::endl;
         try
@@ -384,7 +370,6 @@ public:
                 SuspendableWorkListenerPtr listener = 0;
                 SipAMICallbackPtr cb(new SipAMICallback(listener, mSession, this, false, true));
                 Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
-                mState = CalledBack;
                 mSessionRouter->begin_routeSession(operationId, mSession->getSessionProxy(), mDestination, d);
             }
         }
@@ -417,20 +402,6 @@ public:
         return Complete;
     }
 
-    enum states
-    {
-        /**
-         * First state.
-         * @see processRefer
-         */
-        Initial,
-        /**
-         * State after routing service completes
-         * @see processRoutingResponse
-         */
-        CalledBack,
-    } mState;
-
     PJSipSessionModulePtr mSessionModule;
     SipEndpointPtr mCaller;
     AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx> mSessionRouter;
@@ -606,24 +577,10 @@ public:
             const SipSessionPtr& session,
             const AsteriskSCF::Discovery::SmartProxy<SessionRouterPrx>& sessionRouter,
             const int moduleId)
-        : mState(Initial), mInv(inv), mTsx(tsx), mTdata(tdata), 
+        : mInv(inv), mTsx(tsx), mTdata(tdata), 
         mTargetSipUri(target_sip_uri), mSession(session), mSessionRouter(sessionRouter),
         mModuleId(moduleId), mWasWithDestination(false) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr& workListener)
-    {
-        switch (mState)
-        {
-        case Initial:
-            return processRefer(workListener);
-        case CalledBack:
-            return processRoutingResponse(workListener);
-        default:
-            lg(Error) << "We're in a bad state here...";
-            return Complete;
-        }
-    }
-
     /**
      * This is what is initially called when the operation is queued.
      *
@@ -634,7 +591,7 @@ public:
      * When this operation is successful, it will result in work for this session
      * being suspended until the routing service returns.
      */
-    SuspendableWorkResult processRefer(const SuspendableWorkListenerPtr& workListener)
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr& workListener)
     {
         // Determine if this is a blind transfer or an attended transfer
         pj_str_t replaces = pj_str((char*)"Replaces");
@@ -735,7 +692,6 @@ public:
                 Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
 
                 lg(Debug) << "handleRefer() calling router connectBridgedSessions(). ";
-                mState = CalledBack;
                 mSessionRouter->begin_connectBridgedSessions(operationId, mSession->getSessionProxy(), other_session->getSessionProxy(), d);
                 pjsip_dlg_dec_lock(other_dlg);
                 return Complete;
@@ -764,7 +720,6 @@ public:
 
                 lg(Debug) << "handleRefer() calling router connectBridgedSessionsWithDestination(). ";
                 mWasWithDestination = true;
-                mState = CalledBack;
                 mSessionRouter->begin_connectBridgedSessionsWithDestination(operationId, session->getSessionProxy(), target, d);
                 return Complete;
             }
@@ -782,7 +737,7 @@ public:
      * Once the routing service has allowed for work to be resumed,
      * this is where the final work is done
      */
-    SuspendableWorkResult processRoutingResponse(const SuspendableWorkListenerPtr&)
+    SuspendableWorkResult calledBack(const SuspendableWorkListenerPtr&)
     {
         assert(mAsyncResult);
         SessionRouterPrx router = SessionRouterPrx::uncheckedCast(mAsyncResult->getProxy());
@@ -820,19 +775,6 @@ public:
         return Complete;
     }
 
-    enum states
-    {
-        /**
-         * First state.
-         * @see processRefer
-         */
-        Initial,
-        /**
-         * State after routing service completes
-         * @see processRoutingResponse
-         */
-        CalledBack,
-    } mState;
     /**
      * The INVITE session, which contains the dialog on which the
      * REFER was received.
@@ -980,23 +922,9 @@ class HandleInviteResponseOperation : public SipQueueableOperation
 {
 public:
     HandleInviteResponseOperation(int respCode, const int invState, const SipSessionPtr& session)
-        : mState(Initial), mRespCode(respCode), mInvState(invState), mSession(session) { }
+        : mRespCode(respCode), mInvState(invState), mSession(session) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        switch (mState)
-        {
-        case Initial:
-            return processInviteResponse();
-        case CalledBack:
-            return processSessionListenerResult();
-        default:
-            lg(Error) << "We're in a bad state here...";
-            return Complete;
-        }
-    }
-
-    SuspendableWorkResult processInviteResponse()
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         std::cout << "Handling response to an INVITE yo!" << std::endl;
         //Treat all 1XX messages we don't recognize the same as a 180
@@ -1021,7 +949,6 @@ public:
                 {
                     SipAMICallbackPtr cb(new SipAMICallback(0, mSession, this, false, true));
                     Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
-                    mState = CalledBack;
                     (*listener)->begin_indicated(mSession->getSessionProxy(), new RingingIndication(), d);
                 }
                 catch (const Ice::Exception &ex)
@@ -1046,7 +973,6 @@ public:
                     Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
                     ProgressingIndicationPtr progressing(new ProgressingIndication());
                     progressing->response = response;
-                    mState = CalledBack;
                     (*listener)->begin_indicated(mSession->getSessionProxy(), progressing, d);
                 }
                 catch (const Ice::Exception &ex)
@@ -1069,7 +995,6 @@ public:
                     {
                         SipAMICallbackPtr cb(new SipAMICallback(0, mSession, this, false, true));
                         Ice::CallbackPtr d = Ice::newCallback(cb, &SipAMICallback::callback);
-                        mState = CalledBack;
                         (*listener)->begin_indicated(mSession->getSessionProxy(), new ConnectedIndication(), d);
                     }
                     catch (const Ice::Exception &ex)
@@ -1082,7 +1007,7 @@ public:
         return Complete;
     }
 
-    SuspendableWorkResult processSessionListenerResult()
+    SuspendableWorkResult calledBack()
     {
         assert(mAsyncResult);
         SessionListenerPrx listener = SessionListenerPrx::uncheckedCast(mAsyncResult->getProxy());
@@ -1096,21 +1021,7 @@ public:
         }
         return Complete;
     }
-    
-    enum states
-    {
-        /**
-         * First state.
-         * @see processRefer
-         */
-        Initial,
-        /**
-         * State after routing service completes
-         * @see processSessionListenerResult
-         */
-        CalledBack,
-    } mState;
-
+   
     int mRespCode;
     const int mInvState;
     SipSessionPtr mSession;
@@ -1145,7 +1056,7 @@ public:
             const int tsxState)
         : mSessionModule(module), mTsx(tsx), mInv(inv), mEventType(eventType), mTsxState(tsxState) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         std::cout << "The transaction has address " << mTsx << std::endl;
         PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
@@ -1198,7 +1109,7 @@ public:
     InviteStateOperation(const PJSipSessionModulePtr& module, pjsip_inv_session* inv, const int eventType, const int invState, const std::string branch)
         : mSessionModule(module), mInv(inv), mEventType(eventType), mInvState(invState), mEventBranch(branch) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         if (mInvState == PJSIP_INV_STATE_DISCONNECTED)
         {
@@ -1399,7 +1310,7 @@ public:
     HandleMediaUpdate(pjsip_inv_session *inv, const int moduleId, const ServiceLocatorPrx& serviceLocator)
         : mInv(inv), mModuleId(moduleId), mServiceLocator(serviceLocator) { }
 
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    SuspendableWorkResult initial(const SuspendableWorkListenerPtr&)
     {
         const pjmedia_sdp_session *remote_sdp;
         pj_status_t status;
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index a8968d3..0a8a872 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -138,33 +138,105 @@ typedef IceUtil::Handle<PJSipSessionModule> PJSipSessionModulePtr;
 
 /**
  * Operation that may be queued.
+ *
+ * Operations that are queued due to the arrival of SIP messages tend to follow a pattern. That
+ * is, they do some initial processing based on the SIP message, then they make an AMI call to
+ * a session listener, and then they process the response of the AMI call.
+ *
+ * This class makes facilitating such a pattern relatively easy.
  */
 class SipQueueableOperation : virtual public AsteriskSCF::System::WorkQueue::V1::SuspendableWork
 {
 public:
-    virtual ~SipQueueableOperation() { };
+    SipQueueableOperation() : mState(Initial) { }
+    virtual ~SipQueueableOperation() { }
     /**
      * Queueable operations may call out to AMI methods. AMI callbacks happen
      * in Ice client threads. We want to process the result of the AMI call in one
      * of our thread pool's threads, though. The AMI callback can set the operation's
-     * AsyncResult so that the operation will be able to actually do something with
-     * the AMI call's result.
+     * AsyncResult so that the operation may process the result of the AMI call in
+     * one of our threads.
      */
     void setAsyncResult(const Ice::AsyncResultPtr& r) {mAsyncResult = r;}
+
     /**
      * Override of SuspendableWorkExecute()
      */
-    virtual AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult execute(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr&)
+    AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult execute(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr& listener)
+    {
+        AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult result =
+            AsteriskSCF::System::WorkQueue::V1::Complete;
+        switch (mState)
+        {
+            case Initial:
+                result = initial(listener);
+                // Change the state now so that
+                // when the AMI callback occurs,
+                // the proper followup will be called.
+                mState = CalledBack;
+                break;
+            case CalledBack:
+                result = calledBack(listener);
+                break;
+            default:
+                break;
+        }
+        return result;
+    }
+
+    /**
+     * All SipQueueableOperations are required to provide an overload
+     * of this function. This is where initial processing takes place.
+     */
+    virtual AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult initial(
+            const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr&) = 0;
+
+    /**
+     * If a SipQueueableOperation has made an AMI call, then when the AMI method
+     * returns, this will be where the AMI result can be processed.
+     *
+     * Since not all SipQueueableOperations make use of AMI, this method need
+     * not always be overloaded.
+     */
+    virtual AsteriskSCF::System::WorkQueue::V1::SuspendableWorkResult calledBack(
+            const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkListenerPtr&)
     {
         return AsteriskSCF::System::WorkQueue::V1::Complete;
     }
 protected:
+    enum states
+    {
+        /**
+         * State of the operation upon construction.
+         * @see initial
+         */
+        Initial,
+        /**
+         * State when AMI result is received.
+         * @see calledBack
+         */
+        CalledBack,
+    } mState;
+
+    /**
+     * Ice asynchronous result.
+     *
+     * Used for processing the result of AMI calls.
+     * @see setAsyncResult
+     */
     Ice::AsyncResultPtr mAsyncResult;
-    SipQueueableOperation() { }
 };
 
 typedef IceUtil::Handle<SipQueueableOperation> SipQueueableOperationPtr;
 
+/**
+ * General AMI callback class used with SipQueueableOperation
+ *
+ * This AMI callback doesn't actually process results itself. Rather,
+ * it passes the result back to the original operation that made the
+ * AMI call so that the AMI result can be processed in the proper
+ * thread.
+ */
 class SipAMICallback : public IceUtil::Shared
 {
 public:

commit 30f4658ce0ba340fd90667a5483714ada1e5097c
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 17:42:53 2011 -0500

    Fix another crash that could happen if a transaction terminates after the session is stopped.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 45f05c0..c20ac28 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1362,11 +1362,21 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
     //function from there.
 
     PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
-    SipSessionPtr session = session_mod_info->getSessionPtr();
 
-    std::string method(pj_strbuf(&tsx->method.name), pj_strlen(&tsx->method.name));
-    std::cout << "Queuing a Transaction state operation for transaction " << tsx  << " Method: " << method << std::endl;
-    enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state), inv);
+    //When a transaction is terminated, it will call into here. In the situation where we are the UAS, this
+    //may happen after the session has been stopped, and therefore the session_mod_info is NULL.
+    //
+    //XXX This can be problematic with regards to transaction state replication since we may not communicate
+    //to the replica that the transaction has been terminated. This will need to be addressed when transaction
+    //state replication is worked on.
+    if (session_mod_info)
+    {
+        SipSessionPtr session = session_mod_info->getSessionPtr();
+
+        std::string method(pj_strbuf(&tsx->method.name), pj_strlen(&tsx->method.name));
+        std::cout << "Queuing a Transaction state operation for transaction " << tsx  << " Method: " << method << std::endl;
+        enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state), inv);
+    }
 }
 
 /**

commit c807bf56d40a56549bc37ea3a3e46d8f540821da
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 16:58:31 2011 -0500

    Prevent a potential crash.
    
    During testing, the bridge will call removeBridge (or removeListener, or both) on
    a session that had told the bridge that the session had already stopped. This causes
    an issue since state replication has ceased and the pointer to the object on which
    we would run session replication commands is now NULL. Since we're not denying replicas
    any hot juicy session state information by simply not attempting to replicate state
    in such a scenario, that's exactly what we'll do here now.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 7b35442..16930b6 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -150,8 +150,14 @@ public:
             PJSipSessionModInfo *session_mod_info =
                 static_cast<PJSipSessionModInfo*>(
                     mInviteSession->mod_data[mManager->getSessionModule()->getModule().id]);
-            session_mod_info->updateSessionState(mInviteSession);
-            mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
+            //session listeners seem to have a tendency to call operations like this one
+            //after we have already indicated to them that we have stopped. Since we already
+            //have ceased state replication, checking for NULLity here is safe and proper.
+            if (session_mod_info)
+            {
+                session_mod_info->updateSessionState(mInviteSession);
+                mManager->getSessionModule()->replicateState(NULL, NULL, session_mod_info);
+            }
         }
     }
 

commit 7246f8002b621284be27c987248888c5f701b7de
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 16:48:36 2011 -0500

    Fix crash problem that would occur on connection.
    
    It helps to check for NULLity of a pointer *before* you attempt
    to actually use it, not after.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 0768b45..45f05c0 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1269,22 +1269,25 @@ public:
                 session_mod_info->updateSessionState(mInv);
             }
             mSessionModule->replicateState(NULL, NULL, session_mod_info);
-    
-            std::string invBranch(pj_strbuf(&mInv->invite_tsx->branch), pj_strlen(&mInv->invite_tsx->branch));
-            //Compare branches to see if this got handled by the transaction layer.
-            if (mInv->invite_tsx && mEventBranch != invBranch)
+
+            if (mInv->invite_tsx)
             {
-                //Mismatched branch!
-                //XXX There's a check for if session_mod_info is NULL above. I don't
-                //know why session_mod_info would be NULL here since we should have created
-                //the session_mod_info when the INVITE was received. Still, I'm being safe
-                //here.
-                if (session_mod_info)
+                std::string invBranch(pj_strbuf(&mInv->invite_tsx->branch), pj_strlen(&mInv->invite_tsx->branch));
+                //Compare branches to see if this got handled by the transaction layer.
+                if (mEventBranch != invBranch)
                 {
-                    lg(Debug) << "Queuing a TransactionStateOperation";
-                    mSessionModule->enqueueSessionWork(
-                            new TransactionStateOperation(mSessionModule, mInv->invite_tsx, mInv, mEventType, mInv->invite_tsx->state),
-                            mInv);
+                    //Mismatched branch!
+                    //XXX There's a check for if session_mod_info is NULL above. I don't
+                    //know why session_mod_info would be NULL here since we should have created
+                    //the session_mod_info when the INVITE was received. Still, I'm being safe
+                    //here.
+                    if (session_mod_info)
+                    {
+                        lg(Debug) << "Queuing a TransactionStateOperation";
+                        mSessionModule->enqueueSessionWork(
+                                new TransactionStateOperation(mSessionModule, mInv->invite_tsx, mInv, mEventType, mInv->invite_tsx->state),
+                                mInv);
+                    }
                 }
             }
         }

commit b04ec118712501b0512f7c231015dfba60d8d965
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu May 19 15:51:06 2011 -0500

    Commit a bunch of changes that have helped since testing of this started.

diff --git a/src/PJSipManager.h b/src/PJSipManager.h
index 15d4e83..f36b0ac 100644
--- a/src/PJSipManager.h
+++ b/src/PJSipManager.h
@@ -111,6 +111,58 @@ private:
 
 typedef boost::shared_ptr<PJSipManager> PJSipManagerPtr;
 
+/**
+ * Wrapper class around pj_thread_desc.
+ */
+class ThreadDescWrapper
+{
+public:
+    /**
+     * pjthread thread description information, must persist for the life of the thread
+     */
+    pj_thread_desc mDesc;
+};
+
+/**
+ * Type definition used to create a smart pointer for the above.
+ */
+typedef boost::shared_ptr<ThreadDescWrapper> ThreadDescWrapperPtr;
+
+/**
+ * Implementation of the Ice::ThreadNotification class.
+ */
+class pjlibHook : public Ice::ThreadNotification
+{
+public:
+    /**
+     * Implementation of the start function which is called when a thread starts.
+     */
+    void start()
+    {
+        ThreadDescWrapperPtr wrapper = ThreadDescWrapperPtr(new ThreadDescWrapper());
+        pj_thread_t *thread;
+        pj_thread_register("ICE Thread", wrapper->mDesc, &thread);
+        pjThreads.insert(std::make_pair(thread, wrapper));
+    }
+
+    /**
+     * Implementation of the stop function which is called when a thread stops.
+     */
+    void stop()
+    {
+        if (pj_thread_is_registered())
+        {
+            pjThreads.erase(pj_thread_this());
+        }
+    }
+
+private:
+    /**
+     * A map containing thread lifetime persistent data.
+     */
+    std::map<pj_thread_t*, ThreadDescWrapperPtr> pjThreads;
+};
+
 }; //End namespace SipSessionManager
 
 }; //End namespace AsteriskSCF
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index df2714e..0768b45 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -348,6 +348,7 @@ public:
 
     SuspendableWorkResult initial()
     {
+        std::cout << "SessionCreationOperation running. About to create a session!" << std::endl;
         try
         {
             mSession = mCaller->createSession(mDestination);
@@ -361,15 +362,11 @@ public:
         }
         mSession->setInviteSession(mInv);
         mSession->setDialog(mInv->dlg);
-        PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(mInv->dlg);
-        PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(mInv->invite_tsx);
+        PJSipDialogModInfo *dlg_mod_info =(PJSipDialogModInfo*)mInv->dlg->mod_data[mSessionModule->getModule().id];
+        PJSipTransactionModInfo *tsx_mod_info = (PJSipTransactionModInfo *)mInv->invite_tsx->mod_data[mSessionModule->getModule().id];
         PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mSessionModule->getModule().id];
         // Now we can actually set a for-real non-NULL session on the session module information.
         session_mod_info->setSessionPtr(mSession);
-        dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
-        tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
-    
-        mInv->dlg->mod_data[mSessionModule->getModule().id] = (void *)dlg_mod_info;
     
         lg(Debug) << "Replicating state on reception of new SIP INVITE.";
         mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
@@ -504,9 +501,11 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
         lg(Warning) << "Unable to create UAS dialog on incoming INVITE";
         return;
     }
+
     pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
     PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(tsx);
     tsx->mod_data[mModule.id] = (void *)tsx_mod_info;
+    std::cout << "We put mod info into the tsx at address " << tsx << std::endl;
 
     //XXX The sdp argument is NULL for now, but can be changed if we
     //know what has been configured for this particular caller.
@@ -522,6 +521,9 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
 
     // Add our own module as a dialog usage
     pjsip_dlg_add_usage(dlg, &mModule, NULL);
+    
+    PJSipDialogModInfo *dlg_mod_info(new PJSipDialogModInfo(dlg));
+    dlg->mod_data[mModule.id] = (void *)dlg_mod_info;
 
     pjsip_timer_setting session_timer_settings;
     pjsip_timer_setting_default(&session_timer_settings);
@@ -542,6 +544,9 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
     SipSessionPtr nullSession(0);
     PJSipSessionModInfo *session_mod_info(new PJSipSessionModInfo(inv_session, nullSession, sessionWork));
     inv_session->mod_data[mModule.id] = (void *) session_mod_info;
+    
+    dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
+    tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
 
     if (pjsip_inv_send_msg(inv_session, tdata) != PJ_SUCCESS)
     {
@@ -586,6 +591,7 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
         lg(Debug) << "Call is destined for " << destination;
     }
     
+    lg(Debug) << "Queueing a SessionCreationOperation";
     sessionWork->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination));
 }
 
@@ -911,6 +917,7 @@ void PJSipSessionModule::handleRefer(pjsip_inv_session *inv, pjsip_rx_data *rdat
     pjsip_tx_data *tdata;
     pjsip_dlg_create_response(inv->dlg, rdata, 200, NULL, &tdata);
 
+    lg(Debug) << "Queuing a HandleReferOperation";
     enqueueSessionWork(new HandleReferOperation(inv, tsx, tdata, target_sip_uri, session, mSessionRouter, mModule.id), inv);
 }
 
@@ -991,6 +998,7 @@ public:
 
     SuspendableWorkResult processInviteResponse()
     {
+        std::cout << "Handling response to an INVITE yo!" << std::endl;
         //Treat all 1XX messages we don't recognize the same as a 180
         if (mRespCode > 100 && mRespCode < 200 && mRespCode != 183)
         {
@@ -1122,6 +1130,7 @@ void PJSipSessionModule::handleInviteResponse(pjsip_inv_session* inv,
     //XXX There are a BUNCH of response codes we need
     //to add code to handle.
 
+    lg(Debug) << "Queuing a HandleInviteResponseOperation";
     enqueueSessionWork(new HandleInviteResponseOperation(respCode, inv->state, session), inv);
 }
 
@@ -1138,7 +1147,12 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "The transaction has address " << mTsx << std::endl;
         PJSipTransactionModInfo *tsx_mod_info = static_cast<PJSipTransactionModInfo *> (mTsx->mod_data[mSessionModule->getModule().id]);
+        if (!tsx_mod_info)
+        {
+            return Complete;
+        }
         if (mTsxState != PJSIP_TSX_STATE_DESTROYED)
         {
             tsx_mod_info->updateTransactionState(mTsx);
@@ -1150,10 +1164,9 @@ public:
         if (mEventType == PJSIP_EVENT_TSX_STATE)
         {
             pjsip_dialog *dlg = pjsip_tsx_get_dlg(mTsx);
-            PJSipDialogModInfo *dlg_mod_info = NULL;
-            if (dlg)
+            PJSipDialogModInfo *dlg_mod_info = dlg ? static_cast<PJSipDialogModInfo*>(dlg->mod_data[mSessionModule->getModule().id]) : NULL;
+            if (dlg_mod_info)
             {
-                dlg_mod_info = static_cast<PJSipDialogModInfo*>(dlg->mod_data[mSessionModule->getModule().id]);
                 dlg_mod_info->updateDialogState(dlg);
             }
             PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(mInv->mod_data[mSessionModule->getModule().id]);
@@ -1237,6 +1250,7 @@ public:
             }
             lg(Debug) << "Replicating state on DISCONNECTED inv_state.";
             mSessionModule->replicateState(dlg_mod_info, NULL, session_mod_info);
+            std::cout << "Deleting session mod info on a session" << std::endl;
             delete session_mod_info;
             mInv->mod_data[mSessionModule->getModule().id] = 0;
             if (dlg_mod_info)
@@ -1267,28 +1281,13 @@ public:
                 //here.
                 if (session_mod_info)
                 {
+                    lg(Debug) << "Queuing a TransactionStateOperation";
                     mSessionModule->enqueueSessionWork(
                             new TransactionStateOperation(mSessionModule, mInv->invite_tsx, mInv, mEventType, mInv->invite_tsx->state),
                             mInv);
                 }
             }
         }
-        if (mEventType == PJSIP_EVENT_TSX_STATE && mInvState == PJSIP_INV_STATE_CALLING && mInv->role == PJSIP_ROLE_UAC)
-        {
-            //We have sent an INVITE out. We need to set up the transaction and dialog structures
-            //to have the appropriate mod_data and initiate some state replication here as well.
-            //The inv_session's mod_info was set up in SipSession::start() because we had the SipSession
-            //information there.
-            PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(mInv->dlg);
-            PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(mInv->invite_tsx);
-            PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo *>(mInv->mod_data[mSessionModule->getModule().id]);
-            mInv->invite_tsx->mod_data[mSessionModule->getModule().id] = (void *) tsx_mod_info;
-            mInv->dlg->mod_data[mSessionModule->getModule().id] = (void *) dlg_mod_info;
-            dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
-            tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
-            lg(Debug) << "Replicating state on new outbound INVITE.";
-            mSessionModule->replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
-        }
         return Complete;
     }
 
@@ -1313,7 +1312,25 @@ void PJSipSessionModule::invOnStateChanged(pjsip_inv_session *inv, pjsip_event *
     {
         branch = std::string(pj_strbuf(&event->body.rx_msg.rdata->msg_info.via->branch_param), pj_strlen(&event->body.rx_msg.rdata->msg_info.via->branch_param));
     }
-    
+
+    if (event->type == PJSIP_EVENT_TSX_STATE && inv->state == PJSIP_INV_STATE_CALLING && inv->role == PJSIP_ROLE_UAC)
+    {
+        //We have sent an INVITE out. We need to set up the transaction and dialog structures
+        //to have the appropriate mod_data and initiate some state replication here as well.
+        //The inv_session's mod_info was set up in SipSession::start() because we had the SipSession
+        //information there.
+        PJSipDialogModInfo *dlg_mod_info = new PJSipDialogModInfo(inv->dlg);
+        PJSipTransactionModInfo *tsx_mod_info = new PJSipTransactionModInfo(inv->invite_tsx);
+        PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo *>(inv->mod_data[mModule.id]);
+        inv->invite_tsx->mod_data[mModule.id] = (void *) tsx_mod_info;
+        inv->dlg->mod_data[mModule.id] = (void *) dlg_mod_info;
+        dlg_mod_info->mDialogState->mSessionId = session_mod_info->mSessionState->mSessionId;
+        tsx_mod_info->mTransactionState->mSessionId = session_mod_info->mSessionState->mSessionId;
+        lg(Debug) << "Replicating state on new outbound INVITE.";
+        replicateState(dlg_mod_info, tsx_mod_info, session_mod_info);
+    }
+   
+    lg(Debug) << "Queuing an InviteStateOperation";
     enqueueSessionWork(new InviteStateOperation(this, inv, event->type, inv->state, branch), inv);
 }
 
@@ -1344,6 +1361,8 @@ void PJSipSessionModule::invOnTsxStateChanged(pjsip_inv_session *inv, pjsip_tran
     PJSipSessionModInfo *session_mod_info = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
     SipSessionPtr session = session_mod_info->getSessionPtr();
 
+    std::string method(pj_strbuf(&tsx->method.name), pj_strlen(&tsx->method.name));
+    std::cout << "Queuing a Transaction state operation for transaction " << tsx  << " Method: " << method << std::endl;
     enqueueSessionWork(new TransactionStateOperation(this, tsx, inv, e->type, tsx->state), inv);
 }
 
@@ -1463,6 +1482,7 @@ public:
                 }
                 catch (...)
                 {
+                    std::cout << "EXCEPTION DURING MEDIA UPDATE????" << std::endl;
                     // If we get here the format just isn't supported...
                 }
             }
@@ -1483,6 +1503,7 @@ void PJSipSessionModule::invOnMediaUpdate(pjsip_inv_session *inv, pj_status_t st
         return;
     }
 
+    lg(Debug) << "Queuing HandleMediaUpdate";
     enqueueSessionWork(new HandleMediaUpdate(inv, mModule.id, mServiceLocator), inv);
 }
 
@@ -1530,7 +1551,7 @@ void PJSipSessionModule::enqueueSessionWork(const SuspendableWorkPtr& work, pjsi
 }
 
 PJSipSessionModuleThreadPoolListener::PJSipSessionModuleThreadPoolListener()
-    : mActiveThreads(0) { }
+    : mActiveThreads(0), mPjLibHook(new pjlibHook()) { }
 
 void PJSipSessionModuleThreadPoolListener::stateChanged(const PoolPtr& pool, Ice::Long active, Ice::Long idle, Ice::Long)
 {
@@ -1550,7 +1571,7 @@ void PJSipSessionModuleThreadPoolListener::queueWorkAdded(const PoolPtr& pool, I
     //
     //For now, use one thread per work item.
 
-    lg(Debug) << "Detected the addition of work to SIP's thread pool";
+    lg(Debug) << "Detected the addition of work to SIP's thread pool. Setting the size to " << mActiveThreads + numNewWork;
     int newSize = (int) (mActiveThreads + numNewWork);
     pool->setSize(newSize);
 }
@@ -1560,9 +1581,23 @@ void PJSipSessionModuleThreadPoolListener::queueEmptied(const PoolPtr& pool)
     //XXX Making this behavior more customizable would be nice
     //
     //For now, kill off everything
+
+    lg(Debug) << "The queue is empty so we're killing all the threads";
     pool->setSize(0);
 }
 
+void PJSipSessionModuleThreadPoolListener::threadStart()
+{
+    lg(Debug) << "New thread created. Registering it with PJLIB";
+    mPjLibHook->start();
+}
+
+void PJSipSessionModuleThreadPoolListener::threadStop()
+{
+    lg(Debug) << "Thread has completed. Unregistering it from PJLIB";
+    mPjLibHook->stop();
+}
+
 class SipSessionSuspendableWorkListener : public SuspendableWorkListener
 {
 public:
diff --git a/src/PJSipSessionModule.h b/src/PJSipSessionModule.h
index 8e8a8e3..a8968d3 100644
--- a/src/PJSipSessionModule.h
+++ b/src/PJSipSessionModule.h
@@ -58,6 +58,8 @@ private:
     SessionWorkPtr mSessionWork;
 };
 
+class pjlibHook;
+
 /**
  * Listens to the PJSipSessionModule's thread pool.
  *
@@ -71,8 +73,11 @@ public:
     void stateChanged(const AsteriskSCF::System::ThreadPool::V1::PoolPtr& pool, Ice::Long active, Ice::Long idle, Ice::Long zombie);
     void queueWorkAdded(const AsteriskSCF::System::ThreadPool::V1::PoolPtr& pool, Ice::Long count, bool wasEmpty);
     void queueEmptied(const AsteriskSCF::System::ThreadPool::V1::PoolPtr& pool);
+    void threadStart();
+    void threadStop();
 private:
     Ice::Long mActiveThreads;
+    pjlibHook *mPjLibHook;
 };
 
 typedef IceUtil::Handle<PJSipSessionModuleThreadPoolListener> PJSipSessionModuleThreadPoolListenerPtr;
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index e066cd4..889cbf8 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -257,6 +257,8 @@ std::string SipEndpoint::getId(const Ice::Current&)
 AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(const std::string& destination,
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener, const Ice::Current&)
 {
+
+    std::cout << "Got call over Ice to create a session for endpoint " << mImplPriv->mName << std::endl;
     if (mImplPriv->mConfig.sessionConfig.callDirection != BOTH &&
             mImplPriv->mConfig.sessionConfig.callDirection != INBOUND)
     {
@@ -265,15 +267,16 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
     }
 
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
-            mImplPriv->mServiceLocator, mImplPriv->mReplica);
+            mImplPriv->mServiceLocator, mImplPriv->mReplica, true);
     mImplPriv->mSessions.push_back(session);
+    std::cout << "And now we're returing a session proxy..." << std::endl;
     return session->getSessionProxy();
 }
 
 AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
 {
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
-            mImplPriv->mServiceLocator, mImplPriv->mReplica);
+            mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
     mImplPriv->mSessions.push_back(session);
     return session;
 }
@@ -284,7 +287,7 @@ AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const s
         const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
 {
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasession,
-            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica);
+            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
     mImplPriv->mSessions.push_back(session);
     return session;
 }
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 1d97045..7b35442 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -239,13 +239,59 @@ public:
     AsteriskSCF::System::Component::V1::ReplicaPtr mReplica;
 };
 
+void SipSession::initializePJSIPStructs()
+{
+    pj_str_t local_uri, remote_uri;
+    SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
+    
+    char local[64];
+    pj_ansi_sprintf(local, "sip:%s", config.sessionConfig.sourceAddress.c_str());
+    local_uri = pj_str(local);
+    
+    char remote[64];
+    bool userDefined = mImplPriv->mDestination.size() != 0;
+    pj_ansi_sprintf(remote, "sip:%s%s%s",
+        userDefined ? mImplPriv->mDestination.c_str() : "",
+        userDefined ? "@" : "",
+        config.transportConfig.address.c_str());
+    remote_uri = pj_str(remote);
+
+    pjsip_dialog *dialog;
+    if ((pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, &local_uri, &remote_uri, &remote_uri, &dialog)) !=
+            PJ_SUCCESS)
+    {
+        // What should we do here? Throw an exception?
+        return;
+    }
+    mImplPriv->mDialog = dialog;
+    
+    pjsip_inv_session *inviteSession;
+    pjmedia_sdp_session *sdp = createSDPOffer();
+    if ((pjsip_inv_create_uac(dialog, sdp, 0, &inviteSession)) != PJ_SUCCESS)
+    {
+        pjsip_dlg_terminate(dialog);
+        // What should we do here? Throw an exception?
+        return;
+    }
+
+    pjsip_timer_setting session_timer_settings;
+    pjsip_timer_setting_default(&session_timer_settings);
+    pjsip_timer_init_session(inviteSession, &session_timer_settings);
+
+    SessionWorkPtr sessionWork(new SessionWork(mImplPriv->mManager->getSessionModule()->getThreadPoolQueue()));
+    PJSipSessionModInfo *session_mod_info(new PJSipSessionModInfo(inviteSession, this, sessionWork));
+    inviteSession->mod_data[mImplPriv->mManager->getSessionModule()->getModule().id] = (void*)session_mod_info;
+    pjsip_dlg_add_usage(dialog, &mImplPriv->mManager->getSessionModule()->getModule(), NULL);
+    mImplPriv->mInviteSession = inviteSession;
+}
+
 /**
  * Default constructor.
  */
 SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
         const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
         PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica)
+        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     if (listener != 0)
@@ -263,6 +309,11 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     // Get an RTP session capable of handling the formats we are going to offer
     AsteriskSCF::Media::V1::FormatSeq formats;
     requestRTPSessions(formats);
+
+    if (isUAC)
+    {
+        initializePJSIPStructs();
+    }
 }
 
 /**
@@ -273,7 +324,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
         const Ice::Identity& mediaid, const AsteriskSCF::Media::V1::SessionPrx& mediasession,
         const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
         PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica)
+        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     mImplPriv->mSessionProxy =
@@ -289,6 +340,11 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
 
     mImplPriv->mSources = sources;
     mImplPriv->mSinks = sinks;
+
+    if (isUAC)
+    {
+        initializePJSIPStructs();
+    }
 }
 
 class AddListenerOperation : public SuspendableWork
@@ -302,6 +358,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Actually executing addListener logic" << std::endl;
         mImplPriv->addListener(mListener);
         AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
             mImplPriv->getInfo();
@@ -319,6 +376,7 @@ void SipSession::addListener_async(
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
         const Ice::Current&)
 {
+    std::cout << "addListener called. Queueing operation..." << std::endl;
     enqueueSessionWork(new AddListenerOperation(cb, listener, mImplPriv));
 }
 
@@ -334,6 +392,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing indicate operation" << std::endl;
         AsteriskSCF::SessionCommunications::V1::ConnectIndicationPtr Connect;
         AsteriskSCF::SessionCommunications::V1::FlashIndicationPtr Flash;
         AsteriskSCF::SessionCommunications::V1::HoldIndicationPtr Hold;
@@ -398,6 +457,7 @@ void SipSession::indicate_async(
         const AsteriskSCF::SessionCommunications::V1::IndicationPtr& indication,
         const Ice::Current&)
 {
+    std::cout << "Queuing an indicate operation" << std::endl;
     enqueueSessionWork(new IndicateOperation(cb, indication, mImplPriv, this));
 }
 
@@ -411,6 +471,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing a getEndpoint Operation" << std::endl;
         mCb->ice_response(mImplPriv->mEndpoint->getEndpointProxy());
         return Complete;
     }
@@ -426,6 +487,7 @@ void SipSession::getEndpoint_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getEndpointPtr& cb,
         const Ice::Current&)
 {
+    std::cout << "Queuing a getEndpoint operation" << std::endl;
     enqueueSessionWork(new GetEndpointOperation(cb, mImplPriv));
 }
 
@@ -439,6 +501,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing a GetInfo operation" << std::endl;
         AsteriskSCF::SessionCommunications::V1::SessionInfoPtr sessionInfo =
             mImplPriv->getInfo();
 
@@ -457,6 +520,7 @@ void SipSession::getInfo_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getInfoPtr& cb,
         const Ice::Current&)
 {
+    std::cout << "queuing a getInfo operation" << std::endl;
     enqueueSessionWork(new GetInfoOperation(cb, mImplPriv));
 }
 
@@ -470,6 +534,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing a GetMediaSession operation" << std::endl;
         mCb->ice_response(mImplPriv->mMediaSessionProxy);
         return Complete;
     }
@@ -485,6 +550,7 @@ void SipSession::getMediaSession_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getMediaSessionPtr& cb,
         const Ice::Current&)
 {
+    std::cout << "queuing a getMediaSession operation" << std::endl;
     enqueueSessionWork(new GetMediaSessionOperation(cb, mImplPriv));
 }
 
@@ -497,6 +563,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing a GetBridge operation" << std::endl;
         AsteriskSCF::SessionCommunications::V1::BridgePrx bridge;
         try
         {
@@ -522,6 +589,7 @@ void SipSession::getBridge_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_Session_getBridgePtr& cb,
         const Ice::Current&)
 {
+    std::cout << "queuing a getBridge operation" << std::endl;
     enqueueSessionWork(new GetBridgeOperation(cb, mImplPriv));
 }
 
@@ -539,6 +607,7 @@ public:
     
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Executing a SetBridge operation" << std::endl;
         mSession->setBridge(mBridge);
         mImplPriv->addListener(mListener);
         mCb->ice_response(mImplPriv->getInfo());
@@ -562,6 +631,7 @@ void SipSession::setBridge_async(
     const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
     const Ice::Current& current)
 {
+    std::cout << "queuing a setBridge operation" << std::endl;
     enqueueSessionWork(new SetBridgeOperation(cb, this, mImplPriv, bridge, listener, current));
 }
 
@@ -619,6 +689,7 @@ void SipSession::removeBridge_async(
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
         const Ice::Current& current)
 {
+    std::cout << "queuing a removeBridge operation" << std::endl;
     enqueueSessionWork(new RemoveBridgeOperation(cb, this, mImplPriv, listener, current));
 }
 
@@ -632,6 +703,7 @@ public:
 
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
     {
+        std::cout << "Actually removing listener" << std::endl;
         mImplPriv->removeListener(mListener);
         return Complete;
     }
@@ -644,88 +716,40 @@ public:
  */
 void SipSession::removeListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener, const Ice::Current&)
 {
+    std::cout << "removeListener called. Queuing operation" << std::endl;
     enqueueSessionWork(new RemoveListenerOperation(listener, mImplPriv));
 }
 
 class StartOperation : public SuspendableWork
 {
 public:
-    StartOperation(const SipSessionPtr& session, const boost::shared_ptr<SipSessionPriv>& sessionPriv, PJSipSessionModInfo *session_mod_info)
-        : mSession(session), mImplPriv(sessionPriv), mSessionModInfo(session_mod_info) { }
... 7380 lines suppressed ...


-- 
asterisk-scf/release/sip.git



More information about the asterisk-scf-commits mailing list