[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-server-cvs
Subject:    [Server-cvs]
From:       jgordon () helixcommunity ! org
Date:       2009-10-18 22:29:17
Message-ID: 200910182339.n9INduqA020504 () mailer ! progressive-comp ! com
[Download RAW message or body]

Update of /cvsroot/server/protocol/rtsp
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv18889/rtsp

Modified Files:
	crtspbase.cpp rtspsession.cpp transportparams.cpp 
Log Message:
Synopsis
========
Updates PLAYNOW handling to Rel 7 channel switching

Branches: HEAD (SERVER_CURRENT)
Reviewer: chytanya


Description
===========
Numerous updates for updated semantics.

1. Request is an overloaded PLAY request and meaning of PLAY while in
Playing state is changed.

Most of existing OnPlayRequest method is moved into new method
OnNormalPlayRequest. The initial state handling at the beginning of
OnPlayRequest is updated for new semantics and to determine which
type of PLAY request we have and call an appropriate method (or
handle as keep-alive or fail). Normal channel switch case calls
OnPlaynowRequest and stream switch (new switch type) calls new method
OnSwitchStreamRequest.

2. Regular (non-aggregate) transport parameters are re-used.

Old code stored aggregate transport parameter info only for re-use. It
also used existence of aggregate transport as indication of whether the
transport parameters can be re-used, etc.

Updated to have the new session re-use the old session's
RTSPTransportInstantiator rather than just the one transport params.
RTSPTransportInstantiator is updated to maintain selected transports
in a separate list from available transports (rather than current
behavior where the list changes from available to selected when you
setup) so we can differentiate when switching.

3. Client can select streams to setup (via switch-stream header) if it
already has the SDP; and can specify specific old-stream to new-stream
switches.

Since the request makes individual setups by stream URLs, much of the
existing code needs to be moved to occur *after* we have gotten response
back from the file object with stream header info. Since the
switch-stream header references old session stream-IDs and new session
stream-IDs, we need both around when we parse it. The old session is
now maintained until the new session is totally set up.

Various new methods in RTSPTransportInstantiator to handle switching
transports and stuff. Code moved around between the selectTransport and
canUseTransport methods so that I can reuse appropriately in switching.

4. RTP-Info needs ssrc

This actually should have been added before, not sure why it wasn't
there. It is now.


Not complete with this checkin:
- individual stream switching, starting, or stopping
- switching between content with different number of streams
- aggregate transport
- multi-rate switching

Files Affected
==============
server/protocol/rtsp/crtspbase.cpp
server/protocol/rtsp/rtspsession.cpp
server/protocol/rtsp/transportparams.cpp
server/protocol/rtsp/pub/crtspbase.h
server/protocol/rtsp/pub/rtspsession.h
server/protocol/rtsp/pub/transportparams.h
server/protocol/transport/common/transport.cpp
server/protocol/transport/common/pub/transport.h
server/protocol/transport/rdt/rdt_base.cpp
server/protocol/transport/rtp/rtp_udp.cpp


Testing Performed
=================
Unit Tests:
Manual RTSP verification (telnet):
Fast start up
Switching
Switching with SDP

Integration Tests:
Normal playback RDT/UDP
Normal playback RDT/TCP
Normal playback RTP/UDP
Switching with test client

Leak Tests:
None

Performance Tests:
None

Platforms Tested: win32-i386-vc7, linux-rhel5-i686
Build verified: win32-i386-vc7, linux-rhel5-i686


QA Hints
===============

Demo tests



Index: crtspbase.cpp
===================================================================
RCS file: /cvsroot/server/protocol/rtsp/crtspbase.cpp,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- crtspbase.cpp	16 Oct 2009 00:04:17 -0000	1.68
+++ crtspbase.cpp	18 Oct 2009 22:29:15 -0000	1.69
@@ -1655,7 +1655,7 @@
         {
             HX_ASSERT(!pSession->m_pTransportInstantiator);
             HX_RELEASE(pSession->m_pTransportInstantiator);
-            pSession->m_pTransportInstantiator = new \
RTSPTransportInstantiator(TRUE); +            pSession->m_pTransportInstantiator = \
new RTSPTransportInstantiator(TRUE, TRUE);  \
                pSession->m_pTransportInstantiator->AddRef();
             pSession->m_pTransportInstantiator->Init(m_pContext, sessionID,
                                   (m_pClient->FindSession(sessionID))->m_pSignalBus, \
this); @@ -2106,7 +2106,7 @@
                 memcpy(pSessionNew->m_pStreamUrl, pURLStr, ulURLSize);
                 pSessionNew->m_pStreamUrl[ulURLSize] = '\0';
[...1775 lines suppressed...]
         result = SendSetupStreamResponse(HXR_OK, pSession, m_pFileHeader,
                                 pHeaders, pOptionalValues, pResponseHeaders);
 
         HX_RELEASE(pOptionalValues);
         HX_RELEASE(pKeyedHdrs);
         HX_RELEASE(pResponseHeaders);
-
-        if (HXR_OK != result)
-        {
-            goto exit;
-        }
     }
 
 exit:
@@ -15153,3 +15367,5 @@
                                 RTSPMessage::MIN_VERSION);
     pVersion->Set((const BYTE*)szVersion, strlen(szVersion)+1);
 }
+
+

Index: rtspsession.cpp
===================================================================
RCS file: /cvsroot/server/protocol/rtsp/rtspsession.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- rtspsession.cpp	1 Oct 2009 19:25:15 -0000	1.9
+++ rtspsession.cpp	18 Oct 2009 22:29:15 -0000	1.10
@@ -156,8 +156,8 @@
     m_ulInitiationID(0),
     m_bNeedAggregateTransportHeader(FALSE),
     m_pTransportInstantiator(NULL),
-    m_pAggregateTransportParams(NULL),
-    m_bBookmarkingIsLicensed(FALSE)
+    m_bBookmarkingIsLicensed(FALSE),
+    m_pSwitchStreamHeader(NULL)
 {
     m_pTransportList = new CHXSimpleList;
     m_pBaseProt             = pServProt;
@@ -194,7 +194,7 @@
     clearDescribeMimeTypeList();
 
     HX_RELEASE(m_pTransportInstantiator);
-    HX_RELEASE(m_pAggregateTransportParams);
+    HX_RELEASE(m_pSwitchStreamHeader);
 
     HX_DELETE(m_pMidBoxChallenge);
     HX_DELETE(m_pTransportStreamMap);

Index: transportparams.cpp
===================================================================
RCS file: /cvsroot/server/protocol/rtsp/transportparams.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- transportparams.cpp	7 Feb 2009 06:28:15 -0000	1.20
+++ transportparams.cpp	18 Oct 2009 22:29:15 -0000	1.21
@@ -116,6 +116,7 @@
         m_pDestAddr(NULL),
         m_ulStreamID(0),
         m_bAggregateTransport(0),
+        m_uSwitchStream(HX_INVALID_STREAM),
         m_ulPullSplitID(0),
         m_Protocol(ProtocolType::UDP_UNICAST),
         m_bResendSupported(FALSE),
@@ -196,8 +197,10 @@
 
 
 
-RTSPTransportInstantiator::RTSPTransportInstantiator(BOOL bAggregate)
+RTSPTransportInstantiator::RTSPTransportInstantiator(HXBOOL bAggregate, 
+                                                     HXBOOL bReusable)
                      : m_bAggregateTransport(bAggregate)
+                     , m_bReusable(bReusable)
                      , m_pLocalAddr(NULL)
                      , m_bSelected(FALSE)
                      , m_pBaseProt(NULL)
@@ -259,6 +262,11 @@
         pParams = (RTSPTransportParams*)m_transportParamsList.RemoveHead();
         HX_RELEASE(pParams);
     }
+    while(m_selectedTransportList.IsEmpty() == FALSE)
+    {
+        pParams = (RTSPTransportParams*)m_selectedTransportList.RemoveHead();
+        HX_RELEASE(pParams);
+    }
 }
 
 void
@@ -309,7 +317,8 @@
                                 CRTSPBaseProtocol* pServerProtocol)
 {
     HX_RESULT hresult = HXR_OK;
-	STRACE1(this);
+    STRACE1(this);
+
     m_pContext = pContext;
     m_pContext->AddRef();
 
@@ -420,7 +429,7 @@
         // assume first parameter is transport type
         char szTran[80];
         UINT32 nTranLen = 0;
-        BOOL bIsBCNG = FALSE;
+        HXBOOL bIsBCNG = FALSE;
         szTran[0] = '\0';
 
         if (pIterParam->HasItem())
@@ -771,14 +780,14 @@
  *
  * \return TRUE if we were successful in finding a matching transport
  */
-BOOL
+HXBOOL
 RTSPTransportInstantiator::matchSelected(IHXMIMEHeader* pHeader)
 {
     IHXList* pListField = NULL;
     IHXListIterator* pIterField = NULL;
     IUnknown* pUnkField = NULL;
     IHXMIMEField* pField = NULL;
-    BOOL bMatched = FALSE;
+    HXBOOL bMatched = FALSE;
 
     SPRTSPTransportParams spSelectedParams;
     RTSPTransportParams* pSelectedParams;
@@ -829,17 +838,16 @@
     return bMatched;
 }
 
-
-BOOL
+HXBOOL
 RTSPTransportInstantiator::CanUseTransport(RTSPTransportParams* pParams,
-                                       BOOL bAllowRARTP,
-                                       BOOL bForceRTP, 
-                                       BOOL bAllowDest, 
-                                       BOOL bIsRealDataType,
-                                       BOOL bMulticastOK,
-                                       BOOL bRequireMulticast,
-                                       BOOL bIsMidBox,
-                                       BOOL bIsFirstSetup)
+                                       HXBOOL bAllowRARTP,
+                                       HXBOOL bForceRTP, 
+                                       HXBOOL bAllowDest, 
+                                       HXBOOL bIsRealDataType,
+                                       HXBOOL bMulticastOK,
+                                       HXBOOL bRequireMulticast,
+                                       HXBOOL bIsMidBox,
+                                       HXBOOL bIsFirstSetup)
 {
     STRACE1(this);
 
@@ -922,231 +930,6 @@
 }
 
 /**
- * \brief selectTransport - select a transport to use for data transfer.
- *
- * selectTransport - select a transport to use from the list of transports 
- * the client provided. The rules the server uses to prioritize transports
- * are embedded in this code
- *
- * \param streamNumber [in]
- * \param bAllowRARTP [in] : if TRUE we can use RTP xport with a real datatype 
- * \param bForceRTP [in]
- * \param bAllowDest [in]
- *
- * \return TRUE if we were successful in finding a transport
- */
-HX_RESULT
-RTSPTransportInstantiator::selectTransport(
-             BOOL bAllowRARTP,
-             BOOL bForceRTP, 
-             BOOL bAllowDest, 
-             BOOL bIsRealDataType,
-             BOOL bMulticastOK,
-             BOOL bRequireMulticast,
-             BOOL bIsMidBox,
-             BOOL bIsFirstSetup, 
-             RTSPTransportParams* pExistingAggregateParams,
-             UINT32 ulControlID,
-             UINT16 uStreamNumber)
-{
-#if 0
-    printf("RTSPTransportInstantiator(%p)::selectTransport\n" \
-                       "pExistingAggregateParams %p\n" \
-                       "\tcontrol id             %d\n" \
-                       "\tstream number          %d\n" \
-                       "\tbAllowRARTP            %d\n" \
-                       "\tbForceRTP              %d\n" \
-                       "\tbAllowDest             %d\n" \
-                       "\tbIsRealDataType        %d\n" \
-                       "\tbMulticastOK           %d\n" \
-                       "\tbRequireMulticast      %d\n" \
-                       "\tbIsMidBox              %d\n" \
-                       "\tbIsFirstSetup          %d\n",
-            this, pExistingAggregateParams, (int)ulControlID, 
-            (int)uStreamNumber,
-            bAllowRARTP, bForceRTP, bAllowDest, bIsRealDataType,
-            bMulticastOK, bRequireMulticast, bIsMidBox, bIsFirstSetup);
-#endif
-
-    STRACE1(this);
-    LISTPOSITION pos;
-    RTSPTransportParams* pParams;
-    RTSPTransportParams* pSelectedParams = NULL;
-
-    if (pExistingAggregateParams)
-    {
-        BOOL bMatch = FALSE;
-
-        if (CanUseTransport(pExistingAggregateParams, bAllowRARTP, 
-                     bForceRTP, bAllowDest, bIsRealDataType, bMulticastOK,
-                     bRequireMulticast, bIsMidBox, bIsFirstSetup))
-        {
-            pos = m_transportParamsList.GetHeadPosition();
-            while (pos)
-            {
-                pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
-
-                if (*pParams == *pExistingAggregateParams)
-                {
-                    bMatch = TRUE;
-                }
-            }
-
-            /** if we have a match we want to remove all the entries 
-                in our list and replace them with the aggregate 
-                (which already has a socket - so we are ready to go) */
-            if (bMatch)
-            {
-                clearTransportParamsList();
-        
-                m_transportParamsList.AddTail(pExistingAggregateParams);
-                pExistingAggregateParams->AddRef();
-        
-                m_bSelected = TRUE;
-#if 0
-                printf("RTSPTransportInstantiator(%p)::selectTransport, " \
-                       " existing agg %p matches!\n", 
-                       this, pExistingAggregateParams);
-#endif
-                return HXR_OK;
-            }
-#if 0
-            else
-            {
-                printf("RTSPTransportInstantiator(%p)::selectTransport," \
-                       "no match for existing aggregate %p\n", 
-                       this, pExistingAggregateParams);
-            }
-#endif
-        }
-    }
-
-    if (bIsFirstSetup)
-    {
-        m_usFirstStream = uStreamNumber;
-    }
-
-    /* Find the first valid transport for the given stream */
-    pos = m_transportParamsList.GetHeadPosition();
-    while (pos)
-    {
-        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
-
-        if (!m_bAggregateTransport)
-        {
-            if (pParams->m_ulStreamID != ulControlID)
-            {
-                continue;
-            }
-        }
-
-        pParams->m_streamNumber = uStreamNumber;
-
-        if (!CanUseTransport(pParams,
-                             bAllowRARTP,
-                             bForceRTP,
-                             bAllowDest,
-                             bIsRealDataType,
-                             bMulticastOK,
-                             bRequireMulticast,
-                             bIsMidBox,
-                             bIsFirstSetup))
-        {
-            continue;
-        }
-
-        // Looks like it's valid
-        pSelectedParams = pParams;
-        break;
-    }
-
-    /* Remove unused transports for the given stream */
-    pos = m_transportParamsList.GetHeadPosition();
-    while (pos)
-    {
-        LISTPOSITION curpos = pos;
-        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
-
-        if (m_bAggregateTransport || (pParams->m_ulStreamID == ulControlID))
-        {
-            if (pParams != pSelectedParams)
-            {
-                m_transportParamsList.RemoveAt(curpos);
-                HX_RELEASE(pParams);
-            }
-        }
-    }
-
-    /** At this point if there is a selected transport the list will
-      * either have a single set of transport params in it (if its
-      * an aggregate) or one set of params per stream that has been 
-      * setup so far */
-
-    if (pSelectedParams)
-    {
-        /** We have selected a transport, now we need to know whether
-          * we need to create a socket or share one.
-          *
-          * We need to create a socket if :
-          *        the transport type is one of the UDP transports
-          *        AND the transport is RTP OR its RDT and its the 
-          *        first setup (later setups share the same channel 
-          *        with RDT)
-          *
-          * Note that if the transport is an aggregate createUDPSockets()
-          * will only actually create the socket the first time through.
-          * If its BCNG the underlying transport creates the socket, we
-          * never create here.
-          */
-        HX_RESULT rc = HXR_OK;
-        BOOL bIsRDTUDPClient = 
-                 (IS_CLIENT_TRANSPORT(pSelectedParams->m_lTransportType) &&
-                  !IS_TCP_TRANSPORT(pSelectedParams->m_lTransportType) &&
-                  IS_RDT_TRANSPORT(pSelectedParams->m_lTransportType));
-
-        m_bSelected = TRUE;
-
-        if (!m_bAggregateTransport && bIsRDTUDPClient && !bIsFirstSetup)
-        {
-            /// share the first UDP socket created if RDTvUDP
-            SPRTSPTransportParams spFirstParams;
-
-            GetTransportParams(spFirstParams.AsInOutParam(), m_usFirstStream);
-
-            HX_ASSERT(IS_RDT_TRANSPORT(spFirstParams->m_lTransportType));
-
-            pSelectedParams->m_pSockets[0] = spFirstParams->m_pSockets[0];
-            pSelectedParams->m_pSockets[0]->AddRef();
-        }
-        else
-        {
-            /// we don't need a socket if this is BCNG - special case
-            if (IS_UDP_TRANSPORT(pSelectedParams->m_lTransportType) &&
-                !IS_BCNG_TRANSPORT(pSelectedParams->m_lTransportType))
-            {
-                rc = createUDPSockets(pSelectedParams);
-            }
-        }
-
-        if (!SUCCEEDED(rc))
-        {
-            pSelectedParams = NULL;
-            m_bSelected = FALSE;
-        }
-    }
-
-#if 0
-    printf("RTSPTransportInstantiator(%p)::selectTransport, selected %p, %s\n", 
-               this, pSelectedParams, pSelectedParams ?
-               RTSPTransportMimeMapper::getTransportMimeType(
-                            pSelectedParams->m_lTransportType) : "NULL");
-#endif
-
-    return (pSelectedParams != NULL ? HXR_OK : HXR_FAIL);
-}
-
-
-/**
  * \brief GetTransportParams - return the transport information for a given stream
  *
  * \param ppParams [in] RTSPTransportParams** holds return result
@@ -1175,10 +958,10 @@
         return HXR_FAIL;
     }
 
-    pos = m_transportParamsList.GetHeadPosition();
+    pos = m_selectedTransportList.GetHeadPosition();
     while (pos)
     {
-        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
+        pParams = (RTSPTransportParams*)m_selectedTransportList.GetNext(pos);
 
         if (m_bAggregateTransport || 
                 (pParams->m_streamNumber == streamNumber))
@@ -1192,7 +975,6 @@
     return HXR_FAIL;
 }
 
-
 HX_RESULT
 RTSPTransportInstantiator::SetBCNGParameters(UINT16 uStreamNumber,
                                          UINT32 ulSessionID, UINT32 ulStartTime,  
@@ -1225,7 +1007,7 @@
  * \return pointer to the new header
  */
 IHXMIMEHeader*
-RTSPTransportInstantiator::MakeTransportHeader (BOOL bAggregate, UINT16 \
uStreamNumber) +RTSPTransportInstantiator::MakeTransportHeader (UINT16 uStreamNumber)
 {
     STRACE1(this);
 
@@ -1248,7 +1030,7 @@
         return NULL;
     }
 
-    if (bAggregate)
+    if (m_bAggregateTransport)
     {
         pBuf->Set((BYTE *)"Aggregate-Transport", 19);
     }
@@ -1515,7 +1297,7 @@
 
     pSingleRefPeerAddr->SetPort(pParams->m_sPort);
 
-    BOOL bSuccess;
+    HXBOOL bSuccess;
     do
     {
         bSuccess = TRUE;
@@ -1609,7 +1391,7 @@
     return HXR_OK;
 }
 
-BOOL
+HXBOOL
 RTSPTransportInstantiator::DataCapableTransportExists(void)
 {
     LISTPOSITION pos;
@@ -1750,13 +1532,13 @@
         rc = pTransport->init(m_pContext, pUDPSocket, m_pBaseProt);
         pTransport->IncrProtocolCount();
 
-        /** If this is an aggregate transport we need to tell the transport
+        /** If the socket might be re-used we need to tell the transport
           * because it will close the socket when it is torn down otherwise.
           * This is only relevant with UDP.
           */
-        if (pTransParams->m_bAggregateTransport)
+        if (m_bReusable)
         {
-            pTransport->SetAsAggregate();
+            pTransport->ReuseSocket();
         }
 
         IHXSockAddr* pPeerAddr = getPeerAddress(pTransParams);
@@ -1951,13 +1733,13 @@
     rc = pTransport->init(m_pContext, pSockets[0], m_pBaseProt);
     pTransport->IncrProtocolCount();
 
-    /** If this is an aggregate transport we need to tell the transport
-      * because it will close the socket when it is torn down otherwise.
-      * This is only relevant with UDP.
-      */
-    if (pTransParams->m_bAggregateTransport)
+    /** If the socket might be re-used we need to tell the transport
+     * because it will close the socket when it is torn down otherwise.
+     * This is only relevant with UDP.
+     */
+    if (m_bReusable)
     {
-        pTransport->SetAsAggregate();
+        pTransport->ReuseSocket();
     }
 
     m_pBaseProt->AddTransport(pTransport, pSession->m_sessionID,
@@ -2028,18 +1810,18 @@
                             usStreamNumber);
         }
 
-        /** If this is an aggregate transport we need to tell the transport
+        pRTCPTran->setSessionID(pSession->m_sessionID);
+        pTransport->setRTCPTransport(pRTCPTran);
+
+        /** If the socket might be re-used we need to tell the transport
           * because it will close the socket when it is torn down otherwise.
           * This is only relevant with UDP.
           */
-        if (pTransParams->m_bAggregateTransport)
+        if (m_bReusable)
         {
-            pRTCPTran->SetAsAggregate();
+            pRTCPTran->ReuseSocket();
         }
 
-        pRTCPTran->setSessionID(pSession->m_sessionID);
-        pTransport->setRTCPTransport(pRTCPTran);
-
         //Add StreamInfo to RTCP transport.
         pRTCPTran->addStreamInfo(pStreamInfo);
 
@@ -2209,7 +1991,7 @@
     RTSPStreamInfo* pStreamInfo,
     RTSPTransportParams* pTransParams,
     UINT16 usStreamNumber,
-    BOOL bIsPre12Dot1Proxy)
+    HXBOOL bIsPre12Dot1Proxy)
 {
 #ifndef HELIX_FEATURE_SERVER_BCNG
     return HXR_FAIL;
@@ -2327,6 +2109,53 @@
     return HXR_NOTIMPL;
 }
 
+HXBOOL
+RTSPTransportInstantiator::CanUseTransport(RTSPTransportParams* pParams, 
+                                           RTSPServerSession* pSession,
+                                           UINT16 usStreamNumber)
+{
+    HX_ASSERT(pSession != NULL);
+
+    HXBOOL bAllowRARTP = FALSE;
+    HXBOOL bAllowDest = FALSE;
+
+    if (!pSession->m_ppStreamInfo || 
+        usStreamNumber >= pSession->m_uStreamCount ||
+        !pSession->m_ppStreamInfo[usStreamNumber])
+    {
+        HX_ASSERT(FALSE);
+        return HXR_UNEXPECTED;
+    }
+
+    /** \The idea here is to only allow realAudio via RTP if we have either
+      * already completed the RARTP challenge OR we have not started 
+      * the challenge process yet.
+      */
+    if (m_pBaseProt->m_bRARTPChallengeMet || m_pBaseProt->m_ulChallengeInitMethod == \
RTSP_VERB_NONE) +    {
+        if (pSession->m_bSupportsRARTPChallenge)
+        {
+            bAllowRARTP = TRUE;
+        }
+    }
+
+    INT32 lDestAddrSupported = 0;
+    if (m_pBaseProt->m_pRegistry->GetIntByName("config.SupportRTSPDestinationAddress", \
lDestAddrSupported) == HXR_OK) +    {
+        if (lDestAddrSupported)
+        {
+            bAllowDest = TRUE;
+        }
+    }
+
+    return CanUseTransport(pParams, bAllowRARTP, 
+                            pSession->m_ppStreamInfo[usStreamNumber]->m_bForceRTP,
+                            bAllowDest, pSession->m_bIsRealDataType,
+                            pSession->m_bMulticastOK,
+                            pSession->m_bRequireMulticast,
+                            pSession->m_bIsMidBox, !m_bSelected);
+}
+
 /**
  * \brief selectTransport - help the RTSPServerProtocol select a transport
  *
@@ -2345,116 +2174,349 @@
 
 HX_RESULT
 RTSPTransportInstantiator::selectTransport(RTSPServerSession* pSession,
-                                    UINT16 usStreamNumber)
+                                            UINT16 uStreamNumber)
 {
+    STRACE1(this);
+
     HX_ASSERT(pSession != NULL);
 
-    BOOL bAllowRARTP = FALSE;
-    BOOL bAllowDest = FALSE;
-    UINT32 ulControlID;
+    if (!pSession->m_ppStreamInfo || 
+        uStreamNumber >= pSession->m_uStreamCount ||
+        !pSession->m_ppStreamInfo[uStreamNumber])
+    {
+        HX_ASSERT(FALSE);
+        return HXR_UNEXPECTED;
+    }
 
-    /** With an aggregate transport it is implied that all the streams
-      * use the same underlying transport. So we use the "ForceRTP" from
-      * the first stream to apply across all of them. This is why the 
-      * stream number defaults to 0 in this case. */
-    BOOL bForceRTP = FALSE;
+    UINT32 ulControlID = pSession->m_ppStreamInfo[uStreamNumber]->m_ulControlID;
 
-    if (pSession->m_ppStreamInfo != NULL && pSession->m_uStreamCount)
+    /** Technically this code can't currently be reached in the proxy case,
+      * so the m_pProxyLocalAddr check is for possible future reference */
+    IHXSockAddr* pLocalAddr = m_pBaseProt->m_pProxyLocalAddr;
+
+    if (pLocalAddr)
     {
-        if (!pSession->m_ppStreamInfo[usStreamNumber])
+        pLocalAddr->AddRef();
+    }
+    else
+    {
+        if (FAILED(m_pBaseProt->m_pSock->GetLocalAddr(&pLocalAddr)))
         {
             HX_ASSERT(FALSE);
-            return HXR_UNEXPECTED;
+            return HXR_FAIL;
         }
     }
+ 
+    setLocalAddress(pLocalAddr);
+    HX_RELEASE(pLocalAddr);
 
-    bForceRTP = pSession->m_ppStreamInfo[usStreamNumber]->m_bForceRTP;
-    ulControlID = pSession->m_ppStreamInfo[usStreamNumber]->m_ulControlID;
+    LISTPOSITION pos;
+    LISTPOSITION curpos;
+    RTSPTransportParams* pParams;
+    RTSPTransportParams* pSelectedParams = NULL;
 
-    /** \The idea here is to only allow realAudio via RTP if we have either
-      * already completed the RARTP challenge OR we have not started 
-      * the challenge process yet.
-      */
-    if (m_pBaseProt->m_bRARTPChallengeMet || m_pBaseProt->m_ulChallengeInitMethod == \
RTSP_VERB_NONE) +    /* Find the first valid transport for the given stream */
+    pos = m_transportParamsList.GetHeadPosition();
+    while (pos)
     {
-        if (pSession->m_bSupportsRARTPChallenge)
+        curpos = pos;
+        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
+
+        if (!m_bAggregateTransport)
         {
-            bAllowRARTP = TRUE;
+            if (pParams->m_ulStreamID != ulControlID)
+            {
+                continue;
+            }
         }
+
+        pParams->m_streamNumber = uStreamNumber;
+
+        if (!CanUseTransport(pParams, pSession, uStreamNumber))
+        {
+            continue;
+        }
+
+        // Looks like it's valid
+        // Select it and move it from available to selected
+        pSelectedParams = pParams;
+        m_selectedTransportList.AddTail(pParams);
+        m_transportParamsList.RemoveAt(curpos);
+        break;
     }
 
-    INT32 lDestAddrSupported = 0;
-    if (m_pBaseProt->m_pRegistry->GetIntByName("config.SupportRTSPDestinationAddress", \
lDestAddrSupported) == HXR_OK) +    /* Remove unused transports for the given stream \
*/ +    pos = m_transportParamsList.GetHeadPosition();
+    while (pos)
     {
-        if (lDestAddrSupported)
+        curpos = pos;
+        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
+
+        if (m_bAggregateTransport || (pParams->m_ulStreamID == ulControlID))
         {
-            bAllowDest = TRUE;
+            m_transportParamsList.RemoveAt(curpos);
+            HX_RELEASE(pParams);
         }
     }
 
-    /** Technically this code can't currently be reached in the proxy case,
-      * so the m_pProxyLocalAddr check is for possible future reference */
-    IHXSockAddr* pLocalAddr = m_pBaseProt->m_pProxyLocalAddr;
+    /** At this point if there is a selected transport the list will
+      * either have a single set of transport params in it (if its
+      * an aggregate) or one set of params per stream that has been 
+      * setup so far */
 
-    if (pLocalAddr)
+    if (pSelectedParams)
     {
-        pLocalAddr->AddRef();
+        /** We have selected a transport, now we need to know whether
+          * we need to create a socket or share one.
+          *
+          * We need to create a socket if :
+          *        the transport type is one of the UDP transports
+          *        AND the transport is RTP OR its RDT and its the 
+          *        first setup (later setups share the same channel 
+          *        with RDT)
+          *
+          * Note that if the transport is an aggregate createUDPSockets()
+          * will only actually create the socket the first time through.
+          * If its BCNG the underlying transport creates the socket, we
+          * never create here.
+          */
+        HX_RESULT rc = HXR_OK;
+        HXBOOL bIsRDTUDPClient = 
+                 (IS_CLIENT_TRANSPORT(pSelectedParams->m_lTransportType) &&
+                  !IS_TCP_TRANSPORT(pSelectedParams->m_lTransportType) &&
+                  IS_RDT_TRANSPORT(pSelectedParams->m_lTransportType));
+
+        if (!m_bAggregateTransport && bIsRDTUDPClient && m_bSelected)
+        {
+            /// share the first UDP socket created if RDTvUDP
+            SPRTSPTransportParams spFirstParams;
+
+            GetTransportParams(spFirstParams.AsInOutParam(), m_usFirstStream);
+
+            HX_ASSERT(IS_RDT_TRANSPORT(spFirstParams->m_lTransportType));
+
+            pSelectedParams->m_pSockets[0] = spFirstParams->m_pSockets[0];
+            pSelectedParams->m_pSockets[0]->AddRef();
+        }
+        else
+        {
+            /// we don't need a socket if this is BCNG - special case
+            if (IS_UDP_TRANSPORT(pSelectedParams->m_lTransportType) &&
+                !IS_BCNG_TRANSPORT(pSelectedParams->m_lTransportType))
+            {
+                rc = createUDPSockets(pSelectedParams);
+            }
+        }
+
+        if (SUCCEEDED(rc))
+        {
+            if (!m_bSelected)
+            {
+                m_usFirstStream = uStreamNumber;
+                m_bSelected = TRUE;
+            }
+        }
+        else
+        {
+            pSelectedParams = NULL;
+            m_bSelected = FALSE;
+        }
     }
-    else
+
+#if 0
+    printf("RTSPTransportInstantiator(%p)::selectTransport, selected %p, %s\n", 
+               this, pSelectedParams, pSelectedParams ?
+               RTSPTransportMimeMapper::getTransportMimeType(
+                            pSelectedParams->m_lTransportType) : "NULL");
+#endif
+
+    return (pSelectedParams != NULL ? HXR_OK : HXR_FAIL);
+}
+
+// Switch transport params from one session+stream to new session+stream
+HX_RESULT
+RTSPTransportInstantiator::SwitchTransport(RTSPServerSession* pOldSession,
+                                           RTSPServerSession* pNewSession,
+                                           UINT16& uOldStreamNum, 
+                                           UINT16 uNewStreamNum)
+                                           
+{
+    STRACE1(this);
+
+    LISTPOSITION pos;
+    LISTPOSITION curpos;
+    LISTPOSITION matchpos;
+    RTSPTransportParams* pParams;
+    RTSPTransportParams* pBestMatch = NULL;
+
+    // Find the transport from the old stream if given, or 
+    // best match if old is not specified
+
+    pos = m_transportParamsList.GetHeadPosition();
+    while (pos)
     {
-        if (FAILED(m_pBaseProt->m_pSock->GetLocalAddr(&pLocalAddr)))
+        curpos = pos;
+        pParams = (RTSPTransportParams*)m_transportParamsList.GetNext(pos);
+
+        // If uOldStreamNum is set IN, we need are looking specifically
+        // for that stream's transport params.
+        // Otherwise, we just want the first available, and will set 
+        // uOldStreamNum OUT to inform the caller of the chosen mapping
+
+        if (uOldStreamNum != HX_INVALID_STREAM && 
+            pParams->m_uSwitchStream != uOldStreamNum)
         {
-            HX_ASSERT(FALSE);
-            return HXR_FAIL;
+            // we are looking for a particular stream and this is not it
+        }
+        else if (!CanUseTransport(pParams, pNewSession, uNewStreamNum))
+        {
+            // this stream cannot use this transport
+        }
+        else if (uOldStreamNum == HX_INVALID_STREAM && 
+            (pParams->m_uSwitchStream != HX_INVALID_STREAM || 
+            pNewSession->m_ppStreamInfo[uNewStreamNum]->m_eMediaType !=
+            pOldSession->m_ppStreamInfo[pParams->m_uSwitchStream]->m_eMediaType))
+        {
+            // This one will work if we don't find anything better,
+            // but we need to keep looking for a media type match
+            if (!pBestMatch)
+            {
+                pBestMatch = pParams;
+                matchpos = curpos;
+            }
+        }
+        else
+        {
+            // Okay, we want this one
+            pBestMatch = pParams;
+            matchpos = curpos;
+            break;
         }
     }
 
-    setLocalAddress(pLocalAddr);
-    HX_RELEASE(pLocalAddr);
+    if (pBestMatch)
+    {
+        pParams = pBestMatch;
 
-    if (IsAggregateTransport())
+        // set the chosen old stream number
+        uOldStreamNum = pParams->m_uSwitchStream;
+
+        // set the new stream number and ID
+        pParams->m_streamNumber = uNewStreamNum;
+        pParams->m_uSwitchStream = HX_INVALID_STREAM;
+        pParams->m_ulStreamID = 
+            pNewSession->m_ppStreamInfo[uNewStreamNum]->m_ulControlID;
+        
+        // Move the params over to 'selected' list
+        m_selectedTransportList.AddTail(pParams);
+        m_transportParamsList.RemoveAt(matchpos);
+
+        if (!m_bSelected)
+        {
+            m_usFirstStream = uNewStreamNum;
+            m_bSelected = TRUE;
+        }
+
+        return HXR_OK;
+    }
+    return HXR_FAIL;
+}
+
+// Switch transport to a new stream (within the same session)
+HX_RESULT
+RTSPTransportInstantiator::SwitchStream(RTSPServerSession* pSession,
+                                        UINT16 uOldStreamNum,
+                                        UINT16 uNewStreamNum)
+{
+    STRACE1(this);
+
+    if (!m_bSelected)
     {
-        /** If pSession->m_pAggregateTransportParams is non-NULL, it
-          * points to a pre-existing aggregate that we can try to 
-          * reuse. Otherwise, we select a suitable transport from 
-          * the list we populated when we got the "Aggregate-Transport" 
-          * header
-          **/
-        if (!SUCCEEDED(selectTransport(
-                                       bAllowRARTP,
-                                       bForceRTP,
-                                       bAllowDest,
-                                       pSession->m_bIsRealDataType,
-                                       pSession->m_bMulticastOK,
-                                       pSession->m_bRequireMulticast,
-                                       pSession->m_bIsMidBox,
-                                       FALSE,
-                                       pSession->m_pAggregateTransportParams)))
+        return HXR_FAIL;
+    }
+
+    LISTPOSITION pos;
+    RTSPTransportParams* pParams;
+
+    // Find the transport from the old stream
+    pos = m_selectedTransportList.GetHeadPosition();
+    while (pos)
+    {
+        pParams = (RTSPTransportParams*)m_selectedTransportList.GetNext(pos);
+
+        if (pParams->m_streamNumber == uOldStreamNum &&
+            CanUseTransport(pParams, pSession, uNewStreamNum))
         {
-            return HXR_INVALID_PARAMETER;
+            // set the new stream number and ID
+            pParams->m_streamNumber = uNewStreamNum;
+            pParams->m_ulStreamID = \
pSession->m_ppStreamInfo[uNewStreamNum]->m_ulControlID; +
+            if (m_usFirstStream == uOldStreamNum)
+            {
+                m_usFirstStream = uNewStreamNum;
+            }
+            return HXR_OK;
         }
     }
-    else
+
+    return HXR_FAIL;
+}
+
+HX_RESULT
+RTSPTransportInstantiator::FreeTransport(UINT16 uStreamNum)
+{
+    STRACE1(this);
+
+    if (!m_bSelected)
     {
-        if (!SUCCEEDED(selectTransport(
-                                       bAllowRARTP,
-                                       bForceRTP,
-                                       bAllowDest,
-                                       pSession->m_bIsRealDataType,
-                                       pSession->m_bMulticastOK,
-                                       pSession->m_bRequireMulticast,
-                                       pSession->m_bIsMidBox,
-                                       (pSession->m_sSetupCount == 1),
-                                       NULL,
-                                       ulControlID,
-                                       usStreamNumber)))
+        return HXR_FAIL;
+    }
+
+    LISTPOSITION pos;
+    LISTPOSITION curpos;
+    RTSPTransportParams* pParams;
+
+    // Find this stream's transport
+    pos = m_selectedTransportList.GetHeadPosition();
+    while (pos)
+    {
+        curpos = pos;
+        pParams = (RTSPTransportParams*)m_selectedTransportList.GetNext(pos);
+
+        if (pParams->m_streamNumber == uStreamNum)
         {
-            return HXR_INVALID_PARAMETER;
+            // Move from the in-use list to the available list
+            m_transportParamsList.AddTail(pParams);
+            m_selectedTransportList.RemoveAt(curpos);
+
+            return HXR_OK;
         }
     }
 
-    /** At this point we should have chosen an appropriate
-     *  set of transport params. */
+    // Maybe this should check if this one is set as m_usFirstStream
+    // and try to set something else?? This shouldn't matter though,
+    // I don't think m_usFirstStream is relevant at this point
+    
+    return HXR_FAIL;
+}
+
+HX_RESULT
+RTSPTransportInstantiator::PrepareSwitch()
+{
+    STRACE1(this);
+
+    RTSPTransportParams* pParams;
+
+    m_bSelected = FALSE;
+
+    // Move all transports from in-use to available
+    while(!m_selectedTransportList.IsEmpty())
+    {
+        pParams = (RTSPTransportParams*)m_selectedTransportList.RemoveHead();
+        pParams->m_uSwitchStream = pParams->m_streamNumber;
+        pParams->m_streamNumber = HX_INVALID_STREAM;
+        m_transportParamsList.AddTail(pParams);
+    }
 
     return HXR_OK;
 }


_______________________________________________
Server-cvs mailing list
Server-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/server-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic