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

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue Jun 28 18:43:48 CDT 2011


branch "sessioncontroller" has been created
        at  a47266522a86a264400f6cfa47bc603f115ade3b (commit)

- Log -----------------------------------------------------------------
commit a47266522a86a264400f6cfa47bc603f115ade3b
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Jun 28 20:41:19 2011 -0300

    Add an implementation of removeStreams for SIP.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index f5ce9e4..7e05ef3 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -310,101 +310,168 @@ public:
         : mStreams(streams), mImplPriv(sessionPriv) { }
     
     SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        lg(Debug) << "Executing a changeStreamStates Operation";
+
+        // This boolean is set to true if at least one stream is actually changed. This is to prevent
+        // needless reinvites.
+        bool changed = false;
+            
+        // We iterate through each stream making sure we have one that matches it
+        for (AsteriskSCF::Media::V1::StreamStateDict::const_iterator stream = mStreams.begin();
+             stream != mStreams.end();
+             ++stream)
         {
-            lg(Debug) << "Executing a changeStreamStates Operation";
+            AsteriskSCF::Media::V1::StreamInformationDict::iterator ourStream = mImplPriv->mStreams.find(stream->first);
+                
+            // If we don't have a stream stored locally then they gave us a stream that we really know nothing about it
+            if (ourStream == mImplPriv->mStreams.end())
+            {
+                continue;
+            }
 
-            // This boolean is set to true if at least one stream is actually changed. This is to prevent
-            // needless reinvites.
-            bool changed = false;
+            // If this doesn't actually alter the state of the stream do nothing, since it would just be silly
+            if (ourStream->second->state == stream->second)
+            {
+                continue;
+            }
             
-            // We iterate through each stream making sure we have one that matches it
-            for (AsteriskSCF::Media::V1::StreamStateDict::const_iterator stream = mStreams.begin();
-                 stream != mStreams.end();
-                 ++stream)
+            // The implementation of how we store streams and SDP are linked together, if we can find a stream
+            // in our dictionary of streams than it also exists in the SDP
+            pjmedia_sdp_media *media = mImplPriv->mSDP->media[boost::lexical_cast<int>(stream->first)];
+
+            // Depending on the current state go ahead and remove the current attribute
+            if (ourStream->second->state == SendAndReceive)
+            {
+                pjmedia_sdp_media_remove_all_attr(media, "sendrecv");
+            }
+            else if (ourStream->second->state == SendOnly)
             {
-                AsteriskSCF::Media::V1::StreamInformationDict::iterator ourStream = mImplPriv->mStreams.find(stream->first);
+                pjmedia_sdp_media_remove_all_attr(media, "sendonly");
+            }
+            else if (ourStream->second->state == ReceiveOnly)
+            {
+                pjmedia_sdp_media_remove_all_attr(media, "recvonly");
+            }
+            else if (ourStream->second->state == Inactive)
+            {
+                pjmedia_sdp_media_remove_all_attr(media, "inactive");
+            }
+
+            // Now that the old attribute is removed we can go ahead and update our state
+            ourStream->second->state = stream->second;
+
+            // Now we can go ahead and add in the corret attribute
+            pjmedia_sdp_attr *attr = NULL;
                 
-                // If we don't have a stream stored locally then they gave us a stream that we really know nothing about it
-                if (ourStream == mImplPriv->mStreams.end())
-                {
-                    continue;
-                }
+            if (ourStream->second->state == SendAndReceive)
+            {
+                attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendrecv", NULL);
+            }
+            else if (ourStream->second->state == SendOnly)
+            {
+                attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendonly", NULL);
+            }
+            else if (ourStream->second->state == ReceiveOnly)
+            {
+                attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "recvonly", NULL);
+            }
+            else if (ourStream->second->state == Inactive)
+            {
+                attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "inactive", NULL);
+            }
 
-                // If this doesn't actually alter the state of the stream do nothing, since it would just be silly
-                if (ourStream->second->state == stream->second)
-                {
-                    continue;
-                }
+            if (attr)
+            {
+                pjmedia_sdp_media_add_attr(media, attr);
+                changed = true;
+            }
+        }
 
-                // The implementation of how we store streams and SDP are linked together, if we can find a stream
-                // in our dictionary of streams than it also exists in the SDP
-                pjmedia_sdp_media *media = mImplPriv->mSDP->media[boost::lexical_cast<int>(stream->first)];
+        // If any streams were actually updated trigger a reinvite if need be
+        if (changed == true)
+        {
+            // TODO: Add code here to determine if we really do need to send the reinvite, if we haven't actually answered yet
+            // what we really want to do is just update our answer SDP
+            pjsip_tx_data *packet = NULL;
 
-                // Depending on the current state go ahead and remove the current attribute
-                if (ourStream->second->state == SendAndReceive)
-                {
-                    pjmedia_sdp_media_remove_all_attr(media, "sendrecv");
-                }
-                else if (ourStream->second->state == SendOnly)
-                {
-                    pjmedia_sdp_media_remove_all_attr(media, "sendonly");
-                }
-                else if (ourStream->second->state == ReceiveOnly)
-                {
-                    pjmedia_sdp_media_remove_all_attr(media, "recvonly");
-                }
-                else if (ourStream->second->state == Inactive)
-                {
-                    pjmedia_sdp_media_remove_all_attr(media, "inactive");
-                }
+            if ((pjsip_inv_reinvite(mImplPriv->mInviteSession, NULL, mImplPriv->mSDP, &packet)) == PJ_SUCCESS)
+            {
+                pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
+            }
+        }
+   
+        return Complete;
+    }
+    
+private:
+    AsteriskSCF::Media::V1::StreamStateDict mStreams;
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+};
 
-                // Now that the old attribute is removed we can go ahead and update our state
-                ourStream->second->state = stream->second;
+class RemoveStreamsOperation : public SuspendableWork
+{
+public:
+    RemoveStreamsOperation(
+        const AsteriskSCF::Media::V1::StreamInformationDict& streams,
+        const boost::shared_ptr<SipSessionPriv>& sessionPriv)
+        : mStreams(streams), mImplPriv(sessionPriv) { }
 
-                // Now we can go ahead and add in the corret attribute
-                pjmedia_sdp_attr *attr = NULL;
-                
-                if (ourStream->second->state == SendAndReceive)
-                {
-                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendrecv", NULL);
-                }
-                else if (ourStream->second->state == SendOnly)
-                {
-                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendonly", NULL);
-                }
-                else if (ourStream->second->state == ReceiveOnly)
-                {
-                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "recvonly", NULL);
-                }
-                else if (ourStream->second->state == Inactive)
-                {
-                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "inactive", NULL);
-                }
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        lg(Debug) << "Executing a removeStreams Operation";
 
-                if (attr)
-                {
-                    pjmedia_sdp_media_add_attr(media, attr);
-                    changed = true;
-                }
+        // This gets set to true if at least one stream was actually removed
+        bool removed = false;
+
+        // We iterate through each stream making sure we have one that matches it
+        for (AsteriskSCF::Media::V1::StreamInformationDict::const_iterator stream = mStreams.begin();
+             stream != mStreams.end();
+             ++stream)
+        {
+            AsteriskSCF::Media::V1::StreamInformationDict::iterator ourStream = mImplPriv->mStreams.find(stream->first);
+
+            // If we don't have a stream stored locally then they gave us a stream that we really know nothing about it
+            if (ourStream == mImplPriv->mStreams.end())
+            {
+                continue;
             }
 
-            // If any streams were actually updated trigger a reinvite if need be
-            if (changed == true)
+            // If the stream has already been removed doing it again is silllly
+            if (ourStream->second->state == Removed)
             {
-                // TODO: Add code here to determine if we really do need to send the reinvite
-                pjsip_tx_data *packet = NULL;
+                continue;
+            }
 
-                if ((pjsip_inv_reinvite(mImplPriv->mInviteSession, NULL, mImplPriv->mSDP, &packet)) == PJ_SUCCESS)
-                {
-                    pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
-                }
+            ourStream->second->state = Removed;
+
+            pjmedia_sdp_media *media = mImplPriv->mSDP->media[boost::lexical_cast<int>(stream->first)];
+
+            // Per the RFC removing the stream is accomplished by setting the port to 0
+	    media->desc.port = 0;
+	    media->desc.port_count = 0;
+
+	    // The RFC states that an implementation MAY choose to remove all formats but one and all attributes
+	    // but at this point in time we choose not to do this
+        }
+
+        if (removed == true)
+        {
+            // TODO: Add code here to determine if we really do need to send the reinvite, if we haven't actually answered yet
+            // what we really want to do is just update our answer SDP
+            pjsip_tx_data *packet = NULL;
+
+            if ((pjsip_inv_reinvite(mImplPriv->mInviteSession, NULL, mImplPriv->mSDP, &packet)) == PJ_SUCCESS)
+            {
+                pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
             }
-   
-            return Complete;
         }
-    
+
+        return Complete;
+    }
+
 private:
-    AsteriskSCF::Media::V1::StreamStateDict mStreams;
+    AsteriskSCF::Media::V1::StreamInformationDict mStreams;
     boost::shared_ptr<SipSessionPriv> mImplPriv;
 };
 
@@ -417,18 +484,20 @@ public:
     SipSessionController(boost::shared_ptr<SipSessionPriv> implPriv, const SipSessionPtr& session) :
         mImplPriv(implPriv), mSession(session) { }
     
-    void changeStreamStates(const AsteriskSCF::Media::V1::StreamStateDict& streams, const Ice::Current&)
+    void changeStreamStates(const AsteriskSCF::Media::V1::StreamStateDict& states, const Ice::Current&)
     {
         lg(Debug) << "Queueing changeStreamStates operation";
-        mSession->enqueueSessionWork(new ChangeStreamStatesOperation(streams, mImplPriv));
+        mSession->enqueueSessionWork(new ChangeStreamStatesOperation(states, mImplPriv));
     }
     
     AsteriskSCF::Media::V1::StreamInformationDict addStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
     {
     }
     
-    void removeStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
+    void removeStreams(const AsteriskSCF::Media::V1::StreamInformationDict& streams, const Ice::Current&)
     {
+        lg(Debug) << "Queueing removeStreams operation";
+        mSession->enqueueSessionWork(new RemoveStreamsOperation(streams, mImplPriv));
     }
     
 private:

commit 891c3ae35b077eba1a5cef8ff131d6fdf8c9ac8a
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Jun 28 20:18:42 2011 -0300

    Add an implementation of changeStreamStates for SIP.

diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index d54fe8b..f5ce9e4 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -82,39 +82,6 @@ private:
 };
 
 /**
- * Implementation of a SessionController interface for the SipSession.
- */
-class SipSessionController : public AsteriskSCF::SessionCommunications::V1::SessionController
-{
-public:
-    SipSessionController(boost::shared_ptr<SipSessionPriv> implPriv, const SipSessionPtr& session) :
-        mImplPriv(implPriv), mSession(session) { }
-
-    void changeStreamStates(const AsteriskSCF::Media::V1::StreamStateDict&, const Ice::Current&)
-    {
-    }
-
-    AsteriskSCF::Media::V1::StreamInformationDict addStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
-    {
-    }
-
-    void removeStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
-    {
-    }
-
-private:
-    /**
-     * Private implementation details for SipSession.
-     */
-    boost::shared_ptr<SipSessionPriv> mImplPriv;
-
-    /**
-     * A pointer to the communications session that created us.
-     */
-    SipSessionPtr mSession;
-};
-
-/**
  * Private implementation details for SipSession.
  */
 class SipSessionPriv
@@ -334,6 +301,148 @@ inline T *allocate_from_pool(pj_pool_t *pool)
     return static_cast<T*>(pj_pool_zalloc(pool, sizeof(T)));
 }
 
+class ChangeStreamStatesOperation : public SuspendableWork
+{
+public:
+    ChangeStreamStatesOperation(
+        const AsteriskSCF::Media::V1::StreamStateDict& streams,
+        const boost::shared_ptr<SipSessionPriv>& sessionPriv)
+        : mStreams(streams), mImplPriv(sessionPriv) { }
+    
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+        {
+            lg(Debug) << "Executing a changeStreamStates Operation";
+
+            // This boolean is set to true if at least one stream is actually changed. This is to prevent
+            // needless reinvites.
+            bool changed = false;
+            
+            // We iterate through each stream making sure we have one that matches it
+            for (AsteriskSCF::Media::V1::StreamStateDict::const_iterator stream = mStreams.begin();
+                 stream != mStreams.end();
+                 ++stream)
+            {
+                AsteriskSCF::Media::V1::StreamInformationDict::iterator ourStream = mImplPriv->mStreams.find(stream->first);
+                
+                // If we don't have a stream stored locally then they gave us a stream that we really know nothing about it
+                if (ourStream == mImplPriv->mStreams.end())
+                {
+                    continue;
+                }
+
+                // If this doesn't actually alter the state of the stream do nothing, since it would just be silly
+                if (ourStream->second->state == stream->second)
+                {
+                    continue;
+                }
+
+                // The implementation of how we store streams and SDP are linked together, if we can find a stream
+                // in our dictionary of streams than it also exists in the SDP
+                pjmedia_sdp_media *media = mImplPriv->mSDP->media[boost::lexical_cast<int>(stream->first)];
+
+                // Depending on the current state go ahead and remove the current attribute
+                if (ourStream->second->state == SendAndReceive)
+                {
+                    pjmedia_sdp_media_remove_all_attr(media, "sendrecv");
+                }
+                else if (ourStream->second->state == SendOnly)
+                {
+                    pjmedia_sdp_media_remove_all_attr(media, "sendonly");
+                }
+                else if (ourStream->second->state == ReceiveOnly)
+                {
+                    pjmedia_sdp_media_remove_all_attr(media, "recvonly");
+                }
+                else if (ourStream->second->state == Inactive)
+                {
+                    pjmedia_sdp_media_remove_all_attr(media, "inactive");
+                }
+
+                // Now that the old attribute is removed we can go ahead and update our state
+                ourStream->second->state = stream->second;
+
+                // Now we can go ahead and add in the corret attribute
+                pjmedia_sdp_attr *attr = NULL;
+                
+                if (ourStream->second->state == SendAndReceive)
+                {
+                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendrecv", NULL);
+                }
+                else if (ourStream->second->state == SendOnly)
+                {
+                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "sendonly", NULL);
+                }
+                else if (ourStream->second->state == ReceiveOnly)
+                {
+                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "recvonly", NULL);
+                }
+                else if (ourStream->second->state == Inactive)
+                {
+                    attr = pjmedia_sdp_attr_create(mImplPriv->mDialog->pool, "inactive", NULL);
+                }
+
+                if (attr)
+                {
+                    pjmedia_sdp_media_add_attr(media, attr);
+                    changed = true;
+                }
+            }
+
+            // If any streams were actually updated trigger a reinvite if need be
+            if (changed == true)
+            {
+                // TODO: Add code here to determine if we really do need to send the reinvite
+                pjsip_tx_data *packet = NULL;
+
+                if ((pjsip_inv_reinvite(mImplPriv->mInviteSession, NULL, mImplPriv->mSDP, &packet)) == PJ_SUCCESS)
+                {
+                    pjsip_inv_send_msg(mImplPriv->mInviteSession, packet);
+                }
+            }
+   
+            return Complete;
+        }
+    
+private:
+    AsteriskSCF::Media::V1::StreamStateDict mStreams;
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+};
+
+/**
+ * Implementation of a SessionController interface for the SipSession.
+ */
+class SipSessionController : public AsteriskSCF::SessionCommunications::V1::SessionController
+{
+public:
+    SipSessionController(boost::shared_ptr<SipSessionPriv> implPriv, const SipSessionPtr& session) :
+        mImplPriv(implPriv), mSession(session) { }
+    
+    void changeStreamStates(const AsteriskSCF::Media::V1::StreamStateDict& streams, const Ice::Current&)
+    {
+        lg(Debug) << "Queueing changeStreamStates operation";
+        mSession->enqueueSessionWork(new ChangeStreamStatesOperation(streams, mImplPriv));
+    }
+    
+    AsteriskSCF::Media::V1::StreamInformationDict addStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
+    {
+    }
+    
+    void removeStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
+    {
+    }
+    
+private:
+    /**
+     * Private implementation details for SipSession.
+     */
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+    
+    /**
+     * A pointer to the communications session that created us.
+     */
+    SipSessionPtr mSession;
+};
+
 void SipSession::initializePJSIPStructs()
 {
     pj_str_t local_uri, remote_uri;

commit d6a4f1e97ddde4de20071c6e28fdbaa802097fd3
Author: Joshua Colp <jcolp at digium.com>
Date:   Tue Jun 28 19:51:55 2011 -0300

    Add support for storing stream information, making it available, and replicating it. Additionally add a blank SessionController and replicate the object ID of it.

diff --git a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
index 605b249..db8dd79 100644
--- a/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
+++ b/slice/AsteriskSCF/Replication/SipSessionManager/SipStateReplicationIf.ice
@@ -152,8 +152,10 @@ module V1
       string mEndpointName;
       Ice::Identity mSessionObjectId;
       Ice::Identity mMediaSessionObjectId;
+      Ice::Identity mSessionControllerObjectId;
       AsteriskSCF::Media::V1::StreamSourceSeq mSources;
       AsteriskSCF::Media::V1::StreamSinkSeq mSinks;
+      AsteriskSCF::Media::V1::StreamInformationDict mStreams;
       RTPMediaSessionSeq mRTPMediaSessions;
       SessionListenerSeq mListeners;
       AsteriskSCF::SessionCommunications::V1::Bridge *mBridge;
diff --git a/src/PJSipSessionModule.cpp b/src/PJSipSessionModule.cpp
index 7128453..48b2bba 100644
--- a/src/PJSipSessionModule.cpp
+++ b/src/PJSipSessionModule.cpp
@@ -96,10 +96,12 @@ void PJSipSessionModInfo::updateSessionState(pjsip_inv_session *inv_session)
         mSessionState->mEndpointName = mSession->getEndpoint()->getName();
         mSessionState->mSessionObjectId = mSession->getSessionProxy()->ice_getIdentity();
         mSessionState->mMediaSessionObjectId = mSession->getMediaSessionProxy()->ice_getIdentity();
+	mSessionState->mSessionControllerObjectId = mSession->getOurSessionControllerProxy()->ice_getIdentity();
         mSessionState->mSources = mSession->getSources();
         mSessionState->mSinks = mSession->getSinks();
         mSessionState->mRTPMediaSessions = mSession->getRTPMediaSessions();
         mSessionState->mListeners = mSession->getListeners();
+	mSessionState->mStreams = mSession->getStreams();
         try
         {
             mSessionState->mBridge = mSession->getBridge();
diff --git a/src/SipEndpoint.cpp b/src/SipEndpoint.cpp
index ac3518a..0d44513 100644
--- a/src/SipEndpoint.cpp
+++ b/src/SipEndpoint.cpp
@@ -343,12 +343,13 @@ AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const s
 }
 
 AsteriskSCF::SipSessionManager::SipSessionPtr SipEndpoint::createSession(const std::string& destination,
-                                                                         const Ice::Identity& sessionid, const Ice::Identity& mediaid,
+                                                                         const Ice::Identity& sessionid, const Ice::Identity& controllerid,
+                                                                         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, mediasessions,
+    SipSessionPtr session = new SipSession(mImplPriv->mAdapter, this, destination, sessionid, controllerid, mediaid, mediasessions,
             sources, sinks, mImplPriv->mManager, mImplPriv->mServiceLocator, mImplPriv->mReplica, false);
     mImplPriv->mSessions.push_back(session);
     return session;
diff --git a/src/SipEndpoint.h b/src/SipEndpoint.h
index ebf4d87..b5b7e02 100644
--- a/src/SipEndpoint.h
+++ b/src/SipEndpoint.h
@@ -245,7 +245,7 @@ public:
     // dependency insanity
     //
     AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&);
-    AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&, const Ice::Identity&,
+    AsteriskSCF::SipSessionManager::SipSessionPtr createSession(const std::string&, const Ice::Identity&, const Ice::Identity&,
                                                                 const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
                                                                 const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&);
 
diff --git a/src/SipSession.cpp b/src/SipSession.cpp
index 6210963..d54fe8b 100644
--- a/src/SipSession.cpp
+++ b/src/SipSession.cpp
@@ -82,6 +82,39 @@ private:
 };
 
 /**
+ * Implementation of a SessionController interface for the SipSession.
+ */
+class SipSessionController : public AsteriskSCF::SessionCommunications::V1::SessionController
+{
+public:
+    SipSessionController(boost::shared_ptr<SipSessionPriv> implPriv, const SipSessionPtr& session) :
+        mImplPriv(implPriv), mSession(session) { }
+
+    void changeStreamStates(const AsteriskSCF::Media::V1::StreamStateDict&, const Ice::Current&)
+    {
+    }
+
+    AsteriskSCF::Media::V1::StreamInformationDict addStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
+    {
+    }
+
+    void removeStreams(const AsteriskSCF::Media::V1::StreamInformationDict&, const Ice::Current&)
+    {
+    }
+
+private:
+    /**
+     * Private implementation details for SipSession.
+     */
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+
+    /**
+     * A pointer to the communications session that created us.
+     */
+    SipSessionPtr mSession;
+};
+
+/**
  * Private implementation details for SipSession.
  */
 class SipSessionPriv
@@ -191,6 +224,16 @@ public:
     AsteriskSCF::Media::V1::SessionPrx mMediaSessionProxy;
 
     /**
+     * An instance of a session controller.
+     */
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPtr mOurSessionController;
+
+    /**
+     * A proxy to our own session controller.
+     */
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mOurSessionControllerProxy;
+
+    /**
      * A proxy to this communications session.
      */
     AsteriskSCF::SessionCommunications::V1::SessionPrx mSessionProxy;
@@ -270,6 +313,16 @@ public:
      * Whether the SDP has been finalized or not.
      */
     bool mSDPFinalized;
+
+    /**
+     * Streams present on the session.
+     */
+    StreamInformationDict mStreams;
+
+    /**
+     * A proxy to the SessionController we are controlling.
+     */
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mSessionController;
 };
 
 /**
@@ -364,6 +417,10 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     mImplPriv->mMediaSessionProxy =
         AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->addWithUUID(mImplPriv->mMediaSession));
 
+    mImplPriv->mOurSessionController = new SipSessionController(mImplPriv, this);
+    mImplPriv->mOurSessionControllerProxy =
+        AsteriskSCF::SessionCommunications::V1::SessionControllerPrx::uncheckedCast(adapter->addWithUUID(mImplPriv->mOurSessionController));
+
     if (isUAC)
     {
         lg(Debug) << "New session is UAC, so we're creating the necessary PJSIP structures";
@@ -376,6 +433,7 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
  */
 SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPtr& endpoint,
                        const std::string& destination, const Ice::Identity& sessionid,
+                       const Ice::Identity& controllerid,
                        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,
@@ -389,6 +447,10 @@ SipSession::SipSession(const Ice::ObjectAdapterPtr& adapter, const SipEndpointPt
     mImplPriv->mMediaSessionProxy =
         AsteriskSCF::Media::V1::SessionPrx::uncheckedCast(adapter->add(mImplPriv->mMediaSession, mediaid));
 
+    mImplPriv->mOurSessionController = new SipSessionController(mImplPriv, this);
+    mImplPriv->mOurSessionControllerProxy =
+        AsteriskSCF::SessionCommunications::V1::SessionControllerPrx::uncheckedCast(adapter->add(mImplPriv->mOurSessionController, controllerid));
+
     mImplPriv->mRTPSessions = mediasessions;
     mImplPriv->mSources = sources;
     mImplPriv->mSinks = sinks;
@@ -658,6 +720,115 @@ void SipSession::getBridge_async(
     enqueueSessionWork(new GetBridgeOperation(cb, mImplPriv));
 }
 
+class GetStreamsOperation : public SuspendableWork
+{
+public:
+    GetStreamsOperation(const AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr& cb,
+                       const boost::shared_ptr<SipSessionPriv>& sessionPriv)
+        : mCb(cb), mImplPriv(sessionPriv) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+    {
+        lg(Debug) << "Executing a GetStreams operation";
+        mCb->ice_response(mImplPriv->mStreams);
+        return Complete;
+    }
+
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr mCb;
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+};
+
+/**
+ * An implementation of the getStreams method as defined in SessionCommunications.ice
+ */
+void SipSession::getStreams_async(
+    const AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr& cb,
+    const Ice::Current&)
+{
+    lg(Debug) << "queuing a getStreams operation";
+    enqueueSessionWork(new GetStreamsOperation(cb, mImplPriv));
+}
+
+class SetAndGetSessionControllerOperation : public SuspendableWork
+{
+public:
+    SetAndGetSessionControllerOperation(const AsteriskSCF::SessionCommunications::V1::AMD_Session_setAndGetSessionControllerPtr& cb,
+                                        const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& controller,
+                                        const boost::shared_ptr<SipSessionPriv>& sessionPriv)
+        : mCb(cb), mController(controller), mImplPriv(sessionPriv) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+        {
+            lg(Debug) << "Executing a SetAndGetSessionController operation";
+            
+            if (mImplPriv->mSessionController)
+            {
+                mCb->ice_response(0);
+            }
+
+            mImplPriv->mSessionController = mController;
+            mCb->ice_response(mImplPriv->mOurSessionControllerProxy);
+            return Complete;
+        }
+
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_Session_setAndGetSessionControllerPtr mCb;
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mController;
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+};
+
+/**
+ * An implementation of the setAndGetSessionController method as defined in SessionCommunications.ice
+ */
+void SipSession::setAndGetSessionController_async(
+    const AsteriskSCF::SessionCommunications::V1::AMD_Session_setAndGetSessionControllerPtr& cb,
+    const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& controller,
+    const Ice::Current&)
+{
+    lg(Debug) << "queueing a setAndGetSessionController operation";
+    enqueueSessionWork(new SetAndGetSessionControllerOperation(cb, controller, mImplPriv));
+}
+
+class RemoveSessionControllerOperation : public SuspendableWork
+{
+public:
+    RemoveSessionControllerOperation(const AsteriskSCF::SessionCommunications::V1::AMD_Session_removeSessionControllerPtr& cb,
+                                     const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& controller,
+                                     const boost::shared_ptr<SipSessionPriv>& sessionPriv)
+        : mCb(cb), mController(controller), mImplPriv(sessionPriv) { }
+
+    SuspendableWorkResult execute(const SuspendableWorkListenerPtr&)
+        {
+            lg(Debug) << "Executing a RemoveSessionController operation";
+
+            if (mImplPriv->mSessionController == mController)
+            {
+                mImplPriv->mSessionController = 0;
+            }
+
+            mCb->ice_response();
+            return Complete;
+        }
+
+private:
+    AsteriskSCF::SessionCommunications::V1::AMD_Session_removeSessionControllerPtr mCb;
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx mController;
+    boost::shared_ptr<SipSessionPriv> mImplPriv;
+};
+
+
+/**
+ * An implementation of the removeSessionController method as defined in SessionCommunications.ice
+ */
+void SipSession::removeSessionController_async(const AsteriskSCF::SessionCommunications::V1::AMD_Session_removeSessionControllerPtr& cb,
+                                               const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& controller,
+                                               const Ice::Current&)
+{
+    lg(Debug) << "queueing a removeSessionController operation";
+    enqueueSessionWork(new RemoveSessionControllerOperation(cb, controller, mImplPriv));
+}
+
 class SetBridgeOperation : public SuspendableWork
 {
 public:
@@ -1203,6 +1374,8 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
         mImplPriv->mSDP = createSDP();
     }
 
+    int streamNum = 0;
+
     // Iterate through each stream present in the topology
     for (StreamTopologyMap::const_iterator stream = streams.begin();
          stream != streams.end();
@@ -1231,14 +1404,25 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
             continue;
         }
 
+	// Instantiate a stream information class to contain details about this stream
+	StreamInformationPtr ourStream = new StreamInformation();
+
+	// Formats we already have so just copy them
+	ourStream->formats = stream->second;
+
+	// You might notice we do not set the state of the stream, this is because by default it is already
+	// set to be send and receive.
+
         // 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);
+	ourStream->sinks.push_back(sink);
 
         // Ditto goes for source
         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);
@@ -1285,6 +1469,9 @@ pjmedia_sdp_session *SipSession::createSDPOffer()
 
         // The SDP has been finalized enough
         mImplPriv->mSDPFinalized = true;
+
+	// Now that all is done we can add this stream in
+	mImplPriv->mStreams.insert(make_pair(boost::lexical_cast<std::string>(streamNum++), ourStream));
     }
 
     return mImplPriv->mSDPFinalized == true ? mImplPriv->mSDP : 0;
@@ -1446,15 +1633,40 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
             continue;
         }
 
+        // Instantiate a stream information class so we can keep track of this stream
+        StreamInformationPtr ourStream = new StreamInformation();
+
+        // Formats actually accepted by us were determined above so we can just copy them
+        ourStream->formats = formats;
+
+        // Determine the state of the stream
+	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;
+        }
+
+	// We don't explicitly look for sendrecv since the default state of a newly created StreamInformation
+	// is SendAndReceive, which is also implied if none of the above are found in the SDP
+
         // 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);
+        ourStream->sinks.push_back(sink);
 
         // Ditto goes for source
         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);
@@ -1492,6 +1704,9 @@ pjmedia_sdp_session *SipSession::createSDPAnswer(const pjmedia_sdp_session* offe
 
         // The SDP has been finalized enough
         mImplPriv->mSDPFinalized = true;
+
+        // Add this as a stream to ourselves, yay!
+        mImplPriv->mStreams.insert(make_pair(boost::lexical_cast<std::string>(stream), ourStream));
     }
 
     return mImplPriv->mSDPFinalized == true ? mImplPriv->mSDP : 0;
@@ -1568,6 +1783,14 @@ std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> SipSessi
 }
 
 /**
+ * Internal function which gets the streams on this session.
+ */
+AsteriskSCF::Media::V1::StreamInformationDict& SipSession::getStreams()
+{
+    return mImplPriv->mStreams;
+}
+
+/**
  * Internal function which gets the endpoint associated with the session.
  */
 SipEndpointPtr SipSession::getEndpoint()
@@ -1592,6 +1815,14 @@ AsteriskSCF::Media::V1::SessionPrx& SipSession::getMediaSessionProxy()
 }
 
 /**
+ * Internal function which gets the proxy to our session controller.
+ */
+AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& SipSession::getOurSessionControllerProxy()
+{
+    return mImplPriv->mOurSessionControllerProxy;
+}
+
+/**
  * Internal function which sets the listeners explicitly.
  */
 void SipSession::setListeners(const SessionListenerSeq& listeners)
@@ -1607,6 +1838,14 @@ RTPMediaSessionSeq SipSession::getRTPMediaSessions()
     return mImplPriv->mRTPSessions;
 }
 
+/**
+ * Internal function which sets the streams explicitly.
+ */
+void SipSession::setStreams(const AsteriskSCF::Media::V1::StreamInformationDict& streams)
+{
+    mImplPriv->mStreams = streams;
+}
+
 bool SipSession::operator==(const SipSession &other) const {
     return (this->mImplPriv->mInviteSession == other.mImplPriv->mInviteSession);
 }
diff --git a/src/SipSession.h b/src/SipSession.h
index ce5dd43..1ad2a41 100644
--- a/src/SipSession.h
+++ b/src/SipSession.h
@@ -101,6 +101,7 @@ public:
         bool isUAC);
 
     SipSession(const Ice::ObjectAdapterPtr&, const SipEndpointPtr&, const std::string&, const Ice::Identity&,
+               const Ice::Identity&,
                const Ice::Identity&, const AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq&,
                const AsteriskSCF::Media::V1::StreamSourceSeq&, const AsteriskSCF::Media::V1::StreamSinkSeq&,
                PJSipManager *manager, const AsteriskSCF::Core::Discovery::V1::ServiceLocatorPrx& serviceLocator,
@@ -169,6 +170,19 @@ public:
     AsteriskSCF::SessionCommunications::V1::SessionCookies getCookies();
     AsteriskSCF::SessionCommunications::V1::SessionCookieDict getAllCookies();
 
+    void getStreams_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_Session_getStreamsPtr&,
+        const Ice::Current&);
+
+    void setAndGetSessionController_async(
+        const AsteriskSCF::SessionCommunications::V1::AMD_Session_setAndGetSessionControllerPtr&,
+        const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx&,
+        const Ice::Current&);
+
+    void removeSessionController_async(const AsteriskSCF::SessionCommunications::V1::AMD_Session_removeSessionControllerPtr&,
+                                       const AsteriskSCF::SessionCommunications::V1::SessionControllerPrx&,
+                                       const Ice::Current&);
+
     /**
      * Implementation specific functions.
      */
@@ -195,14 +209,20 @@ public:
 
     std::vector<AsteriskSCF::SessionCommunications::V1::SessionListenerPrx> getListeners();
 
+    AsteriskSCF::Media::V1::StreamInformationDict& getStreams();
+
     SipEndpointPtr getEndpoint();
 
     AsteriskSCF::SessionCommunications::V1::SessionPrx& getSessionProxy();
 
     AsteriskSCF::Media::V1::SessionPrx& getMediaSessionProxy();
 
+    AsteriskSCF::SessionCommunications::V1::SessionControllerPrx& getOurSessionControllerProxy();
+
     void setListeners(const AsteriskSCF::Replication::SipSessionManager::V1::SessionListenerSeq&);
 
+    void setStreams(const AsteriskSCF::Media::V1::StreamInformationDict& streams);
+
     AsteriskSCF::Replication::SipSessionManager::V1::RTPMediaSessionSeq getRTPMediaSessions();
 
     void enqueueSessionWork(const AsteriskSCF::System::WorkQueue::V1::SuspendableWorkPtr&);
diff --git a/src/SipStateReplicatorListener.cpp b/src/SipStateReplicatorListener.cpp
index c80d019..fad4ece 100644
--- a/src/SipStateReplicatorListener.cpp
+++ b/src/SipStateReplicatorListener.cpp
@@ -102,6 +102,7 @@ public:
 
                     // Now that all is well we can create an actual session
                     SipSessionPtr localSession = endpoint->createSession("", session->mSessionObjectId,
+                                                                         session->mSessionControllerObjectId,
                         session->mMediaSessionObjectId, session->mRTPMediaSessions, session->mSources, session->mSinks);
                     localitem->setSession(localSession);
                 }
@@ -113,6 +114,7 @@ public:
                 localitem->getSession()->setListeners(session->mListeners);
                 localitem->getSession()->setBridge(session->mBridge);
 		localitem->getSession()->setCookies(session->mCookies);
+                localitem->getSession()->setStreams(session->mStreams);
             }
             else if ((dialog = SipDialogStateItemPtr::dynamicCast((*item))))
             {

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


-- 
asterisk-scf/integration/sip.git



More information about the asterisk-scf-commits mailing list