[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "t38udptl" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Fri Sep 16 16:05:39 CDT 2011


branch "t38udptl" has been created
        at  1c58e78ff33ecc57b2d881275f2d8974b2b7b58c (commit)

- Log -----------------------------------------------------------------
commit 1c58e78ff33ecc57b2d881275f2d8974b2b7b58c
Author: Joshua Colp <jcolp at digium.com>
Date:   Fri Sep 16 18:11:30 2011 -0300

    Add progress thus far on adding UDPTL support to the SIP component.

diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index 09e4af4..2dfe710 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -19,6 +19,7 @@
 #include <Ice/Identity.ice>
 #include <AsteriskSCF/Media/MediaIf.ice>
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.ice>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.ice>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice>
 #include <AsteriskSCF/System/Component/ConfigurationIf.ice>
@@ -140,6 +141,7 @@ module V1
    };
 
    sequence<AsteriskSCF::Media::RTP::V1::RTPSession*> RTPMediaSessionSeq;
+   sequence<AsteriskSCF::Media::UDPTL::V1::UDPTLSession*> UDPTLMediaSessionSeq;
 
    class SipSessionStateItem extends SipStateItem
    {
@@ -153,6 +155,7 @@ module V1
       AsteriskSCF::Media::V1::StreamSinkSeq sinks;
       AsteriskSCF::Media::V1::StreamInformationDict streams;
       RTPMediaSessionSeq rtpMediaSessions;
+      UDPTLMediaSessionSeq udptlMediaSessions;
       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 61aada4..30d0a4e 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -108,6 +108,7 @@ void PJSipSessionModInfo::updateSessionState(pjsip_inv_session *inv_session)
         mSessionState->sources = mSession->getMediaSources();
         mSessionState->sinks = mSession->getMediaSinks();
         mSessionState->rtpMediaSessions = mSession->getRTPMediaSessions();
+        mSessionState->udptlMediaSessions = mSession->getUDPTLMediaSessions();
         mSessionState->listeners = mSession->getListeners();
 	    mSessionState->streams = mSession->getStreams();
         try
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index f88691b..cb2d24d 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -672,6 +672,12 @@ StreamInformationDict SipEndpoint::getStreamTopology()
          configuredFormat != mImplPriv->mFormats.end();
          ++configuredFormat)
     {
+        // Initial stream topology does not support T.38 streams
+        if ((*configuredFormat)->getDescriptor()->type == "image")
+        {
+            continue;
+        }
+
         // See if a stream already exists for this type
         StreamInformationDict::iterator stream = topology.find((*configuredFormat)->getDescriptor()->type);
 
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index f550ce9..c14ceb9 100755
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -35,6 +35,8 @@
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
 #include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTCPIf.h>
+#include <AsteriskSCF/Media/UDPTL/MediaUDPTLIf.h>
+#include <AsteriskSCF/Media/Formats/T38UdptlFormat.h>
 #include <AsteriskSCF/SessionCookies/SipSessionManager/SipSessionCookiesIf.h>
 #include "NATOptions.h"
 
@@ -45,6 +47,8 @@ using namespace AsteriskSCF::Media::RTP::V1;
 using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::Media;
 using namespace AsteriskSCF::Media::SDP::V1;
+using namespace AsteriskSCF::Media::UDPTL::V1;
+using namespace AsteriskSCF::Media::Formats::T38Udptl::V1;
 using namespace std;
 
 namespace
@@ -247,6 +251,11 @@ public:
     RTPMediaSessionSeq mRTPSessions;
 
     /**
+     * A vector of UDPTL media sessions belonging to this session.
+     */
+    UDPTLMediaSessionSeq mUDPTLSessions;
+
+    /**
      * A vector of media sources associated with this endpoint.
      */
     AsteriskSCF::Media::V1::StreamSourceSeq mSources;
@@ -1766,6 +1775,19 @@ public:
                     lg(Error) << "Exception caught while trying to release a media session\n" << ex.what();
                 }
            }
+
+            for (UDPTLMediaSessionSeq::const_iterator i = mSessionPriv->mUDPTLSessions.begin();
+                 i != mSessionPriv->mUDPTLSessions.end(); ++i)
+            {
+                try
+                {
+                    (*i)->release();
+                }
+                catch (const Ice::Exception& ex)
+                {
+                    lg(Error) << "Exception caught while trying to release a udptl session\n" << ex.what();
+                }
+            }
         }
         mSessionPriv->mEndpoint->removeSession(mSession);
         return Complete;
@@ -2042,95 +2064,182 @@ pjmedia_sdp_session *SipSession::createSDPOffer(const AsteriskSCF::Media::V1::St
         // Update the stream with the actual formats
         stream->second->formats = formats;
 
-        RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
-        params->category = "rtp";
-        params->formats = stream->second->formats;
-        params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
-
-        // Try to find a factory for RTP sessions matching what we need
-        RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+        // Determine what media this stream is carrying
+        AudioFormatPtr audio;
+        VideoFormatPtr video;
+	T38UdptlFormatPtr t38;
 
-        // If none exist we can't provide the stream
-        if (factory == 0)
+        // If this stream contains an audio or video format the stream is transported using RTP
+        if ((audio = AudioFormatPtr::dynamicCast(formats.front())) || (video = VideoFormatPtr::dynamicCast(formats.front())))
         {
-            continue;
-        }
+            RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
+            params->category = "rtp";
+            params->formats = stream->second->formats;
+            params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
+
+            // Try to find a factory for RTP sessions matching what we need
+            RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
 
-        // Allocate a new RTP session to carry the media formats we have in common
-        RTPSessionPrx session = factory->allocate(params);
+            // If none exist we can't provide the stream
+            if (factory == 0)
+            {
+                continue;
+            }
 
-        // Double check to make sure they actually gave us a sesson back... they could have had a problem
-        if (session == 0)
-        {
-            continue;
-        }
+            // Allocate a new RTP session to carry the media formats we have in common
+            RTPSessionPrx session = factory->allocate(params);
+
+            // Double check to make sure they actually gave us a sesson back... they could have had a problem
+            if (session == 0)
+            {
+                continue;
+            }
+
+            // RTP sessions should only provide a single sink, so grab it and update the connection details with that
+            // of the remote party
+            StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
+            mImplPriv->mSinks.push_back(sink);
+            stream->second->sinks.push_back(sink);
 
-        // RTP sessions should only provide a single sink, so grab it and update the connection details with that
-        // of the remote party
-        StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
-        mImplPriv->mSinks.push_back(sink);
-	stream->second->sinks.push_back(sink);
+            // Ditto goes for source
+            StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+            mImplPriv->mSources.push_back(source);
+            stream->second->sources.push_back(source);
 
-        // Ditto goes for source
-        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
-        mImplPriv->mSources.push_back(source);
-	stream->second->sources.push_back(source);
+            // Update the SIP session with some RTP session details
+            mImplPriv->mRTPSessions.push_back(session);
+         
+	    // Add the stream to the SDP
+	    pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
 
-        // Update the SIP session with some RTP session details
-        mImplPriv->mRTPSessions.push_back(session);
+	    // The media count is purposely not incremented here since it is done when the stream is added to the sequence
+	    // of streams
+	    mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
+	    pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
+                           stream->second->formats.front())->type.c_str());
 
-        // Add the stream to the SDP
-        pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+	    pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
 
-        // The media count is purposely not incremented here since it is done when the stream is added to the sequence
-        // of streams
-        mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
-        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
-                       stream->second->formats.front())->type.c_str());
+            // Add connection level details
+            media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
 
-        // TODO: This should not be hardcoded
-        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
+            if (params->ipv6 == true)
+            {
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+            }
+            else
+            {
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
+            }
 
-        // Add connection level details
-        media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
-        pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
+            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
 
-        if (params->ipv6 == true)
-        {
-            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+            // If session level connection information has not yet been set then set it to us
+            if (!mImplPriv->mSDP->conn)
+            {
+                mImplPriv->mSDP->conn = media->conn;
+            }
+
+            media->desc.port = (pj_uint16_t) source->getLocalPort();
+            media->desc.port_count = 1;
+
+            RTCP::V1::RTCPSessionPrx rtcpSession;
+            if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
+            {
+                pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+                pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "rtcp");
+                pj_strdup2(mImplPriv->mDialog->pool, &attr->value, boost::lexical_cast<std::string>(rtcpSession->getLocalPort()).c_str());
+                media->attr[media->attr_count++] = attr;
+            }
+
+            PayloadMap payloads;
+
+            // Add all of the formats to the SDP
+            addFormatstoSDP(stream->second->formats, media, payloads);
+
+            // Push the payload mapping to the RTP session so it'll correctly map things
+            session->associatePayloads(payloads);
         }
-        else
+        else if ((t38 = T38UdptlFormatPtr::dynamicCast(formats.front())))
         {
-            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
-        }
+            UDPTLServiceLocatorParamsPtr params = new UDPTLServiceLocatorParams();
+            params->category = "udptl";
+            params->ipv6 = false;
+//            params->ipv6 = mImplPriv->mEndpoint->getConfig().sessionConfig.rtpOverIPv6;
 
-        pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+            UDPTLMediaServicePrx factory = UDPTLMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+            if (factory == 0)
+            {
+                continue;
+            }
 
-        // If session level connection information has not yet been set then set it to us
-        if (!mImplPriv->mSDP->conn)
-        {
-            mImplPriv->mSDP->conn = media->conn;
-        }
+            UDPTLSessionPrx session = factory->allocate(params);
+            if (session == 0)
+            {
+                continue;
+            }
 
-        media->desc.port = (pj_uint16_t) source->getLocalPort();
-        media->desc.port_count = 1;
+            StreamSinkUDPTLPrx sink = StreamSinkUDPTLPrx::uncheckedCast(session->getSinks().front());
+            mImplPriv->mSinks.push_back(sink);
+            stream->second->sinks.push_back(sink);
 
-        RTCP::V1::RTCPSessionPrx rtcpSession;
-        if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
-        {
-            pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
-            pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "rtcp");
-            pj_strdup2(mImplPriv->mDialog->pool, &attr->value, boost::lexical_cast<std::string>(rtcpSession->getLocalPort()).c_str());
-            media->attr[media->attr_count++] = attr;
-        }
+            StreamSourceUDPTLPrx source = StreamSourceUDPTLPrx::uncheckedCast(session->getSources().front());
+            mImplPriv->mSources.push_back(source);
+            stream->second->sources.push_back(source);
+
+            mImplPriv->mUDPTLSessions.push_back(session);
+
+            // Add the stream to the SDP
+            pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+
+            // The media count is purposely not incremented here since it is done when the stream is added to the sequence
+            // of streams
+            mImplPriv->mSDP->media[mImplPriv->mSDP->media_count] = media;
+            pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(
+                           stream->second->formats.front())->type.c_str());
+
+            pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "UDPTL");
+
+            // Add connection level details
+            media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->net_type, "IN");
 
-        PayloadMap payloads;
+            if (params->ipv6 == true)
+            {
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP6");
+            }
+            else
+            {
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr_type, "IP4");
+            }
 
-        // Add all of the formats to the SDP
-        addFormatstoSDP(stream->second->formats, media, payloads);
+            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+
+            // If session level connection information has not yet been set then set it to us
+            if (!mImplPriv->mSDP->conn)
+            {
+                mImplPriv->mSDP->conn = media->conn;
+            }
 
-        // Push the payload mapping to the RTP session so it'll correctly map things
-        session->associatePayloads(payloads);
+            media->desc.port = (pj_uint16_t) source->getLocalPort();
+            media->desc.port_count = 1;
+
+            SDPDescriptorPtr ourDescriptor = mImplPriv->mEndpoint->getDescriptor(t38);
+            for (SDPFormatParameterSeq::const_iterator parameter = ourDescriptor->parameters.begin();
+                 parameter != ourDescriptor->parameters.end();
+                 ++parameter)
+            {
+                pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+                pj_strdup2(mImplPriv->mDialog->pool, &attr->name, (*parameter).c_str());
+                media->attr[media->attr_count++] = attr;
+            }
+        }
+        else
+        {
+            // The media format type is just unknown to us, so we can not create a stream for this
+            continue;
+        }
 
         // Make the caller aware of this new stream
         newStreams.insert(make_pair(boost::lexical_cast<std::string>(mImplPriv->mSDP->media_count), stream->second));
@@ -2219,11 +2328,21 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
         {
             SDPDescriptorPtr descriptor = new SDPDescriptor();
 
-	    std::string payload = std::string(pj_strbuf(&offer->media[stream]->desc.fmt[format]),
-                pj_strlen(&offer->media[stream]->desc.fmt[format]));
-	    descriptor->payload = boost::lexical_cast<int>(payload);
             descriptor->type = std::string(pj_strbuf(&offer->media[stream]->desc.media),
                                            pj_strlen(&offer->media[stream]->desc.media));
+	    std::string payload = std::string(pj_strbuf(&offer->media[stream]->desc.fmt[format]),
+                pj_strlen(&offer->media[stream]->desc.fmt[format]));
+
+            // If this is for T.38 it is actually special
+            if (descriptor->type == "image" && (payload == "UDPTL" || payload == "udptl"))
+            {
+                descriptor->payload = 96;
+                descriptor->subtype = "t38udptl";
+            }
+            else
+            {
+                descriptor->payload = boost::lexical_cast<int>(payload);
+            }
 
             // Some devices rely solely on the payload for known formats (such as PCMU) so the following format
             // parameters are completely optional
@@ -2311,6 +2430,27 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
 	// Update the stream with the formats
 	ourStream->formats = formats;
 
+        // Record the old state so we can relay the state change to the controller if needed
+        StreamState oldState = ourStream->state;
+
+        // Determine the state of the stream and update it
+        if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendonly", NULL))
+        {
+            ourStream->state = SendOnly;
+        }
+        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "recvonly", NULL))
+        {
+            ourStream->state = ReceiveOnly;
+        }
+        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "inactive", NULL))
+        {
+            ourStream->state = Inactive;
+        }
+        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendrecv", NULL))
+        {
+            ourStream->state = SendAndReceive;
+        }
+
         // Assume that no connection level details exist until proven otherwise
         std::string connection = destination;
         if (offer->media[stream]->conn)
@@ -2319,153 +2459,254 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
                                      pj_strlen(&offer->media[stream]->conn->addr));
         }
 
-        RTPSessionPrx session;
-
-	// If no sink and no source is present then this stream has no RTP session yet so find one
-	if (ourStream->sinks.empty() && ourStream->sources.empty())
-	{
-	    RTPServiceLocatorParamsPtr params;
-	    if (mImplPriv->mNatOptions.enableICE)
-	    {
-		AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams =
-		    new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
-		params = iceParams;
-		iceParams->enableRTPOverICE = true;
-		iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
-	    }
-	    else
-	    {
-		params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
-	    }
+        AudioFormatPtr audio;
+        VideoFormatPtr video;
+        T38UdptlFormatPtr t38;
 
-            params->category = "rtp";
-            params->formats = formats;
+        if ((audio = AudioFormatPtr::dynamicCast(formats.front())) || (video = VideoFormatPtr::dynamicCast(formats.front())))
+        {
+            RTPSessionPrx session;
 
-            // See what address family the connection address is in so we can request the right RTP service
-            if (connection.find(":") != std::string::npos)
+            // If no sink and no source is present then this stream has no RTP session yet so find one
+            if (ourStream->sinks.empty() && ourStream->sources.empty())
             {
-                params->ipv6 = true;
+                RTPServiceLocatorParamsPtr params;
+                if (mImplPriv->mNatOptions.enableICE)
+                {
+                    AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParamsPtr iceParams =
+                        new AsteriskSCF::Media::RTP::V1::RTPOverICEServiceLocatorParams;
+                    params = iceParams;
+                    iceParams->enableRTPOverICE = true;
+                    iceParams->enableTURN = mImplPriv->mNatOptions.enableTURN;
+                }
+                else
+                {
+                    params = new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams;
+                }
+
+                params->category = "rtp";
+                params->formats = formats;
+
+                // See what address family the connection address is in so we can request the right RTP service
+                if (connection.find(":") != std::string::npos)
+                {
+                    params->ipv6 = true;
+                }
+                else
+                {
+                    params->ipv6 = false;
+                }
+
+                // Try to find a factory for RTP sessions matching what we need
+                RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+
+                // If none exist we can't provide accept the stream
+                if (factory == 0)
+                {
+                    // The only time this should ever occur is on the initial INVITE so removing the stream from everywhere
+                    // is perfectly acceptable since nothing has seen it
+                    mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
+                    newStreams.erase(boost::lexical_cast<std::string>(stream));
+                    continue;
+                }
+
+                // Allocate a new RTP session to carry the media formats we have in common
+                session = factory->allocate(params);
+
+                // Double check to make sure they actually gave us a sesson back... they could have had a problem
+                if (session == 0)
+                {
+                    // The only time this should ever occur is on the initial INVITE so removing the stream from everywhere
+                    // is perfectly acceptable since nothing has seen it
+                    mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
+                    newStreams.erase(boost::lexical_cast<std::string>(stream));
+                    continue;
+                }
+
+                // RTP sessions only provide a single sink and source so that makes this easy
+                StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
+                mImplPriv->mSinks.push_back(sink);
+                ourStream->sinks.push_back(sink);
+
+                StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+                mImplPriv->mSources.push_back(source);
+                ourStream->sources.push_back(source);
+
+                // Update the SIP session with some RTP session details
+                mImplPriv->mRTPSessions.push_back(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
+                pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+                mImplPriv->mSDP->media[mImplPriv->mSDP->media_count++] = media;
+
+                // Since our stream should be like the offering stream we can just use some values from there
+                media->desc.media = offer->media[stream]->desc.media;
+                media->desc.transport = offer->media[stream]->desc.transport;
+
+                // Add connection level information so they know our IP address
+                media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+                media->conn->net_type = offer->origin.net_type;
+                media->conn->addr_type = offer->origin.addr_type;
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+
+                // If session level connection information has not yet been set then set it to us
+                if (!mImplPriv->mSDP->conn)
+                {
+                    mImplPriv->mSDP->conn = media->conn;
+                }
+
+                // Add port information so they can talk to us
+                media->desc.port = (pj_uint16_t) source->getLocalPort();
+                media->desc.port_count = 1;
+
+                PayloadMap payloads;
+
+                addFormatstoSDP(formats, media, payloads);
+
+                // Push the payload mapping to the RTP session so it'll correctly map things
+                session->associatePayloads(payloads);
             }
-            else
+
+            // If the RTP session supports RTCP determine the connection details for it
+            RTCP::V1::RTCPSessionPrx rtcpSession;
+            if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
             {
-                params->ipv6 = false;
-            }
+                // Assume RTCP is destined for the same address and the RTP port + 1 as it probably is
+                std::string rtcpConnection = connection;
+                int rtcpPort = offer->media[stream]->desc.port + 1;
 
-            // Try to find a factory for RTP sessions matching what we need
-            RTPMediaServicePrx factory = RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
+                pjmedia_sdp_attr *attr;
+                pjmedia_sdp_rtcp_attr rtcpAttr;
 
-            // If none exist we can't provide accept the stream
-            if (factory == 0)
-            {
-                // The only time this should ever occur is on the initial INVITE so removing the stream from everywhere
-                // is perfectly acceptable since nothing has seen it
-                mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
-                newStreams.erase(boost::lexical_cast<std::string>(stream));
-                continue;
+                if ((attr = pjmedia_sdp_media_find_attr2(offer->media[stream], "rtcp", NULL)) &&
+                    (pjmedia_sdp_attr_get_rtcp(attr, &rtcpAttr) == PJ_SUCCESS))
+                {
+                    rtcpPort = rtcpAttr.port;
+
+                    if (rtcpAttr.addr.slen)
+                    {
+                        rtcpConnection = std::string(pj_strbuf(&rtcpAttr.addr), pj_strlen(&rtcpAttr.addr));
+                    }
+                }
+
+                rtcpSession->setRemoteDetails(rtcpConnection, rtcpPort);
             }
 
-            // Allocate a new RTP session to carry the media formats we have in common
-            session = factory->allocate(params);
+            // Update connection information
+            StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(ourStream->sinks.front());
 
-            // Double check to make sure they actually gave us a sesson back... they could have had a problem
-            if (session == 0)
+            // If the remote party attempts to use an invalid address bring down the session since obviously
+            // something is critically wrong and stuff will most likely fall apart quickly
+            try
             {
-                // The only time this should ever occur is on the initial INVITE so removing the stream from everywhere
-                // is perfectly acceptable since nothing has seen it
-                mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
-                newStreams.erase(boost::lexical_cast<std::string>(stream));
-                continue;
+                sink->setRemoteDetails(connection, offer->media[stream]->desc.port);
+            }
+            catch (const AsteriskSCF::Media::RTP::V1::InvalidAddress&)
+            {
+                pjsip_tx_data *packet;
+                if (pjsip_inv_end_session(mImplPriv->mInviteSession, 488, NULL, &packet) == PJ_SUCCESS)
+                {
+                    pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
+                }
+                return 0;
             }
+        }
+        else if ((t38 = T38UdptlFormatPtr::dynamicCast(formats.front())))
+        {
+            if (ourStream->sinks.empty() && ourStream->sources.empty())
+            {
+                UDPTLServiceLocatorParamsPtr params = new UDPTLServiceLocatorParams();
+                params->category = "udptl";
 
-            // RTP sessions only provide a single sink and source so that makes this easy
-            StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(session->getSinks().front());
-            mImplPriv->mSinks.push_back(sink);
-            ourStream->sinks.push_back(sink);
+                if (connection.find(":") != std::string::npos)
+                {
+                    params->ipv6 = true;
+                }
+                else
+                {
+                    params->ipv6 = false;
+                }
 
-            StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
-            mImplPriv->mSources.push_back(source);
-            ourStream->sources.push_back(source);
+                UDPTLMediaServicePrx factory = UDPTLMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
 
-            // Update the SIP session with some RTP session details
-            mImplPriv->mRTPSessions.push_back(session);
+                if (factory == 0)
+                {
+                    mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
+                    newStreams.erase(boost::lexical_cast<std::string>(stream));
+                    continue;
+                }
 
-            // 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
-            pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
-            mImplPriv->mSDP->media[mImplPriv->mSDP->media_count++] = media;
+                UDPTLSessionPrx session = factory->allocate(params);
 
-            // Since our stream should be like the offering stream we can just use some values from there
-            media->desc.media = offer->media[stream]->desc.media;
-            media->desc.transport = offer->media[stream]->desc.transport;
+                if (session == 0)
+                {
+                    mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
+                    newStreams.erase(boost::lexical_cast<std::string>(stream));
+                    continue;
+                }
 
-            // Add connection level information so they know our IP address
-            media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
-            media->conn->net_type = offer->origin.net_type;
-            media->conn->addr_type = offer->origin.addr_type;
-            pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
+                StreamSinkUDPTLPrx sink = StreamSinkUDPTLPrx::uncheckedCast(session->getSinks().front());
+                mImplPriv->mSinks.push_back(sink);
+                ourStream->sinks.push_back(sink);
 
-            // If session level connection information has not yet been set then set it to us
-            if (!mImplPriv->mSDP->conn)
-            {
-                mImplPriv->mSDP->conn = media->conn;
-            }
+                StreamSourceUDPTLPrx source = StreamSourceUDPTLPrx::uncheckedCast(session->getSources().front());
+                mImplPriv->mSources.push_back(source);
+                ourStream->sources.push_back(source);
 
-            // Add port information so they can talk to us
-            media->desc.port = (pj_uint16_t) source->getLocalPort();
-            media->desc.port_count = 1;
+                mImplPriv->mUDPTLSessions.push_back(session);
 
-            PayloadMap payloads;
+                pjmedia_sdp_media *media = allocate_from_pool<pjmedia_sdp_media>(mImplPriv->mDialog->pool);
+                mImplPriv->mSDP->media[mImplPriv->mSDP->media_count++] = media;
 
-            addFormatstoSDP(formats, media, payloads);
+                media->desc.media = offer->media[stream]->desc.media;
+                media->desc.transport = offer->media[stream]->desc.transport;
 
-            // Push the payload mapping to the RTP session so it'll correctly map things
-            session->associatePayloads(payloads);
-        }
+                media->conn = allocate_from_pool<pjmedia_sdp_conn>(mImplPriv->mDialog->pool);
+                media->conn->net_type = offer->origin.net_type;
+                media->conn->addr_type = offer->origin.addr_type;
+                pj_strdup2(mImplPriv->mDialog->pool, &media->conn->addr, source->getLocalAddress().c_str());
 
-        // Record the old state so we can relay the state change to the controller if needed
-        StreamState oldState = ourStream->state;
-        
-        // Determine the state of the stream and update it
-	if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendonly", NULL))
-        {
-            ourStream->state = SendOnly;
-        }
-        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "recvonly", NULL))
-        {
-            ourStream->state = ReceiveOnly;
-        }
-        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "inactive", NULL))
-        {
-            ourStream->state = Inactive;
-        }
-        else if (pjmedia_sdp_media_find_attr2(offer->media[stream], "sendrecv", NULL))
-        {
-            ourStream->state = SendAndReceive;
-        }
+                if (!mImplPriv->mSDP->conn)
+                {
+                    mImplPriv->mSDP->conn = media->conn;
+                }
 
-        // If the RTP session supports RTCP determine the connection details for it
-        RTCP::V1::RTCPSessionPrx rtcpSession;
-        if ((rtcpSession = RTCP::V1::RTCPSessionPrx::checkedCast(session, RTCP::V1::SessionFacet)))
-        {
-            // Assume RTCP is destined for the same address and the RTP port + 1 as it probably is
-            std::string rtcpConnection = connection;
-            int rtcpPort = offer->media[stream]->desc.port + 1;
+                media->desc.port = (pj_uint16_t) source->getLocalPort();
+                media->desc.port_count = 1;
 
-            pjmedia_sdp_attr *attr;
-            pjmedia_sdp_rtcp_attr rtcpAttr;
+                SDPDescriptorPtr ourDescriptor = mImplPriv->mEndpoint->getDescriptor(t38);
+                for (SDPFormatParameterSeq::const_iterator parameter = ourDescriptor->parameters.begin();
+                     parameter != ourDescriptor->parameters.end();
+                     ++parameter)
+                {
+                    pjmedia_sdp_attr *attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+                    pj_strdup2(mImplPriv->mDialog->pool, &attr->name, (*parameter).c_str());
+                    media->attr[media->attr_count++] = attr;
+                }
+            }
 
-            if ((attr = pjmedia_sdp_media_find_attr2(offer->media[stream], "rtcp", NULL)) &&
-                (pjmedia_sdp_attr_get_rtcp(attr, &rtcpAttr) == PJ_SUCCESS))
+            StreamSinkUDPTLPrx sink = StreamSinkUDPTLPrx::uncheckedCast(ourStream->sinks.front());
+            try
             {
-                rtcpPort = rtcpAttr.port;
-
-                if (rtcpAttr.addr.slen)
+                sink->setRemoteDetails(connection, offer->media[stream]->desc.port);
+            }
+            catch (const AsteriskSCF::Media::UDPTL::V1::InvalidAddress&)
+            {
+                pjsip_tx_data *packet;
+                if (pjsip_inv_end_session(mImplPriv->mInviteSession, 488, NULL, &packet) == PJ_SUCCESS)
                 {
-                    rtcpConnection = std::string(pj_strbuf(&rtcpAttr.addr), pj_strlen(&rtcpAttr.addr));
+                    pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
                 }
+                return 0;
             }
-
-            rtcpSession->setRemoteDetails(rtcpConnection, rtcpPort);
+        }
+        else
+        {
+            // The type of this stream is just unknown to us, we can not accept it
+            mImplPriv->mStreams.erase(boost::lexical_cast<std::string>(stream));
+            newStreams.erase(boost::lexical_cast<std::string>(stream));
+            continue;
         }
 
         // If the state changed we need to notify the controller if one is around
@@ -2473,25 +2714,6 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
         {
             streamsChanged.insert(make_pair(boost::lexical_cast<std::string>(stream), ourStream->state));
         }
-
-        // Update connection information
-        StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(ourStream->sinks.front());
-
-        // If the remote party attempts to use an invalid address bring down the session since obviously
-        // something is critically wrong and stuff will most likely fall apart quickly
-        try
-        {
-            sink->setRemoteDetails(connection, offer->media[stream]->desc.port);
-        }
-        catch (const InvalidAddress&)
-        {
-            pjsip_tx_data *packet;
-            if (pjsip_inv_end_session(mImplPriv->mInviteSession, 488, NULL, &packet) == PJ_SUCCESS)
-            {
-                pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
-            }
-            return 0;
-        }
     }
 
     if (mImplPriv->mSessionController)
@@ -2780,6 +3002,14 @@ RTPMediaSessionSeq SipSession::getRTPMediaSessions()
 }
 
 /**
+ * Internal function which returns the UDPTL media sessions that are hidden inside the SIP session.
+ */
+UDPTLMediaSessionSeq SipSession::getUDPTLMediaSessions()
+{
+    return mImplPriv->mUDPTLSessions;
+}
+
+/**
  * Internal function which sets the streams explicitly.
  */
 void SipSession::setStreams(const AsteriskSCF::Media::V1::StreamInformationDict& streams)
diff --git a/src/SipSession.h b/src/SipSession.h
index 8da0248..515682f 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -311,6 +311,8 @@ public:
 
     AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq getRTPMediaSessions();
 
+    AsteriskSCF::Replication::SipSessionManager::V1::UDPTLMediaSessionSeq getUDPTLMediaSessions();
+
     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
 
     void setTelephonyEventSourcesAndSinks(const SipEndpointConfig& config);

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list