[asterisk-scf-commits] asterisk-scf/integration/sip.git branch "session-decorator" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Jul 13 09:48:20 CDT 2011


branch "session-decorator" has been updated
       via  26ec91cf1ad7ae654b38a57e355d85cd7b2a6495 (commit)
       via  c36e88cc66b3a9f5e5cce710df4359e88079d9d9 (commit)
       via  fc8f71159530653f06e3217ec733058ce033d4fb (commit)
       via  7d43289b0a830b2c545b4509ca3df7d8dd510186 (commit)
      from  b41a0dc88850f05a29d0adbf62016e22e625a26e (commit)

Summary of changes:
 config/Sip.config                                  |    4 +-
 config/SipConfigurator.py                          |   22 +
 .../SipSessionManager/SipConfigurationIf.ice       |   44 ++-
 .../SipSessionManager/SipStateReplicationIf.ice    |    6 +-
 src/PJSipSessionModule.cpp                         |  171 +++----
 src/SipConfiguration.cpp                           |   10 +
 src/SipEndpoint.cpp                                |  222 ++++++++-
 src/SipEndpoint.h                                  |   28 +-
 src/SipSession.cpp                                 |  564 +++++++++++++++----
 src/SipSession.h                                   |   22 +-
 src/SipStateReplicatorListener.cpp                 |    2 +-
 11 files changed, 856 insertions(+), 239 deletions(-)


- Log -----------------------------------------------------------------
commit 26ec91cf1ad7ae654b38a57e355d85cd7b2a6495
Merge: c36e88c fc8f711
Author: Mark Michelson <mmichelson at digium.com>
Date:   Wed Jul 13 09:43:48 2011 -0500

    Merge branch 'master' into session-decorator

diff --cc src/PJSipSessionModule.cpp
index 41cf906,7128453..294a8f6
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@@ -26,8 -26,9 +26,10 @@@
  #include <AsteriskSCF/Core/Endpoint/EndpointIf.h>
  #include <AsteriskSCF/Core/Routing/RoutingIf.h>
  #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 +#include <AsteriskSCF/SessionCommunications/SessionCommunicationsExtensionPointsIf.h>
  #include <AsteriskSCF/Media/MediaIf.h>
+ #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+ #include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
  #include <AsteriskSCF/logger.h>
  #include <AsteriskSCF/WorkQueue/WorkQueue.h>
  #include <AsteriskSCF/WorkQueue/SuspendableWorkQueue.h>
@@@ -53,8 -54,9 +55,10 @@@ namespace SipSessionManage
  using namespace AsteriskSCF::Core::Routing::V1;
  using namespace AsteriskSCF::Core::Endpoint::V1;
  using namespace AsteriskSCF::SessionCommunications::V1;
 +using namespace AsteriskSCF::SessionCommunications::ExtensionPoints::V1;
  using namespace AsteriskSCF::Media::V1;
+ using namespace AsteriskSCF::Media::RTP::V1;
+ using namespace AsteriskSCF::Media::SDP::V1;
  using namespace AsteriskSCF::Replication::SipSessionManager::V1;
  using namespace AsteriskSCF::System::ThreadPool::V1;
  using namespace AsteriskSCF::System::WorkQueue::V1;
diff --cc src/SipSession.cpp
index c32f64e,6210963..0b54281
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@@ -390,14 -375,15 +415,14 @@@ SipSession::SipSession(const Ice::Objec
   * Replica constructor.
   */
  SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
-         const std::string& destination, const Ice::Identity& sessionid,
-         const Ice::Identity& mediaid, const AsteriskSCF::Media::V1::SessionPrx& mediasession,
-         const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
-         PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-         const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
+                        const std::string& destination, const Ice::Identity& sessionid,
+                        const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                        const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
+                        PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+                        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
      : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
  {
 -    mImplPriv->mSessionProxy =
 -        AsteriskSCF::SessionCommunications::V1::SessionPrx::uncheckedCast(adapter->add(this, sessionid));
 +    activateIceObjects(mImplPriv->mManager->getSessionModule()->getSessionDecoratorHooks());
  
      mImplPriv->mMediaSession = new SipMediaSession(this);
      mImplPriv->mMediaSessionProxy =

commit c36e88cc66b3a9f5e5cce710df4359e88079d9d9
Author: Mark Michelson <mmichelson at digium.com>
Date:   Tue Jul 12 18:07:36 2011 -0500

    Adjust for new slice API for session decorator.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 96efd1f..c32f64e 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -236,7 +236,7 @@ public:
     /**
      * A vector of listeners that want to be notified of responses from the SIP endpoint.
      */
-    std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> mListeners;
+    AsteriskSCF::SessionCommunications::V1::SessionListenerSeq mListeners;
 
     /**
      * A proxy to the bridge that this session is currently in.
@@ -329,11 +329,12 @@ void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::Ex
             iter != hooks.end(); ++iter)
     {
         AsteriskSCF::SessionCommunications::V1::SessionPrx decorator;
+        AsteriskSCF::SessionCommunications::V1::SessionListenerPrx decoratorListener;
         AsteriskSCF::System::Hook::V1::HookResult result;
 
         try
         {
-            result = (*iter)->decorateSession(mImplPriv->mSessionProxy, decorator);
+            result = (*iter)->decorateSession(mImplPriv->mSessionProxy, mImplPriv->mListeners, decorator, decoratorListener);
         }
         catch (const Ice::Exception& ex)
         {
@@ -346,6 +347,8 @@ void SipSession::activateIceObjects(const AsteriskSCF::SessionCommunications::Ex
         {
             lg(Debug) << "Setting our session proxy to be the decorator " << decorator->ice_getIdentity().name;
             mImplPriv->mSessionDecoratorProxy = decorator;
+            mImplPriv->mListeners.clear();
+            mImplPriv->mListeners.push_back(decoratorListener);
             decoratorSet = true;
             break;
         }
@@ -1274,7 +1277,7 @@ AsteriskSCF::Media::V1::StreamSinkSeq& SipSession::getSinks()
 /**
  * Internal function which gets the listeners on this session.
  */
-std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> SipSession::getListeners()
+AsteriskSCF::SessionCommunications::V1::SessionListenerSeq SipSession::getListeners()
 {
     return mImplPriv->mListeners;
 }

commit fc8f71159530653f06e3217ec733058ce033d4fb
Author: Joshua Colp <jcolp at digium.com>
Date:   Sun Jul 10 11:50:10 2011 -0300

    Merge revised media design implementation.

diff --git a/config/Sip.config b/config/Sip.config
index 176d796..ac8e349 100644
--- a/config/Sip.config
+++ b/config/Sip.config
@@ -79,4 +79,6 @@ direction=both
 securetransport=none
 # Whether to use IPv6 for media transport or not
 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
diff --git a/config/SipConfigurator.py b/config/SipConfigurator.py
index 7db7217..1d34378 100755
--- a/config/SipConfigurator.py
+++ b/config/SipConfigurator.py
@@ -157,6 +157,28 @@ class SipSectionVisitors(Configurator.SectionVisitors):
             mapper.execute(group, section, option)
         mapper.finish(group)
 
+        try:
+            formats = config.get(section, 'formats')
+            configuredFormats = formats.split(',')
+            for format in configuredFormats:
+                name, found, rest = format.partition('/')
+                sampleRate, found, rest = rest.partition('@')
+                frameSize, found, formatSpecific = rest.partition(';')
+
+                item = AsteriskSCF.Configuration.SipSessionManager.V1.SipMediaFormatItem()
+                item.name = name
+                if sampleRate:
+                    item.sampleRate = sampleRate
+                if frameSize:
+                    item.frameSize = frameSize
+                item.formatSpecific = [ ]
+                if formatSpecific:
+                    item.formatSpecific.append(formatSpecific)
+
+                group.configurationItems[format] = item
+        except:
+            print 'No configured formats for endpoint ' + section
+
         self.groups.append(group)
 
     def visit_unsupported(self, config, section):
diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index ed2dbe3..f37030d 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -362,6 +362,36 @@ module V1
    };
 
    /**
+    * Allowable media format item
+    */
+   class SipMediaFormatItem extends SipConfigurationItem
+   {
+       /**
+        * Name of the media format
+        */
+       string name;
+
+       /**
+        * Sample rate for frames
+        *
+        * This is specified in Hz and has a default value of 8000. 
+        */
+       int sampleRate = 8000;
+
+       /**
+        * Amount of audio in frames
+        *
+        * This is specified in 
+        */
+       int frameSize;
+
+       /**
+        * Any format specific parameters
+        */
+       Ice::StringSeq formatSpecific;
+   };
+
+   /**
     * User agent presentation configuration item
     */
    class SipUserAgentItem extends SipConfigurationItem
diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index 5e613db..605b249 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -18,6 +18,7 @@
 #include <Ice/BuiltinSequences.ice>
 #include <Ice/Identity.ice>
 #include <AsteriskSCF/Media/MediaIf.ice>
+#include <AsteriskSCF/Media/RTP/MediaRTPIf.ice>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.ice>
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.ice>
 #include <AsteriskSCF/System/Component/ConfigurationIf.ice>
@@ -142,8 +143,7 @@ module V1
 
    sequence<AsteriskSCF::SessionCommunications::V1::SessionListener*> SessionListenerSeq;
 
-   // Should this exist within MediaIf.ice? Are we going to pass around a sequence of sessions elsewhere?
-   //sequence<AsteriskSCF::Media::V1::Session*> MediaSessionSeq;
+   sequence<AsteriskSCF::Media::RTP::V1::RTPSession*> RTPMediaSessionSeq;
 
    class SipSessionStateItem extends SipStateItem
    {
@@ -154,7 +154,7 @@ module V1
       Ice::Identity mMediaSessionObjectId;
       AsteriskSCF::Media::V1::StreamSourceSeq mSources;
       AsteriskSCF::Media::V1::StreamSinkSeq mSinks;
-      AsteriskSCF::Media::V1::Session *mMediaSession;
+      RTPMediaSessionSeq mRTPMediaSessions;
       SessionListenerSeq mListeners;
       AsteriskSCF::SessionCommunications::V1::Bridge *mBridge;
       AsteriskSCF::SessionCommunications::V1::SessionCookieDict mCookies;
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index b6719d5..7128453 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -27,6 +27,8 @@
 #include <AsteriskSCF/Core/Routing/RoutingIf.h>
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 #include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 #include <AsteriskSCF/logger.h>
 #include <AsteriskSCF/WorkQueue/WorkQueue.h>
 #include <AsteriskSCF/WorkQueue/SuspendableWorkQueue.h>
@@ -53,6 +55,8 @@ using namespace AsteriskSCF::Core::Routing::V1;
 using namespace AsteriskSCF::Core::Endpoint::V1;
 using namespace AsteriskSCF::SessionCommunications::V1;
 using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::Media::RTP::V1;
+using namespace AsteriskSCF::Media::SDP::V1;
 using namespace AsteriskSCF::Replication::SipSessionManager::V1;
 using namespace AsteriskSCF::System::ThreadPool::V1;
 using namespace AsteriskSCF::System::WorkQueue::V1;
@@ -94,7 +98,7 @@ void PJSipSessionModInfo::updateSessionState(pjsip_inv_session *inv_session)
         mSessionState->mMediaSessionObjectId = mSession->getMediaSessionProxy()->ice_getIdentity();
         mSessionState->mSources = mSession->getSources();
         mSessionState->mSinks = mSession->getSinks();
-        mSessionState->mMediaSession = mSession->getHiddenMediaSession();
+        mSessionState->mRTPMediaSessions = mSession->getRTPMediaSessions();
         mSessionState->mListeners = mSession->getListeners();
         try
         {
@@ -214,7 +218,14 @@ void PJSipSessionModule::replicateState(PJSipDialogModInfo *dlgInfo, PJSipTransa
         lg(Debug) << "Endpoint name: " << sessionInfo->mSessionState->mEndpointName;
         lg(Debug) << "Session object identity: " << sessionInfo->mSessionState->mSessionObjectId.name;
         lg(Debug) << "Media session object identity: " << sessionInfo->mSessionState->mMediaSessionObjectId.name;
-        lg(Debug) << "Media session: " << sessionInfo->mSessionState->mMediaSession;
+
+	for (RTPMediaSessionSeq::const_iterator mediaSession = sessionInfo->mSessionState->mRTPMediaSessions.begin();
+             mediaSession != sessionInfo->mSessionState->mRTPMediaSessions.end();
+             ++mediaSession)
+        {
+            lg(Debug) << "Media session: " << (*mediaSession);
+        }
+
         lg(Debug) << "Bridge: " << sessionInfo->mSessionState->mBridge;
         lg(Debug) << "--- Begin Invite Session " << sessionInfo->mInviteState->key;
         lg(Debug) << "Current state: " << sessionInfo->mInviteState->mCurrentState;
@@ -352,8 +363,37 @@ protected:
             pjsip_inv_send_msg(mInv, mTdata);
             return Complete;
         }
-        mSession->setInviteSession(mInv);
-        mSession->setDialog(mInv->dlg);
+
+	mSession->setInviteSession(mInv);
+	mSession->setDialog(mInv->dlg);
+
+        // Create an SDP offer or answer
+	const pjmedia_sdp_session *remote_sdp = NULL;
+        pjmedia_sdp_session *sdp;
+
+	if (!mInv->neg || (pjmedia_sdp_neg_get_neg_remote(mInv->neg, &remote_sdp) != PJ_SUCCESS))
+        {
+            // No SDP was present in the INVITE so we need to create an offer
+            sdp = mSession->createSDPOffer();
+        }
+        else
+        {
+            // SDP was present in the INVITE so we need to create an answer using their offer
+            sdp = mSession->createSDPAnswer(remote_sdp);
+        }
+
+        if (!sdp)
+        {
+            // If no SDP was created we can not accept this INVITE
+            lg(Error) << "No compatible formats found in offer\n";
+            pjsip_inv_end_session(mInv, 488, NULL, &mTdata);
+            pjsip_inv_send_msg(mInv, mTdata);
+            return Complete;
+        }
+
+	// Provide the produced SDP as our offer or answer
+	pjsip_inv_set_sdp_answer(mInv, sdp);
+
         PJSipDialogModInfo *dlg_mod_info =(PJSipDialogModInfo*)mInv->dlg->mod_data[mSessionModule->getModule().id];
         PJSipTransactionModInfo *tsx_mod_info = (PJSipTransactionModInfo *)mInv->invite_tsx->mod_data[mSessionModule->getModule().id];
         PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mSessionModule->getModule().id];
@@ -571,6 +611,8 @@ void PJSipSessionModule::handleNewInvite(pjsip_rx_data *rdata)
         destination = std::string(pj_strbuf(&sipRuri->user), pj_strlen(&sipRuri->user));
         lg(Debug) << "Call is destined for " << destination;
     }
+
+    // See if any SDP was present on this INVITE
     
     lg(Debug) << "Queueing a SessionCreationOperation";
     sessionWork->enqueueWork(new SessionCreationOperation(this, caller, mSessionRouter, inv_session, tdata, replaced_dlg, destination));
@@ -1387,108 +1429,55 @@ protected:
 	    return Complete;
         }
 
-        const pjmedia_sdp_conn *remote_conn = remote_sdp->media[0]->conn ? remote_sdp->media[0]->conn : remote_sdp->conn;
-
         PJSipSessionModInfo *session_mod_info = (PJSipSessionModInfo*)mInv->mod_data[mModuleId];
         SipSessionPtr session = session_mod_info->getSessionPtr();
-        std::string destination(pj_strbuf(&remote_conn->addr), pj_strlen(&remote_conn->addr));
 
-	try
-	{
-	    session->setRemoteDetails(destination, remote_sdp->media[0]->desc.port);
-	}
-	catch (const AsteriskSCF::Media::RTP::V1::InvalidAddress&)
-	{
-	    pjsip_tx_data *packet;
-            if (pjsip_inv_end_session(mInv, 488, NULL, &packet) == PJ_SUCCESS)
-            {
-                pjsip_inv_send_msg(mInv, packet);
-            }
-            return Complete;
-	}
+        // In case there is no stream level connection details store this away
+        std::string destination(pj_strbuf(&remote_sdp->conn->addr), pj_strlen(&remote_sdp->conn->addr));
+
+	StreamSinkSeq sinks = session->getSinks();
 
         // Each stream has its own set of formats, so go to that granularity
         for (unsigned int stream = 0; stream < remote_sdp->media_count; stream++)
         {
-            // We should have the parsing of the connection information here
-
-            // We should have the parsing of the rtcp attribute here
-
-            FormatSeq formats;
-
-            // Next step is to see what formats exist on this stream
-            for (unsigned int format = 0; format < remote_sdp->media[stream]->desc.fmt_count; format++)
+	    // Do some sanity checking to confirm we have a stream setup for their answer stream
+            if (sinks.size() < (stream + 1))
             {
-                FormatDiscoverySDPPtr params = new FormatDiscoverySDP();
-                params->category = "media_format";
-                std::stringstream(pj_strbuf(&remote_sdp->media[stream]->desc.fmt[format])) >> params->payload;
-                params->type = std::string(pj_strbuf(&remote_sdp->media[stream]->desc.media),
-                        pj_strlen(&remote_sdp->media[stream]->desc.media));
-
-                // Some devices rely solely on the payload for known formats (such as PCMU) so the following format
-                // parameters are optional
-                const pjmedia_sdp_attr *attr;
-                if ((attr = pjmedia_sdp_media_find_attr2(remote_sdp->media[stream], "rtpmap",
-                                        &remote_sdp->media[stream]->desc.fmt[format])))
-                {
-                    pjmedia_sdp_rtpmap *rtpmap;
-                    if ((pjmedia_sdp_attr_to_rtpmap(mInv->pool_active, attr, &rtpmap)) == PJ_SUCCESS)
-                    {
-                        params->subtype = std::string(pj_strbuf(&rtpmap->enc_name), pj_strlen(&rtpmap->enc_name));
-                        params->samplerate = rtpmap->clock_rate;
-                    }
-                }
-
-                // Next we move on to the format specific parameters
-                if ((attr = pjmedia_sdp_media_find_attr2(remote_sdp->media[stream], "fmtp",
-                                        &remote_sdp->media[stream]->desc.fmt[format])))
-                {
-                    pjmedia_sdp_fmtp fmtp;
-                    if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS)
-                    {
-                        std::string parameter = std::string(pj_strbuf(&fmtp.fmt_param), pj_strlen(&fmtp.fmt_param));
-                        params->parameters.push_back(parameter);
-                    }
-                }
+                continue;
+            }
 
-                // Next up are attributes that are not specific to the format, such as ptime
-                for (unsigned int attribute = 0; attribute < remote_sdp->media[stream]->attr_count; attribute++)
-                {
-                    // Attributes we already touch above OR know aren't helpful to the media format component don't need to
-                    // be given to it, obviously
-                    if (!pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "rtpmap") ||
-                        !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "fmtp") ||
-                        !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "rtcp") ||
-                        !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "sendrecv") ||
-                        !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "sendonly") ||
-                        !pj_strcmp2(&remote_sdp->media[stream]->attr[attribute]->name, "recvonly"))
-                    {
-                        continue;
-                    }
+            // Assume no stream level details until proven otherwise
+            std::string connection = destination;
+            if (remote_sdp->media[stream]->conn)
+            {
+                connection = std::string(pj_strbuf(&remote_sdp->media[stream]->conn->addr),
+                                         pj_strlen(&remote_sdp->media[stream]->conn->addr));
+            }
 
-                    std::string parameter = std::string(pj_strbuf(&remote_sdp->media[stream]->attr[attribute]->name),
-                            pj_strlen(&remote_sdp->media[stream]->attr[attribute]->name)) + ':' +
-                        std::string(pj_strbuf(&remote_sdp->media[stream]->attr[attribute]->value),
-                                pj_strlen(&remote_sdp->media[stream]->attr[attribute]->value));
-                    params->parameters.push_back(parameter);
-                }
+            // TODO: Add parsing of RTCP attribute
 
-                try
-                {
-                    MediaFormatServicePrx service = MediaFormatServicePrx::uncheckedCast(mServiceLocator->locate(params));
+            // The order of the media lines should match our offer so we can get the sink to update
+            // connection details on based on what stream number this is, easy!
+            StreamSinkRTPPrx sink = StreamSinkRTPPrx::uncheckedCast(sinks[stream]);
 
-                    // It is entirely possible for the service locator to not find a service that knows about this media
-                    // format
-                    if (service != 0)
-                    {
-                        formats.push_back(FormatPtr::dynamicCast(service->getFormat(params)));
-                    }
-                }
-                catch (...)
+            // If this throws an exception then they answered with an address that is incompatible
+            // for the session, so we abort since our relationship with the other side seems to be
+            // broken
+            try
+            {
+                sink->setRemoteDetails(connection, remote_sdp->media[stream]->desc.port);
+            }
+            catch (const InvalidAddress&)
+            {
+                pjsip_tx_data *packet;
+                if (pjsip_inv_end_session(mInv, 488, NULL, &packet) == PJ_SUCCESS)
                 {
-                    // If we get here the format just isn't supported...
+                    pjsip_inv_send_msg(mInv, packet);
                 }
+                return Complete;
             }
+
+            // TODO: Add format parsing stuff here so we can determine the formats actually negotiated
         }
         return Complete;
     }
diff --git a/src/SipConfiguration.cpp b/src/SipConfiguration.cpp
index a9ed619..d4077a8 100644
--- a/src/SipConfiguration.cpp
+++ b/src/SipConfiguration.cpp
@@ -183,6 +183,11 @@ class EndpointConfigHelper : public boost::enable_shared_from_this<EndpointConfi
         {
             mUpdates.push_back(boost::bind(&EndpointConfigHelper::updateDirection, mConfig, direction));
         }
+
+	void visitSipMediaFormatItem(const SipMediaFormatItemPtr& format)
+	{
+            mUpdates.push_back(boost::bind(&EndpointConfigHelper::addFormat, mConfig, format));
+	}
         
         void visitSipSourceTransportAddressItem(const SipSourceTransportAddressItemPtr& source)
         {
@@ -258,6 +263,11 @@ public:
         mEndpoint->setCallDirection(translateCallDirection(direction->callDirection));
     }
 
+    void addFormat(const SipMediaFormatItemPtr& format)
+    {
+	mEndpoint->addFormat(format->name, format->sampleRate, format->frameSize, format->formatSpecific);
+    }
+
     void updateSource(const SipSourceTransportAddressItemPtr& source)
     {
         mEndpoint->setSourceAddress(source->host, source->port);
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index 2a6af1a..ac3518a 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -21,8 +21,13 @@
 
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
 #include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 
 using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::Media::SDP::V1;
+using namespace AsteriskSCF::Core::Discovery::V1;
 
 namespace
 {
@@ -35,6 +40,121 @@ namespace SipSessionManager
 {
 
 /**
+ * Class used to store information about the configured formats.
+ */
+class ConfiguredFormat : public IceUtil::Shared
+{
+public:
+    ConfiguredFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific) :
+        mName(name), mSampleRate(sampleRate), mFrameSize(frameSize), mFormatSpecific(formatSpecific), mAvailable(false) { }
+
+    void locateCB(const Ice::ObjectPrx& service)
+    {
+        // Store away the descriptor service proxy for future use
+        mDescriptorService = SDPDescriptorServicePrx::uncheckedCast(service);
+
+	// Setup an AMI request to get the named format
+        Callback_SDPDescriptorService_getNamedFormatPtr descriptorCB = newCallback_SDPDescriptorService_getNamedFormat(
+            this, &ConfiguredFormat::getNamedFormatCB, &ConfiguredFormat::getNamedFormatFailureCB);
+
+	// Send it off
+	mDescriptorService->begin_getNamedFormat(mName, mSampleRate, mFrameSize, mFormatSpecific, descriptorCB);
+    }
+
+    void locateFailureCB(const Ice::Exception&)
+    {
+    }
+
+    void getNamedFormatCB(const FormatPtr& format)
+    {
+	// Store away the format
+	mFormat = format;
+
+	// Setup an AMI request to get the SDP descriptor
+        Callback_SDPDescriptorService_getDescriptorPtr descriptorCB = newCallback_SDPDescriptorService_getDescriptor(
+            this, &ConfiguredFormat::getDescriptorCB, &ConfiguredFormat::getDescriptorFailureCB);
+
+        // Send it off
+        mDescriptorService->begin_getDescriptor(mFormat, descriptorCB);
+    }
+
+    void getNamedFormatFailureCB(const Ice::Exception&)
+    {
+    }
+
+    void getDescriptorCB(const SDPDescriptorPtr& descriptor)
+    {
+	// Store it away
+	mDescriptor = descriptor;
+
+	// This configured format is now available for use
+	mAvailable = true;
+    }
+
+    void getDescriptorFailureCB(const Ice::Exception&)
+    {
+    }
+
+    SDPDescriptorServicePrx getDescriptorService()
+    {
+        return mDescriptorService;
+    }
+
+    SDPDescriptorPtr getDescriptor()
+    {
+        return mDescriptor;
+    }
+
+    FormatPtr getFormat()
+    {
+        return mFormat;
+    }
+
+private:
+    /**
+     * Name of the media format.
+     */
+    std::string mName;
+
+    /**
+     * Sample rate of the media.
+     */
+    int mSampleRate;
+
+    /**
+     * Size of the media frames.
+     */
+    int mFrameSize;
+
+    /**
+     * Format specific parameters.
+     */
+    Ice::StringSeq mFormatSpecific;
+
+    /**
+     * Whether this configured format is available or not.
+     */
+    bool mAvailable;
+
+    /**
+     * SDP descriptor service for this media format.
+     */
+    SDPDescriptorServicePrx mDescriptorService;
+
+    /**
+     * Media format concrete class, retrieved from SDP descriptor service.
+     */
+    FormatPtr mFormat;
+
+    /**
+     * SDP descriptor class, retrieved from the SDP descriptor service.
+     */
+    SDPDescriptorPtr mDescriptor;
+};
+
+typedef IceUtil::Handle<ConfiguredFormat> ConfiguredFormatPtr;
+
+/**
  * Private implementation details for SipEndpoint.
  */
 class SipEndpointImplPriv
@@ -78,6 +198,11 @@ public:
     std::vector<SipSessionPtr> mSessions;
 
     /**
+     * A vector of configured formats for this endpoint.
+     */
+    std::vector<ConfiguredFormatPtr> mFormats;
+
+    /**
      * A proxy to our endpoint.
      */
     AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx mEndpointProxy;
@@ -141,6 +266,20 @@ void SipEndpoint::setRTPOverIPv6(bool enabled)
     mImplPriv->mConfig.sessionConfig.rtpOverIPv6 = enabled;
 }
 
+void SipEndpoint::addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific)
+{
+    SDPDescriptorServiceLocatorParamsPtr params = new SDPDescriptorServiceLocatorParams();
+    params->category = "Media/SDP_Descriptor";
+    params->name = name;
+
+    ConfiguredFormatPtr configuredFormat = new ConfiguredFormat(name, sampleRate, frameSize, formatSpecific);
+    Callback_ServiceLocator_locatePtr descriptorCB = newCallback_ServiceLocator_locate(
+        configuredFormat, &ConfiguredFormat::locateCB, &ConfiguredFormat::locateFailureCB);
+
+    mImplPriv->mFormats.push_back(configuredFormat);
+    mImplPriv->mServiceLocator->begin_locate(params, descriptorCB);
+}
+
 Direction SipEndpointConfig::stringToDirection(const std::string& directionString)
 {
     if (directionString == "Both")
@@ -189,7 +328,7 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
     }
 
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, listener, mImplPriv->mManager,
-        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, true);
+        mImplPriv->mServiceLocator, mImplPriv->mReplica, true);
     mImplPriv->mSessions.push_back(session);
     std::cout << "And now we're returing a session proxy..." << std::endl;
     return session->getSessionProxy();
@@ -198,17 +337,18 @@ AsteriskSCF::SessionCommunications::V1::SessionPrx SipEndpoint::createSession(co
 AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination)
 {
     SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, 0, mImplPriv->mManager,
-        mImplPriv->mServiceLocator, mImplPriv->mReplica, mImplPriv->mConfig.sessionConfig.rtpOverIPv6, false);
+        mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
     mImplPriv->mSessions.push_back(session);
     return session;
 }
 
 AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination,
-        const Ice::Identity& sessionid, const Ice::Identity& mediaid,
-        const AsteriskSCF::Media::V1::SessionPrx& mediasession, const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
-        const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
+                                                                         const Ice::Identity& sessionid, const Ice::Identity& mediaid,
+                                                                         const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                                                                         const AsteriskSCF::Media::V1::StreamSourceSeq& sources,
+                                                                         const AsteriskSCF::Media::V1::StreamSinkSeq& sinks)
 {
-    SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasession,
+    SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, mediaid, mediasessions,
             sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
     mImplPriv->mSessions.push_back(session);
     return session;
@@ -249,5 +389,75 @@ AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx SipEndpoint::getEndpo
     return mImplPriv->mEndpointProxy;
 }
 
+SDPDescriptorServicePrx SipEndpoint::getDescriptorService(const SDPDescriptorPtr& descriptor)
+{
+    for (std::vector<ConfiguredFormatPtr>::const_iterator configuredFormat = mImplPriv->mFormats.begin();
+         configuredFormat != mImplPriv->mFormats.end();
+         ++configuredFormat)
+    {
+        // Dynamic payloads get searched via name while static payloads get searched by number
+        if (descriptor->payload < 96)
+        {
+            if ((*configuredFormat)->getDescriptor()->payload == descriptor->payload)
+            {
+                return (*configuredFormat)->getDescriptorService();
+            }
+        }
+        else
+        {
+            if ((*configuredFormat)->getDescriptor()->subtype == descriptor->subtype)
+            {
+                return (*configuredFormat)->getDescriptorService();
+            }
+        }
+    }
+
+    return 0;
+}
+
+SDPDescriptorPtr SipEndpoint::getDescriptor(const FormatPtr& format)
+{
+    for (std::vector<ConfiguredFormatPtr>::const_iterator configuredFormat = mImplPriv->mFormats.begin();
+         configuredFormat != mImplPriv->mFormats.end();
+         ++configuredFormat)
+    {
+        if ((*configuredFormat)->getFormat()->name == format->name)
+        {
+            return (*configuredFormat)->getDescriptor();
+        }
+    }
+
+    return 0;
+}
+
+StreamTopologyMap SipEndpoint::getStreamTopology()
+{
+    StreamTopologyMap topology;
+
+    // Iterate through all the configured formats placing the same types on the same stream
+    for (std::vector<ConfiguredFormatPtr>::const_iterator configuredFormat = mImplPriv->mFormats.begin();
+         configuredFormat != mImplPriv->mFormats.end();
+         ++configuredFormat)
+    {
+        // See if a stream already exists for this type
+        StreamTopologyMap::iterator stream = topology.find((*configuredFormat)->getDescriptor()->type);
+
+        if (stream == topology.end())
+        {
+            // If one does not exist we have to create it and add it to the map
+            FormatSeq formats;
+            formats.push_back((*configuredFormat)->getFormat());
+            topology.insert(make_pair((*configuredFormat)->getDescriptor()->type, formats));
+        }
+        else
+        {
+            // If one does exist we can simply add the format to it
+            stream->second.push_back((*configuredFormat)->getFormat());
+        }
+    }
+
+    return topology;
+}
+
 }; // end SipSessionManager
 }; // end AsteriskSCF
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index cb91a66..ebf4d87 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -32,6 +32,7 @@
 #include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 
 #include "SipSession.h"
 
@@ -204,6 +205,12 @@ private:
 };
 
 /**
+ * A type def for a sequence of stream topology entries, each entry represents a stream and the contents are the formats
+ * carried over the stream.
+ */
+typedef std::map<std::string, AsteriskSCF::Media::V1::FormatSeq> StreamTopologyMap;
+
+/**
  * Private implementation details for SipEndpoint.
  */
 class SipEndpointImplPriv;
@@ -239,8 +246,8 @@ public:
     //
     AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&);
     AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&, const Ice::Identity&,
-            const Ice::Identity&, const AsteriskSCF::Media::V1::SessionPrx&,
-            const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&);
+                                                                const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
+                                                                const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&);
 
     void removeSession(const AsteriskSCF::SessionCommunications::V1::SessionPtr&);
 
@@ -254,6 +261,23 @@ public:
     void setCallDirection(enum Direction);
     void setSecureTransport(enum Direction);
     void setRTPOverIPv6(bool);
+    void addFormat(const std::string& name, int sampleRate, int frameSize, const Ice::StringSeq& formatSpecific);
+
+    /**
+     * API call which returns a proxy to an SDP descriptor service given a descriptor.
+     */
+    AsteriskSCF::Media::SDP::V1::SDPDescriptorServicePrx getDescriptorService(
+        const AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr&);
+    
+    /**
+     * API call which returns a descriptor given a media format.
+     */
+    AsteriskSCF::Media::SDP::V1::SDPDescriptorPtr getDescriptor(const AsteriskSCF::Media::V1::FormatPtr&);
+
+    /**
+     * API call which returns the stream topology to be used for an SDP offer.
+     */
+    StreamTopologyMap getStreamTopology();
 
 private:
     /**
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 972b5b0..6210963 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -24,11 +24,18 @@
 
 #include <boost/thread.hpp>
 #include <boost/thread/shared_mutex.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include <AsteriskSCF/System/WorkQueue/WorkQueueIf.h>
 #include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/Media/RTP/MediaRTPIf.h>
+#include <AsteriskSCF/Media/SDP/MediaSDPIf.h>
 
 using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Media::V1;
+using namespace AsteriskSCF::Media::RTP::V1;
+using namespace AsteriskSCF::Media::SDP::V1;
 
 namespace
 {
@@ -88,7 +95,7 @@ public:
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
         const AsteriskSCF::System::Component::V1::ReplicaPtr& replica)
         : mAdapter(adapter), mDialog(0), mInviteSession(0), mEndpoint(endpoint), mDestination(destination),
-          mManager(manager), mServiceLocator(serviceLocator), mReplica(replica) { };
+          mManager(manager), mServiceLocator(serviceLocator), mReplica(replica), mSDP(0), mSDPFinalized(false) { };
 
     AsteriskSCF::SessionCommunications::V1::SessionInfoPtr getInfo()
     {
@@ -206,7 +213,7 @@ public:
     /**
      * A vector of RTP media sessions belonging to this endpoint.
      */
-    std::vector<AsteriskSCF::Media::RTP::V1::RTPSessionPrx> mRTPSessions;
+    RTPMediaSessionSeq mRTPSessions;
 
     /**
      * A vector of media sources associated with this endpoint.
@@ -253,8 +260,27 @@ public:
     AsteriskSCF::System::Component::V1::ReplicaPtr mReplica;
 
     SessionWorkPtr mSessionWork;
+
+    /**
+     * SDP that has been produced for this session.
+     */
+    pjmedia_sdp_session *mSDP;
+
+    /**
+     * Whether the SDP has been finalized or not.
+     */
+    bool mSDPFinalized;
 };
 
+/**
+ * Template for allocating from a pool.
+ */
+template<typename T>
+inline T *allocate_from_pool(pj_pool_t *pool)
+{
+    return static_cast<T*>(pj_pool_zalloc(pool, sizeof(T)));
+}
+
 void SipSession::initializePJSIPStructs()
 {
     pj_str_t local_uri, remote_uri;
@@ -294,7 +320,10 @@ void SipSession::initializePJSIPStructs()
     mImplPriv->mDialog = dialog;
     
     pjsip_inv_session *inviteSession;
+
+    // Create an SDP offer based on what is configured
     pjmedia_sdp_session *sdp = createSDPOffer();
+
     if ((pjsip_inv_create_uac(dialog, sdp, 0, &inviteSession)) != PJ_SUCCESS)
     {
         lg(Error) << "Failed to create a UAC INVITE session!";
@@ -318,9 +347,9 @@ void SipSession::initializePJSIPStructs()
  * Default constructor.
  */
 SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
-        const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
-        PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool ipv6, bool isUAC)
+                       const std::string& destination,  const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener,
+                       PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     if (listener != 0)
@@ -335,10 +364,6 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     mImplPriv->mMediaSessionProxy =
         AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->addWithUUID(mImplPriv->mMediaSession));
 
-    // Get an RTP session capable of handling the formats we are going to offer
-    AsteriskSCF::Media::V1::FormatSeq formats;
-    requestRTPSessions(formats, ipv6);
-
     if (isUAC)
     {
         lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
@@ -350,11 +375,11 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
  * Replica constructor.
  */
 SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
-        const std::string& destination, const Ice::Identity& sessionid,
-        const Ice::Identity& mediaid, const AsteriskSCF::Media::V1::SessionPrx& mediasession,
-        const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
-        PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
+                       const std::string& destination, const Ice::Identity& sessionid,
+                       const Ice::Identity& mediaid, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq& mediasessions,
+                       const AsteriskSCF::Media::V1::StreamSourceSeq& sources, const AsteriskSCF::Media::V1::StreamSinkSeq& sinks,
+                       PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+                       const AsteriskSCF::System::Component::V1::ReplicaPtr& replica, bool isUAC)
     : mImplPriv(new SipSessionPriv(adapter, endpoint, destination, manager, serviceLocator, replica))
 {
     mImplPriv->mSessionProxy =
@@ -364,10 +389,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     mImplPriv->mMediaSessionProxy =
         AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->add(mImplPriv->mMediaSession, mediaid));
 
-    AsteriskSCF::Media::RTP::V1::RTPSessionPrx rtpsession =
-        AsteriskSCF::Media::RTP::V1::RTPSessionPrx::uncheckedCast(mediasession);
-    mImplPriv->mRTPSessions.push_back(rtpsession);
-
+    mImplPriv->mRTPSessions = mediasessions;
     mImplPriv->mSources = sources;
     mImplPriv->mSinks = sinks;
 
@@ -435,8 +457,7 @@ public:
         if ((Connect = AsteriskSCF::SessionCommunications::V1::ConnectIndicationPtr::dynamicCast(mIndication)))
         {
             lg(Debug) << "Processing a Connect indication";
-            pjmedia_sdp_session *sdp = mSession->createSDPOffer();
-            status = pjsip_inv_answer(mImplPriv->mInviteSession, 200, NULL, sdp, &packet);
+            status = pjsip_inv_answer(mImplPriv->mInviteSession, 200, NULL, NULL, &packet);
         }
         else if ((Flash = AsteriskSCF::SessionCommunications::V1::FlashIndicationPtr::dynamicCast(mIndication)))
         {
@@ -453,8 +474,7 @@ public:
         else if ((Progress = AsteriskSCF::SessionCommunications::V1::ProgressIndicationPtr::dynamicCast(mIndication)))
         {
             lg(Debug) << "Processing a Progress indication";
-            pjmedia_sdp_session *sdp = mSession->createSDPOffer();
-            status = pjsip_inv_answer(mImplPriv->mInviteSession, 183, NULL, sdp, &packet);
+            status = pjsip_inv_answer(mImplPriv->mInviteSession, 183, NULL, NULL, &packet);
         }
         else if ((Ring = AsteriskSCF::SessionCommunications::V1::RingIndicationPtr::dynamicCast(mIndication)))
         {
@@ -1019,8 +1039,8 @@ public:
         {
             //XXX This loop may be a candidate for making AMI-ified and returning "Suspended"
             // Release all the RTP sessions we are using
-            for (std::vector<AsteriskSCF::Media::RTP::V1::RTPSessionPrx>::const_iterator i =
-                     mSessionPriv->mRTPSessions.begin(); i != mSessionPriv->mRTPSessions.end(); ++i)
+            for (RTPMediaSessionSeq::const_iterator i = mSessionPriv->mRTPSessions.begin();
+		 i != mSessionPriv->mRTPSessions.end(); ++i)
             {
                 try
                 {
@@ -1051,12 +1071,11 @@ void SipSession::destroy()
 }
 
 /**
- * Internal function called to produce an SDP session structure.
+ * Internal function called to produce an SDP session structure without any streams.
  */
-pjmedia_sdp_session *SipSession::createSDPOffer()
+pjmedia_sdp_session *SipSession::createSDP()
 {
-    pjmedia_sdp_session *sdp = static_cast<pjmedia_sdp_session*>(
-        pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_session)));
+    pjmedia_sdp_session *sdp = allocate_from_pool<pjmedia_sdp_session>(mImplPriv->mDialog->pool);
 
     pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.user, "AsteriskSCF");
     pj_time_val tv;
@@ -1064,113 +1083,418 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
     sdp->origin.version = sdp->origin.id = (pj_uint32_t) (tv.sec + 2208988800UL);
     pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.net_type, "IN");
 
-    // Right now we only support a single stream so go and get it
-    AsteriskSCF::Media::RTP::V1::StreamSourceRTPPrx stream =
-        AsteriskSCF::Media::RTP::V1::StreamSourceRTPPrx::uncheckedCast(mImplPriv->mSources.front());
+    sdp->origin.addr = *pj_gethostname();
 
-    std::string address = stream->getLocalAddress();
+    std::string address = std::string(pj_strbuf(&sdp->origin.addr), pj_strlen(&sdp->origin.addr));
 
     lg(Debug) << "The local address we are placing in our SDP is " << address;
     if (address.find(":") != std::string::npos)
     {
-	pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP6");
+        pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP6");
     }
     else
     {
-	pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP4");
+        pj_strdup2(mImplPriv->mDialog->pool, &sdp->origin.addr_type, "IP4");
     }
 
-    sdp->origin.addr = *pj_gethostname();
     sdp->name = sdp->origin.user;
-    sdp->time.start = 0;
-    sdp->time.stop = 0;
-    sdp->attr_count = 0;
-
-    // Add connection details at the session level since we currently only support one media stream.
-    sdp->conn = static_cast<pjmedia_sdp_conn*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_conn)));
-    sdp->conn->net_type = sdp->origin.net_type;
-    sdp->conn->addr_type = sdp->origin.addr_type;
-    pj_strdup2(mImplPriv->mDialog->pool, &sdp->conn->addr, address.c_str());
-
-    // Add a single media stream
-    sdp->media_count = 1;
-    pjmedia_sdp_media* media =
-        static_cast<pjmedia_sdp_media*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_media)));
-    sdp->media[0] = media;
-    pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, "audio");
-    media->desc.port = (pj_uint16_t) stream->getLocalPort();
-    media->desc.port_count = 1;
-    pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
-
-    // Populate the stream with codec details
-    sdp->media[0]->desc.fmt_count = 1;
-    sdp->media[0]->attr_count = 0;
-
-    // TODO: We should iterate over the formats to produce this instead of hardcoding
-    pjmedia_sdp_rtpmap rtpmap;
-    pjmedia_sdp_attr *attr;
-
-    // This is hardcoded value for ULAW for now
-    pj_strdup2(mImplPriv->mDialog->pool, &media->desc.fmt[0], "0");
-    rtpmap.pt = media->desc.fmt[0];
-    rtpmap.clock_rate = 8000;
-    pj_strdup2(mImplPriv->mDialog->pool, &rtpmap.enc_name, "PCMU");
-    rtpmap.param.slen = 0;
-    pjmedia_sdp_rtpmap_to_attr(mImplPriv->mDialog->pool, &rtpmap, &attr);
-    sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
-
-    // Might as well add sendrecv
-    attr = static_cast<pjmedia_sdp_attr*>(pj_pool_zalloc(mImplPriv->mDialog->pool, sizeof(pjmedia_sdp_attr)));
-    pj_strdup2(mImplPriv->mDialog->pool, &attr->name, "sendrecv");
-    sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr;
 
     return sdp;
 }
 
 /**
- * Internal function called to request needed RTP sessions.
+ * Internal function called to add formats to an SDP media stream
  */
-void SipSession::requestRTPSessions(AsteriskSCF::Media::V1::FormatSeq& formats, bool ipv6)
+void SipSession::addFormatstoSDP(const FormatSeq& formats, pjmedia_sdp_media *media, PayloadMap& payloads)
 {
-    // TODO: This needs to be improved for multiple streams
-    AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParamsPtr params =
-        new AsteriskSCF::Media::RTP::V1::RTPServiceLocatorParams();
-    params->category = "rtp";
-    params->formats = formats;
-    params->ipv6 = ipv6;
-
-    AsteriskSCF::Media::RTP::V1::RTPMediaServicePrx factory =
-        AsteriskSCF::Media::RTP::V1::RTPMediaServicePrx::uncheckedCast(mImplPriv->mServiceLocator->locate(params));
-    AsteriskSCF::Media::RTP::V1::RTPSessionPrx session = factory->allocate(params);
-    mImplPriv->mRTPSessions.push_back(session);
-
-    // Create a local copy of the sources, this won't get changed by the RTP session so it's all good
-    mImplPriv->mSources = session->getSources();
-
-    // Create a local copy of the sinks, this won't get changed by the RTP session so it's all good
-    mImplPriv->mSinks = session->getSinks();
-
-    // For testing push a static payload mapping for ULAW into the RTP session
-    AsteriskSCF::Media::RTP::V1::PayloadMap payloads;
-    AsteriskSCF::Media::V1::AudioFormatPtr format = new AsteriskSCF::Media::V1::AudioFormat();
-    format->name = "ulaw";
-    format->sampleRate = 8000;
-    format->frameSize = 20;
-    format->maximumFrameSize = 20;
-    format->minimumFrameSize = 20;
-    payloads.insert(std::make_pair(0, format));
-
-    session->associatePayloads(payloads);
+    // Start dynamic payload assignment at 96
+    int dynamicPayload = 96;
+
+    // Iterate through each format adding it to the SDP
+    for (FormatSeq::const_iterator mediaformat = formats.begin();
+         mediaformat != formats.end();
+         ++mediaformat)
+    {
+        // Attempt to get our configured descriptor
+        SDPDescriptorPtr ourDescriptor = mImplPriv->mEndpoint->getDescriptor((*mediaformat));
+
+        // This should not happen... if we can not get our descriptor then there is a disassociation
+        // between their SDP and our SDP
+        if (!ourDescriptor)
+        {
+            continue;
+        }
+
+        int payload = ourDescriptor->payload;
+
+        // If we have been told to assign a dynamic payload ourselves do so
+        if (payload == -1)
+        {
+            // Ensure we don't assign a payload that has been specified by checking the payload -> format mapping
+            for (; dynamicPayload < 130; dynamicPayload++)
+            {
+                if (payloads.find(dynamicPayload) == payloads.end())
+                {
+                    payload = dynamicPayload;
+                    break;
+                }
+            }
+
+            // If the payload still has not been decided we have no more room in the dynamic payload range
+            if (payload == -1)
+            {
+                continue;
+            }
+        }
+
+        // Add the format to the 'm' line
+        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.fmt[media->desc.fmt_count++],
+                   boost::lexical_cast<std::string>(payload).c_str());
+
+        // Add an rtpmap attribute line for the format
+        pjmedia_sdp_rtpmap rtpmap;
+        pjmedia_sdp_attr *attr;
+
+        rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
+        rtpmap.clock_rate = ourDescriptor->samplerate;
+        pj_strdup2(mImplPriv->mDialog->pool, &rtpmap.enc_name, ourDescriptor->subtype.c_str());
+        rtpmap.param.slen = 0;
+        pjmedia_sdp_rtpmap_to_attr(mImplPriv->mDialog->pool, &rtpmap, &attr);
+        media->attr[media->attr_count++] = attr;
+
+        // Add any fmtp attributes for the format
+        for (SDPFormatParameterSeq::const_iterator parameter = ourDescriptor->parameters.begin();
+             parameter != ourDescriptor->parameters.end();
+             ++parameter)
+        {
+            attr = allocate_from_pool<pjmedia_sdp_attr>(mImplPriv->mDialog->pool);
+            std::string parameters = "fmtp:" + boost::lexical_cast<std::string>(payload) + " " + (*parameter);
+            pj_strdup2(mImplPriv->mDialog->pool, &attr->name, parameters.c_str());
+            media->attr[media->attr_count++] = attr;
+        }
+
+        payloads.insert(std::make_pair(payload, (*mediaformat)));
+    }
 }
 
 /**
- * Internal function called to set the remote details for RTP.
+ * Internal function called to produce an SDP session structure using configuration.
  */
-void SipSession::setRemoteDetails(const std::string& destination, int port)
+pjmedia_sdp_session *SipSession::createSDPOffer()
 {
-    AsteriskSCF::Media::RTP::V1::StreamSinkRTPPrx sink =
-        AsteriskSCF::Media::RTP::V1::StreamSinkRTPPrx::uncheckedCast(mImplPriv->mSinks.front());
-    sink->setRemoteDetails(destination, port);
+    // If SDP has already been produced then just return it, don't recreate it
+    if (mImplPriv->mSDPFinalized == true)
+    {
+        return mImplPriv->mSDP;
+    }
+
+    // Retrieve the stream topology from the endpoint
+    StreamTopologyMap streams = mImplPriv->mEndpoint->getStreamTopology();
+
+    // If there are no streams then we can not create an SDP offer
+    if (streams.empty())
+    {
+        return 0;
+    }
+
+    // Create the most common part of the SDP if not already done
+    if (!mImplPriv->mSDP)
+    {
+        mImplPriv->mSDP = createSDP();
+    }
+
+    // Iterate through each stream present in the topology
+    for (StreamTopologyMap::const_iterator stream = streams.begin();
+         stream != streams.end();
+         ++stream)
+    {
+        RTPServiceLocatorParamsPtr params = new RTPServiceLocatorParams();
+        params->category = "rtp";
+        params->formats = stream->second;
+        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));
+
+        // If none exist we can't provide the stream
+        if (factory == 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);
+
+        // Ditto goes for source
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+        mImplPriv->mSources.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);
+        mImplPriv->mSDP->media[mImplPriv->mSDP->media_count++] = media;
+        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.media, mImplPriv->mEndpoint->getDescriptor(stream->second.front())->type.c_str());
+
+        // TODO: This should not be hardcoded
+        pj_strdup2(mImplPriv->mDialog->pool, &media->desc.transport, "RTP/AVP");
+
+        // 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");
+
+        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");
+        }
+
+        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;
+        }
+
+        media->desc.port = (pj_uint16_t) source->getLocalPort();
+        media->desc.port_count = 1;
+
+        PayloadMap payloads;
+
+        // Add all of the formats to the SDP
+        addFormatstoSDP(stream->second, media, payloads);
+
+        // Push the payload mapping to the RTP session so it'll correctly map things
+        session->associatePayloads(payloads);
+
+        // The SDP has been finalized enough
+        mImplPriv->mSDPFinalized = true;
+    }
+
+    return mImplPriv->mSDPFinalized == true ? mImplPriv->mSDP : 0;
+}
+
+/**
+ * Internal function called to produce an SDP session structure using configuration and an SDP offer.
+ */
+pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offer)
+{
+    // If SDP has already been produced then just return it, don't recreate it
+    if (mImplPriv->mSDPFinalized == true)
+    {
+        return mImplPriv->mSDP;
+    }
+
+    // Create the most common part of the SDP if not already done
+    if (!mImplPriv->mSDP)
+    {
+        mImplPriv->mSDP = createSDP();
+    }
+
+    // Get the non-stream level connection information in case there is no connection level one
+    std::string destination(pj_strbuf(&offer->conn->addr), pj_strlen(&offer->conn->addr));
+
+    // Iterate through each stream seeing if we are configured to support at least one format they have
+    for (unsigned int stream = 0; stream < offer->media_count; stream++)
+    {
+        // If a format is actually found we add it to this sequence so we can create an RTP session
+        FormatSeq formats;
+
+        // Iterate through formats that exist on this stream, creating an SDP descriptor class
+        for (unsigned int format = 0; format < offer->media[stream]->desc.fmt_count; format++)
+        {
+            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));
+
+            // Some devices rely solely on the payload for known formats (such as PCMU) so the following format
+            // parameters are completely optional
+            const pjmedia_sdp_attr *attr;
+            if ((attr = pjmedia_sdp_media_find_attr2(offer->media[stream], "rtpmap",
+                                                     &offer->media[stream]->desc.fmt[format])))
+            {
+                pjmedia_sdp_rtpmap *rtpmap;
+                if ((pjmedia_sdp_attr_to_rtpmap(mImplPriv->mInviteSession->pool_active, attr, &rtpmap)) == PJ_SUCCESS)
+                {
+                    descriptor->subtype = std::string(pj_strbuf(&rtpmap->enc_name), pj_strlen(&rtpmap->enc_name));
+                    descriptor->samplerate = rtpmap->clock_rate;
+                }
+            }
+
+            // Next we move on to format specific parameters
+            if ((attr = pjmedia_sdp_media_find_attr2(offer->media[stream], "fmtp",
+                                                     &offer->media[stream]->desc.fmt[format])))
+            {
+                pjmedia_sdp_fmtp fmtp;
+                if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS)
+                {
+                    std::string parameter = std::string(pj_strbuf(&fmtp.fmt_param), pj_strlen(&fmtp.fmt_param));
+                    descriptor->parameters.push_back(parameter);
+                }
+            }
+
+            // Next up are attributes that are not specific to the format, such as ptime
+            for (unsigned int attribute = 0; attribute < offer->media[stream]->attr_count; attribute++)
+            {
+                // Attributes we already touch above OR know aren't helpful to the SDP descriptor service don't need to
+                // be given to it, obviously
+                if (!pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "rtpmap") ||
+                    !pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "fmtp") ||
+                    !pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "rtcp") ||
+                    !pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "sendrecv") ||
+                    !pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "sendonly") ||
+                    !pj_strcmp2(&offer->media[stream]->attr[attribute]->name, "recvonly"))
+                {
+                    continue;
+                }
+
+                std::string parameter = std::string(pj_strbuf(&offer->media[stream]->attr[attribute]->name),
+                                                    pj_strlen(&offer->media[stream]->attr[attribute]->name)) + ':' +
+                    std::string(pj_strbuf(&offer->media[stream]->attr[attribute]->value),
+                                pj_strlen(&offer->media[stream]->attr[attribute]->value));
+                descriptor->parameters.push_back(parameter);
+            }
+
+            // Use the configured formats to find what SDP descriptor service to use to turn this into
+            // a media format concrete class
+            SDPDescriptorServicePrx descriptorService = mImplPriv->mEndpoint->getDescriptorService(descriptor);
+
+            // If no descriptor service was found then they offered something that we are not configured to
+            // accept
+            if (descriptorService == 0)
+            {
+                continue;
+            }
+
+            // Try to turn the SDP descriptor class into a media format class, if this fails then whatever
+            // they have in their SDP is something the service is unwilling to accept and we have to consider
+            // it unsupported
+            FormatPtr mediaformat = descriptorService->getDescribedFormat(descriptor);
+
+            if (mediaformat == 0)
+            {
+                continue;
+            }
+
+            // This is a supported format so add it to the sequence
+            formats.push_back(mediaformat);
+        }
+
+        // If no formats were found on this stream that we are configured with then move on to the next one
+        if (formats.empty())
+        {
+            continue;
+        }
+
+        // Assume that no connection level details exist until proven otherwise
+        std::string connection = destination;
+        if (offer->media[stream]->conn)
+        {
+            connection = std::string(pj_strbuf(&offer->media[stream]->conn->addr),
+                                     pj_strlen(&offer->media[stream]->conn->addr));
+        }
+
+        RTPServiceLocatorParamsPtr params = new 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)
+        {
+            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());
+        sink->setRemoteDetails(connection, offer->media[stream]->desc.port);
+        mImplPriv->mSinks.push_back(sink);
+
+        // Ditto goes for source
+        StreamSourceRTPPrx source = StreamSourceRTPPrx::uncheckedCast(session->getSources().front());
+        mImplPriv->mSources.push_back(source);
+
+        // Update the SIP session with some RTP session details
+        mImplPriv->mRTPSessions.push_back(session);
+
+        // Add a new stream to the answer SDP
+        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);
+
+        // The SDP has been finalized enough
+        mImplPriv->mSDPFinalized = true;
+    }
+
+    return mImplPriv->mSDPFinalized == true ? mImplPriv->mSDP : 0;
 }
 
 /**
@@ -1276,12 +1600,11 @@ void SipSession::setListeners(const SessionListenerSeq& listeners)
 }
 
 /**
- * Internal function which returns the media session that is hidden inside the SIP session.
+ * Internal function which returns the RTP media sessions that are hidden inside the SIP session.
  */
-AsteriskSCF::Media::V1::SessionPrx SipSession::getHiddenMediaSession()
+RTPMediaSessionSeq SipSession::getRTPMediaSessions()
 {
-    // TODO: This should return a sequence
-    return mImplPriv->mRTPSessions.front();
+    return mImplPriv->mRTPSessions;
 }
 
 bool SipSession::operator==(const SipSession &other) const {
diff --git a/src/SipSession.h b/src/SipSession.h
index f670454..ce5dd43 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -98,14 +98,14 @@ public:
         const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx&, PJSipManager *manager,
         const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
         const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
-        bool ipv6, bool isUAC);
+        bool isUAC);
 
     SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&,
-        const Ice::Identity&, const AsteriskSCF::Media::V1::SessionPrx&,
-        const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
-        PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
-        const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
-        bool isUAC);
+               const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
+               const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
+               PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
+               const AsteriskSCF::System::Component::V1::ReplicaPtr& replica,
+               bool isUAC);
 
     bool operator==(const SipSession &other) const;
 
@@ -176,7 +176,7 @@ public:
 
     pjmedia_sdp_session *createSDPOffer();
 
-    void setRemoteDetails(const std::string&, int);
+    pjmedia_sdp_session *createSDPAnswer(const pjmedia_sdp_session*);
 
     void setDialog(pjsip_dialog *dialog);
 
@@ -203,14 +203,18 @@ public:
 
     void setListeners(const AsteriskSCF::Replication::SipSessionManager::V1::SessionListenerSeq&);
 
-    AsteriskSCF::Media::V1::SessionPrx getHiddenMediaSession();
+    AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq getRTPMediaSessions();
 
     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
 private:
-    void requestRTPSessions(AsteriskSCF::Media::V1::FormatSeq& formats, bool ipv6);
 
     void initializePJSIPStructs();
 
+    pjmedia_sdp_session *createSDP();
+
+    void addFormatstoSDP(const AsteriskSCF::Media::V1::FormatSeq& formats, pjmedia_sdp_media *media,
+                         AsteriskSCF::Media::RTP::V1::PayloadMap& payloads);
+
     /**
      * Private implementation details.
      */
diff --git a/src/SipStateReplicatorListener.cpp b/src/SipStateReplicatorListener.cpp
index 6949339..c80d019 100644
--- a/src/SipStateReplicatorListener.cpp
+++ b/src/SipStateReplicatorListener.cpp
@@ -102,7 +102,7 @@ public:
 
                     // Now that all is well we can create an actual session
                     SipSessionPtr localSession = endpoint->createSession("", session->mSessionObjectId,
-                        session->mMediaSessionObjectId, session->mMediaSession, session->mSources, session->mSinks);
+                        session->mMediaSessionObjectId, session->mRTPMediaSessions, session->mSources, session->mSinks);
                     localitem->setSession(localSession);
                 }
                 else

commit 7d43289b0a830b2c545b4509ca3df7d8dd510186
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Wed Jul 6 16:53:33 2011 -0500

    Remove some unnecessary "visitor" metadata tags.

diff --git a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
index 849992d..ed2dbe3 100644
--- a/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
+++ b/slice/AsteriskSCF/Configuration/SipSessionManager/SipConfigurationIf.ice
@@ -120,7 +120,7 @@ module V1
     * Generic SIP transport group that others derive from, primarily created since each one has
     * the requirement of a name
     */
-   ["visitor:SipConfigurationGroupVisitor"] class SipTransportGroup extends SipConfigurationGroup
+   class SipTransportGroup extends SipConfigurationGroup
    {
       /**
        * Name of the specific transport. Since each one may have multiple transports this differentiates
@@ -132,7 +132,7 @@ module V1
    /**
     * Host information configuration item
     */
-   ["visitor:SipConfigurationItemVisitor"] class SipHostItem extends SipConfigurationItem
+   class SipHostItem extends SipConfigurationItem
    {
       /**
        * String containing the IP address or string address
@@ -148,14 +148,14 @@ module V1
    /**
     * Source transport address configuration item
     */
-   ["visitor:SipConfigurationItemVisitor"] class SipSourceTransportAddressItem extends SipHostItem
+   class SipSourceTransportAddressItem extends SipHostItem
    {
    };
 
    /**
     * Target destination address configuration item
     */
-   ["visitor:SipConfigurationItemVisitor"] class SipTargetDestinationAddressItem extends SipHostItem
+   class SipTargetDestinationAddressItem extends SipHostItem
    {
    };
 
@@ -386,21 +386,21 @@ module V1
    /**
     * Group of configuration items related to a UDP transport
    */
-   ["visitor:SipConfigurationGroupVisitor"] class SipUDPTransportGroup extends SipTransportGroup
+   class SipUDPTransportGroup extends SipTransportGroup
    {
    };
 
    /**
     * Group of configuration items related to a TCP transport
     */
-   ["visitor:SipConfigurationGroupVisitor"] class SipTCPTransportGroup extends SipTransportGroup
+   class SipTCPTransportGroup extends SipTransportGroup
    {
    };
 
    /**
     * Group of configuration items related to a TLS transport
     */
-   ["visitor:SipConfigurationGroupVisitor"] class SipTLSTransportGroup extends SipTransportGroup
+   class SipTLSTransportGroup extends SipTransportGroup
    {
    };
 

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list