[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 Oct 3 17:07:58 CDT 2011


branch "master" has been updated
       via  bf97df459f0c054d095331534252ec3755abc1e2 (commit)
      from  74d1103527d97fa8cd5887ab510a748b20ceb8ff (commit)

Summary of changes:
 config/Sip.config                                  |    5 +
 config/SipConfigurator.py                          |    3 +
 .../SipSessionManager/SipConfigurationIf.ice       |   11 +
 .../SipSessionManager/SipStateReplicationIf.ice    |    4 +-
 src/PJSipSessionModule.cpp                         |    4 +-
 src/SipConfiguration.cpp                           |   10 +
 src/SipEndpoint.cpp                                |    8 +-
 src/SipEndpoint.h                                  |    7 +-
 src/SipSession.cpp                                 |  342 ++++++++++++++++++--
 src/SipSession.h                                   |   12 +-
 10 files changed, 376 insertions(+), 30 deletions(-)


- Log -----------------------------------------------------------------
commit bf97df459f0c054d095331534252ec3755abc1e2
Author: Joshua Colp <jcolp at digium.com>
Date:   Mon Oct 3 19:07:36 2011 -0300

    Merge direct media connection support.

diff --git a/config/Sip.config b/config/Sip.config
index 5646d97..7946dba 100644
--- a/config/Sip.config
+++ b/config/Sip.config
@@ -92,6 +92,10 @@ rtpoveripv6=no
 # Allowable media formats for the endpoint. Each format is separated using , and follows the format
 # <name>/<sample rate>@<frame size>;<format specific parameters>
 formats=ulaw/8000,alaw/8000
+
+# Whether media should be allowed to flow directly between endpoints or not
+directmedia=no
+
 #
 # Simple fields for a single identity record
 name='robert foo bar'
@@ -143,3 +147,4 @@ ids=bob-bar-office,bob-bar-cell
 #
 # baseport=[pick a number]
 
+
diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index bd9a383..5505f2a 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -203,6 +203,9 @@ class SipSectionVisitors(Configurator.SectionVisitors):
         item = AsteriskSCF.Configuration.SipSessionManager.V1.SipRTPMediaServiceItem()
         mapper.map('rtpoveripv6', item, 'requireIPv6', 'mediaservice', config.getboolean, None)
 
+        item = AsteriskSCF.Configuration.SipSessionManager.V1.DirectMediaItem()
+        mapper.map('directmedia', item, 'enabled', 'directmedia', config.getboolean, None)
+
         item = AsteriskSCF.Configuration.SipSessionManager.V1.SipCryptoCertificateItem()
         mapper.map('certificateauthorityfile', item, 'certificateAuthority', 'cryptocert', config.get, None)
         mapper.map('certificatefile', item, 'certificate', 'cryptocert', config.get, None)
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 119a010..c22c91b 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -254,6 +254,17 @@ class SRTPCryptoKey
 sequence<SRTPCryptoKey> SRTPCryptoKeySeq;
 
 /**
+ * Direct media configuration item
+ */
+class DirectMediaItem extends SipConfigurationItem
+{
+    /**
+     * Whether direct media support is enabled or not
+     */
+    bool enabled = false;
+};
+
+/**
  * SRTP crypto configuration.
  */
 class SRTPCryptoItem extends SipConfigurationItem
diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index 09e4af4..f982668 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -139,7 +139,7 @@ module V1
 	  bool isClient;
    };
 
-   sequence<AsteriskSCF::Media::RTP::V1::RTPSession*> RTPMediaSessionSeq;
+   dictionary<string, AsteriskSCF::Media::RTP::V1::RTPSession*> RTPMediaSessionDict;
 
    class SipSessionStateItem extends SipStateItem
    {
@@ -152,7 +152,7 @@ module V1
       AsteriskSCF::Media::V1::StreamSourceSeq sources;
       AsteriskSCF::Media::V1::StreamSinkSeq sinks;
       AsteriskSCF::Media::V1::StreamInformationDict streams;
-      RTPMediaSessionSeq rtpMediaSessions;
+      RTPMediaSessionDict rtpMediaSessions;
       AsteriskSCF::SessionCommunications::V1::SessionListenerSeq listeners;
       AsteriskSCF::SessionCommunications::V1::Bridge *bridge;
       AsteriskSCF::SessionCommunications::V1::SessionCookieDict cookies;
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 4a08875..3b97fd4 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -256,11 +256,11 @@ void PJSipSessionModule::replicateState(PJSipDialogModInfo *dlgInfo, PJSipTransa
         lg(Debug) << "Session object identity: " << sessionInfo->mSessionState->sessionObjectId.name;
         lg(Debug) << "Media session object identity: " << sessionInfo->mSessionState->mediaSessionObjectId.name;
 
-	for (RTPMediaSessionSeq::const_iterator mediaSession = sessionInfo->mSessionState->rtpMediaSessions.begin();
+	for (RTPMediaSessionDict::const_iterator mediaSession = sessionInfo->mSessionState->rtpMediaSessions.begin();
              mediaSession != sessionInfo->mSessionState->rtpMediaSessions.end();
              ++mediaSession)
         {
-            lg(Debug) << "Media session: " << (*mediaSession);
+            lg(Debug) << "Media session: " << mediaSession->second;
         }
 
         lg(Debug) << "Bridge: " << sessionInfo->mSessionState->bridge;
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index 5c2bca9..f4c07ef 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -300,6 +300,11 @@ class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfi
             mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateTarget, mConfig, target));
         };
 
+        void visitDirectMediaItem(const DirectMediaItemPtr& direct)
+        {
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDirectMedia, mConfig, direct));
+        };
+
 	void visitSipRTPMediaServiceItem(const SipRTPMediaServiceItemPtr& service)
 	{
 	    mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateMediaService, mConfig, service));
@@ -445,6 +450,11 @@ public:
         mEndpoint->setTargetAddress(target->host, target->port);
     }
 
+    void updateDirectMedia(const DirectMediaItemPtr& direct)
+    {
+        mEndpoint->setDirectMedia(direct->enabled);
+    }
+
     void updateMediaService(const SipRTPMediaServiceItemPtr& service)
     {
 	mEndpoint->setRTPOverIPv6(service->requireIPv6);
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 2c5bf9d..d017a06 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -337,6 +337,12 @@ void SipEndpoint::setRTPOverIPv6(bool enabled)
     mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
 }
 
+
+void SipEndpoint::setDirectMedia(bool enabled)
+{
+    mImplPriv->mConfig.sessionConfig.directMedia = enabled;
+}
+
 void SipEndpoint::setMediaNATOptions(bool useICE, bool useTURN)
 {
     mImplPriv->mConfig.sessionConfig.rtpOverICE = useICE;
@@ -486,7 +492,7 @@ SipSessionPtr SipEndpoint::createSession
                 const Ice::Identity& sessionid, 
 		const Ice::Identity& controllerid,
                 const Ice::Identity& mediaid,
-                const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
                 const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
                 const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
 {
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index efc3a8c..0a07081 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -159,6 +159,8 @@ public:
     // Whether we are using IPv6 for media transport
     // or not.
     bool rtpOverIPv6;
+    // Whether we are allowing direct media or not
+    bool directMedia;
     // The method by which we will transmit
     // DTMF to an endpoint
     AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf;
@@ -318,7 +320,7 @@ public:
     //
     AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&);
     AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&, const Ice::Identity&, const Ice::Identity&,
-                                                                const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
+                                                                const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict&,
                                                                 const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&);
 
     void removeSession(const AsteriskSCF::SessionCommunications::V1::SessionPtr&);
@@ -333,6 +335,7 @@ public:
     void setCallDirection(enum Direction);
     void setSecureTransport(enum Direction);
     void setRTPOverIPv6(bool);
+    void setDirectMedia(bool);
     void addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific);
 
     /**
@@ -349,9 +352,11 @@ public:
     /**
      * API call which returns the stream topology to be used for an SDP offer.
      */
+
     void setMediaNATOptions(bool useICE, bool useTURN);
     void setSRTPOptions(const SipEndpointMediaSRTPConfig& srtpConfig);
     void setSignalingNATOptions(bool enable);
+
     AsteriskSCF::Media::V1::StreamInformationDict getStreamTopology();
     void setDTMFMethod(AsteriskSCF::Configuration::SipSessionManager::V1::SipDTMFOption dtmf);
 
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 106524a..dce14ab 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -31,6 +31,8 @@
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 #include <AsteriskSCF/SessionCommunications/SessionCookieIf.h>
 #include <AsteriskSCF/System/ExceptionsIf.h>
+#include <AsteriskSCF/Helpers/Network.h>
+
 #include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
 #include <AsteriskSCF/logger.h>
 #include <AsteriskSCF/System/NAT/NATTraversalIf.h>
@@ -51,6 +53,7 @@ using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::Media;
 using namespace AsteriskSCF::Media::SDP::V1;
 using namespace AsteriskSCF::System::V1;
+using namespace AsteriskSCF::Helpers;
 using namespace std;
 
 namespace
@@ -276,9 +279,9 @@ public:
     pjsip_inv_session *mInviteSession;
 
     /**
-     * A vector of RTP media sessions belonging to this endpoint.
+     * A dictionary of RTP media sessions belonging to this endpoint.
      */
-    RTPMediaSessionSeq mRTPSessions;
+    RTPMediaSessionDict mRTPSessions;
 
     /**
      * A vector of media sources associated with this endpoint.
@@ -415,11 +418,11 @@ public:
         AsteriskSCF::Media::V1::SessionCookies results;
 
         // Gather the cookies from all of the Session's RTP Media Sessions. 
-        RTPMediaSessionSeq mediaSessions = mSession->getRTPMediaSessions();
-        for(RTPMediaSessionSeq::iterator i = mediaSessions.begin(); 
+        RTPMediaSessionDict mediaSessions = mSession->getRTPMediaSessions();
+        for(RTPMediaSessionDict::iterator i = mediaSessions.begin(); 
             i != mediaSessions.end(); ++i)
         {
-            AsteriskSCF::Media::V1::SessionCookies cookies = (*i)->getCookies(mCookieTypes);
+            AsteriskSCF::Media::V1::SessionCookies cookies = i->second->getCookies(mCookieTypes);
             results.insert(results.end(), cookies.begin(), cookies.end());
         }
 
@@ -459,11 +462,11 @@ public:
         AsteriskSCF::Media::V1::SessionCookies results;
 
         // Set the cookies on all of the Session's RTP Media Sessions. 
-        RTPMediaSessionSeq mediaSessions = mSession->getRTPMediaSessions();
-        for(RTPMediaSessionSeq::iterator i = mediaSessions.begin(); 
+        RTPMediaSessionDict mediaSessions = mSession->getRTPMediaSessions();
+        for(RTPMediaSessionDict::iterator i = mediaSessions.begin(); 
             i != mediaSessions.end(); ++i)
         {
-            (*i)->setCookies(mCookies);
+            i->second->setCookies(mCookies);
         }
 
         return Complete;
@@ -499,11 +502,11 @@ public:
         AsteriskSCF::Media::V1::SessionCookies results;
 
         // Set the cookies on all of the Session's RTP Media Sessions. 
-        RTPMediaSessionSeq mediaSessions = mSession->getRTPMediaSessions();
-        for(RTPMediaSessionSeq::iterator i = mediaSessions.begin(); 
+        RTPMediaSessionDict mediaSessions = mSession->getRTPMediaSessions();
+        for(RTPMediaSessionDict::iterator i = mediaSessions.begin(); 
             i != mediaSessions.end(); ++i)
         {
-            (*i)->removeCookies(mCookieTypes);
+            i->second->removeCookies(mCookieTypes);
         }
 
         return Complete;
@@ -895,6 +898,7 @@ private:
     SipSessionPtr mSession;
 };
 
+
 /**
  * Sets the party id cookies to indicate that this session's SessionOwnerId is the Caller. 
  */
@@ -921,6 +925,133 @@ void SipSession::setSelfAsCaller()
     mImplPriv->mSessionCookies[dialed->ice_id()] = dialed;
 }
 
+class CheckDirectConnectionsOperation : public SuspendableWork
+{
+public:
+    CheckDirectConnectionsOperation(
+        const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_checkDirectConnectionsPtr& cb,
+        const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections,
+        const SipSessionPtr& session)
+        : mCb(cb), mConnections(connections), mSession(session) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        lg(Debug) << "Executing a checkDirectConnections Operation";
+
+        mCb->ice_response(mSession->checkDirectConnections(mConnections));
+
+        return Complete;
+    }
+
+private:
+    AsteriskSCF::Media::V1::AMD_DirectMediaConnection_checkDirectConnectionsPtr mCb;
+    AsteriskSCF::Media::V1::DirectMediaConnectionDict mConnections;
+    SipSessionPtr mSession;
+};
+
+class ConnectStreamsOperation : public SuspendableWork
+{
+public:
+    ConnectStreamsOperation(
+        const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_connectStreamsPtr& cb,
+        const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections,
+        const SipSessionPtr& session)
+        : mCb(cb), mConnections(connections), mSession(session) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        if (mSession->getInviteSession()->invite_tsx)
+        {
+            mSession->enqueueSessionWork(this);
+            return Complete;
+        }
+
+        pjmedia_sdp_session *sdp = mSession->modifySDPforDirectConnections(mConnections);
+        pjsip_tx_data *packet = NULL;
+
+        if ((pjsip_inv_reinvite(mSession->getInviteSession(), NULL, sdp, &packet)) == PJ_SUCCESS)
+        {
+            pjsip_inv_send_msg(mSession->getInviteSession(), packet);
+        }
+
+        mCb->ice_response();
+
+        return Complete;
+    }
+
+private:
+    AsteriskSCF::Media::V1::AMD_DirectMediaConnection_connectStreamsPtr mCb;
+    AsteriskSCF::Media::V1::DirectMediaConnectionDict mConnections;
+    const SipSessionPtr mSession;
+};
+
+class DisconnectStreamsOperation : public SuspendableWork
+{
+public:
+    DisconnectStreamsOperation(
+        const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_disconnectStreamsPtr& cb,
+        const Ice::StringSeq& streams,
+        const SipSessionPtr& session)
+        : mCb(cb), mStreams(streams), mSession(session) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        pjmedia_sdp_session *sdp = mSession->modifySDP(mStreams);
+        pjsip_tx_data *packet = NULL;
+
+        if ((pjsip_inv_reinvite(mSession->getInviteSession(), NULL, sdp, &packet)) == PJ_SUCCESS)
+        {
+            pjsip_inv_send_msg(mSession->getInviteSession(), packet);
+        }
+
+        mCb->ice_response();
+
+        return Complete;
+    }
+
+private:
+    AsteriskSCF::Media::V1::AMD_DirectMediaConnection_disconnectStreamsPtr mCb;
+    Ice::StringSeq mStreams;
+    const SipSessionPtr mSession;
+};
+
+/**
+ * Implementation of a DirectMediaConnection interface for the SipSession.
+ */
+class SipDirectMediaConnection : public AsteriskSCF::Media::V1::DirectMediaConnection
+{
+public:
+    SipDirectMediaConnection(const SipSessionPtr& session) :
+        mSession(session) { }
+
+    void checkDirectConnections_async(const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_checkDirectConnectionsPtr& cb,
+                                      const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections, const Ice::Current&)
+    {
+        lg(Debug) << "Queueing checkDirectConnections operation";
+        mSession->enqueueSessionWork(new CheckDirectConnectionsOperation(cb, connections, mSession));
+    }
+
+    void connectStreams_async(const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_connectStreamsPtr& cb,
+                              const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections, const Ice::Current&)
+    {
+        lg(Debug) << "Queueing connectStreams operation";
+        mSession->enqueueSessionWork(new ConnectStreamsOperation(cb, connections, mSession));
+    }
+
+    void disconnectStreams_async(const AsteriskSCF::Media::V1::AMD_DirectMediaConnection_disconnectStreamsPtr& cb,
+                                 const Ice::StringSeq& streams, const Ice::Current&)
+    {
+        lg(Debug) << "Queueing disconnectStreams operation";
+        mSession->enqueueSessionWork(new DisconnectStreamsOperation(cb, streams, mSession));
+    }
+
+private:
+    /**
+     * A pointer to the communications session that created us.
+     */
+    SipSessionPtr mSession;
+};
+
 void SipSession::initializePJSIPStructs()
 {
     SipEndpointConfig& config = mImplPriv->mEndpoint->getConfig();
@@ -1150,7 +1281,7 @@ SipSessionPtr SipSession::create(const Ice::ObjectAdapterPtr& adapter,
                        const Ice::Identity& sessionid,
                        const Ice::Identity& controllerid,
                        const Ice::Identity& mediaid, 
-                       const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                       const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
                        const AsteriskSCF::Media::V1::StreamSourceSeq& sources, 
                        const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
                        const PJSipManagerPtr& manager, 
@@ -1224,6 +1355,9 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
     mImplPriv->mOurSessionControllerProxy =
         AsteriskSCF::SessionCommunications::V1::SessionControllerPrx::uncheckedCast(adapter->addWithUUID(mImplPriv->mOurSessionController));
 
+    DirectMediaConnectionPtr directMedia = new SipDirectMediaConnection(this);
+    adapter->addFacet(directMedia, mImplPriv->mSessionProxy->ice_getIdentity(), directMediaConnectionFacet);
+
     if (isUAC)
     {
         lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
@@ -1238,10 +1372,10 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
 SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
                        const SipEndpointPtr& endpoint,
                        const std::string& destination, 
-                       const Ice::Identity& /* sessionid */,
+                       const Ice::Identity& sessionid,
                        const Ice::Identity& controllerid,
                        const Ice::Identity& mediaid,
-                       const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                       const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
                        const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
                        const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
                        const PJSipManagerPtr& manager,
@@ -1263,6 +1397,9 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter,
     mImplPriv->mOurSessionControllerProxy =
         AsteriskSCF::SessionCommunications::V1::SessionControllerPrx::uncheckedCast(adapter->add(mImplPriv->mOurSessionController, controllerid));
 
+    DirectMediaConnectionPtr directMedia = new SipDirectMediaConnection(this);
+    adapter->addFacet(directMedia, sessionid, directMediaConnectionFacet);
+
     mImplPriv->mRTPSessions = mediasessions;
     mImplPriv->mSources = sources;
     mImplPriv->mSinks = sinks;
@@ -2285,12 +2422,12 @@ public:
         {
             //XXX This loop may be a candidate for making AMI-ified and returning "Suspended"
             // Release all the RTP sessions we are using
-            for (RTPMediaSessionSeq::const_iterator i = mSessionPriv->mRTPSessions.begin();
-         i != mSessionPriv->mRTPSessions.end(); ++i)
+            for (RTPMediaSessionDict::const_iterator i = mSessionPriv->mRTPSessions.begin();
+		 i != mSessionPriv->mRTPSessions.end(); ++i)
             {
                 try
                 {
-                    (*i)->release();
+                    i->second->release();
                 }
                 catch (const Ice::Exception& ex)
                 {
@@ -2624,7 +2761,7 @@ pjmedia_sdp_session *SipSession::createSDPOffer(const AsteriskSCF::Media::V1::St
     stream->second->sources.push_back(source);
 
         // Update the SIP session with some RTP session details
-        mImplPriv->mRTPSessions.push_back(session);
+        mImplPriv->mRTPSessions.insert(make_pair(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count), session));
 
         // Add the stream to the SDP
         pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
@@ -2949,7 +3086,7 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
             ourStream->sources.push_back(source);
 
             // Update the SIP session with some RTP session details
-            mImplPriv->mRTPSessions.push_back(session);
+            mImplPriv->mRTPSessions.insert(make_pair(boost::lexical_cast<std::string>(stream), session));
 
             // Just by common sense alone since we just got an RTP session for this stream we obviously
             // have not added it to the answer SDP either, so do it
@@ -3083,7 +3220,7 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
 }
 
 /**
- * Internal function which modifies our SDP.
+ * Internal function which modifies our SDP to contain remote destination and format details.
  */
 pjmedia_sdp_session *SipSession::modifySDP(const AsteriskSCF::Media::V1::StreamInformationDict& toRemove)
 {
@@ -3130,6 +3267,98 @@ pjmedia_sdp_session *SipSession::modifySDP(const AsteriskSCF::Media::V1::StreamI
 }
 
 /**
+ * Internal function which modifies our SDP to contain remote destination and format details.
+ */
+pjmedia_sdp_session *SipSession::modifySDPforDirectConnections(const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections)
+{
+    // In order to modify SDP you have to have SDP
+    if (!mImplPriv->mSDP)
+    {
+        return 0;
+    }
+
+    // Iterate through each connection request
+    for (AsteriskSCF::Media::V1::DirectMediaConnectionDict::const_iterator connection = connections.begin();
+         connection != connections.end();
+         ++connection)
+    {
+        unsigned int streamNum = boost::lexical_cast<unsigned int>(connection->first);
+
+        if (streamNum >= mImplPriv->mSDP->media_count)
+        {
+            continue;
+        }
+
+        pjmedia_sdp_media *media = mImplPriv->mSDP->media[streamNum];
+
+        // Skip unknown streams
+        if (!media)
+        {
+            continue;
+        }
+
+        StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(connection->second);
+
+        // Update connection details on the stream
+        pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, sink->getRemoteAddress().c_str());
+        media->desc.port = (pj_uint16_t) sink->getRemotePort();
+
+        // Drop all existing formats and attributes by changing the counts to zero, this is fine since the SDP generator
+        // uses the count to determine how far to go
+        media->desc.fmt_count = 0;
+        media->attr_count = 0;
+
+        // Add formats present on the sink, this is fine to do because an SDP descriptor will only be found for ones
+        // which are naturally configured on this endpoint
+        PayloadMap payloads;
+        addFormatstoSDP(sink->getFormats(), media, payloads);
+    }
+
+    return mImplPriv->mSDP;
+}
+
+/**
+ * Internal function which modifies our SDP to contain our local destination details and formats.
+ */
+pjmedia_sdp_session *SipSession::modifySDP(const Ice::StringSeq& streams)
+{
+    // In order to modify SDP you have to have SDP
+    if (!mImplPriv->mSDP)
+    {
+        return 0;
+    }
+
+    // Iterate through each stream
+    for (Ice::StringSeq::const_iterator stream = streams.begin();
+         stream != streams.end();
+         ++stream)
+    {
+        StreamInformationDict::const_iterator ourStream = mImplPriv->mStreams.find((*stream));
+
+        // Ignore streams that we don't know about
+        if (ourStream == mImplPriv->mStreams.end())
+        {
+            continue;
+        }
+
+        // These *will* exist and be true due to implementation
+        pjmedia_sdp_media *media = mImplPriv->mSDP->media[boost::lexical_cast<int>((*stream))];
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(ourStream->second->sources.front());
+
+        pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+        media->desc.port = (pj_uint16_t) source->getLocalPort();
+
+        media->desc.fmt_count = 0;
+        media->attr_count = 0;
+
+        PayloadMap payloads;
+        addFormatstoSDP(ourStream->second->formats, media, payloads);
+    }
+
+    return mImplPriv->mSDP;
+}
+
+/**
  * Internal function which sets the PJsip dialog.
  */
 void SipSession::setDialog(pjsip_dialog *dialog)
@@ -3336,7 +3565,7 @@ void SipSession::setListeners(const AsteriskSCF::SessionCommunications::V1::Sess
 /**
  * Internal function which returns the RTP media sessions that are hidden inside the SIP session.
  */
-RTPMediaSessionSeq SipSession::getRTPMediaSessions()
+RTPMediaSessionDict SipSession::getRTPMediaSessions()
 {
     return mImplPriv->mRTPSessions;
 }
@@ -3349,6 +3578,77 @@ void SipSession::setStreams(const AsteriskSCF::Media::V1::StreamInformationDict&
     mImplPriv->mStreams = streams;
 }
 
+/**
+ * Internal function which retrieves possible direct connections.
+ */
+Ice::StringSeq SipSession::checkDirectConnections(const AsteriskSCF::Media::V1::DirectMediaConnectionDict& connections)
+{
+    SipEndpointConfig &config = mImplPriv->mEndpoint->getConfig();
+
+    // If direct media connections are disabled or if NAT is enabled don't even bother checking
+    if (config.sessionConfig.directMedia == false || config.transportConfig.enableNAT == true)
+    {
+        return Ice::StringSeq();
+    }
+
+    Ice::StringSeq allowedStreams;
+
+    // Iterate through each requested connection checking if it is possible
+    for (AsteriskSCF::Media::V1::DirectMediaConnectionDict::const_iterator connection = connections.begin();
+         connection != connections.end();
+         ++connection)
+    {
+        // Do we have a local stream that matches this?
+        StreamInformationDict::const_iterator stream = mImplPriv->mStreams.find(connection->first);
+
+        // Uh, if they passed in a stream that we know nothing about skip it...
+        if (stream == mImplPriv->mStreams.end())
+        {
+            continue;
+        }
+
+        RTPMediaSessionDict::const_iterator session = mImplPriv->mRTPSessions.find(connection->first);
+
+        // We only support connecting streams directly that use RTP
+        if (session == mImplPriv->mRTPSessions.end())
+        {
+            continue;
+        }
+
+        // If the session is using SRTP we can not directly connect
+        SRTPSessionPrx srtp = SRTPSessionPrx::checkedCast(session->second);
+
+        if (srtp)
+        {
+            continue;
+        }
+
+        StreamSinkRTPPrx sink = StreamSinkRTPPrx::checkedCast(connection->second);
+
+        // If the provided sink is not an RTP one this connection is not possible
+        if (!sink)
+        {
+            continue;
+        }
+
+        AddressPtr theirAddress(new Address(sink->getRemoteAddress(), 0));
+
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(stream->second->sources.front());
+        AddressPtr ourAddress(new Address(source->getLocalAddress(), 0));
+
+        // Ensure both are IPv4 or IPv6
+        if (theirAddress->isIPV6() != ourAddress->isIPV6())
+        {
+            continue;
+        }
+
+        // It passed! We can establish a direct external media connection
+        allowedStreams.push_back(connection->first);
+    }
+
+    return allowedStreams;
+}
+
 bool SipSession::operator==(const SipSession &other) const {
     return (this->mImplPriv->mInviteSession == other.mImplPriv->mInviteSession);
 }
diff --git a/src/SipSession.h b/src/SipSession.h
index 895e56e..bb36ff5 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -140,7 +140,7 @@ public:
         const Ice::Identity& sessionid,
         const Ice::Identity& controllerid,
         const Ice::Identity& mediaid, 
-	const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+	const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict& mediasessions,
         const AsteriskSCF::Media::V1::StreamSourceSeq& sources, 
 	const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
         const PJSipManagerPtr& manager, 
@@ -284,6 +284,10 @@ public:
 
     pjmedia_sdp_session *modifySDP(const AsteriskSCF::Media::V1::StreamInformationDict&);
 
+    pjmedia_sdp_session *modifySDPforDirectConnections(const AsteriskSCF::Media::V1::DirectMediaConnectionDict&);
+
+    pjmedia_sdp_session *modifySDP(const Ice::StringSeq&);
+
     void setDialog(pjsip_dialog *dialog);
 
     pjsip_dialog *getDialog();
@@ -292,6 +296,8 @@ public:
 
     pjsip_inv_session *getInviteSession();
 
+    Ice::StringSeq checkDirectConnections(const AsteriskSCF::Media::V1::DirectMediaConnectionDict&);
+
     //
     // TODO: Are these thread safe?
     //
@@ -323,7 +329,7 @@ public:
 
     void setStreams(const AsteriskSCF::Media::V1::StreamInformationDict& streams);
 
-    AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq getRTPMediaSessions();
+    AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict getRTPMediaSessions();
 
     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
 
@@ -349,7 +355,7 @@ private:
         bool ipv6, bool isUAC, const SipEndpointConfig& config, const NATEndpointOptions& natOptions);
 
     SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&, const Ice::Identity&,
-        const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
+        const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionDict&,
         const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
         const PJSipManagerPtr& manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
         const SipReplicationContextPtr& replicationContext,

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


-- 
asterisk-scf/release/sip.git



More information about the asterisk-scf-commits mailing list