[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "telephone-events" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Jul 20 14:08:39 CDT 2011


branch "telephone-events" has been updated
       via  6f8904c6e789bb9aa71600da73ab81cc06563572 (commit)
       via  f76eb1c42e1d092c857ab97b1b4d16217117eb72 (commit)
       via  857167eac79c21b941df3c6da33e18a781ce0200 (commit)
       via  4e0d5ca1bd9541b4008fc6509d1d35b023d8da85 (commit)
       via  8ad92e0f71d3a6c512290a47009599745b331a49 (commit)
       via  7f73fcd33096ed9ae2e62f766d16fe8b5cc14ff0 (commit)
       via  e808b0bd8e49f3db8b3a4dbb96c8f864b2516d3b (commit)
       via  3e10abd5f24d590a9473631e26f3388d948bb1aa (commit)
       via  460e021559101b15e5f4b6cc26ed6ccdaf32635a (commit)
       via  a6c749627f93884ec497b66cafa0f3fe21afb7d6 (commit)
       via  9c6e22b59b6f63216629692f7aaad9aef61af856 (commit)
       via  36a1f7d1dda63edfeb93da238084c6be4e63d330 (commit)
       via  a40b4875461e729ed6e2d04881f163c209ab269f (commit)
       via  4f837a1a907c55ee0ee181b9efca036fffa42cf9 (commit)
       via  1cd868e3e2c2b46501aa3c37fc92275349befc2f (commit)
       via  7fbb239ffea714b04ecd722e176b42d6c2e8b6f6 (commit)
       via  63876621702e4612a815f0ec09e8876ae1b1b969 (commit)
       via  25a7e17f104524927281ffdccb402e250d55441d (commit)
       via  7199e1b3e192331a72ef0b7a4565efcbcd84b6a3 (commit)
       via  1bc6f6ab98e4cb6d5700c0e738fce54417bd1ca3 (commit)
       via  bc7436f4c69f1f9c68fcbd5d5d0da32100c8f83d (commit)
       via  f10ab08b0e4f1226ad2ba213d98c2ab905f41b51 (commit)
       via  c3251d20e8eebdcc809f906abd0b021dd3c20045 (commit)
       via  548ff031608447bea09380e34f582050fb2ffbe9 (commit)
       via  26d2049b6e33bd12b5c522a0b15cd9da38c600ed (commit)
       via  5cd389dd2155476fee88c9464bf0e5b6d2a1ab37 (commit)
       via  61fe208d8f18a300137f4ea96518d1747cec2be8 (commit)
       via  6577d75e59c8b2f4241103f48fd114da433c8597 (commit)
       via  fc8f71159530653f06e3217ec733058ce033d4fb (commit)
       via  7d43289b0a830b2c545b4509ca3df7d8dd510186 (commit)
       via  e528d7be81f34ac1789b74ad7415de949a1c19ed (commit)
       via  b61e242edd548a82eb5a492c7ffb16835746ceaa (commit)
       via  32c65526dd56d0bc7e03148dfd407bfa40423fff (commit)
       via  ef373b282be4a218a92e9981fc0c3163c181603b (commit)
       via  0a84ba53e4041c3d0afcab7caf954529b60b6f63 (commit)
       via  768256f0d324d42905eb9f3832c054193cd750b2 (commit)
       via  162d8a50bf6df93a6bc24d06e9042b5026c088ee (commit)
       via  41e944174785ff3370b4e165d491e8ff92cc0827 (commit)
       via  f860396ac01e1581dfe5f56ca30434c8b01b4270 (commit)
       via  be2641c8edb8a41556c4a0d9c2d86fb023917792 (commit)
       via  1ea02fa8ec59f386d62f04a0ef3c1adb77fd5319 (commit)
       via  3fa68dd21a3f9a62ca80400e48832d0e6225a2ea (commit)
       via  fc2f64b78c4c57c4c3b8fea3233a9fd3f52147f6 (commit)
       via  575abed0a58ba2e9f321b8ccc121a32356c7288d (commit)
       via  b0d2423c8b01c4432c7289f9648213e16406174a (commit)
       via  1dda9776c5a1f55037ac61f5290593e25a5677cb (commit)
       via  34797f06098f619838f094d9af7ec1a8c3ad4724 (commit)
       via  cfa23a3f19760c5266a9f4be0ad9302c977bfe8a (commit)
       via  a6bfcd47c9f662ac6dd4a2318d96579737a12837 (commit)
       via  57993cd407779a00004dc426cb282f06bccb5bd5 (commit)
       via  413750665895171f8eae4c8d86ff672b04a8f7cd (commit)
       via  b874caeeddf70e7b3911a4312494c8ae6de1ffd4 (commit)
       via  89e5e5522e81f9f9be4351eb6aab5f346a35586d (commit)
       via  448088a4f28ccdf90471cb60642d28bd4fdfd589 (commit)
       via  abbaa0220ce9faf1e97fd4845ee7f78076436193 (commit)
       via  0ffdaa56376184435e2ebb6b59dac42fbde51ab9 (commit)
       via  47ce4d4e87b887297289ff6511bde2feb807a476 (commit)
       via  e2736843dca94388a5ad562b7096a53451e2d037 (commit)
       via  9394b46cf8c83c0cfa83e73a34886aeb9f63913b (commit)
       via  66b54622b2edd8c6f41fb76950e81121813804e2 (commit)
       via  66c548481a50dbbaaa4f886d41af64cc39a5bfa3 (commit)
       via  b694e978ae5146b198914f8e114fff6333a75662 (commit)
       via  1f56ea5e07117170b407e17cc298ea9a79b60860 (commit)
       via  706a6986e046909d0035038412d759ba1e6c199c (commit)
       via  1624b232fe8cd35ab4a88ae0aa7d74498d98e3c9 (commit)
       via  591d2f8183dbed4dce5734ae09e5c2d2cb2de8c3 (commit)
       via  ae5e868cf90a06e489748299eca32564f248d52b (commit)
       via  1a6d54ba8e42b022e2dea6c696ab26ebac0345a2 (commit)
       via  c5ed036baf4b2eea39a2496e8c8267be96766dc2 (commit)
       via  433163526c9c788f53fb52ae4b389e3c77f7dc31 (commit)
       via  fa87159c9237db447843c6523f1daa7da2a67607 (commit)
       via  9ab8adb83f3038c03b8c1619bebcabbffc4e352e (commit)
       via  cb2abe96f218864eb0088c343b3a91ffa6e578e8 (commit)
       via  480dca6e1d5a251dd2ab680f776b46f37a052660 (commit)
       via  871d682ad8f89f934e68326fa6b3d861479321da (commit)
       via  2e6f61b3697981bb4a1af0a4f2738ff786668269 (commit)
       via  f8ba9bd5baffb67df87d1726c8635bb7d5d63ff2 (commit)
       via  49064db0f2c505427f826c7fc9608e39d3a2ffe2 (commit)
       via  72fce78916b051f6d76a4e61de9fb5d26eec10de (commit)
       via  51d7a0addacb9eae0fc88bea5b010a0559b4b887 (commit)
       via  df0ebe1c9b2b5eb5b99f1a5e4140dd13b3a14622 (commit)
       via  c5eff00eb9e4e64bac262fbc8f0ff7631c9b5cf8 (commit)
       via  5aa5e56f84e645b9c5238215ef4fdeb0eba28f20 (commit)
       via  dd490ab030f402537f7edac3d1fcd443bc602e68 (commit)
      from  b6c7ea6815ff93f17fd2355ef5f003712e0242fe (commit)

Summary of changes:
 config/Sip.config                                  |    4 +-
 config/SipConfigurator.py                          |   27 +-
 .../SipSessionManager/SipConfigurationIf.ice       |   44 +-
 .../SipSessionManager/SipStateReplicationIf.ice    |   23 +-
 src/CMakeLists.txt                                 |    9 +
 src/PJSipManager.cpp                               |   25 +
 src/PJSipManager.h                                 |   18 +
 src/PJSipRegistrarModule.cpp                       |  831 ++++++++++++++++++++
 src/PJSipRegistrarModule.h                         |  203 +++++
 src/PJSipRegistrarModuleConstruction.cpp           |  104 +++
 src/PJSipSessionModule.cpp                         |  217 +++---
 src/SipConfiguration.cpp                           |   10 +
 src/SipEndpoint.cpp                                |  233 ++++++-
 src/SipEndpoint.h                                  |   30 +-
 src/SipEndpointFactory.cpp                         |   13 +-
 src/SipEndpointFactory.h                           |    2 +
 src/SipRegistrarListener.cpp                       |  113 +++
 src/SipRegistrarListener.h                         |   46 ++
 src/SipSession.cpp                                 |  739 ++++++++++++++----
 src/SipSession.h                                   |   66 +-
 src/SipSessionManagerApp.cpp                       |   32 +-
 src/SipSessionManagerEndpointLocator.cpp           |   14 +-
 src/SipStateReplicator.h                           |    1 +
 src/SipStateReplicatorListener.cpp                 |  174 ++++-
 src/SipTelephonyEventSink.cpp                      |  220 ++++++
 src/SipTelephonyEventSink.h                        |   61 ++
 src/SipTelephonyEventSource.cpp                    |  103 +++
 src/SipTelephonyEventSource.h                      |   63 ++
 28 files changed, 3100 insertions(+), 325 deletions(-)
 create mode 100644 src/PJSipRegistrarModule.cpp
 create mode 100644 src/PJSipRegistrarModule.h
 create mode 100644 src/PJSipRegistrarModuleConstruction.cpp
 create mode 100644 src/SipRegistrarListener.cpp
 create mode 100644 src/SipRegistrarListener.h
 create mode 100644 src/SipTelephonyEventSink.cpp
 create mode 100644 src/SipTelephonyEventSink.h
 create mode 100644 src/SipTelephonyEventSource.cpp
 create mode 100644 src/SipTelephonyEventSource.h


- Log -----------------------------------------------------------------
commit 6f8904c6e789bb9aa71600da73ab81cc06563572
Merge: f76eb1c b6c7ea6
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Jul 20 14:09:04 2011 -0500

    Merge branch 'telephone-events' of git.asterisk.org:asterisk-scf/integration/sip into telephone-events
    
    Conflicts:
    	config/SipConfigurator.py
    	src/PJSipSessionModule.cpp
    	src/SipEndpoint.h
    	src/SipSession.cpp
    	src/SipSession.h


commit f76eb1c42e1d092c857ab97b1b4d16217117eb72
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Jul 20 13:33:11 2011 -0500

    Deal with the possibility the out parameter of an RTP session allocation call could be a NULL handle.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 5ab24d3..c2d5103 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -1332,7 +1332,7 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
         // Allocate a new RTP session to carry the media formats we have in common
 
         RTPOptionsPtr options(new RTPOptions());
-        RTPAllocationOutputsPtr outputs(new RTPAllocationOutputs());
+        RTPAllocationOutputsPtr outputs;
         SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
 
         if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::RFC4733)
@@ -1347,9 +1347,11 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
             continue;
         }
 
-        // XXX Here we need to take the proxies in outputs and do stuff with them.
-        mImplPriv->mExternalEventSources = outputs->eventSources;
-        mImplPriv->mExternalEventSinks = outputs->eventSinks;
+        if (outputs)
+        {
+            mImplPriv->mExternalEventSources = outputs->eventSources;
+            mImplPriv->mExternalEventSinks = outputs->eventSinks;
+        }
 
         // RTP sessions should only provide a single sink, so grab it and update the connection details with that
         // of the remote party
@@ -1558,7 +1560,7 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
         }
 
         RTPOptionsPtr options(new RTPOptions());
-        RTPAllocationOutputsPtr outputs(new RTPAllocationOutputs());
+        RTPAllocationOutputsPtr outputs;
         SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
 
         if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::RFC4733)
@@ -1574,7 +1576,11 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
             continue;
         }
 
-        //XXX Here we need to take the proxies in outputs and do stuff with them.
+        if (outputs)
+        {
+            mImplPriv->mExternalEventSources = outputs->eventSources;
+            mImplPriv->mExternalEventSinks = outputs->eventSinks;
+        }
 
         // RTP sessions should only provide a single sink, so grab it and update the connection details with that
         // of the remote party

commit 857167eac79c21b941df3c6da33e18a781ce0200
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Jul 20 11:17:23 2011 -0500

    Use AMD for getSources and getSinks.
    
    Avoid ambiguity by changing some method names.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 7e13016..062f997 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -98,8 +98,8 @@ void PJSipSessionModInfo::updateSessionState(pjsip_inv_session *inv_session)
         mSessionState->mEndpointName = mSession->getEndpoint()->getName();
         mSessionState->mSessionObjectId = mSession->getSessionProxy()->ice_getIdentity();
         mSessionState->mMediaSessionObjectId = mSession->getMediaSessionProxy()->ice_getIdentity();
-        mSessionState->mSources = mSession->getSources();
-        mSessionState->mSinks = mSession->getSinks();
+        mSessionState->mSources = mSession->getMediaSources();
+        mSessionState->mSinks = mSession->getMediaSinks();
         mSessionState->mRTPMediaSessions = mSession->getRTPMediaSessions();
         mSessionState->mListeners = mSession->getListeners();
         try
@@ -1667,7 +1667,7 @@ protected:
         // In case there is no stream level connection details store this away
         std::string destination(pj_strbuf(&remote_sdp->conn->addr), pj_strlen(&remote_sdp->conn->addr));
 
-	StreamSinkSeq sinks = session->getSinks();
+        StreamSinkSeq sinks = session->getMediaSinks();
 
         // Each stream has its own set of formats, so go to that granularity
         for (unsigned int stream = 0; stream < remote_sdp->media_count; stream++)
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index a8acbfe..5ab24d3 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -58,12 +58,12 @@ public:
 
     AsteriskSCF::Media::V1::StreamSourceSeq getSources(const Ice::Current&)
     {
-        return mSession->getSources();
+        return mSession->getMediaSources();
     }
 
     AsteriskSCF::Media::V1::StreamSinkSeq getSinks(const Ice::Current&)
     {
-        return mSession->getSinks();
+        return mSession->getMediaSinks();
     }
 
     virtual std::string getId(const Ice::Current&)
@@ -276,10 +276,14 @@ public:
     SipTelephonyEventSinkPtr mEventSink;
 
     AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mEventSinkPrx;
+
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq mExternalEventSinks;
     
     SipTelephonyEventSourcePtr mEventSource;
 
     AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mEventSourcePrx;
+
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq mExternalEventSources;
 };
 
 /**
@@ -1045,16 +1049,72 @@ AsteriskSCF::SessionCommunications::V1::SessionCookieDict SipSession::getAllCook
     return mImplPriv->mSessionCookies;
 }
 
-AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq SipSession::getSources(const Ice::Current&)
+class GetSources : public SuspendableWork
+{
+public:
+    GetSources(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr& cb,
+            const SipSessionPtr& session)
+        : mCB(cb), mSession(session) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mCB->ice_response(mSession->getSources());
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr mCB;
+    SipSessionPtr mSession;
+};
+
+void SipSession::getSources_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr& cb,
+        const Ice::Current&)
+{
+    enqueueSessionWork(new GetSources(cb, this));
+}
+
+AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq SipSession::getSources()
+{
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq sources(mImplPriv->mExternalEventSources);
+    if (mImplPriv->mEventSource)
+    {
+        sources.push_back(mImplPriv->mEventSourcePrx);
+    }
+    return sources;
+}
+
+class GetSinks : public SuspendableWork
+{
+public:
+    GetSinks(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr& cb,
+            const SipSessionPtr& session)
+        : mCB(cb), mSession(session) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mCB->ice_response(mSession->getSinks());
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr mCB;
+    SipSessionPtr mSession;
+};
+
+void SipSession::getSinks_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr& cb,
+        const Ice::Current&)
 {
-    //Stub
-    return AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq();
+    enqueueSessionWork(new GetSinks(cb, this));
 }
 
-AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipSession::getSinks(const Ice::Current&)
+AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipSession::getSinks()
 {
-    //Stub
-    return AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq();
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq sinks(mImplPriv->mExternalEventSinks);
+    if (mImplPriv->mEventSink)
+    {
+        sinks.push_back(mImplPriv->mEventSinkPrx);
+    }
+    return sinks;
 }
 
 /**
@@ -1288,6 +1348,8 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
         }
 
         // XXX Here we need to take the proxies in outputs and do stuff with them.
+        mImplPriv->mExternalEventSources = outputs->eventSources;
+        mImplPriv->mExternalEventSinks = outputs->eventSinks;
 
         // RTP sessions should only provide a single sink, so grab it and update the connection details with that
         // of the remote party
@@ -1614,7 +1676,7 @@ pjsip_inv_session *SipSession::getInviteSession()
 /**
  * Internal function which gets the media sources on the endpoint.
  */
-AsteriskSCF::Media::V1::StreamSourceSeq& SipSession::getSources()
+AsteriskSCF::Media::V1::StreamSourceSeq& SipSession::getMediaSources()
 {
     return mImplPriv->mSources;
 }
@@ -1622,7 +1684,7 @@ AsteriskSCF::Media::V1::StreamSourceSeq& SipSession::getSources()
 /**
  * Internal function which gets the media sinks on the endpoint.
  */
-AsteriskSCF::Media::V1::StreamSinkSeq& SipSession::getSinks()
+AsteriskSCF::Media::V1::StreamSinkSeq& SipSession::getMediaSinks()
 {
     return mImplPriv->mSinks;
 }
diff --git a/src/SipSession.h b/src/SipSession.h
index be70f46..6e8d7a5 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -177,8 +177,22 @@ public:
     /**
      * TelephonySession overrides
      */
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq getSources(const Ice::Current&);
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks(const Ice::Current&);
+    void getSources_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSourcesPtr&,
+            const Ice::Current&);
+    /**
+     * Only called from within a queued operation
+     */
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourceSeq getSources();
+
+    void getSinks_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonySession_getSinksPtr&,
+            const Ice::Current&);
+
+    /**
+     * Only called from within a queued operation
+     */
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks();
 
     /**
      * Implementation specific functions.
@@ -200,9 +214,9 @@ public:
     //
     // TODO: Are these thread safe?
     //
-    AsteriskSCF::Media::V1::StreamSourceSeq& getSources();
+    AsteriskSCF::Media::V1::StreamSourceSeq& getMediaSources();
 
-    AsteriskSCF::Media::V1::StreamSinkSeq& getSinks();
+    AsteriskSCF::Media::V1::StreamSinkSeq& getMediaSinks();
 
     std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> getListeners();
 

commit 4e0d5ca1bd9541b4008fc6509d1d35b023d8da85
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Jul 20 09:42:43 2011 -0500

    Add Telephony event sources and sinks to our object adapter when we create them.
    And of course remove them from our object adapter when the session dies.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 3efce0e..a8acbfe 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -274,7 +274,12 @@ public:
     bool mSDPFinalized;
 
     SipTelephonyEventSinkPtr mEventSink;
+
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mEventSinkPrx;
+    
     SipTelephonyEventSourcePtr mEventSource;
+
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mEventSourcePrx;
 };
 
 /**
@@ -353,7 +358,12 @@ void SipSession::setTelephonyEventSourcesAndSinks(const SipEndpointConfig& confi
     if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
     {
         mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
+        mImplPriv->mEventSinkPrx =
+            AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx::uncheckedCast(mImplPriv->mAdapter->addWithUUID(mImplPriv->mEventSink));
+
         mImplPriv->mEventSource = new SipTelephonyEventSource(mImplPriv->mSessionWork);
+        mImplPriv->mEventSourcePrx =
+            AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx::uncheckedCast(mImplPriv->mAdapter->addWithUUID(mImplPriv->mEventSource));
     }
 }
 
@@ -413,6 +423,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     if (isUAC)
     {
         initializePJSIPStructs();
+        setTelephonyEventSourcesAndSinks(config);
     }
 }
 
@@ -1061,6 +1072,14 @@ public:
         // Remove all of the different interfaces we have exposed to the world.
         mSessionPriv->mAdapter->remove(mSessionPriv->mSessionProxy->ice_getIdentity());
         mSessionPriv->mAdapter->remove(mSessionPriv->mMediaSessionProxy->ice_getIdentity());
+        if (mSessionPriv->mEventSink)
+        {
+            mSessionPriv->mAdapter->remove(mSessionPriv->mEventSinkPrx->ice_getIdentity());
+        }
+        if (mSessionPriv->mEventSource)
+        {
+            mSessionPriv->mAdapter->remove(mSessionPriv->mEventSourcePrx->ice_getIdentity());
+        }
         mSessionPriv->mMediaSession = 0;
 
         if (mSessionPriv->mReplica->isActive() == true)

commit 8ad92e0f71d3a6c512290a47009599745b331a49
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 17:50:09 2011 -0500

    Send a response to INFO messages even if we are not going to actually process them further.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 2a11d24..7e13016 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -1131,6 +1131,11 @@ void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata
 
     if (!session->isTelephonyEventSource())
     {
+        //RFC 2976 Section 2.2 states that if we receive an INFO request with a body
+        //type we understand but have no intention of processing, we should respond
+        //with a 200 OK
+
+        pjsip_dlg_respond(inv->dlg, rdata, 200, NULL, NULL, NULL);
         return;
     }
 

commit 7f73fcd33096ed9ae2e62f766d16fe8b5cc14ff0
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 17:48:02 2011 -0500

    I got two parameter mixed up in the mapper.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index e08b811..e85efe3 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -166,7 +166,7 @@ class SipSectionVisitors(Configurator.SectionVisitors):
 
         item = AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFItem()
         dtmfTransformer = DTMFMethodTransformer(config)
-        mapper.map('dtmfmethod', item, 'dtmfmethod', 'dtmf', dtmfTransformer.get, AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733)
+        mapper.map('dtmfmethod', item, 'dtmf', 'dtmfmethod', dtmfTransformer.get, AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733)
 
         for option in config.options(section):
             mapper.execute(group, section, option)

commit e808b0bd8e49f3db8b3a4dbb96c8f864b2516d3b
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 17:24:02 2011 -0500

    Make sure to create a DTMF item or else configuration will be really screwy.

diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 6514cf5..e08b811 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -164,8 +164,9 @@ class SipSectionVisitors(Configurator.SectionVisitors):
                 if self.config.get(section, item) == 'inband':
                     return AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.Inband
 
-        transformer = DTMFMethodTransformer(config)
-        mapper.map('dtmfmethod', item, 'dtmfmethod', 'dtmf', transformer.get, AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733)
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFItem()
+        dtmfTransformer = DTMFMethodTransformer(config)
+        mapper.map('dtmfmethod', item, 'dtmfmethod', 'dtmf', dtmfTransformer.get, AsteriskSCF.Configuration.SipSessionManager.V1.SipDTMFOption.RFC4733)
 
         for option in config.options(section):
             mapper.execute(group, section, option)

commit 3e10abd5f24d590a9473631e26f3388d948bb1aa
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 16:59:31 2011 -0500

    Move telephony source and sink code to their own files.

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b4570ac..9f1b610 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,10 @@ astscf_component_add_files(SipSessionManager SipEndpoint.cpp)
 astscf_component_add_files(SipSessionManager SipEndpoint.h)
 astscf_component_add_files(SipSessionManager SipSession.cpp)
 astscf_component_add_files(SipSessionManager SipSession.h)
+astscf_component_add_files(SipSessionManager SipTelephonyEventSource.cpp)
+astscf_component_add_files(SipSessionManager SipTelephonyEventSource.h)
+astscf_component_add_files(SipSessionManager SipTelephonyEventSink.cpp)
+astscf_component_add_files(SipSessionManager SipTelephonyEventSink.h)
 astscf_component_add_files(SipSessionManager PJSipManager.cpp)
 astscf_component_add_files(SipSessionManager PJSipManager.h)
 astscf_component_add_files(SipSessionManager PJSipModule.cpp)
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 20c9c2c..2a11d24 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -20,6 +20,7 @@
 #include "SipSession.h"
 #include "PJSipManager.h"
 #include "SipStateReplicator.h"
+#include "SipTelephonyEventSource.h"
 
 #include <IceUtil/UUID.h>
 #include <boost/lexical_cast.hpp>
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 584baba..3efce0e 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -18,6 +18,8 @@
 #include "SipEndpointFactory.h"
 #include "SipEndpoint.h"
 #include "SipSession.h"
+#include "SipTelephonyEventSource.h"
+#include "SipTelephonyEventSink.h"
 
 #include <Ice/Ice.h>
 #include <IceUtil/UUID.h>
@@ -284,273 +286,6 @@ inline T *allocate_from_pool(pj_pool_t *pool)
     return static_cast<T*>(pj_pool_zalloc(pool, sizeof(T)));
 }
 
-class WriteTelephonyEvent : public SuspendableWork
-{
-public:
-    WriteTelephonyEvent(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
-            pjsip_inv_session *inv)
-        : mCB(cb), mEvent(event), mInv(inv) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        lg(Debug) << "Writing a telephony event";
-
-        AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr beginDTMF;
-        AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr endDTMF;
-        AsteriskSCF::SessionCommunications::V1::FlashEventPtr flash;
-
-        if ((beginDTMF = AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr::dynamicCast(mEvent)))
-        {
-            // XXX Since the only DTMF support we have is INFO, we won't get any beginDTMF indications. Sorry.
-        }
-        else if ((endDTMF = AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr::dynamicCast(mEvent)))
-        {
-            try
-            {
-                sendDTMFINFO(endDTMF);
-            }
-            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
-            {
-                mCB->ice_exception(ex);
-            }
-        }
-        else if ((flash = AsteriskSCF::SessionCommunications::V1::FlashEventPtr::dynamicCast(mEvent)))
-        {
-            try
-            {
-                sendFlashINFO();
-            }
-            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
-            {
-                mCB->ice_exception(ex);
-            }
-        }
-        mCB->ice_response();
-        return Complete;
-    }
-private:
-
-    pjsip_tx_data *createINFORequest()
-    {
-        pjsip_method infoMethod;
-        pj_str_t infoStr;
-        pj_cstr(&infoStr, "INFO");
-        pjsip_method_init_np(&infoMethod, &infoStr);
-
-        pj_status_t status;
-        pjsip_tx_data *tdata;
-        status = pjsip_dlg_create_request(mInv->dlg, &infoMethod, -1, &tdata);
-        
-        if (status != PJ_SUCCESS)
-        {
-            throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
-        }
-
-        return tdata;
-    }
-
-    void fillINFOBody(pjsip_tx_data *tdata, char signal, int duration)
-    {
-        pj_str_t type;
-        pj_cstr(&type, "application");
-        pj_str_t subtype;
-        pj_cstr(&subtype, "dtmf-relay");
-        std::stringstream bodyText;
-        bodyText << "Signal= " << signal 
-            << "\r\nDuration= " << duration << "\r\n\r\n";
-        pj_str_t bodyStr;
-        pj_cstr(&bodyStr, bodyText.str().c_str());
-
-        pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
-
-        if (!body)
-        {
-            throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
-        }
-
-        tdata->msg->body = body;
-    }
-
-    void sendDTMFINFO(const AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr& endDTMF)
-    {
-        pjsip_tx_data *tdata = createINFORequest();
-
-        pj_str_t infoPackage;
-        pj_cstr(&infoPackage, "Info-Package");
-        pj_str_t infoPackageVal;
-        pj_cstr(&infoPackageVal, "dtmf");
-        pjsip_generic_string_hdr *infoPackageHdr = pjsip_generic_string_hdr_create(tdata->pool, &infoPackage, &infoPackageVal);
-
-        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) infoPackageHdr);
-
-        fillINFOBody(tdata, endDTMF->digit, endDTMF->duration);
-
-        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
-    }
-
-    void sendFlashINFO()
-    {
-        pjsip_tx_data *tdata = createINFORequest();
-        fillINFOBody(tdata, '!', 100);
-        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
-    }
-
-    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr mCB;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr mEvent;
-    pjsip_inv_session *mInv;
-};
-
-SipTelephonyEventSink::SipTelephonyEventSink(const SessionWorkPtr& sessionWork, pjsip_inv_session *inv)
-    : mSessionWork(sessionWork), mInv(inv)  { }
-
-void SipTelephonyEventSink::write_async(
-        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
-        const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
-        const Ice::Current&)
-{
-    mSessionWork->enqueueWork(new WriteTelephonyEvent(cb, event, mInv));
-}
-
-class SetTelephonyEventSource : public SuspendableWork
-{
-public:
-    SetTelephonyEventSource(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
-            const SipTelephonyEventSinkPtr& sink, 
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
-        : mSink(sink), mSource(source) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        mSink->setSource(mSource);
-        mCB->ice_response();
-        return Complete;
-    }
-private:
-    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr mCB;
-    SipTelephonyEventSinkPtr mSink;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
-};
-
-void SipTelephonyEventSink::setSource_async(
-        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
-        const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source,
-        const Ice::Current&)
-{
-    mSessionWork->enqueueWork(new SetTelephonyEventSource(cb, this, source));
-}
-
-void SipTelephonyEventSink::setSource(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
-{
-    mSource = source;
-}
-
-class GetTelephonyEventSource : public SuspendableWork
-{
-public:
-    GetTelephonyEventSource(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
-            const SipTelephonyEventSinkPtr& sink)
-        : mSink(sink) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        mCB->ice_response(mSink->getSource());
-        return Complete;
-    }
-private:
-    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr mCB;
-    SipTelephonyEventSinkPtr mSink;
-};
-
-void SipTelephonyEventSink::getSource_async(
-        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
-        const Ice::Current&)
-{
-    mSessionWork->enqueueWork(new GetTelephonyEventSource(cb, this));
-}
-
-AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx SipTelephonyEventSink::getSource()
-{
-    return mSource;
-}
-
-void SipTelephonyEventSource::distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event)
-{
-    for (AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq::iterator iter = mSinks.begin();
-            iter != mSinks.end(); ++iter)
-    {
-        (*iter)->write(event);
-    }
-}
-
-SipTelephonyEventSource::SipTelephonyEventSource(const SessionWorkPtr& sessionWork)
-    : mSessionWork(sessionWork) { }
-
-class AddSink : public SuspendableWork
-{
-public:
-    AddSink(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
-            const SipTelephonyEventSourcePtr& source,
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
-        : mCB(cb), mSource(source), mSink(sink) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        mSource->addSink(mSink);
-        mCB->ice_response();
-    }
-private:
-    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr mCB;
-    SipTelephonyEventSourcePtr mSource;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mSink;
-};
-
-void SipTelephonyEventSource::addSink_async(
-        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
-        const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
-        const Ice::Current&)
-{
-    mSessionWork->enqueueWork(new AddSink(cb, this, sink));
-}
-
-void SipTelephonyEventSource::addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
-{
-    mSinks.push_back(sink);
-}
-
-class GetSinks : public SuspendableWork
-{
-public:
-    GetSinks(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
-            const SipTelephonyEventSourcePtr& source)
-        : mCB(cb), mSource(source) { }
-
-    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
-    {
-        mCB->ice_response(mSource->getSinks());
-    }
-private:
-    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr mCB;
-    SipTelephonyEventSourcePtr mSource;
-};
-
-void SipTelephonyEventSource::getSinks_async(
-        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
-        const Ice::Current&)
-{
-    mSessionWork->enqueueWork(new GetSinks(cb, this));
-}
-
-AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipTelephonyEventSource::getSinks()
-{
-    return mSinks;
-}
-
 void SipSession::initializePJSIPStructs()
 {
     pj_str_t local_uri, remote_uri;
diff --git a/src/SipSession.h b/src/SipSession.h
index 45ad844..be70f46 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -88,76 +88,7 @@ private:
 
 typedef IceUtil::Handle<SessionWork> SessionWorkPtr;
 
-class SipTelephonyEventSink : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSink
-{
-public:
-    SipTelephonyEventSink(const SessionWorkPtr& sessionWork, pjsip_inv_session *inv);
-    void write_async(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr&,
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr&,
-            const Ice::Current&);
-    void setSource_async(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr&,
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source,
-            const Ice::Current&);
-
-    /**
-     * Only called from within a queued operation.
-     */
-    void setSource(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source);
-
-    void getSource_async(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr&,
-            const Ice::Current&);
-
-    /**
-     * Only called from within a queued operation.
-     */
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx getSource();
-
-private:
-    SessionWorkPtr mSessionWork;
-    pjsip_inv_session *mInv;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
-};
-
-typedef IceUtil::Handle<SipTelephonyEventSink> SipTelephonyEventSinkPtr;
-
-class SipTelephonyEventSource : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSource
-{
-public:
-
-    SipTelephonyEventSource(const SessionWorkPtr&);
-
-    void addSink_async(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr&,
-            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
-            const Ice::Current&);
-
-    /**
-     * Only to be called from within a queued operation
-     */
-    void addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink);
-
-    void getSinks_async(
-            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr&,
-            const Ice::Current&);
-
-    /**
-     * Only to be called from within a queued operation
-     */
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks();
-    /**
-     * Write an event to all the configured sinks.
-     *
-     * This should only be called from a queued operation
-     */
-    void distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event);
-private:
-    SessionWorkPtr mSessionWork;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq mSinks;
-};
-
+class SipTelephonyEventSource;
 typedef IceUtil::Handle<SipTelephonyEventSource> SipTelephonyEventSourcePtr;
 
 class SipEndpointConfig;
diff --git a/src/SipTelephonyEventSink.cpp b/src/SipTelephonyEventSink.cpp
new file mode 100644
index 0000000..d7b320d
--- /dev/null
+++ b/src/SipTelephonyEventSink.cpp
@@ -0,0 +1,220 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "SipTelephonyEventSink.h"
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+using namespace AsteriskSCF::System::WorkQueue::V1;
+
+class WriteTelephonyEvent : public SuspendableWork
+{
+public:
+    WriteTelephonyEvent(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
+            pjsip_inv_session *inv)
+        : mCB(cb), mEvent(event), mInv(inv) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr beginDTMF;
+        AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr endDTMF;
+        AsteriskSCF::SessionCommunications::V1::FlashEventPtr flash;
+
+        if ((beginDTMF = AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr::dynamicCast(mEvent)))
+        {
+            // XXX Since the only DTMF support we have is INFO, we won't get any beginDTMF indications. Sorry.
+        }
+        else if ((endDTMF = AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr::dynamicCast(mEvent)))
+        {
+            try
+            {
+                sendDTMFINFO(endDTMF);
+            }
+            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
+            {
+                mCB->ice_exception(ex);
+            }
+        }
+        else if ((flash = AsteriskSCF::SessionCommunications::V1::FlashEventPtr::dynamicCast(mEvent)))
+        {
+            try
+            {
+                sendFlashINFO();
+            }
+            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
+            {
+                mCB->ice_exception(ex);
+            }
+        }
+        mCB->ice_response();
+        return Complete;
+    }
+private:
+
+    pjsip_tx_data *createINFORequest()
+    {
+        pjsip_method infoMethod;
+        pj_str_t infoStr;
+        pj_cstr(&infoStr, "INFO");
+        pjsip_method_init_np(&infoMethod, &infoStr);
+
+        pj_status_t status;
+        pjsip_tx_data *tdata;
+        status = pjsip_dlg_create_request(mInv->dlg, &infoMethod, -1, &tdata);
+        
+        if (status != PJ_SUCCESS)
+        {
+            throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
+        }
+
+        return tdata;
+    }
+
+    void fillINFOBody(pjsip_tx_data *tdata, char signal, int duration)
+    {
+        pj_str_t type;
+        pj_cstr(&type, "application");
+        pj_str_t subtype;
+        pj_cstr(&subtype, "dtmf-relay");
+        std::stringstream bodyText;
+        bodyText << "Signal= " << signal 
+            << "\r\nDuration= " << duration << "\r\n\r\n";
+        pj_str_t bodyStr;
+        pj_cstr(&bodyStr, bodyText.str().c_str());
+
+        pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
+
+        if (!body)
+        {
+            throw AsteriskSCF::SessionCommunications::V1::TelephonyEventException();
+        }
+
+        tdata->msg->body = body;
+    }
+
+    void sendDTMFINFO(const AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr& endDTMF)
+    {
+        pjsip_tx_data *tdata = createINFORequest();
+
+        pj_str_t infoPackage;
+        pj_cstr(&infoPackage, "Info-Package");
+        pj_str_t infoPackageVal;
+        pj_cstr(&infoPackageVal, "dtmf");
+        pjsip_generic_string_hdr *infoPackageHdr = pjsip_generic_string_hdr_create(tdata->pool, &infoPackage, &infoPackageVal);
+
+        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) infoPackageHdr);
+
+        fillINFOBody(tdata, endDTMF->digit, endDTMF->duration);
+
+        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+    }
+
+    void sendFlashINFO()
+    {
+        pjsip_tx_data *tdata = createINFORequest();
+        fillINFOBody(tdata, '!', 100);
+        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+    }
+
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr mCB;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr mEvent;
+    pjsip_inv_session *mInv;
+};
+
+
+SipTelephonyEventSink::SipTelephonyEventSink(const SessionWorkPtr& sessionWork, pjsip_inv_session *inv)
+    : mSessionWork(sessionWork), mInv(inv)  { }
+
+void SipTelephonyEventSink::write_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr& cb,
+        const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new WriteTelephonyEvent(cb, event, mInv));
+}
+
+class SetTelephonyEventSource : public SuspendableWork
+{
+public:
+    SetTelephonyEventSource(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
+            const SipTelephonyEventSinkPtr& sink, 
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
+        : mSink(sink), mSource(source) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mSink->setSource(mSource);
+        mCB->ice_response();
+        return Complete;
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr mCB;
+    SipTelephonyEventSinkPtr mSink;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
+};
+
+void SipTelephonyEventSink::setSource_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr& cb,
+        const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new SetTelephonyEventSource(cb, this, source));
+}
+
+void SipTelephonyEventSink::setSource(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source)
+{
+    mSource = source;
+}
+
+class GetTelephonyEventSource : public SuspendableWork
+{
+public:
+    GetTelephonyEventSource(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
+            const SipTelephonyEventSinkPtr& sink)
+        : mSink(sink) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mCB->ice_response(mSink->getSource());
+        return Complete;
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr mCB;
+    SipTelephonyEventSinkPtr mSink;
+};
+
+void SipTelephonyEventSink::getSource_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new GetTelephonyEventSource(cb, this));
+}
+
+AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx SipTelephonyEventSink::getSource()
+{
+    return mSource;
+}
+
+};
+};
diff --git a/src/SipTelephonyEventSink.h b/src/SipTelephonyEventSink.h
new file mode 100644
index 0000000..be38512
--- /dev/null
+++ b/src/SipTelephonyEventSink.h
@@ -0,0 +1,61 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+#include "SipSession.h"
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+class SipTelephonyEventSink : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSink
+{
+public:
+    SipTelephonyEventSink(const SessionWorkPtr& sessionWork, pjsip_inv_session *inv);
+    void write_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr&,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr&,
+            const Ice::Current&);
+    void setSource_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_setSourcePtr&,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source,
+            const Ice::Current&);
+
+    /**
+     * Only called from within a queued operation.
+     */
+    void setSource(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx& source);
+
+    void getSource_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr&,
+            const Ice::Current&);
+
+    /**
+     * Only called from within a queued operation.
+     */
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx getSource();
+
+private:
+    SessionWorkPtr mSessionWork;
+    pjsip_inv_session *mInv;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx mSource;
+};
+
+typedef IceUtil::Handle<SipTelephonyEventSink> SipTelephonyEventSinkPtr;
+
+};
+};
diff --git a/src/SipTelephonyEventSource.cpp b/src/SipTelephonyEventSource.cpp
new file mode 100644
index 0000000..3985481
--- /dev/null
+++ b/src/SipTelephonyEventSource.cpp
@@ -0,0 +1,103 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#include "SipTelephonyEventSource.h"
+#include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+using namespace AsteriskSCF::System::WorkQueue::V1;
+
+void SipTelephonyEventSource::distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event)
+{
+    for (AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq::iterator iter = mSinks.begin();
+            iter != mSinks.end(); ++iter)
+    {
+        (*iter)->write(event);
+    }
+}
+
+SipTelephonyEventSource::SipTelephonyEventSource(const SessionWorkPtr& sessionWork)
+    : mSessionWork(sessionWork) { }
+
+class AddSink : public SuspendableWork
+{
+public:
+    AddSink(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
+            const SipTelephonyEventSourcePtr& source,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
+        : mCB(cb), mSource(source), mSink(sink) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mSource->addSink(mSink);
+        mCB->ice_response();
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr mCB;
+    SipTelephonyEventSourcePtr mSource;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mSink;
+};
+
+void SipTelephonyEventSource::addSink_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
+        const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new AddSink(cb, this, sink));
+}
+
+void SipTelephonyEventSource::addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
+{
+    mSinks.push_back(sink);
+}
+
+class GetSinks : public SuspendableWork
+{
+public:
+    GetSinks(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
+            const SipTelephonyEventSourcePtr& source)
+        : mCB(cb), mSource(source) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mCB->ice_response(mSource->getSinks());
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr mCB;
+    SipTelephonyEventSourcePtr mSource;
+};
+
+void SipTelephonyEventSource::getSinks_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new GetSinks(cb, this));
+}
+
+AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipTelephonyEventSource::getSinks()
+{
+    return mSinks;
+}
+
+};
+};
diff --git a/src/SipTelephonyEventSource.h b/src/SipTelephonyEventSource.h
new file mode 100644
index 0000000..730b4bd
--- /dev/null
+++ b/src/SipTelephonyEventSource.h
@@ -0,0 +1,63 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#pragma once
+#include "SipSession.h"
+
+namespace AsteriskSCF
+{
+
+namespace SipSessionManager
+{
+
+class SipTelephonyEventSource : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSource
+{
+public:
+
+    SipTelephonyEventSource(const SessionWorkPtr&);
+
+    void addSink_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr&,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
+            const Ice::Current&);
+
+    /**
+     * Only to be called from within a queued operation
+     */
+    void addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink);
+
+    void getSinks_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr&,
+            const Ice::Current&);
+
+    /**
+     * Only to be called from within a queued operation
+     */
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks();
+    /**
+     * Write an event to all the configured sinks.
+     *
+     * This should only be called from a queued operation
+     */
+    void distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event);
+private:
+    SessionWorkPtr mSessionWork;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq mSinks;
+};
+
+typedef IceUtil::Handle<SipTelephonyEventSource> SipTelephonyEventSourcePtr;
+};
+};

commit 460e021559101b15e5f4b6cc26ed6ccdaf32635a
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 16:38:20 2011 -0500

    Send Flash INFO messages as well.
    
    THis allows a big chunk of commented-out code to get removed.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 2ff7b15..584baba 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -299,6 +299,7 @@ public:
 
         AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr beginDTMF;
         AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr endDTMF;
+        AsteriskSCF::SessionCommunications::V1::FlashEventPtr flash;
 
         if ((beginDTMF = AsteriskSCF::SessionCommunications::V1::BeginDTMFEventPtr::dynamicCast(mEvent)))
         {
@@ -310,7 +311,18 @@ public:
             {
                 sendDTMFINFO(endDTMF);
             }
-            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException &ex)
+            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
+            {
+                mCB->ice_exception(ex);
+            }
+        }
+        else if ((flash = AsteriskSCF::SessionCommunications::V1::FlashEventPtr::dynamicCast(mEvent)))
+        {
+            try
+            {
+                sendFlashINFO();
+            }
+            catch (const AsteriskSCF::SessionCommunications::V1::TelephonyEventException& ex)
             {
                 mCB->ice_exception(ex);
             }
@@ -378,6 +390,13 @@ private:
         pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
     }
 
+    void sendFlashINFO()
+    {
+        pjsip_tx_data *tdata = createINFORequest();
+        fillINFOBody(tdata, '!', 100);
+        pjsip_dlg_send_request(mInv->dlg, tdata, -1, NULL);
+    }
+
     AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_writePtr mCB;
     AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr mEvent;
     pjsip_inv_session *mInv;
@@ -714,10 +733,6 @@ public:
         AsteriskSCF::SessionCommunications::V1::ProgressIndicationPtr Progress;
         AsteriskSCF::SessionCommunications::V1::RingIndicationPtr Ring;
         AsteriskSCF::SessionCommunications::V1::UnholdIndicationPtr Unhold;
-#if 0
-        AsteriskSCF::SessionCommunications::V1::BeginDTMFPtr beginDTMF;
-        AsteriskSCF::SessionCommunications::V1::EndDTMFPtr endDTMF;
-#endif
         pjsip_tx_data *packet = NULL;
         pj_status_t status = -1;
 
@@ -726,18 +741,10 @@ public:
             lg(Debug) << "Processing a Connect indication";
             status = pjsip_inv_answer(mImplPriv->mInviteSession, 200, NULL, NULL, &packet);
         }
-#if 0
         else if ((Flash = AsteriskSCF::SessionCommunications::V1::FlashIndicationPtr::dynamicCast(mIndication)))
         {
             lg(Debug) << "Processing a Flash indication";
-            SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
-            if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
-            {
-                sendFlashINFO();
-            }
-            // This is usually transported using INFO or RFC2833, so for now just pretend it does not exist
         }
-#endif
         else if ((Hold = AsteriskSCF::SessionCommunications::V1::HoldIndicationPtr::dynamicCast(mIndication)))
         {
             // TODO: Update SDP with sendonly attribute and no IP
@@ -762,24 +769,6 @@ public:
             lg(Debug) << "Processing a Unhold indication";
             status = pjsip_inv_reinvite(mImplPriv->mInviteSession, NULL, NULL, &packet);
         }
-#if 0
-        else if ((beginDTMF = AsteriskSCF::SessionCommunications::V1::BeginDTMFPtr::dynamicCast(mIndication)))
-        {
-            // XXX Since the only DTMF support we have is INFO, we won't get any beginDTMF indications. Sorry.
-        }
-        else if ((endDTMF = AsteriskSCF::SessionCommunications::V1::EndDTMFPtr::dynamicCast(mIndication)))
-        {
-            SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
-            if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
-            {
-                sendDTMFINFO(endDTMF);
-            }
-            else
-            {
-                lg(Debug) << "Not using INFO";
-            }
-        }
-#endif
         else
         {
             lg(Error) << "Unknown indication received";
@@ -796,75 +785,6 @@ public:
     }
 
 private:
-
-#if 0
-    pjsip_tx_data *createINFORequest()
-    {
-        pjsip_method infoMethod;
-        pj_str_t infoStr;
-        pj_cstr(&infoStr, "INFO");
-        pjsip_method_init_np(&infoMethod, &infoStr);
-
-        pj_status_t status;
-        pjsip_tx_data *tdata;
-        status = pjsip_dlg_create_request(mImplPriv->mInviteSession->dlg, &infoMethod, -1, &tdata);
-        
-        if (status != PJ_SUCCESS)
-        {
-            throw AsteriskSCF::SessionCommunications::V1::IndicationException();
-        }
-
-        return tdata;
-    }
-
-    void fillINFOBody(pjsip_tx_data *tdata, char signal, int duration)
-    {
-        pj_str_t type;
-        pj_cstr(&type, "application");
-        pj_str_t subtype;
-        pj_cstr(&subtype, "dtmf-relay");
-        std::stringstream bodyText;
-        bodyText << "Signal= " << signal 
-            << "\r\nDuration= " << duration << "\r\n\r\n";
-        pj_str_t bodyStr;
-        pj_cstr(&bodyStr, bodyText.str().c_str());
-
-        pjsip_msg_body *body = pjsip_msg_body_create(tdata->pool, &type, &subtype, &bodyStr);
-
-        if (!body)
-        {
-            throw AsteriskSCF::SessionCommunications::V1::IndicationException();
-        }
-
-        tdata->msg->body = body;
-
-    }
-
-    void sendDTMFINFO(const AsteriskSCF::SessionCommunications::V1::EndDTMFEventPtr& endDTMF)
-    {
-        pjsip_tx_data *tdata = createINFORequest();
-
-        pj_str_t infoPackage;
-        pj_cstr(&infoPackage, "Info-Package");
-        pj_str_t infoPackageVal;
-        pj_cstr(&infoPackageVal, "dtmf");
-        pjsip_generic_string_hdr *infoPackageHdr = pjsip_generic_string_hdr_create(tdata->pool, &infoPackage, &infoPackageVal);
-
-        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) infoPackageHdr);
-
-        fillINFOBody(tdata, endDTMF->digit, endDTMF->duration);
-
-        pjsip_dlg_send_request(mImplPriv->mInviteSession->dlg, tdata, -1, NULL);
-    }
-
-    void sendFlashINFO()
-    {
-        pjsip_tx_data *tdata = createINFORequest();
-        fillINFOBody(tdata, '!', 100);
-        pjsip_dlg_send_request(mImplPriv->mInviteSession->dlg, tdata, -1, NULL);
-    }
-#endif
-
     AsteriskSCF::SessionCommunications::V1::AMD_Session_indicatePtr mCb;
     AsteriskSCF::SessionCommunications::V1::IndicationPtr mIndication;
     boost::shared_ptr<SipSessionPriv> mImplPriv;

commit a6c749627f93884ec497b66cafa0f3fe21afb7d6
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 16:30:19 2011 -0500

    Finish up the telephony event source work.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 91d675b..20c9c2c 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -979,7 +979,8 @@ public:
         {
             event = new EndDTMFEvent(mDTMF, mDuration);
         }
-        //XXX We need to let the source distribute the event to its sinks.
+        SipTelephonyEventSourcePtr source = mSession->getSipTelephonyEventSource();
+        source->distributeToSinks(event);
         pjsip_dlg_send_response(mInv->dlg, mTsx, mTdata);
     }
 
@@ -1126,7 +1127,8 @@ void PJSipSessionModule::handleInfo(pjsip_inv_session *inv, pjsip_rx_data *rdata
     //ignore.
     PJSipSessionModInfo *sessionModInfo = static_cast<PJSipSessionModInfo*>(inv->mod_data[mModule.id]);
     SipSessionPtr session = sessionModInfo->getSessionPtr();
-    if (session->isTelephonyEventSource())
+
+    if (!session->isTelephonyEventSource())
     {
         return;
     }
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 386ddea..2ff7b15 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -271,8 +271,8 @@ public:
      */
     bool mSDPFinalized;
 
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPtr mEventSink;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePtr mEventSource;
+    SipTelephonyEventSinkPtr mEventSink;
+    SipTelephonyEventSourcePtr mEventSource;
 };
 
 /**
@@ -450,7 +450,7 @@ void SipTelephonyEventSink::getSource_async(
         const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSink_getSourcePtr& cb,
         const Ice::Current&)
 {
-    cb->ice_response(mSource);
+    mSessionWork->enqueueWork(new GetTelephonyEventSource(cb, this));
 }
 
 AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx SipTelephonyEventSink::getSource()
@@ -458,15 +458,78 @@ AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePrx SipTelephonyEven
     return mSource;
 }
 
-void SipTelephonyEventSource::addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink, const Ice::Current&)
+void SipTelephonyEventSource::distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event)
 {
-    //stub
+    for (AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq::iterator iter = mSinks.begin();
+            iter != mSinks.end(); ++iter)
+    {
+        (*iter)->write(event);
+    }
 }
 
-AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipTelephonyEventSource::getSinks(const Ice::Current&)
+SipTelephonyEventSource::SipTelephonyEventSource(const SessionWorkPtr& sessionWork)
+    : mSessionWork(sessionWork) { }
+
+class AddSink : public SuspendableWork
 {
-    //stub
-    return AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq();
+public:
+    AddSink(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
+            const SipTelephonyEventSourcePtr& source,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
+        : mCB(cb), mSource(source), mSink(sink) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mSource->addSink(mSink);
+        mCB->ice_response();
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr mCB;
+    SipTelephonyEventSourcePtr mSource;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx mSink;
+};
+
+void SipTelephonyEventSource::addSink_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr& cb,
+        const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new AddSink(cb, this, sink));
+}
+
+void SipTelephonyEventSource::addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink)
+{
+    mSinks.push_back(sink);
+}
+
+class GetSinks : public SuspendableWork
+{
+public:
+    GetSinks(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
+            const SipTelephonyEventSourcePtr& source)
+        : mCB(cb), mSource(source) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        mCB->ice_response(mSource->getSinks());
+    }
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr mCB;
+    SipTelephonyEventSourcePtr mSource;
+};
+
+void SipTelephonyEventSource::getSinks_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr& cb,
+        const Ice::Current&)
+{
+    mSessionWork->enqueueWork(new GetSinks(cb, this));
+}
+
+AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq SipTelephonyEventSource::getSinks()
+{
+    return mSinks;
 }
 
 void SipSession::initializePJSIPStructs()
@@ -536,7 +599,7 @@ void SipSession::setTelephonyEventSourcesAndSinks(const SipEndpointConfig& confi
     if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
     {
         mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
-        mImplPriv->mEventSource = new SipTelephonyEventSource();
+        mImplPriv->mEventSource = new SipTelephonyEventSource(mImplPriv->mSessionWork);
     }
 }
 
@@ -1973,6 +2036,11 @@ bool SipSession::isTelephonyEventSource()
     return mImplPriv->mEventSource != 0;
 }
 
+SipTelephonyEventSourcePtr SipSession::getSipTelephonyEventSource()
+{
+    return mImplPriv->mEventSource;
+}
+
 bool SipSession::isTelephonyEventSink()
 {
     return mImplPriv->mEventSink != 0;
diff --git a/src/SipSession.h b/src/SipSession.h
index a423c46..45ad844 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -125,10 +125,41 @@ typedef IceUtil::Handle<SipTelephonyEventSink> SipTelephonyEventSinkPtr;
 
 class SipTelephonyEventSource : public AsteriskSCF::SessionCommunications::V1::TelephonyEventSource
 {
-    void addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink, const Ice::Current&);
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks(const Ice::Current&);
+public:
+
+    SipTelephonyEventSource(const SessionWorkPtr&);
+
+    void addSink_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_addSinkPtr&,
+            const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink,
+            const Ice::Current&);
+
+    /**
+     * Only to be called from within a queued operation
+     */
+    void addSink(const AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPrx& sink);
+
+    void getSinks_async(
+            const AsteriskSCF::SessionCommunications::V1::AMD_TelephonyEventSource_getSinksPtr&,
+            const Ice::Current&);
+
+    /**
+     * Only to be called from within a queued operation
+     */
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq getSinks();
+    /**
+     * Write an event to all the configured sinks.
+     *
+     * This should only be called from a queued operation
+     */
+    void distributeToSinks(const AsteriskSCF::SessionCommunications::V1::TelephonyEventPtr& event);
+private:
+    SessionWorkPtr mSessionWork;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkSeq mSinks;
 };
 
+typedef IceUtil::Handle<SipTelephonyEventSource> SipTelephonyEventSourcePtr;
+
 class SipEndpointConfig;
 
 /*
@@ -260,6 +291,8 @@ public:
 
     bool isTelephonyEventSource();
 
+    SipTelephonyEventSourcePtr getSipTelephonyEventSource();
+
     bool isTelephonyEventSink();
 private:
 

commit 9c6e22b59b6f63216629692f7aaad9aef61af856
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 15:26:58 2011 -0500

    Make sure that initialization of Telephony event sources and sinks does not result in badness.

diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 6c6527c..91d675b 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -365,14 +365,16 @@ protected:
             return Complete;
         }
 
-	mSession->setInviteSession(mInv);
-	mSession->setDialog(mInv->dlg);
+        mSession->setInviteSession(mInv);
+        mSession->setDialog(mInv->dlg);
+
+        mSession->setTelephonyEventSourcesAndSinks(mCaller->getConfig());
 
         // Create an SDP offer or answer
-	const pjmedia_sdp_session *remote_sdp = NULL;
+        const pjmedia_sdp_session *remote_sdp = NULL;
         pjmedia_sdp_session *sdp;
 
-	if (!mInv->neg || (pjmedia_sdp_neg_get_neg_remote(mInv->neg, &remote_sdp) != PJ_SUCCESS))
+        if (!mInv->neg || (pjmedia_sdp_neg_get_neg_remote(mInv->neg, &remote_sdp) != PJ_SUCCESS))
         {
             // No SDP was present in the INVITE so we need to create an offer
             sdp = mSession->createSDPOffer();
@@ -392,8 +394,8 @@ protected:
             return Complete;
         }
 
-	// Provide the produced SDP as our offer or answer
-	pjsip_inv_set_sdp_answer(mInv, sdp);
+        // Provide the produced SDP as our offer or answer
+        pjsip_inv_set_sdp_answer(mInv, sdp);
 
         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];
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 94c0e09..386ddea 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -531,6 +531,15 @@ void SipSession::initializePJSIPStructs()
     setInviteSession(inviteSession);
 }
 
+void SipSession::setTelephonyEventSourcesAndSinks(const SipEndpointConfig& config)
+{
+    if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
+    {
+        mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
+        mImplPriv->mEventSource = new SipTelephonyEventSource();
+    }
+}
+
 /**
  * Default constructor.
  */
@@ -557,12 +566,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     {
         lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
         initializePJSIPStructs();
-    }
-
-    if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
-    {
-        mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
-        mImplPriv->mEventSource = new SipTelephonyEventSource();
+        setTelephonyEventSourcesAndSinks(config);
     }
 }
 
diff --git a/src/SipSession.h b/src/SipSession.h
index 8f3ef7e..a423c46 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -256,6 +256,8 @@ public:
 
     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
 
+    void setTelephonyEventSourcesAndSinks(const SipEndpointConfig& config);
+
     bool isTelephonyEventSource();
 
     bool isTelephonyEventSink();

commit 36a1f7d1dda63edfeb93da238084c6be4e63d330
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 19 15:08:40 2011 -0500

    Create telephony event sources or sinks at session creation time if configuration dictates to do so.

diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 31ab0e1..a37281f 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -342,7 +342,7 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
     }
 
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
-        mImplPriv->mServiceLocator, mImplPriv->mReplica, true);
+        mImplPriv->mServiceLocator, mImplPriv->mReplica, true, mImplPriv->mConfig);
     mImplPriv->mSessions.push_back(session);
     std::cout << "And now we're returing a session proxy..." << std::endl;
     return session->getSessionProxy();
@@ -351,7 +351,7 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
 AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
 {
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
-        mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
+        mImplPriv->mServiceLocator, mImplPriv->mReplica, false, mImplPriv->mConfig);
     mImplPriv->mSessions.push_back(session);
     return session;
 }
@@ -363,7 +363,7 @@ AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const s
                                                                          const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
 {
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasessions,
-            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
+            sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false, mImplPriv->mConfig);
     mImplPriv->mSessions.push_back(session);
     return session;
 }
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index ff5c4a6..94c0e09 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -271,8 +271,8 @@ public:
      */
     bool mSDPFinalized;
 
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPtr eventSink;
-    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePtr eventSource;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSinkPtr mEventSink;
+    AsteriskSCF::SessionCommunications::V1::TelephonyEventSourcePtr mEventSource;
 };
 
 /**
@@ -537,7 +537,8 @@ void SipSession::initializePJSIPStructs()
 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 isUAC)
+                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC,
+                       const SipEndpointConfig &config)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     if (listener != 0)
@@ -557,6 +558,12 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
         lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
         initializePJSIPStructs();
     }
+
+    if (config.sessionConfig.dtmf == AsteriskSCF::Configuration::SipSessionManager::V1::INFO)
+    {
+        mImplPriv->mEventSink = new SipTelephonyEventSink(mImplPriv->mSessionWork, mImplPriv->mInviteSession);
+        mImplPriv->mEventSource = new SipTelephonyEventSource();
+    }
 }
 
 /**
@@ -567,7 +574,8 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
                        const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
                        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, bool isUAC)
+                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC,
+                       const SipEndpointConfig &config)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     mImplPriv->mSessionProxy =
@@ -1958,12 +1966,12 @@ void SipSession::enqueueSessionWork(const SuspendableWorkPtr& task)
 
 bool SipSession::isTelephonyEventSource()
 {
-    return mImplPriv->eventSource != 0;
+    return mImplPriv->mEventSource != 0;
 }
... 1680 lines suppressed ...


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list