[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