rtspclnt.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 218k
Category:

Symbian

Development Platform:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: rtspclnt.cpp,v 1.63.2.8.2.1 2004/12/13 23:10:25 gwright Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #if defined _UNIX
  51. #if defined _SOLARIS || defined _IRIX || defined _FREEBSD || defined _OPENBSD || defined _NETBSD
  52. #include <sys/types.h>
  53. #endif
  54. #include <sys/socket.h>
  55. #include <netinet/in.h>
  56. #ifndef _BEOS
  57. #include <arpa/inet.h>
  58. #endif
  59. #endif
  60. #include <stdlib.h>
  61. #include "hxtypes.h"
  62. #include "timeval.h"
  63. #include "hxstring.h"
  64. #include "hxslist.h"
  65. #include "hxmarsh.h"
  66. #include "hxtick.h"
  67. #include "netbyte.h"
  68. #include "hxengin.h"
  69. #include "hxcore.h"
  70. #include "hxpnets.h"
  71. #include "ihxpckts.h"
  72. #include "hxcomm.h"
  73. #include "hxprefs.h"
  74. #include "hxpref.h"
  75. #include "hxplugn.h"
  76. #include "hxencod.h"
  77. #include "hxrsdbf.h"
  78. #include "plghand2.h"
  79. #ifdef HELIX_FEATURE_SERVER
  80. #include "plgnhand.h"
  81. #endif
  82. #include "hxplugn.h"
  83. #include "hxsdesc.h"
  84. #include "netbyte.h"
  85. #include "chxpckts.h"
  86. #include "asmrulep.h"
  87. #include "growingq.h"
  88. #include "mimehead.h"
  89. #include "mimescan.h"
  90. #include "timerep.h"
  91. #include "hxthread.h"
  92. #include "rtspmsg.h"
  93. #include "rtsppars.h"
  94. #include "rtspmdsc.h"
  95. #include "basepkt.h"
  96. #include "servrsnd.h"
  97. #include "portaddr.h"
  98. #include "chxkeepalive.h"
  99. #include "rtspclnt.h"
  100. #include "rtsputil.h"
  101. #include "sdptools.h"
  102. #include "hxurl.h"
  103. #include "hxstrutl.h"
  104. #include "trmimemp.h"
  105. #include "rtptypes.h"
  106. #include "stream_desc_hlpr.h"
  107. #include "hxheap.h"
  108. #ifdef _DEBUG
  109. #undef HX_THIS_FILE
  110. static const char HX_THIS_FILE[] = __FILE__;
  111. #endif
  112. #define RN_COMMON_MIME_TYPE_FRAGMENT "x-pn-"
  113. #ifndef BUFFER_DEPTH_UNDEFINED
  114. #define BUFFER_DEPTH_UNDEFINED 0xffffffff
  115. #endif
  116. #define MULTICAST_ADDRESS_RANGE_LOW     3758096384  // 224.0.0.0
  117. #define MULTICAST_ADDRESS_RANGE_HIGH    4026531839  // 239.255.255.255
  118. #define DEFAULT_SERVER_TIMEOUT          90          // in seconds
  119. #define MINIMUM_TIMEOUT                 5           // in seconds
  120. const RTSPTableEntry RTSPClientProtocol::zm_pRTSPTable[RTSP_TABLE_SIZE] =
  121. {
  122.     { "SETUP", SETUP     },
  123.     { "REDIRECT", REDIRECT    },
  124.     { "PLAY", PLAY     },
  125.     { "PAUSE", PAUSE     },
  126.     { "SET_PARAMETER", SET_PARAM   },
  127.     { "GET_PARAMETER", GET_PARAM   },
  128.     { "OPTIONS", OPTIONS     },
  129.     { "DESCRIBE", DESCRIBE    },
  130.     { "TEARDOWN", TEARDOWN    },
  131.     { "RECORD", RECORD     },
  132.     { "ANNOUNCE", ANNOUNCE    }
  133. };
  134. /*
  135.  * RTSPTransportInfo methods
  136.  */
  137. RTSPTransportInfo::RTSPTransportInfo():
  138.     m_pTransport(0),
  139.     m_pRTCPTransport(0)
  140. {
  141. }
  142. RTSPTransportInfo::~RTSPTransportInfo()
  143. {
  144.     if(m_pTransport)
  145.     {
  146. m_pTransport->Done();
  147.     }
  148.     if(m_pRTCPTransport)
  149.     {
  150. m_pRTCPTransport->Done();
  151.     }
  152.     HX_RELEASE(m_pTransport);
  153.     HX_RELEASE(m_pRTCPTransport);
  154. }
  155. void
  156. RTSPTransportInfo::addStreamNumber(UINT16 streamNumber)
  157. {
  158.     m_streamNumberList.AddTail((void*)streamNumber);
  159. }
  160. BOOL
  161. RTSPTransportInfo::containsStreamNumber(UINT16 streamNumber)
  162. {
  163.     CHXSimpleList::Iterator i;
  164.     for(i=m_streamNumberList.Begin();i!=m_streamNumberList.End();++i)
  165.     {
  166. UINT16 sNumber = (UINT16)(PTR_INT)(*i);
  167. if(sNumber == streamNumber)
  168. {
  169.     return TRUE;
  170. }
  171.     }
  172.     return FALSE;
  173. }
  174. /*
  175.  * RTSPTransportRequest methods
  176.  */
  177. RTSPTransportRequest::RTSPTransportRequest(RTSPTransportTypeEnum tType,
  178.     UINT16 sPort):
  179. m_lTransportType(tType),
  180. m_sPort(sPort),
  181. m_bDelete(FALSE)
  182. {
  183. }
  184. RTSPTransportRequest::~RTSPTransportRequest()
  185. {
  186.     CHXSimpleList::Iterator i;
  187.     for(i=m_transportInfoList.Begin();i!=m_transportInfoList.End();++i)
  188.     {
  189. RTSPTransportInfo* pInfo = (RTSPTransportInfo*)(*i);
  190. delete pInfo;
  191.     }
  192. }
  193. RTSPTransportInfo*
  194. RTSPTransportRequest::getTransportInfo(UINT16 streamNumber)
  195. {
  196.     CHXSimpleList::Iterator i;
  197.     for(i=m_transportInfoList.Begin();i!=m_transportInfoList.End();++i)
  198.     {
  199. RTSPTransportInfo* pInfo = (RTSPTransportInfo*)(*i);
  200. if(pInfo->containsStreamNumber(streamNumber))
  201. {
  202.     return pInfo;
  203. }
  204.     }
  205.     return 0;
  206. }
  207. RTSPTransportInfo*
  208. RTSPTransportRequest::getFirstTransportInfo()
  209. {
  210.     m_lListPos = m_transportInfoList.GetHeadPosition();
  211.     if(m_lListPos)
  212.     {
  213. return (RTSPTransportInfo*)m_transportInfoList.GetNext(m_lListPos);
  214.     }
  215.     return 0;
  216. }
  217. RTSPTransportInfo*
  218. RTSPTransportRequest::getNextTransportInfo()
  219. {
  220.     if(m_lListPos)
  221.     {
  222. return (RTSPTransportInfo*)m_transportInfoList.GetNext(m_lListPos);
  223.     }
  224.     return 0;
  225. }
  226. HX_RESULT
  227. RTSPTransportRequest::addTransportInfo(RTSPTransport* pTrans,
  228.     RTCPBaseTransport* pRTCPTrans, UINT16 streamNumber, UINT16 sPort)
  229. {
  230.     HX_RESULT retVal = HXR_OK;
  231.     RTSPTransportInfo* pTransInfo = new RTSPTransportInfo;
  232.     if(pTransInfo)
  233.     {
  234.         pTransInfo->m_pTransport = pTrans; // already AddRef'd
  235.         pTransInfo->m_pRTCPTransport = pRTCPTrans;
  236.         pTransInfo->addStreamNumber(streamNumber);
  237.         pTransInfo->m_sPort = sPort;
  238.         LISTPOSITION listRet = m_transportInfoList.AddTail(pTransInfo);
  239.         if( listRet == NULL )
  240.         {
  241.             HX_DELETE(pTransInfo);
  242.             retVal = HXR_OUTOFMEMORY;
  243.         }
  244.     }
  245.     else
  246.     {
  247.         retVal = HXR_OUTOFMEMORY;
  248.     }
  249.     return retVal;
  250. }
  251. // static initializations
  252. RTSPClientSessionManagerType RTSPClientSessionManager::zm_pSessionManager = 0;
  253. /*
  254.  * RTSPClientProtocol methods
  255.  */
  256. /*
  257.  * IUnknown methods
  258.  */
  259. STDMETHODIMP
  260. RTSPClientProtocol::QueryInterface(REFIID riid, void** ppvObj)
  261. {
  262.     QInterfaceList qiList[] =
  263.     {
  264. { GET_IIDHANDLE(IID_IUnknown), this },
  265. { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*) this },
  266. { GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*) this },
  267. { GET_IIDHANDLE(IID_IHXResolverResponse), (IHXResolverResponse*) this },
  268. { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
  269. { GET_IIDHANDLE(IID_IHXResendBufferControl), (IHXResendBufferControl*) this },
  270. { GET_IIDHANDLE(IID_IHXThinnableSource), (IHXThinnableSource*) this },
  271. { GET_IIDHANDLE(IID_IHXTransportSyncServer), (IHXTransportSyncServer*) this },
  272. { GET_IIDHANDLE(IID_IHXTransportBufferLimit), (IHXTransportBufferLimit*) this },
  273.     };
  274.     if(QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj) == HXR_OK)
  275.     {
  276. return HXR_OK;
  277.     }
  278.     else if (m_pTransportStreamMap &&
  279.      !m_pTransportStreamMap->IsEmpty() &&
  280.      ((void *)((*m_pTransportStreamMap)[0])) &&
  281.      (HXR_OK == ((RTSPTransport*)(*m_pTransportStreamMap)[0])->
  282. QueryInterface(riid, ppvObj)))
  283.     {
  284. return HXR_OK;
  285.     }
  286.     *ppvObj = NULL;
  287.     return HXR_NOINTERFACE;
  288. }
  289. STDMETHODIMP_(UINT32)
  290. RTSPClientProtocol::AddRef()
  291. {
  292.     return InterlockedIncrement(&m_lRefCount);
  293. }
  294. STDMETHODIMP_(UINT32)
  295. RTSPClientProtocol::Release()
  296. {
  297.     if (InterlockedDecrement(&m_lRefCount) > 0)
  298.     {
  299.         return m_lRefCount;
  300.     }
  301.     delete this;
  302.     return 0;
  303. }
  304. /*
  305.  * RTSPClientProtocol methods
  306.  */
  307. RTSPClientProtocol::RTSPClientProtocol():
  308.     m_foreignPort(0),
  309.     m_pTransportStreamMap(0),
  310.     m_pTransportPortMap(0),
  311.     m_pTransportMPortMap(0),
  312.     m_pTransportChannelMap(0),
  313.     m_pControlToStreamNoMap(0),
  314.     m_foreignAddr(0),
  315.     m_ulConnectToAddr(0),
  316.     m_lRefCount(0),
  317.     m_pResp(0),
  318.     m_pFileHeader(0),
  319.     m_bSetupRecord(FALSE),
  320.     m_setupResponseCount(0),
  321.     m_pSessionHeaders(0),
  322.     m_pResponseHeaders(0),
  323.     m_pCloakValues(NULL),
  324.     m_pSession(0),
  325.     m_pRegistry(0),
  326.     m_bClientDone(FALSE),
  327.     m_bMessageDebug(FALSE),
  328.     m_bUseProxy(FALSE),
  329.     m_bHTTPOnly(FALSE),
  330.     m_pUDPSocketStreamMap(0),
  331.     m_pRTCPSocketStreamMap(0),
  332.     m_pResolver(0),
  333.     m_bSeqValueReceived(FALSE),
  334.     m_bNoReuseConnection(FALSE),
  335.     m_bLoadTest(FALSE),
  336.     m_bEntityRequired(TRUE),
  337.     m_pMutex(NULL),
  338.     m_uProtocolType(0),
  339.     m_pConnectionlessControl(0),
  340.     m_bConnectionlessControl(FALSE),
  341.     m_pConnectionCheckCallback(0),
  342.     m_uConnectionCheckCallbackHandle(0),
  343.     m_bConnectionAlive(FALSE),
  344.     m_uConnectionTimeout(DEFAULT_CONN_TIMEOUT),
  345.     m_ulBufferDepth(BUFFER_DEPTH_UNDEFINED),
  346.     m_pInterruptState(NULL),
  347.     m_pScheduler(NULL),
  348.     m_bUseHTTPProxy(FALSE),
  349.     m_bSplitterConsumer(FALSE),
  350.     m_pPacketFilter(NULL),
  351.     // workaround...
  352.     m_bNonRSRTP(FALSE),
  353.     m_pSetupRequestHeader(NULL),
  354.     m_bPlayJustSent(FALSE),
  355.     m_bIPTV(FALSE),
  356.     m_bColumbia(FALSE),
  357.     m_bNoKeepAlive(FALSE),
  358.     m_bForceUCaseTransportMimeType(FALSE),
  359.     m_bPrefetch(FALSE),
  360.     m_bFastStart(FALSE),
  361.     m_pCloakPorts(NULL),
  362.     m_nCloakPorts(0),
  363.     m_currentTransport(TCPMode),
  364.     m_bReportedSuccessfulTransport(FALSE),
  365.     m_bSDPInitiated(FALSE),
  366.     m_bMulticast(FALSE),
  367.     m_ulMulticastAddress(0),
  368.     m_pSDPFileHeader(NULL),
  369.     m_pSDPStreamHeaders(NULL),
  370.     m_bSessionSucceeded(FALSE),
  371.     m_bHasSyncMasterStream(FALSE),
  372.     m_pNetworkServices(NULL),
  373.     m_pPreferences(NULL),
  374.     m_pSessionTimeout(NULL),
  375.     m_pTimeoutCallback(NULL),
  376.     m_bUseLegacyTimeOutMsg(TRUE),
  377.     m_bKeepAlivePending(FALSE),
  378.     m_bPaused(FALSE),
  379.     m_ulServerTimeOut(DEFAULT_SERVER_TIMEOUT),
  380.     m_ulCurrentTimeOut(0),
  381.     m_pUAProfURI(NULL),
  382.     m_pUAProfDiff(NULL)
  383. #if defined(_MACINTOSH)
  384.     , m_pCallback(NULL)
  385. #endif /* _MACINTOSH */
  386. {
  387.     /*
  388.      * Byte queue must be as large as possible because messages may be
  389.      * bigger than MAX_RTSP_MSG
  390.      */
  391.     m_state = RTSPClientProtocol::INIT;
  392.     // all methods supported...
  393.     memset(m_pIsMethodSupported, 1, sizeof(BOOL) * RTSP_TABLE_SIZE);
  394. #ifdef THREADS_SUPPORTED
  395. HXMutex::MakeMutex(m_pMutex);
  396. #else
  397. HXMutex::MakeStubMutex(m_pMutex);
  398. #endif
  399. }
  400. RTSPClientProtocol::~RTSPClientProtocol()
  401. {
  402.     clearStreamInfoList();
  403.     clearTransportRequestList();
  404.     clearUDPResponseHelperList();
  405.     reset();
  406.     HX_DELETE(m_pMutex);
  407.     HX_RELEASE(m_pUAProfDiff);
  408.     HX_RELEASE(m_pUAProfURI);
  409.     HX_RELEASE(m_pPreferences);
  410.     HX_RELEASE(m_pNetworkServices);
  411.     HX_RELEASE(m_pRegistry);
  412.     HX_RELEASE(m_pFileHeader);
  413.     HX_RELEASE(m_pSessionHeaders);
  414.     HX_RELEASE(m_pResponseHeaders);
  415.     HX_RELEASE(m_pCloakValues);
  416.     HX_RELEASE(m_pInterruptState);
  417.     HX_RELEASE(m_pScheduler);
  418. }
  419. /*
  420.  * IHXRTSPClientProtocol methods
  421.  */
  422. void
  423. RTSPClientProtocol::SetSplitterConsumer(BOOL b)
  424. {
  425.     m_bSplitterConsumer = b;
  426. }
  427. STDMETHODIMP
  428. RTSPClientProtocol::Init(IUnknown* pContext,
  429. const char* pHostName,
  430. UINT16 foreignPort,
  431. IHXRTSPClientProtocolResponse* pClient,
  432. UINT32 initializationType,
  433. IHXValues* pSessionHeaders,
  434. IHXValues* pInfo,
  435. BOOL bHTTPCloak,
  436. UINT16 uCloakPort,
  437. BOOL bNoReuseConnection)
  438. {
  439.     m_pSessionManager = RTSPClientSessionManager::instance();
  440.     return InitExt(pContext,
  441.    pHostName,
  442.    foreignPort,
  443.    pClient,
  444.    initializationType,
  445.    pSessionHeaders,
  446.    pInfo,
  447.    bHTTPCloak,
  448.    uCloakPort,
  449.    bNoReuseConnection);
  450. }
  451. HX_RESULT
  452. RTSPClientProtocol::InitExt(IUnknown*   pContext,
  453.     const char* pHostName,
  454.     UINT16 foreignPort,
  455.     IHXRTSPClientProtocolResponse* pClient,
  456.     UINT32 initializationType,
  457.     IHXValues* pSessionHeaders,
  458.     IHXValues* pInfo,
  459.     BOOL bHTTPCloak,
  460.     UINT16 uCloakPort,
  461.     BOOL bNoReuseConnection)
  462. {
  463.     HX_RESULT       hresult = HXR_OK;
  464.     IUnknown*     pUnknown = NULL;
  465.     IHXResolver*    pResolver = NULL;
  466.     IHXBuffer*      pBuffer = NULL;
  467.     IHXBuffer*      pHostBuffer = NULL;
  468.     IHXBuffer*      pSrcBuffer = NULL;
  469.     IHXValues*      pURLProps = NULL;
  470.     CHXURL*         pURL = NULL;
  471.     if (!m_pContext)
  472.     {
  473. m_pContext = pContext;
  474. m_pContext->AddRef();
  475.     }
  476.     if (!m_pResp)
  477.     {
  478. m_pResp = pClient;
  479. m_pResp->AddRef();
  480.     }
  481.     HX_RELEASE(m_pCommonClassFactory);
  482.     hresult = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  483.                                          (void**) &m_pCommonClassFactory);
  484.     if (HXR_OK != hresult)
  485.     {
  486.         goto cleanup;
  487.     }
  488.     HX_RELEASE(m_pInterruptState);
  489.     hresult = m_pContext->QueryInterface(IID_IHXInterruptState,
  490.                                          (void**) &m_pInterruptState);
  491.     if (HXR_OK != m_pContext->QueryInterface(IID_IHXNetworkServices, (void**)&m_pNetworkServices) ||
  492. HXR_OK != m_pContext->QueryInterface(IID_IHXPreferences, (void**)&m_pPreferences))
  493.     {
  494. hresult = HXR_FAILED;
  495.         goto cleanup;
  496.     }
  497.     if (NULL == pHostName &&
  498.         NULL != pInfo &&
  499.         HXR_OK == pInfo->GetPropertyCString("helix-sdp", pSrcBuffer))
  500.     {
  501.         m_bSDPInitiated = TRUE;
  502.         if (HXR_OK != ParseSDP("application/sdp", pSrcBuffer))
  503.         {
  504.             hresult = HXR_FAILED;
  505.             goto cleanup;
  506.         }
  507.         if (!m_sessionHost.IsEmpty())
  508.         {
  509.     UINT32 addr = HXinet_addr((const char*)m_sessionHost);
  510.     UINT32 ulHostAddr = DwToHost(addr);
  511.             if (ulHostAddr >= MULTICAST_ADDRESS_RANGE_LOW &&
  512.                 ulHostAddr <= MULTICAST_ADDRESS_RANGE_HIGH)
  513.             {
  514.                 m_bMulticast = TRUE;
  515.                 m_ulMulticastAddress = ulHostAddr;
  516.                 pHostName = (const char*)m_sessionHost;
  517.                 pInfo->SetPropertyULONG32("MulticastOnly", 1);
  518.                 m_pSDPFileHeader->SetPropertyULONG32("LiveStream", 1);
  519.             }
  520.         }
  521.         if (!m_bMulticast)
  522.         {
  523.             pURL = new CHXURL(m_headerControl);
  524.             if (!(pURLProps = pURL->GetProperties()))
  525.             {
  526.                 hresult = HXR_FAILED;
  527.                 goto cleanup;
  528.             }
  529.             ULONG32 ulForeignPort = 0;
  530.             pURLProps->GetPropertyULONG32(PROPERTY_PORT, ulForeignPort);
  531.             foreignPort = (UINT16)ulForeignPort;
  532.             if (HXR_OK != pURLProps->GetPropertyBuffer(PROPERTY_HOST, pHostBuffer))
  533.             {
  534.                 hresult = HXR_FAILED;
  535.                 goto cleanup;
  536.             }
  537.             pHostName = (char*)pHostBuffer->GetBuffer();
  538.         }
  539.     }
  540.     ReadPrefINT32(m_pPreferences, "ConnectionTimeOut", m_uConnectionTimeout);
  541.     ReadPrefINT32(m_pPreferences, "ServerTimeOut", m_ulServerTimeOut);
  542.     if (m_ulServerTimeOut < MINIMUM_TIMEOUT)
  543.     {
  544.         m_ulServerTimeOut = MINIMUM_TIMEOUT;
  545.     }
  546.     m_ulServerTimeOut *= MILLISECS_PER_SECOND;
  547.     if (bHTTPCloak && m_bUseProxy)
  548.     {
  549. m_bUseHTTPProxy = TRUE;
  550.     }
  551.     ReadPrefBOOL(m_pPreferences, "RTSPMessageDebug", m_bMessageDebug);
  552.     if (m_bMessageDebug)
  553.     {
  554. if (HXR_OK == m_pPreferences->ReadPref("RTSPMessageDebugFile", pBuffer))
  555. {
  556.     if (pBuffer->GetSize() <= 0)
  557.     {
  558. // no file name, no log
  559. m_bMessageDebug = FALSE;
  560.     }
  561.     else
  562.     {
  563. m_messageDebugFileName = (const char*)pBuffer->GetBuffer();
  564.     }
  565. }
  566.         HX_RELEASE(pBuffer);
  567.     }
  568.     // XXXGo - Interop workaround
  569.     ReadPrefBOOL(m_pPreferences, "NonRS", m_bNonRSRTP);
  570.     if (m_bNonRSRTP)
  571.     {
  572. m_pIsMethodSupported[SET_PARAM] = FALSE;
  573. m_pIsMethodSupported[GET_PARAM] = FALSE;
  574. m_pIsMethodSupported[RECORD] = FALSE;
  575. m_pIsMethodSupported[ANNOUNCE] = FALSE;
  576.     }
  577.     ReadPrefBOOL(m_pPreferences, "RTSPNoReuseConnection", bNoReuseConnection);
  578.     ReadPrefBOOL(m_pPreferences, "LoadTest", m_bLoadTest);
  579.     if (!m_pTransportStreamMap)
  580.     {
  581. m_pTransportStreamMap = new CHXMapLongToObj;
  582.         if(!m_pTransportStreamMap)
  583.         {
  584.             hresult = HXR_OUTOFMEMORY;
  585.             goto cleanup;
  586.         }
  587.     }
  588.     if (!m_pTransportPortMap)
  589.     {
  590. m_pTransportPortMap = new CHXMapLongToObj;
  591.         if(!m_pTransportPortMap)
  592.         {
  593.             hresult = HXR_OUTOFMEMORY;
  594.             goto cleanup;
  595.         }
  596.     }
  597.     if (!m_pTransportMPortMap)
  598.     {
  599. m_pTransportMPortMap = new CHXMapLongToObj;
  600.         if(!m_pTransportMPortMap)
  601.         {
  602.             hresult = HXR_OUTOFMEMORY;
  603.             goto cleanup;
  604.         }
  605.     }
  606.     m_hostName = pHostName;
  607.     m_foreignPort = foreignPort;
  608.     m_bHTTPOnly = bHTTPCloak;
  609.     m_uCloakPort = uCloakPort;
  610.     m_bNoReuseConnection = bNoReuseConnection;
  611.     if (m_bHTTPOnly)
  612.     {
  613. m_currentTransport = HTTPCloakMode;
  614.     }
  615.     if(pSessionHeaders && !m_pSessionHeaders)
  616.     {
  617. m_pSessionHeaders = pSessionHeaders;
  618. m_pSessionHeaders->AddRef();
  619.     }
  620.     HX_RELEASE(m_pResponseHeaders);
  621.     if (HXR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IHXKeyValueList, (void**)&pUnknown))
  622.     {
  623. hresult = HXR_FAILED;
  624. goto cleanup;
  625.     }
  626.     if (HXR_OK != pUnknown->QueryInterface(IID_IHXKeyValueList, (void**)&m_pResponseHeaders))
  627.     {
  628. hresult = HXR_FAILED;
  629. goto cleanup;
  630.     }
  631.     if(!m_pRegistry)
  632.     {
  633. #if defined(HELIX_FEATURE_REGISTRY)
  634. // get registry ptr
  635. IHXRegistry* pRegistry = 0;
  636. hresult = m_pContext->QueryInterface(IID_IHXRegistry,
  637. (void**)&pRegistry);
  638. HX_VERIFY(HXR_OK == hresult);
  639. if(hresult == HXR_OK)
  640. {
  641.     m_pRegistry = pRegistry;
  642. }
  643. #endif /* HELIX_FEATURE_REGISTRY */
  644.     }
  645.     if(!m_pResolver)
  646.     {
  647. m_pNetworkServices->CreateResolver(&pResolver);
  648. if(!pResolver)
  649. {
  650.     hresult = HXR_OUTOFMEMORY;
  651.     goto cleanup;
  652. }
  653. HX_RELEASE(m_pResolver);
  654. m_pResolver = pResolver;
  655. m_pResolver->Init(this);
  656.         CHXString pHost;
  657. if (m_bUseHTTPProxy || m_bUseProxy)
  658. {
  659.             pHost = m_proxyHost;
  660.         }
  661.         else
  662.         {
  663.             pHost = m_hostName;
  664.         }
  665. if(IsNumericAddr(pHost, pHost.GetLength()))
  666. {
  667.     UINT32 addr = HXinet_addr((const char*)pHost);
  668.     UINT32 ulHostAddr = DwToHost(addr);
  669.     hresult = GetHostByNameDone(HXR_OK, ulHostAddr);
  670. }
  671. else
  672. {
  673.     hresult = m_pResolver->GetHostByName(pHost);
  674. }
  675.     }
  676.     HX_RELEASE(m_pScheduler);
  677.     if (HXR_OK != m_pContext->QueryInterface(IID_IHXScheduler,
  678.                                              (void**)&m_pScheduler))
  679.     {
  680. hresult = HXR_OUTOFMEMORY;
  681. goto cleanup;
  682.     }
  683.     // check for UAProf headers
  684.     if (m_pPreferences)
  685.     {
  686. HX_RELEASE(m_pUAProfURI);
  687. HX_RELEASE(m_pUAProfDiff);
  688. m_pPreferences->ReadPref("XWapProfileURI", m_pUAProfURI);
  689. m_pPreferences->ReadPref("XWapProfileDiff", m_pUAProfDiff);
  690.     }
  691. #if defined(_MACINTOSH)
  692.     if (m_pCallback &&
  693. m_pCallback->m_bIsCallbackPending &&
  694. m_pScheduler)
  695.     {
  696. m_pCallback->m_bIsCallbackPending = FALSE;
  697. m_pScheduler->Remove(m_pCallback->m_Handle);
  698.     }
  699. #endif /* _MACINTOSH */
  700. cleanup:
  701.     HX_RELEASE(pSrcBuffer);
  702.     HX_RELEASE(pURLProps);
  703.     HX_RELEASE(pUnknown);
  704.     HX_RELEASE(pHostBuffer);            
  705.     HX_DELETE(pURL);
  706.     return hresult;
  707. }
  708. STDMETHODIMP
  709. RTSPClientProtocol::SetProxy(const char* pProxyHost, UINT16 uProxyPort)
  710. {
  711.     m_bUseProxy = TRUE;
  712.     m_proxyHost = pProxyHost;
  713.     m_proxyPort = uProxyPort;
  714.     return HXR_OK;
  715. }
  716. STDMETHODIMP
  717. RTSPClientProtocol::SetResponse(IHXRTSPClientProtocolResponse* pResp)
  718. {
  719.     HX_RELEASE(m_pResp);
  720.     m_pResp = pResp;
  721.     m_pResp->AddRef();
  722.     return HXR_OK;
  723. }
  724. STDMETHODIMP
  725. RTSPClientProtocol::SetBuildVersion(const char* pVersionString)
  726. {
  727.     m_versionString = pVersionString;
  728.     return HXR_OK;
  729. }
  730. STDMETHODIMP
  731. RTSPClientProtocol::Done()
  732. {
  733.     m_bClientDone = TRUE;
  734.     if (m_pMutex)
  735.     {
  736. m_pMutex->Lock();
  737.     }
  738. #if defined(_MACINTOSH)
  739.     if (m_pCallback &&
  740. m_pCallback->m_bIsCallbackPending &&
  741. m_pScheduler)
  742.     {
  743. m_pCallback->m_bIsCallbackPending = FALSE;
  744. m_pScheduler->Remove(m_pCallback->m_Handle);
  745.     }
  746.     HX_RELEASE(m_pCallback);
  747. #endif /* _MACINTOSH */
  748.     while (!m_sessionList.IsEmpty())
  749.     {
  750. RTSPClientSession* pTempSession = (RTSPClientSession*)m_sessionList.RemoveHead();
  751. m_pSessionManager->removeFromSession(this, pTempSession);
  752.     }
  753.     HX_ASSERT(m_pSessionManager && m_pSessionManager->isValid());
  754.     if (m_pSession)
  755.     {
  756. m_pSessionManager->removeFromSession(this, m_pSession);
  757.         m_pSession = NULL;
  758.     }
  759.     HX_RELEASE(m_pSessionManager);
  760.     clearSocketStreamMap(m_pUDPSocketStreamMap);
  761.     clearSocketStreamMap(m_pRTCPSocketStreamMap);
  762.     reset();
  763.     if (m_pMutex)
  764.     {
  765. m_pMutex->Unlock();
  766.     }
  767.     return HXR_OK;
  768. }
  769. STDMETHODIMP
  770. RTSPClientProtocol::SendStreamDescriptionRequest(const char* pURL,
  771.     IHXValues* pRequestHeaders)
  772. {
  773. #ifdef _MACINTOSH
  774.     if (m_pInterruptState && m_pInterruptState->AtInterruptTime())
  775.     {
  776. /*
  777. * We cannot load DLLs (Stream Desc Plugins) at deferred time.
  778. * Also, encodeURL calls HXIsLeadByte->CharType->...internally
  779. * calls GetPort. Mac does not like that either at deferred time.
  780. * Schedule a callback and do this operation at system time
  781. */
  782. if (!m_pCallback)
  783. {
  784.     m_pCallback = new RTSPClientProtocolCallback(this);
  785.             if(!m_pCallback)
  786.             {
  787.                 return HXR_OUTOFMEMORY;
  788.             }
  789.     m_pCallback->AddRef();
  790. }
  791. HX_ASSERT(m_pScheduler);
  792. if (!m_pCallback->m_bIsCallbackPending)
  793. {
  794.     m_pCallback->m_bIsCallbackPending = TRUE;
  795.     m_pCallback->m_Handle =
  796. m_pScheduler->RelativeEnter(m_pCallback, 0);
  797. }
  798. /*
  799. * If we receive a SendStreamDescriptionRequest when
  800. * one is already pending, we do not queue them up.
  801. * The last one wins
  802. */
  803. m_pCallback->m_PendingDescURL = pURL;
  804. HX_RELEASE(m_pCallback->m_pPendingRequestHeaders);
  805. m_pCallback->m_pPendingRequestHeaders = pRequestHeaders;
  806. m_pCallback->m_pPendingRequestHeaders->AddRef();
  807. return HXR_OK;
  808.     }
  809.     HX_ASSERT(m_pScheduler);
  810.     /* remove any previously scheduled callback */
  811.     if (m_pCallback &&
  812. m_pCallback->m_bIsCallbackPending)
  813.     {
  814. m_pCallback->m_bIsCallbackPending = FALSE;
  815. m_pScheduler->Remove(m_pCallback->m_Handle);
  816.     }
  817. #endif
  818.     return sendPendingStreamDescription(pURL, pRequestHeaders);
  819. }
  820. HX_RESULT
  821. RTSPClientProtocol::sendPendingStreamDescription(const char* pURL,
  822.     IHXValues* pRequestHeaders)
  823. {
  824.     m_pMutex->Lock();
  825.     HX_RESULT rc = HXR_OK;
  826.     if (HXR_OUTOFMEMORY == extractExistingAuthorizationInformation(pRequestHeaders))
  827.     {
  828.         m_pMutex->Unlock();
  829.         return HXR_OUTOFMEMORY;
  830.     }
  831.     RTSPDescribeMessage* pMsg = new RTSPDescribeMessage;
  832.     if(!pMsg)
  833.     {
  834.         m_pMutex->Unlock();
  835.         return HXR_OUTOFMEMORY;
  836.     }
  837.     CHXString encodedURL;
  838.     CHXURL::encodeURL(pURL, encodedURL);
  839.     UINT32 stringSize = 7 + m_hostName.GetLength() + 1 + 5 + 1 + encodedURL.GetLength() + 1;
  840.     char* pURLBuffer = new char[ stringSize ];
  841.     if(!pURLBuffer)
  842.     {
  843.         HX_DELETE(pMsg);
  844.         m_pMutex->Unlock();
  845.         return HXR_OUTOFMEMORY;
  846.     }
  847.     SafeSprintf( pURLBuffer, stringSize, "rtsp://%s:%u/%s", (const char*)m_hostName, m_foreignPort, (const char*)encodedURL ); /* Flawfinder: ignore */
  848.     m_url = pURLBuffer;
  849.     delete [] pURLBuffer;
  850.     pMsg->setURL(m_url);
  851.     IHXValues* pValuesRequestHeaders = NULL;
  852.     pValuesRequestHeaders = new CHXHeader();
  853.     if(!pValuesRequestHeaders)
  854.     {
  855.         HX_DELETE(pMsg);
  856.         m_pMutex->Unlock();
  857.         return HXR_OUTOFMEMORY;
  858.     }
  859.     pValuesRequestHeaders->AddRef();
  860.     if (m_bEntityRequired)
  861.     {
  862. CHXString CHXStringRequireValue
  863. (
  864.     RTSPClientProtocol::RTSPRequireOptionsTable
  865.     [
  866. RTSPClientProtocol::RTSP_REQUIRE_ENTITY
  867.     ].pcharOption
  868. );
  869. IHXBuffer* pBufferRequireValue = NULL;
  870. CHXBuffer::FromCharArray
  871. (
  872.     CHXStringRequireValue.GetBuffer(0),
  873.     &pBufferRequireValue
  874. );
  875. // Set require header
  876. pValuesRequestHeaders->SetPropertyCString
  877. (
  878.     "Require",
  879.     pBufferRequireValue
  880. );
  881. HX_RELEASE(pBufferRequireValue);
  882.     }
  883.     addUAProfHeaders(pValuesRequestHeaders);
  884.     CHXHeader::mergeHeaders
  885.     (
  886. pValuesRequestHeaders,
  887. pRequestHeaders
  888.     );
  889.     // get all StreamDescription plugin mime types
  890.     CHXString mimeTypes;
  891.     IHXCommonClassFactory* pClassFactory     = NULL;
  892.     IHXPluginGroupEnumerator* pPluginGroupEnum    = NULL;
  893.     // ok we are going to get an IRMA PluginGroupEnumerator from the core.
  894.     if
  895.     (
  896. SUCCEEDED
  897. (
  898.     m_pContext->QueryInterface
  899.     (
  900. IID_IHXCommonClassFactory,
  901. (void**) &pClassFactory
  902.     )
  903. )
  904.     )
  905.     {
  906. pClassFactory->CreateInstance
  907. (
  908.     CLSID_IHXPluginGroupEnumerator,
  909.     (void**)&pPluginGroupEnum
  910. );
  911. HX_RELEASE(pClassFactory);
  912.     }
  913.     if(pPluginGroupEnum &&
  914.        (HXR_OK == pPluginGroupEnum->Init(IID_IHXStreamDescription)))
  915.     {
  916. IUnknown* pUnknown = NULL;
  917. ULONG32 ulNumPlugins = pPluginGroupEnum->GetNumOfPlugins();
  918. for(ULONG32 i=0;i<ulNumPlugins;++i)
  919. {
  920.     if (SUCCEEDED(pPluginGroupEnum->GetPlugin(i, pUnknown)))
  921.     {
  922.                 GetStreamDescriptionInfo(pUnknown, mimeTypes);
  923.                 HX_RELEASE(pUnknown);
  924.     }
  925. }
  926.     }
  927.     else
  928.     {
  929. // if we don't have a CCF or we don't have a pluginGroupEnumerator
  930. // then we will have to use a plugin Enumerator.
  931. IHXPluginEnumerator* pPluginEnumerator = NULL;
  932. m_pContext->QueryInterface
  933. (
  934.     IID_IHXPluginEnumerator,
  935.     (void**)&pPluginEnumerator
  936. );
  937. if(pPluginEnumerator)
  938. {
  939.     IUnknown* pUnknown = NULL;
  940.             ULONG32 ulNumPlugins = pPluginEnumerator->GetNumOfPlugins();
  941.     for(ULONG32 i=0;i<ulNumPlugins;++i)
  942.     {
  943. if(SUCCEEDED(pPluginEnumerator->GetPlugin(i, pUnknown)))
  944. {
  945.                     GetStreamDescriptionInfo(pUnknown, mimeTypes);
  946.                     HX_RELEASE(pUnknown);
  947.                 }
  948.     }
  949.     pPluginEnumerator->Release();
  950. }
  951.     }
  952.     HX_RELEASE(pPluginGroupEnum);
  953.     pMsg->addHeader("Accept", (const char*)mimeTypes);
  954.     AddCommonHeaderToMsg(pMsg);
  955.     addRFC822Headers(pMsg, pValuesRequestHeaders);
  956.     appendAuthorizationHeaders(pMsg);
  957.     HX_RELEASE(pValuesRequestHeaders);
  958.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  959.     rc = sendRequest(pMsg, seqNo);
  960.     m_pMutex->Unlock();
  961.     return rc;
  962. }
  963. STDMETHODIMP
  964. RTSPClientProtocol::SendStreamRecordDescriptionRequest(
  965.     const char* pURL,
  966.     IHXValues* pFileHeader,
  967.     CHXSimpleList* pStreams,
  968.     IHXValues* pRequestHeaders)
  969. {
  970.     HX_RESULT rc = HXR_OK;
  971.     IHXBuffer* pDescription = 0;
  972.     if (!m_pIsMethodSupported[ANNOUNCE])
  973.     {
  974. return HXR_OK;
  975.     }
  976.     // Let's make sure we have enough mem before we do the mutex lock.
  977.     RTSPAnnounceMessage* pMsg = new RTSPAnnounceMessage;
  978.     if(!pMsg)
  979.     {
  980.         return HXR_OUTOFMEMORY;
  981.     }
  982.     m_pMutex->Lock();
  983.     pMsg->setURL(pURL);
  984.     m_url = pURL;
  985.     const char* pDesc = 0;
  986.     addRFC822Headers(pMsg, pRequestHeaders);
  987.     clearStreamInfoList();
  988.     // use the first stream description plugin found...
  989.     char* pMimeType = 0;
  990.     if(HXR_OK == getStreamDescriptionMimeType(pMimeType))
  991.     {
  992. IHXStreamDescription* pSD = 
  993.     getStreamDescriptionInstance(pMimeType);
  994. if(pSD)
  995. {
  996.     UINT32 streamNumber;
  997.     UINT32 needReliable;
  998.     UINT32 rtpPayloadType;
  999.     UINT32 ulIsLive;
  1000.     IHXBuffer* pControlString;
  1001.     UINT32 ulIsSessionLive = 0;
  1002.     // if we are talking to a realserver, we will make an old sdpfile
  1003.     // for now...We need to check version and send the spec complient
  1004.     // sdp!
  1005.     IHXValues* pResponseHeaders = NULL;
  1006.     if (HXR_OK ==
  1007. m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  1008.     {
  1009. pFileHeader->SetPropertyULONG32("SdpFileType",
  1010.     GetSdpFileTypeWeNeed(pResponseHeaders));
  1011.     }
  1012.     HX_RELEASE(pResponseHeaders);
  1013.     UINT16 nStreams = pStreams->GetCount();
  1014.     IHXValues** ppValues = new IHXValues*[nStreams+2];
  1015.             if(!ppValues)
  1016.             {
  1017.                 rc = HXR_OUTOFMEMORY;
  1018.                 HX_DELETE(pMsg);
  1019.                 goto overandout;
  1020.             }
  1021.     ppValues[0] = pFileHeader;
  1022.     ppValues[1] = 0;    // no options
  1023.     pFileHeader->GetPropertyULONG32("LiveStream", ulIsSessionLive);
  1024.     CHXSimpleList::Iterator i;
  1025.     INT16 j=2;
  1026.     for(i=pStreams->Begin();i!=pStreams->End();++i,++j)
  1027.     {
  1028. // reset...
  1029. streamNumber = 0;
  1030. needReliable = 0;
  1031. rtpPayloadType = (UINT32)-1;
  1032. ulIsLive = ulIsSessionLive;
  1033. pControlString = 0;
  1034. ppValues[j] = (IHXValues*)(*i);
  1035. // build stream info list
  1036. RTSPStreamInfo* pInfo = new RTSPStreamInfo;
  1037.                 if(!pInfo)
  1038.                 {
  1039.                     rc = HXR_OUTOFMEMORY;
  1040.                     HX_DELETE(pMsg);
  1041.                     HX_VECTOR_DELETE(ppValues);
  1042.                     goto overandout;
  1043.                 }
  1044. ppValues[j]->GetPropertyULONG32("StreamNumber",
  1045.     streamNumber);
  1046. ppValues[j]->GetPropertyULONG32("NeedReliablePackets",
  1047.     needReliable);
  1048. ppValues[j]->GetPropertyULONG32("RTPPayloadType",
  1049.     rtpPayloadType);
  1050. ppValues[j]->GetPropertyCString("Control",
  1051.     pControlString);
  1052. ppValues[j]->GetPropertyULONG32("LiveStream", ulIsLive);
  1053. pInfo->m_streamNumber = (UINT16)streamNumber;
  1054. pInfo->m_bNeedReliablePackets = needReliable? TRUE: FALSE;
  1055. pInfo->m_rtpPayloadType = (INT16)rtpPayloadType;
  1056. pInfo->m_bIsLive = ulIsLive ? TRUE : FALSE;
  1057. pInfo->m_sPort = 0;
  1058. if(pControlString)
  1059. {
  1060.     pInfo->m_streamControl = pControlString->GetBuffer();
  1061.     // done with the buffer
  1062.     pControlString->Release();
  1063.     pControlString = NULL;
  1064. }
  1065. else
  1066. {
  1067.     char tmp[32];
  1068.     SafeSprintf(tmp,32, "streamid=%u", (UINT16)streamNumber);
  1069.     pInfo->m_streamControl = tmp;
  1070. }
  1071. m_streamInfoList.AddTail(pInfo);
  1072.     }
  1073.     pSD->GetDescription(nStreams+2, ppValues, pDescription);
  1074.     pDesc = (const char*)pDescription->GetBuffer();
  1075.     pSD->Release();
  1076.     delete[] ppValues;
  1077. }
  1078.     }
  1079.     if(pDesc)
  1080.     {
  1081. m_bSetupRecord = TRUE;
  1082. #ifdef _MACINTOSH
  1083. // someday, someone in core should look at why m_pSession is NULL when
  1084. // an invalid port is used, and yet m_pSession is assumed to be valid, and subsequently
  1085. // crashes macs HARD. I would attempt to investigate this further, however
  1086. // the core deferred task keeps crashing the debugger while I am attempting
  1087. // to trace through why m_pSession never gets assigned. since Mac Producer goes
  1088. // beta in 2 weeks, I'm putting this 'fix' in here now.. rlovejoy 2/16/00
  1089. if (m_pSession == NULL) {
  1090. rc = HXR_PORT_IN_USE;
  1091. } else
  1092. #endif
  1093. {
  1094.         UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1095. rc = sendRequest(pMsg, pDesc, pMimeType, seqNo);
  1096. }
  1097. // done with the description, we need to clean it up
  1098. pDescription->Release();
  1099.     }
  1100.     else
  1101.     {
  1102. rc = HXR_FAIL;
  1103.     }
  1104. overandout:
  1105.     delete[] pMimeType;
  1106.     m_pMutex->Unlock();
  1107.     return rc;
  1108. }
  1109. STDMETHODIMP
  1110. RTSPClientProtocol::SendSetupRequest
  1111. (
  1112.     RTSPTransportType* pTransType,
  1113.     UINT16 nTransTypes,
  1114.     IHXValues* pIHXValuesRequestHeaders
  1115. )
  1116. {
  1117.     m_pMutex->Lock();
  1118.     HX_RESULT           rc = HXR_OK;
  1119.     IHXUDPSocket*       pUDPSocket = NULL;
  1120.     IHXUDPSocket*       pRTCPUDPSocket = NULL;
  1121.     RTSPTransport*      pTrans = NULL;
  1122.     RTCPUDPTransport*   pRTCPTrans = NULL;
  1123.     RTSPStreamInfo*     pStreamInfo = NULL;
  1124.     IHXSetSocketOption* pSockOpt = NULL;
  1125.     CHXSimpleList::Iterator i;
  1126. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  1127.     if (m_bSDPInitiated && m_bMulticast)
  1128.     {
  1129.         RTSPTransportRequest* pRequest = new RTSPTransportRequest(RTSP_TR_RTP_MCAST, 0);
  1130.         if(pRequest)
  1131.         {
  1132.     m_transportRequestList.AddTail(pRequest);
  1133. }
  1134.         else
  1135.         {
  1136.             rc = HXR_OUTOFMEMORY;
  1137.             goto cleanup;
  1138.         }
  1139.         for (i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
  1140.         {
  1141.             pStreamInfo = (RTSPStreamInfo*)(*i);
  1142.             pUDPSocket = (IHXUDPSocket*)(*m_pUDPSocketStreamMap)[pStreamInfo->m_streamNumber];
  1143.             pRTCPUDPSocket = (IHXUDPSocket*)(*m_pRTCPSocketStreamMap)[pStreamInfo->m_streamNumber];
  1144.             // create a new transport for each setup
  1145.             pTrans = new RTPUDPTransport(m_bSetupRecord);
  1146.             if(!pTrans)
  1147.             {
  1148.                 rc = HXR_OUTOFMEMORY;
  1149.                 goto cleanup;
  1150.             }
  1151.             pTrans->AddRef();
  1152.             if (HXR_OK != ((RTPUDPTransport*)pTrans)->init(m_pContext,
  1153.                                                    pUDPSocket,
  1154.                                                    (IHXRTSPTransportResponse*)this))
  1155.             {
  1156.                 rc = HXR_BAD_TRANSPORT;
  1157.                 goto cleanup;
  1158.             }
  1159.             pTrans->notifyEmptyRTPInfo();
  1160.             // create an RTCP transport for this stream
  1161.             pRTCPTrans = new RTCPUDPTransport(m_bSetupRecord);
  1162.             if (!pRTCPTrans)
  1163.             {
  1164.                 rc = HXR_OUTOFMEMORY;
  1165.                 goto cleanup;
  1166.             }
  1167.             pRTCPTrans->AddRef();
  1168.             if (HXR_OK != pRTCPTrans->init(m_pContext, pRTCPUDPSocket, (RTPUDPTransport*)pTrans,
  1169.                            (IHXRTSPTransportResponse*) this, pStreamInfo->m_streamNumber))
  1170.             {
  1171.                 rc = HXR_BAD_TRANSPORT;
  1172.                 goto cleanup;
  1173.             }
  1174.             pRTCPTrans->notifyEmptyRTPInfo();
  1175.             ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTrans);
  1176.             pTrans->addStreamInfo(pStreamInfo);
  1177.     (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
  1178.     (*m_pTransportMPortMap)[pStreamInfo->m_sPort] = pTrans;
  1179.             pTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort, pUDPSocket);
  1180.     (*m_pTransportMPortMap)[pStreamInfo->m_sPort+1] = pRTCPTrans;
  1181.             pRTCPTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort + 1, pRTCPUDPSocket);
  1182.     if ((!m_bHasSyncMasterStream) && 
  1183. (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
  1184.     {
  1185.         pStreamInfo->m_bIsSyncMaster = TRUE;
  1186. m_bHasSyncMasterStream = TRUE;
  1187.             }
  1188.     mapControlToStreamNo(pStreamInfo->m_streamControl, pStreamInfo->m_streamNumber);
  1189.     rc = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTrans, pStreamInfo->m_streamNumber, 0);
  1190.             if( rc == HXR_OUTOFMEMORY )
  1191.             {
  1192.                 goto cleanup;
  1193.             }
  1194.             
  1195.       rc = pUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  1196.             if( rc == HXR_OUTOFMEMORY )
  1197.             {
  1198.                 goto cleanup;
  1199.             }
  1200.             rc = pRTCPUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  1201.             if( rc == HXR_OUTOFMEMORY )
  1202.             {
  1203.                 goto cleanup;
  1204.             }
  1205.         }
  1206.         m_uProtocolType = 1;
  1207.         m_pResp->HandleSetupResponse(HXR_OK);
  1208.         goto cleanup;
  1209.     }
  1210. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  1211.     if( HXR_OUTOFMEMORY == extractExistingAuthorizationInformation(pIHXValuesRequestHeaders))
  1212.     {
  1213.         rc = HXR_OUTOFMEMORY;
  1214.         goto cleanup;
  1215.     }
  1216.     if(pTransType)
  1217.     {
  1218. for(int i=0;i<nTransTypes;++i)
  1219. {
  1220.     RTSPTransportRequest* pRequest =
  1221. new RTSPTransportRequest(pTransType[i].m_lTransportType,
  1222.     pTransType[i].m_sPort);
  1223.             if(pRequest)
  1224.             {
  1225.         m_transportRequestList.AddTail(pRequest);
  1226.     }
  1227.             else
  1228.             {
  1229.                 rc = HXR_OUTOFMEMORY;
  1230.                 break;
  1231.             }
  1232. }
  1233.     }
  1234.     if (m_bIPTV && rc == HXR_OK)
  1235.     {
  1236. // we are going to keep this around for now to send cookie in all SETUP.
  1237. m_pSetupRequestHeader = pIHXValuesRequestHeaders;
  1238. m_pSetupRequestHeader->AddRef();
  1239.     }
  1240.     if (rc == HXR_OK)
  1241.     {
  1242.         rc =  sendFirstSetupRequest(pIHXValuesRequestHeaders);
  1243.     }
  1244. cleanup:
  1245.     if (HXR_OK != rc)
  1246.     {
  1247.         HX_RELEASE(pRTCPTrans);
  1248.         HX_RELEASE(pTrans);
  1249.     }
  1250.     m_pMutex->Unlock();
  1251.     return rc;
  1252. }
  1253. HX_RESULT
  1254. RTSPClientProtocol::sendFirstSetupRequest
  1255. (
  1256.     IHXValues* pIHXValuesRequestHeaders
  1257. )
  1258. {
  1259.     m_setupResponseCount = 0;
  1260.     if (!m_streamInfoList.IsEmpty())
  1261.     {
  1262. RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)m_streamInfoList.GetHead();
  1263. if(pStreamInfo)
  1264. {
  1265.     return sendSetupRequestMessage
  1266.     (
  1267. pStreamInfo,
  1268. pIHXValuesRequestHeaders,
  1269. TRUE
  1270.     );
  1271. }
  1272.     }
  1273.     return HXR_FAIL;
  1274. }
  1275. HX_RESULT
  1276. RTSPClientProtocol::sendRemainingSetupRequests()
  1277. {
  1278.     HX_RESULT status = HXR_OK;
  1279.     CHXSimpleList::Iterator i;
  1280.     BOOL bFirst = TRUE;
  1281.     for(i=m_streamInfoList.Begin();
  1282.     status == HXR_OK && (i!=m_streamInfoList.End());++i)
  1283.     {
  1284. if(bFirst)
  1285. {
  1286.     bFirst = FALSE;
  1287. }
  1288. else
  1289. {
  1290.     RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)(*i);
  1291.     status = sendSetupRequestMessage(pStreamInfo, NULL, FALSE);
  1292. }
  1293.     }
  1294.     return status;
  1295. }
  1296. HX_RESULT
  1297. RTSPClientProtocol::sendSetupRequestMessage(RTSPStreamInfo* pStreamInfo,
  1298.     IHXValues* pIHXValuesRequestHeaders, BOOL bFirstSetup)
  1299. {
  1300.     m_pMutex->Lock();
  1301.     RTSPSetupMessage* pMsg = new RTSPSetupMessage;
  1302.     if(!pMsg)
  1303.     {
  1304.         m_pMutex->Unlock();
  1305.         return HXR_OUTOFMEMORY;
  1306.     }
  1307.     HX_RESULT status = HXR_OK;
  1308.     status = sendSetupRequestMessageExt(pStreamInfo,
  1309. pIHXValuesRequestHeaders,
  1310. bFirstSetup,
  1311. pMsg);
  1312.     pMsg->addHeader("User-Agent", m_versionString);
  1313.     if (bFirstSetup && !m_sessionID.IsEmpty())
  1314.     {
  1315.         pMsg->addHeader("If-Match", m_sessionID);
  1316.     }
  1317.     else if (!m_sessionID.IsEmpty())
  1318.     {
  1319.         pMsg->addHeader("Session", m_sessionID);
  1320.     }
  1321.     // append stream control string to request
  1322.     setSetupRequestURL(pMsg, pStreamInfo);
  1323.     if (pIHXValuesRequestHeaders)
  1324.     {
  1325. addUAProfHeaders(pIHXValuesRequestHeaders);
  1326. addRFC822Headers(pMsg, pIHXValuesRequestHeaders);
  1327.     }
  1328.     UINT32 seqNo;
  1329.     seqNo = m_pSession->getNextSeqNo(this);
  1330.     /* Why are we not checking for any error code from above ??? */
  1331.     status = sendRequest(pMsg, seqNo);
  1332.     m_pMutex->Unlock();
  1333.     return status;
  1334. }
  1335. HX_RESULT
  1336. RTSPClientProtocol::sendSetupRequestMessageExt(RTSPStreamInfo* pStreamInfo,
  1337.        IHXValues*& pIHXValuesRequestHeaders,
  1338.        BOOL bFirstSetup,
  1339.        RTSPSetupMessage*& pMsg)
  1340. {
  1341.     MIMEHeader* pHeader = new MIMEHeader("Transport");
  1342.     if(!pHeader)
  1343.     {
  1344.         return HXR_OUTOFMEMORY;
  1345.     }
  1346.     HX_RESULT status = HXR_OK;
  1347.     CHXSimpleList::Iterator i;
  1348.     for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
  1349.     {
  1350. RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
  1351. UINT16 streamNumber = pStreamInfo->m_streamNumber;
  1352. UINT16 nUDPPort = 0;
  1353. #if defined(HELIX_FEATURE_RTP)
  1354. switch(pRequest->m_lTransportType)
  1355. {
  1356.     case RTSP_TR_RTP_UDP:
  1357.     {
  1358. // create a new transport for each setup
  1359. RTSPTransport* pTrans =
  1360.     new RTPUDPTransport(m_bSetupRecord);
  1361.                 if(!pTrans)
  1362.                 {
  1363.                     HX_DELETE(pHeader);
  1364.                     return HXR_OUTOFMEMORY;
  1365.                 }
  1366. pTrans->AddRef();
  1367. if (m_bPrefetch)
  1368. {
  1369.     pTrans->EnterPrefetch();
  1370. }
  1371. IHXUDPSocket* pUDPSocket = (IHXUDPSocket*)
  1372.     (*m_pUDPSocketStreamMap)[streamNumber];
  1373. pUDPSocket->GetLocalPort(nUDPPort);
  1374. IHXUDPSocket* pRTCPSocket = (IHXUDPSocket*)
  1375.     (*m_pRTCPSocketStreamMap)[streamNumber];
  1376. if (HXR_OK !=
  1377.     ((RTPUDPTransport*)pTrans)->init(
  1378. m_pContext,
  1379. pUDPSocket,
  1380. (IHXRTSPTransportResponse*) this))
  1381. {
  1382.     pTrans->Release();
  1383.     return HXR_BAD_TRANSPORT;
  1384. }
  1385. // create an RTCP transport for this stream
  1386. RTCPUDPTransport* pRTCPTran = new RTCPUDPTransport(m_bSetupRecord);
  1387.                 if(!pRTCPTran)
  1388.                 {
  1389.                     HX_DELETE(pHeader);
  1390.                     HX_RELEASE(pTrans);
  1391.     m_pMutex->Unlock();
  1392.                     return HXR_OUTOFMEMORY;
  1393.                 }
  1394. pRTCPTran->AddRef();
  1395. pRTCPTran->init(m_pContext,
  1396. pRTCPSocket,
  1397. (RTPUDPTransport*)pTrans,
  1398. (IHXRTSPTransportResponse*) this,
  1399. streamNumber);
  1400. ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTran);
  1401. status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
  1402.     nUDPPort);
  1403. if (m_bIPTV && m_pSetupRequestHeader && status != HXR_OUTOFMEMORY)
  1404. {
  1405.     addRFC822Headers(pMsg, m_pSetupRequestHeader);
  1406.     // don't add it twice...
  1407.     pIHXValuesRequestHeaders = NULL;
  1408. }
  1409.     }
  1410.     break;
  1411.     case RTSP_TR_RTP_TCP:
  1412.     {
  1413. RTSPTransport* pTrans = new RTPTCPTransport(m_bSetupRecord);
  1414.                 if(!pTrans)
  1415.                 {
  1416.                     HX_DELETE(pHeader);
  1417.                     return HXR_OUTOFMEMORY;
  1418.                 }
  1419. pTrans->AddRef();
  1420. if (m_bPrefetch)
  1421. {
  1422.     pTrans->EnterPrefetch();
  1423. }
  1424. if (HXR_OK != ((RTPTCPTransport*)pTrans)->init(
  1425.                     m_pContext, m_pSocket, (IHXRTSPTransportResponse*)this))
  1426. {
  1427.     status = HXR_BAD_TRANSPORT;
  1428. }
  1429.      // create an RTCP transport for this stream
  1430.      RTCPTCPTransport* pRTCPTran = new RTCPTCPTransport(m_bSetupRecord);
  1431.                 if(!pRTCPTran)
  1432.                 {
  1433.                     HX_DELETE(pHeader);
  1434.                     HX_DELETE(pTrans);
  1435.                     return HXR_OUTOFMEMORY;
  1436.                 }
  1437.      pRTCPTran->AddRef();
  1438.      pRTCPTran->init(m_pContext,
  1439.      m_pSocket,
  1440.      (RTPTCPTransport*)pTrans,
  1441.      (IHXRTSPTransportResponse*)this,
  1442.      streamNumber);
  1443.      ((RTPTCPTransport*)pTrans)->setRTCPTransport((RTCPBaseTransport*)pRTCPTran);
  1444.      status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
  1445.      nUDPPort);
  1446. if (m_bIPTV && m_pSetupRequestHeader)
  1447. {
  1448.     addRFC822Headers(pMsg, m_pSetupRequestHeader);
  1449.     // don't add it twice...
  1450.     pIHXValuesRequestHeaders = NULL;
  1451. }
  1452.     }
  1453.     break;
  1454.     default:
  1455.     {
  1456.     }
  1457.     break;
  1458. }
  1459. #endif /* HELIX_FEATURE_RTP */
  1460. char* pModifiedMimeType = NULL;
  1461. const char* pMimeType =
  1462.     RTSPTransportMimeMapper::getTransportMimeType
  1463.     (
  1464. pRequest->m_lTransportType
  1465.     );
  1466. // Accomodate incompliant servers that understand only upper case
  1467. // transport mime-types
  1468. if (m_bForceUCaseTransportMimeType)
  1469. {
  1470.     ULONG32 ulMimeTypeLength = strlen(pMimeType);
  1471.     if (ulMimeTypeLength != 0)
  1472.     {
  1473. pModifiedMimeType = new char [ulMimeTypeLength + 1];
  1474.                 if(!pModifiedMimeType)
  1475.                 {
  1476.                     HX_DELETE(pHeader);
  1477.                     return HXR_OUTOFMEMORY;
  1478.                 }
  1479.     }
  1480.     if (pModifiedMimeType)
  1481.     {
  1482. strcpy(pModifiedMimeType, pMimeType); /* Flawfinder: ignore */
  1483. StrToUpper(pModifiedMimeType);
  1484. pMimeType = pModifiedMimeType;
  1485.     }
  1486. }
  1487. #if defined(HELIX_FEATURE_RTP)
  1488. switch(pRequest->m_lTransportType)
  1489. {
  1490.     case RTSP_TR_RTP_UDP:
  1491.     case RTSP_TR_RTP_TCP:
  1492.     {
  1493. char portValue[32]; /* Flawfinder: ignore */
  1494. MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue(pMimeType);
  1495.                 if(!pHeaderValue)
  1496.                 {
  1497.                     HX_DELETE(pHeader);
  1498.                     HX_DELETE(pModifiedMimeType);
  1499.                     return HXR_OUTOFMEMORY;
  1500.                 }
  1501.                 if (RTSP_TR_RTP_UDP == pRequest->m_lTransportType)
  1502.                 {
  1503.     SafeSprintf(portValue, 32, "%u-%u", nUDPPort, nUDPPort+1);
  1504.     pHeaderValue->addParameter("client_port", (const char*)portValue);
  1505. #ifdef XXXtbradleyTEST_RTSP_DESTINATION
  1506.                     pHeaderValue->addParameter("destination", "127.0.0.1");
  1507. #endif /* XXXtbradleyTEST_RTSP_DESTINATION */
  1508.                 }
  1509.                 if(m_bSetupRecord)
  1510. {
  1511.     pHeaderValue->addParameter("mode", "record");
  1512. }
  1513. else
  1514. {
  1515.     pHeaderValue->addParameter("mode", "play");
  1516. }
  1517. pHeader->addHeaderValue(pHeaderValue);
  1518.     }
  1519.     break;
  1520.     case RTSP_TR_RTP_MCAST:
  1521.             default:
  1522.     {
  1523.     }
  1524.     break;
  1525. }
  1526. #endif /* HELIX_FEATURE_RTP */
  1527. HX_VECTOR_DELETE(pModifiedMimeType);
  1528.     }
  1529.     pMsg->addHeader(pHeader);
  1530.     return status;
  1531. }
  1532. STDMETHODIMP
  1533. RTSPClientProtocol::SendPlayRequest(UINT32 lFrom, UINT32 lTo,
  1534.     CHXSimpleList* pASMRules)
  1535. {
  1536.     /*
  1537.      * Flush the data packets out of the transport buffers
  1538.      */
  1539.     m_pMutex->Lock();
  1540.     m_bPaused = FALSE;
  1541. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  1542.     if (m_bSDPInitiated && m_bMulticast)
  1543.     {
  1544.         m_pMutex->Unlock();
  1545.         return m_pResp->HandlePlayResponse(HXR_OK);
  1546.     }
  1547. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  1548.     /*
  1549.      * XXXGH...I believe we should be iterating through m_transportRequestList
  1550.      *         here and for SendPauseRequest, SendResumeRequest, etc.
  1551.      */
  1552.     // only used when m_bNonRSRTP is TRUE
  1553.     m_bPlayJustSent = TRUE;
  1554.     if (!m_transportRequestList.IsEmpty())
  1555.     {
  1556. RTSPTransportRequest* pRequest =
  1557.     (RTSPTransportRequest*)m_transportRequestList.GetHead();
  1558. RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
  1559. while(pTransInfo)
  1560. {
  1561.     pTransInfo->m_pTransport->playReset();
  1562.     // set the range in transport...only for RTP
  1563.     pTransInfo->m_pTransport->setPlayRange(lFrom, lTo);
  1564.             pTransInfo->m_pTransport->SetPlayRequestSent(TRUE);
  1565.     pTransInfo->m_pTransport->resumeBuffers();
  1566.     pTransInfo = pRequest->getNextTransportInfo();
  1567. }
  1568.     }
  1569.     HX_RESULT rc = HXR_OK;
  1570.     RTSPPlayMessage* pMsg = new RTSPPlayMessage;
  1571.     if(pMsg)
  1572.     {
  1573.         RTSPRange range(lFrom, lTo, RTSPRange::TR_NPT);
  1574.         pMsg->setURL(m_url);
  1575.         AddCommonHeaderToMsg(pMsg);
  1576.         pMsg->addHeader("Range", (const char*)range.asString());
  1577.         UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1578.         rc = sendRequest(pMsg, seqNo);
  1579.     }
  1580.     else
  1581.     {
  1582.         rc = HXR_OUTOFMEMORY;
  1583.     }
  1584.     m_pMutex->Unlock();
  1585.     return rc;
  1586. }
  1587. STDMETHODIMP
  1588. RTSPClientProtocol::SendRecordRequest()
  1589. {
  1590.     if (!m_pIsMethodSupported[RECORD] || !m_pSession)
  1591.     {
  1592. return HXR_OK;
  1593.     }
  1594.     HX_RESULT rc = HXR_OK;
  1595.     m_pMutex->Lock();
  1596.     // Declaring these here so I can use a goto below!
  1597.     CHXString streamSequenceNumbers;
  1598.     BOOL bIsFirst = TRUE;
  1599.     CHXMapLongToObj::Iterator i;
  1600.     RTSPRecordMessage* pMsg = new RTSPRecordMessage;
  1601.     if(!pMsg)
  1602.     {
  1603.         rc =  HXR_OUTOFMEMORY;
  1604.         goto overandout;
  1605.     }
  1606.     pMsg->setURL(m_url);
  1607.     AddCommonHeaderToMsg(pMsg);
  1608.     /*
  1609.      * Add header for sequence numbers
  1610.      */
  1611.     for(i=m_pTransportStreamMap->Begin(); i!=m_pTransportStreamMap->End(); ++i)
  1612.     {
  1613. int lenTmpBuf = 100 + strlen(m_url);
  1614. char* tmpBuf = new char[lenTmpBuf];
  1615.         if(!tmpBuf)
  1616.         {
  1617.             HX_DELETE(pMsg);
  1618.             rc =  HXR_OUTOFMEMORY;
  1619.             goto overandout;
  1620.         }
  1621. RTSPTransport* pTransport = (RTSPTransport*)(*i);
  1622. pTransport->m_bHackedRecordFlag = TRUE;
  1623. UINT16 streamNumber = (UINT16)i.get_key();
  1624. UINT16 seqNum = pTransport->getSeqNum(streamNumber);
  1625. UINT32 ulTimestamp = pTransport->getTimestamp(streamNumber);
  1626. SafeSprintf(tmpBuf, lenTmpBuf, "url=" + m_url +
  1627.     "/streamid=%d;seq=%d;rtptime=%ld", streamNumber, seqNum,
  1628.     ulTimestamp);
  1629. if(!bIsFirst)
  1630. {
  1631.     streamSequenceNumbers += ", " + CHXString(tmpBuf);
  1632. }
  1633. else
  1634. {
  1635.     bIsFirst = FALSE;
  1636.     streamSequenceNumbers = tmpBuf;
  1637. }
  1638. delete[] tmpBuf;
  1639.     }
  1640.     pMsg->addHeader("RTP-Info", streamSequenceNumbers);
  1641.     if( m_pSession )
  1642.     {
  1643.         UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1644.         rc = sendRequest(pMsg, seqNo);
  1645.     }
  1646. overandout:
  1647.     m_pMutex->Unlock();
  1648.     return rc;
  1649. }
  1650. STDMETHODIMP
  1651. RTSPClientProtocol::SendPauseRequest()
  1652. {
  1653.     m_bPaused = TRUE;
  1654.     /*
  1655.      * Stop the internal buffer timers
  1656.      */
  1657.     if (!m_pIsMethodSupported[PAUSE] || m_transportRequestList.IsEmpty() ||
  1658.         !m_pSession)
  1659.     {
  1660. return HXR_OK;
  1661.     }
  1662.     m_pMutex->Lock();
  1663.     // only used when m_bNonRSRTP is TRUE
  1664.     m_bPlayJustSent = FALSE;
  1665.     SendMsgToTransport(PAUSE_BUFFER);
  1666.     HX_RESULT rc = SendMsgToServer(RTSP_PAUSE);
  1667.     m_pMutex->Unlock();
  1668.     return rc;
  1669. }
  1670. STDMETHODIMP
  1671. RTSPClientProtocol::SendResumeRequest()
  1672. {
  1673.     m_bPaused = FALSE;
  1674.     if (!m_pSession)
  1675.     {
  1676. return HXR_OK;
  1677.     }
  1678.     /*
  1679.      * Restart the internal buffer timers
  1680.      */
  1681.     m_pMutex->Lock();
  1682.     SendMsgToTransport(RESUME_BUFFER);
  1683.     /*
  1684.      * Man, iptv, teracast, and darwin server don't like this even though
  1685.      * this is perfetly legal...
  1686.      */
  1687.     if (m_bNonRSRTP && m_bPlayJustSent)
  1688.     {
  1689. m_pResp->HandlePlayResponse(HXR_OK);
  1690. m_pMutex->Unlock();
  1691. return HXR_OK;
  1692.     }
  1693.     HX_RESULT rc = SendMsgToServer(RTSP_PLAY);
  1694.     m_pMutex->Unlock();
  1695.     return rc;
  1696. }
  1697. STDMETHODIMP
  1698. RTSPClientProtocol::SendTeardownRequest()
  1699. {
  1700.     // make sure not to send a TEARDOWN unless SETUP succeeded
  1701.     if (m_setupResponseCount <= 0 || !m_pSession)
  1702.     {
  1703. // no successful SETUP response received...
  1704. return HXR_OK;
  1705.     }
  1706.     // it's ok if there is no session by spec.
  1707.     m_pMutex->Lock();
  1708.     HX_RESULT rc = SendMsgToServer(RTSP_TEARDOWN);
  1709.     m_pMutex->Unlock();
  1710.     return rc;
  1711. }
  1712. STDMETHODIMP
  1713. RTSPClientProtocol::SendPlayerStats(const char* pStats)
  1714. {
  1715. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1716.     if (!m_pIsMethodSupported[SET_PARAM])
  1717.     {
  1718. return HXR_OK;
  1719.     }
  1720.     if(m_pSession && !m_sessionID.IsEmpty())
  1721.     {
  1722. HX_RESULT rc = HXR_OK;
  1723. m_pMutex->Lock();
  1724. RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  1725.         if(pMsg)
  1726.         {
  1727.     pMsg->setURL(m_url);
  1728.     pMsg->addHeader("Session", m_sessionID);
  1729.     pMsg->addHeader("PlayerStats", pStats);
  1730.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1731.     rc = sendRequest(pMsg, seqNo);
  1732.         }
  1733.         else
  1734.         {
  1735.             rc = HXR_OUTOFMEMORY;
  1736.         }
  1737. m_pMutex->Unlock();
  1738. return rc;
  1739.     }
  1740. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1741.     return HXR_OK;
  1742. }
  1743. STDMETHODIMP
  1744. RTSPClientProtocol::SendKeepAlive()
  1745. {
  1746.     HX_RESULT rc = HXR_OK;
  1747.     // XXXSMP - Not right! :-)
  1748.     m_pMutex->Lock();
  1749.     if (!m_pSession)
  1750.     {
  1751. // just say alive!
  1752. m_pMutex->Unlock();
  1753. return HXR_OK;
  1754.     }
  1755.     // If using session timeout code, send an Options message,
  1756.     // otherwise, send a SetParam.  The SetParam approach is
  1757.     // is for servers that do not specify a session timeout value.
  1758.     if (!m_bUseLegacyTimeOutMsg ||
  1759.         !m_pIsMethodSupported[SET_PARAM] ||
  1760.         m_bNoKeepAlive)
  1761.     {
  1762.         m_bKeepAlivePending = TRUE;
  1763.         rc = SendMsgToServer(RTSP_OPTIONS);
  1764.     }
  1765.     else
  1766.     {
  1767.         RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  1768.         if(pMsg)
  1769.         {
  1770.             pMsg->setURL("*");
  1771.             MIMEHeader* pAlertHeader = new MIMEHeader("Ping");
  1772.             if(pAlertHeader)
  1773.             {
  1774.                 pAlertHeader->addHeaderValue("Pong");
  1775.                 pMsg->addHeader(pAlertHeader);
  1776.                 AddCommonHeaderToMsg(pMsg);
  1777.                 UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1778.                 sendRequest(pMsg, seqNo);
  1779.             }
  1780.             else
  1781.             {
  1782.                 rc = HXR_OUTOFMEMORY;
  1783.             }
  1784.         }
  1785.         else
  1786.         {
  1787.             rc = HXR_OUTOFMEMORY;
  1788.         }
  1789.     }
  1790.     m_pMutex->Unlock();
  1791.     return rc;
  1792. }
  1793. STDMETHODIMP
  1794. RTSPClientProtocol::SendPacket(BasePacket* pPacket)
  1795. {
  1796.     m_pMutex->Lock();
  1797.     HX_RESULT rc = HXR_UNEXPECTED;
  1798.     RTSPTransport* pTrans =
  1799. (RTSPTransport*)(*m_pTransportStreamMap)[pPacket->GetStreamNumber()];
  1800.     if(pTrans)
  1801.     {
  1802. rc = pTrans->sendPacket(pPacket);
  1803.     }
  1804.     m_pMutex->Unlock();
  1805.     return rc;
  1806. }
  1807. STDMETHODIMP
  1808. RTSPClientProtocol::SendStreamDone(UINT16 streamNumber)
  1809. {
  1810.     m_pMutex->Lock();
  1811.     HX_RESULT rc = HXR_UNEXPECTED;
  1812.     RTSPTransport* pTrans =
  1813. (RTSPTransport*)(*m_pTransportStreamMap)[streamNumber];
  1814.     if(pTrans)
  1815.     {
  1816. rc = pTrans->streamDone(streamNumber);
  1817.     }
  1818.     m_pMutex->Unlock();
  1819.     return rc;
  1820. }
  1821. STDMETHODIMP
  1822. RTSPClientProtocol::GetPacket(UINT16 uStreamNumber, REF(IHXPacket*) pPacket)
  1823. {
  1824.     m_pMutex->Lock();
  1825.     /*
  1826.      * Must not return HXR_FAIL because player may request a packet
  1827.      * before the transport is set up
  1828.      */
  1829.     HX_RESULT rc = HXR_NO_DATA;
  1830.     RTSPTransport* pTrans =
  1831. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  1832.     if (pTrans)
  1833.     {
  1834. rc = pTrans->getPacket(uStreamNumber, pPacket);
  1835.     }
  1836.     m_pMutex->Unlock();
  1837.     return rc;
  1838. }
  1839. STDMETHODIMP
  1840. RTSPClientProtocol::StartPackets(UINT16 uStreamNumber)
  1841. {
  1842.     m_pMutex->Lock();
  1843.     HX_RESULT rc = HXR_FAIL;
  1844.     RTSPTransport* pTrans =
  1845. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  1846.     if (pTrans)
  1847.     {
  1848. rc = pTrans->startPackets(uStreamNumber);
  1849.     }
  1850.     m_pMutex->Unlock();
  1851.     return rc;
  1852. }
  1853. STDMETHODIMP
  1854. RTSPClientProtocol::StopPackets(UINT16 uStreamNumber)
  1855. {
  1856.     m_pMutex->Lock();
  1857.     HX_RESULT rc = HXR_FAIL;
  1858.     RTSPTransport* pTrans =
  1859. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  1860.     if (pTrans)
  1861.     {
  1862. /*
  1863. * Must not return HXR_FAIL because player may request a packet
  1864. * before the transport is set up
  1865. */
  1866. rc = pTrans->stopPackets(uStreamNumber);
  1867.     }
  1868.     m_pMutex->Unlock();
  1869.     return rc;
  1870. }
  1871. /*
  1872.  * XXX...This had BETTER GET FIXED when we go to full IRMA
  1873.  */
  1874. STDMETHODIMP_(IHXPendingStatus*)
  1875. RTSPClientProtocol::GetPendingStatus()
  1876. {
  1877.     AddRef();
  1878.     return (IHXPendingStatus*)this;
  1879. }
  1880. STDMETHODIMP_(IHXStatistics*)
  1881. RTSPClientProtocol::GetStatistics()
  1882. {
  1883.     AddRef();
  1884.     return (IHXStatistics*)this;
  1885. }
  1886. STDMETHODIMP_(BOOL)
  1887. RTSPClientProtocol::HttpOnly()
  1888. {
  1889.     if(m_pSession)
  1890.     {
  1891. return m_pSession->HttpOnly();
  1892.     }
  1893.     return FALSE;
  1894. }
  1895. /*
  1896.  * IHXResolverResponse methods
  1897.  */
  1898. STDMETHODIMP
  1899. RTSPClientProtocol::GetHostByNameDone(HX_RESULT status,
  1900.     UINT32 ulAddr)
  1901. {
  1902.     UINT16 uPort = 0;
  1903.     BOOL bUseProxy = FALSE;
  1904.     CHXString host;
  1905.     HX_RELEASE(m_pResolver);
  1906.     /* We may have been deleted by now */
  1907.     if (!m_pResp)
  1908.     {
  1909. return HXR_OK;
  1910.     }
  1911.     m_pMutex->Lock();
  1912.     HX_RESULT rc = HXR_OK;
  1913. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  1914.     if (m_bSDPInitiated && m_bMulticast)
  1915.     {
  1916.         m_ulConnectToAddr = ulAddr;
  1917. m_pResp->InitDone(HXR_OK);
  1918.         IHXValues* pResponseHeaders = NULL;
  1919.         if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  1920.         {
  1921.     rc = m_pResp->HandleStreamDescriptionResponse
  1922.     (
  1923.         HXR_OK,
  1924.         m_pSDPFileHeader,
  1925.         m_pSDPStreamHeaders,
  1926.         pResponseHeaders
  1927.     );
  1928.         }
  1929.         HX_RELEASE(pResponseHeaders);
  1930.         RemoveSDPHeaders();
  1931.         goto exit;
  1932.     }
  1933. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  1934.     if(status == HXR_OK)
  1935.     {
  1936. if (!m_pSessionManager->isValid())
  1937. {
  1938.     // just return, this puppy's going away...
  1939.     goto exit;
  1940. }
  1941. if (!m_pSession && !m_pSocket)
  1942. {
  1943.     RTSPClientSession* pSession = 0;
  1944.     IUnknown* pContextToMatch = NULL;
  1945.     /* Do not reuse connection for connections coming from the
  1946.      * same player. Check for context (IHXPlayer) equality test
  1947.      * Context check is needed to simulate real-world scenario
  1948.      * for SMIL load testing
  1949.      */
  1950.     if (m_bNoReuseConnection && m_bLoadTest)
  1951.     {
  1952. pContextToMatch = m_pContext;
  1953.     }
  1954.     /* We share established connections if
  1955.      * 1. m_bNoReuseConnection is FALSE OR
  1956.      * 2. m_bLoadTest is set to TRUE (in which case we share
  1957.      *    connections ONLY for the same context (see above)
  1958.      * AND
  1959.      * 3. m_bHTTPOnly is FALSE OR
  1960.      * 4. m_pCloakPorts == NULL which means we *not* gonna
  1961.      *    attempt cloakport scanning
  1962.      *
  1963.      * NOTE: Splitter Plugin uses m_bNoReuseConnection = TRUE
  1964.      */
  1965.     if ((!m_bHTTPOnly || !m_pCloakPorts) &&
  1966. (!m_bNoReuseConnection || m_bLoadTest))
  1967.     {
  1968. if(m_bUseProxy || m_bUseHTTPProxy)
  1969. {
  1970.     uPort = m_proxyPort;
  1971. }
  1972. else if (m_bHTTPOnly)
  1973. {
  1974.     uPort = m_uCloakPort;
  1975. }
  1976. else
  1977. {
  1978.     uPort = m_foreignPort;
  1979. }
  1980. pSession = m_pSessionManager->findSession
  1981. (
  1982.     ulAddr,
  1983.     uPort,
  1984.     (m_bUseProxy | m_bUseHTTPProxy),
  1985.     (const char*)m_hostName,
  1986.     (m_bUseHTTPProxy?m_uCloakPort:m_foreignPort),
  1987.     pContextToMatch
  1988. );
  1989.     }
  1990.     if(pSession)
  1991.     {
  1992. pSession->addProtocol(this);
  1993. m_bSessionSucceeded = TRUE;
  1994. m_pSession = pSession;
  1995. m_pSocket = pSession->getSocket();
  1996. sendInitialMessage(m_pSession, m_pSocket);
  1997. IHXPreferredTransportSink* pPreferredTransportSink = NULL;
  1998. if (m_pResp &&
  1999.     HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
  2000.       (void**)&pPreferredTransportSink))
  2001. {
  2002.     pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
  2003. }
  2004. HX_RELEASE(pPreferredTransportSink);
  2005. m_pResp->InitDone(HXR_OK);
  2006.     }
  2007.     else
  2008.     {
  2009. if(m_bUseProxy || m_bUseHTTPProxy)
  2010. {
  2011.     host = m_proxyHost;
  2012.     uPort = m_proxyPort;
  2013.     bUseProxy = TRUE;
  2014. }
  2015. else
  2016. {
  2017.     host = m_hostName;
  2018.     uPort = m_foreignPort;
  2019. }
  2020. // XXX HP: the new session is created based on
  2021. // the actual(foreign) host and port to
  2022. // fix SMIL containing diff. servers
  2023. // the better fix will be send a new
  2024. // Challenge but still sharing the same
  2025. //. session
  2026. if (m_pCloakPorts)
  2027. {
  2028.     HX_ASSERT(m_bHTTPOnly);
  2029.     // initiating cloakport scanning
  2030.     for (int i = 0; i < m_nCloakPorts; i++)
  2031.     {
  2032. rc = m_pSessionManager->newSession(m_pContext,
  2033.   this,
  2034.   host,
  2035.   uPort,
  2036.   ulAddr,
  2037.   bUseProxy,
  2038.   m_bHTTPOnly,
  2039.   m_pCloakPorts[i]);
  2040. HX_ASSERT(HXR_OK == rc);
  2041.     }
  2042.     goto exit;
  2043. }
  2044. else
  2045. {
  2046.     rc = m_pSessionManager->newSession
  2047.     (
  2048. m_pContext,
  2049. this,
  2050. host,
  2051. uPort,
  2052. ulAddr,
  2053. bUseProxy,
  2054. m_bHTTPOnly,
  2055. m_uCloakPort
  2056.     );
  2057.     goto exit;
  2058. }
  2059.     }
  2060. }
  2061. else
  2062. {
  2063.     // being re-inited..
  2064.     //sendInitialMessage();
  2065.     m_pResp->InitDone(HXR_OK);
  2066. }
  2067.     }
  2068.     else
  2069.     {
  2070. m_pResp->InitDone(status);
  2071.     }
  2072. exit:
  2073.     m_pMutex->Unlock();
  2074.     return rc;
  2075. }
  2076. STDMETHODIMP
  2077. RTSPClientProtocol::SendGetParameterRequest(UINT32 lParamType,
  2078.     const char* pParamName)
  2079. {
  2080.     if (!m_pIsMethodSupported[GET_PARAM])
  2081.     {
  2082. return HXR_OK;
  2083.     }
  2084.     HX_RESULT rc = HXR_OK;
  2085.     m_pMutex->Lock();
  2086.     RTSPGetParamMessage* pMsg = new RTSPGetParamMessage;
  2087.     if(pMsg)
  2088.     {
  2089.         pMsg->setURL("*");
  2090.         AddCommonHeaderToMsg(pMsg);
  2091.         UINT32 seqNo = m_pSession->getNextSeqNo(this);
  2092.         rc = sendRequest(pMsg, pParamName, "text/rtsp-parameters", seqNo);
  2093.     }
  2094.     else
  2095.     {
  2096.         rc = HXR_OUTOFMEMORY;
  2097.     }
  2098.     m_pMutex->Unlock();
  2099.     return rc;
  2100. }
  2101. STDMETHODIMP
  2102. RTSPClientProtocol::SendSetParameterRequest(UINT32 lParamType,
  2103.     const char* pParamName, IHXBuffer* pParamValue)
  2104. {
  2105.     if (!m_pIsMethodSupported[SET_PARAM])
  2106.     {
  2107. return HXR_OK;
  2108.     }
  2109.     m_pMutex->Lock();
  2110.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  2111.     pMsg->setURL(m_url);
  2112.     AddCommonHeaderToMsg(pMsg);
  2113.     pMsg->addHeader(pParamName, (const char*)pParamValue->GetBuffer());
  2114.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  2115.     HX_RESULT rc = sendRequest(pMsg, seqNo);
  2116.     m_pMutex->Unlock();
  2117.     return rc;
  2118. }
  2119. STDMETHODIMP
  2120. RTSPClientProtocol::SendSetParameterRequest(const char* pParamName,
  2121. const char* pParamValue, const char* pMimeType,
  2122. const char* pContent)
  2123. {
  2124.     if (!m_pIsMethodSupported[SET_PARAM])
  2125.     {
  2126. return HXR_OK;
  2127.     }
  2128.     m_pMutex->Lock();
  2129.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  2130.     pMsg->setURL(m_url);
  2131.     AddCommonHeaderToMsg(pMsg);
  2132.     pMsg->addHeader(pParamName, pParamValue);
  2133.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  2134.     HX_RESULT rc = sendRequest(pMsg, pContent, pMimeType, seqNo);
  2135.     m_pMutex->Unlock();
  2136.     return rc;
  2137. }
  2138. STDMETHODIMP
  2139. RTSPClientProtocol::PacketReady(HX_RESULT status, const char* pSessionID,
  2140.     IHXPacket* pPacket)
  2141. {
  2142.     m_pMutex->Lock();
  2143.     HX_RESULT rc = m_pResp->HandlePacket(status, pSessionID, pPacket);
  2144.     m_pMutex->Unlock();
  2145.     return rc;
  2146. }
  2147. /*
  2148.  * OnRTTRequest() and OnBWReport() are server-side functions
  2149.  */
  2150. STDMETHODIMP
  2151. RTSPClientProtocol::OnRTTRequest(HX_RESULT status, const char* pSessionID)
  2152. {
  2153.     return HXR_UNEXPECTED;
  2154. }
  2155. STDMETHODIMP
  2156. RTSPClientProtocol::OnRTTResponse(HX_RESULT status, const char* pSessionID,
  2157.     UINT32 ulSecs, UINT32 ulUSecs)
  2158. {
  2159.     m_pMutex->Lock();
  2160.     HX_RESULT rc = m_pResp->HandleRTTResponse(status, pSessionID,
  2161.       ulSecs, ulUSecs);
  2162.     m_pMutex->Unlock();
  2163.     return rc;
  2164. }
  2165. STDMETHODIMP
  2166. RTSPClientProtocol::OnBWReport(HX_RESULT status, const char* pSessionID,
  2167.     INT32 aveBandwidth, INT32 packetLoss, INT32 bandwidthWanted)
  2168. {
  2169.     return HXR_UNEXPECTED;
  2170. }
  2171. STDMETHODIMP
  2172. RTSPClientProtocol::OnCongestion(HX_RESULT status, const char* pSessionID,
  2173.     INT32 xmitMultiplier, INT32 recvMultiplier)
  2174. {
  2175.     m_pMutex->Lock();
  2176.     HX_RESULT rc = m_pResp->HandleCongestion(status, pSessionID,
  2177. xmitMultiplier, recvMultiplier);
  2178.     m_pMutex->Unlock();
  2179.     return rc;
  2180. }
  2181. STDMETHODIMP
  2182. RTSPClientProtocol::OnACK(HX_RESULT status, RTSPResendBuffer* pResendBuffer,
  2183.     UINT16 uStreamNumber, const char* pSessionID,
  2184.     UINT16* pAckList, UINT32 uAckListCount,
  2185.     UINT16* pNakList, UINT32 uNakListCount)
  2186. {
  2187.     /*
  2188.      * While it's ACKing, remote client is alive
  2189.      */
  2190.     m_bConnectionAlive = TRUE;
  2191.     m_pMutex->Lock();
  2192.     HX_RESULT rc = handleACK((IHXPacketResend*)this, pResendBuffer,
  2193.      uStreamNumber,
  2194.      pAckList, uAckListCount,
  2195.      pNakList, uNakListCount,
  2196.      FALSE);
  2197.     m_pMutex->Unlock();
  2198.     return rc;
  2199. };
  2200. STDMETHODIMP
  2201. RTSPClientProtocol::OnStreamDone(HX_RESULT status, UINT16 uStreamNumber)
  2202. {
  2203.     m_pMutex->Lock();
  2204.     HX_RESULT rc = m_pResp->HandleStreamDone(status, uStreamNumber);
  2205.     m_pMutex->Unlock();
  2206.     return rc;
  2207. }
  2208. STDMETHODIMP
  2209. RTSPClientProtocol::OnSourceDone(void)
  2210. {
  2211.     m_pMutex->Lock();
  2212.     HX_RESULT rc = m_pResp->HandleSourceDone();
  2213.     m_pMutex->Unlock();
  2214.     return rc;
  2215. }
  2216. STDMETHODIMP
  2217. RTSPClientProtocol::OnProtocolError(HX_RESULT status)
  2218. {
  2219.     HX_RESULT rc = HXR_OK;
  2220.     // called from transport layer
  2221.     m_pMutex->Lock();
  2222.     if (m_sessionList.IsEmpty() || m_bSessionSucceeded)
  2223.     {
  2224. rc = m_pResp->HandleProtocolError(status);
  2225.     }
  2226.     m_pMutex->Unlock();
  2227.     return rc;
  2228. }
  2229. STDMETHODIMP
  2230. RTSPClientProtocol::GetStatus
  2231. (
  2232.     REF(UINT16) uStatusCode,
  2233.     REF(IHXBuffer*) pStatusDesc,
  2234.     REF(UINT16) ulPercentDone
  2235. )
  2236. {
  2237. #if 0
  2238.     m_pMutex->Lock();
  2239.     HX_RESULT rc = HXR_OK;
  2240.     CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
  2241.     if(i != m_pTransportStreamMap->End())
  2242.     {
  2243. RTSPTransport* pTrans = (RTSPTransport*)(*i);
  2244. rc = pTrans ? pTrans->getStatus(uStatusCode, pStatusDesc, ulPercentDone) : HXR_OK;
  2245.     }
  2246.     else
  2247.     {
  2248. uStatusCode = HX_STATUS_BUFFERING;
  2249. pStatusDesc = 0;
  2250. ulPercentDone = 0;
  2251.     }
  2252.     m_pMutex->Unlock();
  2253.     return rc;
  2254. #else
  2255.     return HXR_NOTIMPL;
  2256. #endif
  2257. }
  2258. STDMETHODIMP
  2259. RTSPClientProtocol::InitializeStatistics
  2260. (
  2261.     UINT32 ulRegistryID
  2262. )
  2263. {
  2264.     HX_RESULT rc = HXR_FAIL;
  2265.     m_pMutex->Lock();
  2266.     CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
  2267.     if(i != m_pTransportStreamMap->End())
  2268.     {
  2269. RTSPTransport* pTrans = (RTSPTransport*)(*i);
  2270. rc = pTrans ? pTrans->initializeStatistics(ulRegistryID) : HXR_FAIL;
  2271.     }
  2272.     m_pMutex->Unlock();
  2273.     return rc;
  2274. }
  2275. STDMETHODIMP
  2276. RTSPClientProtocol::UpdateStatistics()
  2277. {
  2278.     HX_RESULT rc = HXR_FAIL;
  2279.     m_pMutex->Lock();
  2280.     CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
  2281.     if(i != m_pTransportStreamMap->End())
  2282.     {
  2283. RTSPTransport* pTrans = (RTSPTransport*)(*i);
  2284. rc = pTrans ? pTrans->updateStatistics() : HXR_FAIL;
  2285.     }
  2286.     m_pMutex->Unlock();
  2287.     return rc;
  2288. }
  2289. STDMETHODIMP
  2290. RTSPClientProtocol::OnPacket(UINT16 uStreamNumber, BasePacket** ppPacket)
  2291. {
  2292.     BasePacket* pPacket;
  2293.     m_pMutex->Lock();
  2294.     for (; (pPacket = *ppPacket); ppPacket++)
  2295.     {
  2296. SendPacket(pPacket);
  2297.     }
  2298.     m_pMutex->Unlock();
  2299.     return HXR_OK;
  2300. }
  2301. /*
  2302.  * RTSPClientProtocol methods
  2303.  */
  2304. HX_RESULT
  2305. RTSPClientProtocol::HandleUnexpected(RTSPMessage* pMsg)
  2306. {
  2307.     m_pMutex->Lock();
  2308.     RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "405");
  2309.     pRspMsg->addHeader("Allow", allowedMethods());
  2310.     sendResponse(pRspMsg);
  2311.     delete pRspMsg;
  2312.     m_pMutex->Unlock();
  2313.     return HXR_OK;
  2314. }
  2315. HX_RESULT
  2316. RTSPClientProtocol::HandleBadVersion(RTSPMessage* pMsg)
  2317. {
  2318.     m_pMutex->Lock();
  2319.     RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "505");
  2320.     sendResponse(pRspMsg);
  2321.     delete pRspMsg;
  2322.     m_pMutex->Unlock();
  2323.     return HXR_OK;
  2324. }
  2325. HX_RESULT
  2326. RTSPClientProtocol::HandleOptions(RTSPOptionsMessage* pMsg)
  2327. {
  2328.     sendResponse(pMsg->seqNo(), "200");
  2329.     return HXR_OK;
  2330. }
  2331. HX_RESULT
  2332. RTSPClientProtocol::HandleTeardown(RTSPTeardownMessage* pMsg)
  2333. {
  2334.     m_pMutex->Lock();
  2335.     RTSPResponseMessage* pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
  2336.     sendResponse(pRespMsg);
  2337.     delete pRespMsg;
  2338.     m_pMutex->Unlock();
  2339.     return HXR_OK;
  2340. }
  2341. HX_RESULT
  2342. RTSPClientProtocol::HandleGetParam(RTSPGetParamMessage* pMsg)
  2343. {
  2344.     IHXBuffer* pBuffer = 0;
  2345.     m_pMutex->Lock();
  2346.     const char* pParamName = pMsg->getContent();
  2347.     HX_RESULT rc = m_pResp->HandleGetParameterRequest(
  2348. RTSP_PARAM_STRING, pParamName, &pBuffer);
  2349.     RTSPResponseMessage* pRespMsg = 0;
  2350.     if(rc == HXR_OK)
  2351.     {
  2352. pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
  2353. sendResponse(pRespMsg, (const char*)pBuffer->GetBuffer(),
  2354.     "text/rtsp-parameters");
  2355.     }
  2356.     else
  2357.     {
  2358. pRespMsg = makeResponseMessage(pMsg->seqNo(), "451");
  2359. sendResponse(pRespMsg);
  2360.     }
  2361.     delete pRespMsg;
  2362.     m_pMutex->Unlock();
  2363.     return HXR_OK;
  2364. }
  2365. HX_RESULT
  2366. RTSPClientProtocol::HandleSetParam(RTSPSetParamMessage* pMsg)
  2367. {
  2368.     RTSPResponseMessage* pRespMsg = 0;
  2369.     HX_RESULT rc = HXR_OK;
  2370.     IHXValues* pReconnectValues = NULL;
  2371.     BOOL paramOK = FALSE;
  2372.     m_pMutex->Lock();
  2373.     MIMEHeader* pAlert = pMsg->getHeader("Alert");
  2374.     MIMEHeader* pMaxASMBW = pMsg->getHeader("MaximumASMBandwidth");
  2375.     MIMEHeader* pDataConvert = pMsg->getHeader("DataConvertBuffer");
  2376.     MIMEHeader* pReconnect = pMsg->getHeader("Reconnect");
  2377.     MIMEHeader* pAlternateServer = pMsg->getHeader("Alternate-Server");
  2378.     MIMEHeader* pAlternateProxy = pMsg->getHeader("Alternate-Proxy");
  2379.     if(pAlert)
  2380.     {
  2381. paramOK = TRUE;
  2382. MIMEHeaderValue* pHeaderValue = pAlert->getFirstHeaderValue();
  2383. if(pHeaderValue)
  2384. {
  2385.     MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  2386.     if(pParam)
  2387.     {
  2388. const char* pAlertNumber = (const char*)pParam->m_attribute;
  2389. pParam = pHeaderValue->getNextParameter();
  2390. if(pParam)
  2391. {
  2392.     const char* pAlertText = (const char*)pParam->m_attribute;
  2393.     rc = m_pResp->HandleAlertRequest(HXR_OK,
  2394. strtol(pAlertNumber, 0, 10), pAlertText);
  2395. }
  2396.     }
  2397. }
  2398.     }
  2399.     else if(pMaxASMBW)
  2400.     {
  2401. paramOK = TRUE;
  2402. MIMEHeaderValue* pHeaderValue = pMaxASMBW->getFirstHeaderValue();
  2403. if(pHeaderValue)
  2404. {
  2405.     MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  2406.     if(pParam)
  2407.     {
  2408. IHXBuffer * pBuffer;
  2409. pBuffer = new CHXBuffer();
  2410.                 if(pBuffer)
  2411.                 {
  2412.     rc = pBuffer->Set((const unsigned char *)(pParam->m_attribute).
  2413. GetBuffer(1), strlen((const char*)pParam->
  2414. m_attribute)+1);
  2415.                     if( rc != HXR_OUTOFMEMORY )
  2416.                     {
  2417.         pBuffer->AddRef();
  2418.         rc = m_pResp->HandleSetParameterRequest(
  2419.     RTSP_PARAM_STRING, "MaximumASMBandwidth", pBuffer);
  2420.         pBuffer->Release();
  2421.             }
  2422.                     else
  2423.                     {
  2424.                         HX_DELETE(pBuffer);
  2425.                     }
  2426.                 }
  2427.                 else
  2428.                 {
  2429.                     rc = HXR_OUTOFMEMORY;
  2430.                 }
  2431.     }
  2432. }
  2433.     }
  2434.     else if (pDataConvert)
  2435.     {
  2436. rc = m_pResp->HandleSetParameterRequest("DataConvertBuffer",
  2437. "1", pMsg->getContent());
  2438.     }
  2439.     else if (pReconnect)
  2440.     {
  2441. CHXString reconnectFlag = pMsg->getHeaderValue("Reconnect");
  2442. if (reconnectFlag != "" && strcasecmp((const char*)reconnectFlag, "false") == 0)
  2443. {
  2444.     pReconnectValues = new CHXHeader();
  2445.     pReconnectValues->AddRef();
  2446.          pReconnectValues->SetPropertyULONG32("Reconnect", 0);
  2447.     rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
  2448.     HX_RELEASE(pReconnectValues);
  2449. }
  2450.     }
  2451.     else if (pAlternateServer)
  2452.     {
  2453. rc = RetrieveReconnectInfo(pAlternateServer, ALTERNATE_SERVER, pReconnectValues);
  2454. rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
  2455. HX_RELEASE(pReconnectValues);
  2456.     }
  2457.     else if (pAlternateProxy)
  2458.     {
  2459. rc = RetrieveReconnectInfo(pAlternateProxy, ALTERNATE_PROXY, pReconnectValues);
  2460. rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
  2461. HX_RELEASE(pReconnectValues);
  2462.     }
  2463.     else
  2464.     {
  2465. rc = HXR_UNEXPECTED;
  2466.     }
  2467.     if(rc == HXR_OK)
  2468.     {
  2469. pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
  2470.     }
  2471.     else
  2472.     {
  2473. pRespMsg = makeResponseMessage(pMsg->seqNo(), "451");
  2474.     }
  2475.     sendResponse(pRespMsg);
  2476.     delete pRespMsg;
  2477.     m_pMutex->Unlock();
  2478.     return HXR_OK;
  2479. }
  2480. HX_RESULT
  2481. RTSPClientProtocol::HandleUseProxy(RTSPResponseMessage* pMsg)
  2482. {
  2483.     m_pMutex->Lock();
  2484.     HX_RESULT rc = HXR_OK;
  2485.     MIMEHeader* pLocation = pMsg->getHeader("Location");
  2486.     if(pLocation)
  2487.     {
  2488. MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
  2489. if(pURLValue)
  2490. {
  2491.     CHXString proxyURL = pURLValue->value();
  2492.     if(proxyURL.GetLength() > 0)
  2493.     {
  2494. rc = m_pResp->HandleUseProxyRequest((const char*)proxyURL);
  2495. goto exit;
  2496.     }
  2497. }
  2498.     }
  2499.     // bad redirect, inform the response object
  2500.     rc = m_pResp->HandleUseProxyRequest(NULL);
  2501. exit:
  2502.     m_pMutex->Unlock();
  2503.     return rc;
  2504. }
  2505. HX_RESULT
  2506. RTSPClientProtocol::HandleRedirect(RTSPRedirectMessage* pMsg)
  2507. {
  2508.     m_pMutex->Lock();
  2509.     HX_RESULT rc = HXR_OK;
  2510.     RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "200");
  2511.     sendResponse(pRspMsg);
  2512.     delete pRspMsg;
  2513.     UINT32 msFromNow = 0;
  2514.     MIMEHeader* pLocation = pMsg->getHeader("Location");
  2515.     if(pLocation)
  2516.     {
  2517. MIMEHeader* pRangeHeader = pMsg->getHeader("Range");
  2518. if(pRangeHeader)
  2519. {
  2520.     RTSPRange* pRange = (RTSPRange*)pRangeHeader->getFirstHeaderValue();
  2521.     if(pRange)
  2522.     {
  2523. msFromNow = pRange->m_begin;
  2524.     }
  2525. }
  2526. MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
  2527. if(pURLValue)
  2528. {
  2529.     CHXString redirectURL = pURLValue->value();
  2530.     if(redirectURL.GetLength() > 0)
  2531.     {
  2532. rc = m_pResp->HandleRedirectRequest((const char*)redirectURL,
  2533.     msFromNow);
  2534. goto exit;
  2535.     }
  2536. }
  2537.     }
  2538.     rc = m_pResp->HandleRedirectRequest(0, 0);
  2539. exit:
  2540.     m_pMutex->Unlock();
  2541.     return rc;
  2542. }
  2543. HX_RESULT
  2544. RTSPClientProtocol::HandleRedirectResponse(RTSPResponseMessage* pMsg)
  2545. {
  2546.     m_pMutex->Lock();
  2547.     HX_RESULT rc = HXR_OK;
  2548.     IHXValues* pRFC822Headers = NULL;
  2549.     getRFC822Headers(pMsg, pRFC822Headers);
  2550.     if(pRFC822Headers)
  2551.     {
  2552. IHXKeyValueList* pRFC822List = NULL;
  2553. if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
  2554. {
  2555.     m_pResponseHeaders->AppendAllListItems(pRFC822List);
  2556. }
  2557. HX_RELEASE(pRFC822List);
  2558.     }
  2559.     HX_RELEASE(pRFC822Headers);
  2560.     // tell them this is a redirect...
  2561.     IHXValues* pResponseHeaders = NULL;
  2562.     if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  2563.     {
  2564. m_pResp->HandleOptionsResponse(HXR_REDIRECTION, pResponseHeaders);
  2565. HX_RELEASE(pResponseHeaders);
  2566.     }
  2567.     else
  2568.     {
  2569. HX_ASSERT(pResponseHeaders);
  2570. m_pResp->HandleOptionsResponse(HXR_REDIRECTION, NULL);
  2571.     }
  2572.     UINT32 msFromNow;
  2573.     msFromNow = 0;
  2574.     MIMEHeader* pLocation;
  2575.     pLocation = pMsg->getHeader("Location");
  2576.     if(pLocation)
  2577.     {
  2578. MIMEHeader* pRangeHeader = pMsg->getHeader("Range");
  2579. if(pRangeHeader)
  2580. {
  2581.     RTSPRange* pRange = (RTSPRange*)pRangeHeader->getFirstHeaderValue();
  2582.     if(pRange)
  2583.     {
  2584. msFromNow = pRange->m_begin;
  2585.     }
  2586. }
  2587. MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
  2588. if(pURLValue)
  2589. {
  2590.     CHXString redirectURL = pURLValue->value();
  2591.     if(redirectURL.GetLength() > 0)
  2592.     {
  2593. rc = m_pResp->HandleRedirectRequest((const char*)redirectURL,
  2594.     msFromNow);
  2595. goto exit;
  2596.     }
  2597. }
  2598.     }
  2599.     rc = m_pResp->HandleRedirectRequest(0, 0);
  2600. exit:
  2601.     m_pMutex->Unlock();
  2602.     return rc;
  2603. }
  2604. void
  2605. RTSPClientProtocol::SessionCreated(RTSPClientSession* pSession)
  2606. {
  2607.     m_sessionList.AddTail(pSession);
  2608. }
  2609. void
  2610. RTSPClientProtocol::SessionSucceeded(RTSPClientSession* pSession,
  2611.      IHXTCPSocket* pSocket)
  2612. {
  2613.     RTSPClientSession* pTempSession = NULL;
  2614.     m_pMutex->Lock();
  2615.     m_bSessionSucceeded = TRUE;
  2616.     while (!m_sessionList.IsEmpty())
  2617.     {
  2618. pTempSession = (RTSPClientSession*)m_sessionList.RemoveHead();
  2619. if (pTempSession != pSession)
  2620. {
  2621.     m_pSessionManager->removeFromSession(this, pTempSession);
  2622. }
  2623.     }
  2624.     m_pSession = pSession;
  2625.     m_pSocket = pSocket;
  2626.     m_uCloakPort = pSession->m_uCloakPort;
  2627.     m_pMutex->Unlock();
  2628.     return;
  2629. }
  2630. void
  2631. RTSPClientProtocol::SessionFailed(RTSPClientSession* pSession,
  2632.   IHXTCPSocket* pSocket)
  2633. {
  2634.     LISTPOSITION lPos = NULL;
  2635.     m_pMutex->Lock();
  2636.     lPos = m_sessionList.Find((void*)pSession);
  2637.     if (lPos)
  2638.     {
  2639. m_sessionList.RemoveAt(lPos);
  2640.     }
  2641.     m_pMutex->Unlock();
  2642.     return;
  2643. }
  2644. HX_RESULT
  2645. RTSPClientProtocol::InitDone(HX_RESULT status)
  2646. {
  2647.     HX_RESULT rc = HXR_OK;
  2648.     AddRef();
  2649.     m_pMutex->Lock();
  2650.     if (m_sessionList.IsEmpty() ||
  2651. m_bSessionSucceeded ||
  2652. HXR_OK == status)
  2653.     {
  2654. rc = m_pResp->InitDone(status);
  2655.     }
  2656.     m_pMutex->Unlock();
  2657.     Release();
  2658.     return rc;
  2659. }
  2660. STDMETHODIMP
  2661. RTSPClientProtocol::InitSockets()
  2662. {
  2663.     HX_RESULT     hr = HXR_OK;
  2664.     UINT32     nMaxUDPPort = MAX_UDP_PORT;
  2665.     IHXBuffer*     pBuffer = 0;
  2666.     RTSPStreamInfo*     pStreamInfo = NULL;
  2667.     BOOL     bGotSocket = FALSE;
  2668.     BOOL     bUseUDPPort = FALSE;
  2669.     UINT16     datagramPort = 0;
  2670.     UDP_PORTS*     pUDPPort = NULL;
  2671.     CHXSimpleList*     pUDPPortList = new CHXSimpleList();
  2672.     CHXSimpleList::Iterator i;
  2673.     AddRef();
  2674.     if (!m_pNetworkServices || !m_pPreferences)
  2675.     {
  2676. hr = HXR_OUTOFMEMORY;
  2677. goto cleanup;
  2678.     }
  2679.     m_pUDPSocketStreamMap = new CHXMapLongToObj;
  2680.     m_pRTCPSocketStreamMap = new CHXMapLongToObj;
  2681. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  2682.     if (m_bSDPInitiated && m_bMulticast)
  2683.     {
  2684.         for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End() && HXR_OK == hr;++i)
  2685.         {
  2686.     pStreamInfo = (RTSPStreamInfo*)(*i);
  2687.             hr = CreateUDPSockets(pStreamInfo->m_streamNumber, pStreamInfo->m_sPort);
  2688.         }
  2689.     }
  2690.     else
  2691. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  2692.     {
  2693.         /////////////////////////////////////////////////////////////
  2694.         //
  2695.         // Handle Specific UDP Port Preferences here....
  2696.         //
  2697.         ReadPrefBOOL(m_pPreferences, "UseUDPPort", bUseUDPPort);
  2698.         if(!bUseUDPPort)
  2699.         {
  2700.             // If the MaxUDPPort Preference is set, use that instead of our defined limit
  2701.             if (HXR_OK == ReadPrefINT32(m_pPreferences, "MaxUDPPort", nMaxUDPPort))
  2702.             {
  2703.         if(nMaxUDPPort < MIN_UDP_PORT)
  2704.         {
  2705.     nMaxUDPPort = MAX_UDP_PORT;
  2706.         }
  2707.     }
  2708.     pUDPPort = new UDP_PORTS;
  2709.     pUDPPort->uFrom = MIN_UDP_PORT;
  2710.     pUDPPort->uTo = nMaxUDPPort;
  2711.     pUDPPortList->AddTail((void*)pUDPPort);
  2712.         }
  2713.         else
  2714.         {
  2715.     if(m_pPreferences->ReadPref("UDPPort", pBuffer) == HXR_OK)
  2716.     {
  2717.         ReadUDPPorts(pBuffer, pUDPPortList);
  2718.     }
  2719.         }
  2720.         HX_RELEASE(pBuffer);
  2721.         for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
  2722.         {
  2723.     pStreamInfo = (RTSPStreamInfo*)(*i);
  2724.          CHXSimpleList::Iterator lIterator = pUDPPortList->Begin();
  2725.     for (; lIterator != pUDPPortList->End(); ++lIterator)
  2726.     {
  2727.         pUDPPort = (UDP_PORTS*) (*lIterator);
  2728.         if ((pUDPPort->uTo - pUDPPort->uFrom + 1) < 2)
  2729.         {
  2730.     continue;
  2731.         }
  2732.         for (datagramPort = pUDPPort->uFrom; datagramPort <= pUDPPort->uTo; datagramPort += 2)
  2733.         {
  2734.     if (datagramPort % 2)
  2735.     {
  2736.         datagramPort = datagramPort + 1;
  2737.     }
  2738.     if ((pUDPPort->uTo - datagramPort + 1) < 2)
  2739.     {
  2740.         break;
  2741.     }
  2742.                     if (HXR_OK == CreateUDPSockets(pStreamInfo->m_streamNumber, datagramPort))
  2743.                     {
  2744.                         bGotSocket = TRUE;
  2745.                         break;
  2746.                     }
  2747.         }
  2748.         if (bGotSocket)
  2749.         {
  2750.     break;
  2751.         }
  2752.     }
  2753.         }
  2754.         m_currentTransport = UDPMode;
  2755.     }
  2756. cleanup:
  2757.     if (HXR_OK != hr)
  2758.     {
  2759. HX_DELETE(m_pUDPSocketStreamMap);
  2760. HX_DELETE(m_pRTCPSocketStreamMap);
  2761.     }
  2762.     while (pUDPPortList->GetCount())
  2763.     {
  2764. pUDPPort = (UDP_PORTS*)pUDPPortList->RemoveHead();
  2765. HX_DELETE(pUDPPort);
  2766.     }
  2767.     HX_DELETE(pUDPPortList);
  2768.     Release();
  2769.     return hr;
  2770. }
  2771. STDMETHODIMP
  2772. RTSPClientProtocol::GetCurrentBuffering(UINT16     uStreamNumber,
  2773.         REF(INT64)  llLowestTimestamp,
  2774.         REF(INT64)  llHighestTimestamp,
  2775.         REF(UINT32) ulNumBytes,
  2776.         REF(BOOL)   bDone)
  2777. {
  2778.     llLowestTimestamp = 0;
  2779.     llHighestTimestamp = 0;
  2780.     ulNumBytes = 0;
  2781.     bDone = FALSE;
  2782.     HX_ASSERT(m_pTransportStreamMap);
  2783.     if (!m_pTransportStreamMap)
  2784.     {
  2785. return HXR_OK;
  2786.     }
  2787.     HX_RESULT rc = HXR_OK;
  2788.     m_pMutex->Lock();
  2789.     RTSPTransport* pTrans =
  2790. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  2791.     HX_ASSERT(pTrans);
  2792.     rc = pTrans ?
  2793.     pTrans->GetCurrentBuffering(uStreamNumber,
  2794. llLowestTimestamp,
  2795. llHighestTimestamp,
  2796. ulNumBytes,
  2797. bDone) : HXR_OK;
  2798.     m_pMutex->Unlock();
  2799.     return rc;
  2800. }
  2801. STDMETHODIMP
  2802. RTSPClientProtocol::SeekFlush()
  2803. {
  2804.     HX_RESULT rc = HXR_OK;
  2805.     m_pMutex->Lock();
  2806.     CHXMapLongToObj::Iterator i;
  2807.     for(i=m_pTransportStreamMap->Begin();
  2808.     (rc == HXR_OK) &&  i!=m_pTransportStreamMap->End(); ++i)
  2809.     {
  2810. RTSPTransport* pTransport = (RTSPTransport*)(*i);
  2811. UINT16 streamNumber = (UINT16)i.get_key();
  2812. HX_ASSERT(pTransport);
  2813. rc = pTransport ? pTransport->SeekFlush(streamNumber) : HXR_OK;
  2814.     }
  2815.     m_pMutex->Unlock();
  2816.     return rc;
  2817. }
  2818. STDMETHODIMP_(BOOL)
  2819. RTSPClientProtocol::IsDataReceived(void)
  2820. {
  2821.     m_pMutex->Lock();
  2822.     BOOL bReceived = FALSE;
  2823.     CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
  2824.     if(i != m_pTransportStreamMap->End())
  2825.     {
  2826. RTSPTransport* pTrans = (RTSPTransport*)(*i);
  2827. bReceived = pTrans ? pTrans->IsDataReceived() : FALSE;
  2828.     }
  2829.     m_pMutex->Unlock();
  2830.     return bReceived;
  2831. }
  2832. STDMETHODIMP_(BOOL)
  2833. RTSPClientProtocol::IsSourceDone(void)
  2834. {
  2835.     m_pMutex->Lock();
  2836.     BOOL bDone = FALSE;
  2837.     CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
  2838.     if(i != m_pTransportStreamMap->End())
  2839.     {
  2840. RTSPTransport* pTrans = (RTSPTransport*)(*i);
  2841. bDone = pTrans ? pTrans->IsSourceDone() : FALSE;
  2842.     }
  2843.     m_pMutex->Unlock();
  2844.     return bDone;
  2845. }
  2846. STDMETHODIMP
  2847. RTSPClientProtocol::RuleChange(CHXSimpleList* pSubList)
  2848. {
  2849.     if (!m_pIsMethodSupported[SET_PARAM] || !m_pSession)
  2850.     {
  2851. return HXR_OK;
  2852.     }
  2853.     m_pMutex->Lock();
  2854.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  2855.     pMsg->setURL(m_url);
  2856.     CHXString SubString;
  2857.     CHXString UnSubString;
  2858.     CHXSimpleList::Iterator i;
  2859.     BOOL bFirstSub = TRUE;
  2860.     BOOL bFirstUnSub = TRUE;
  2861.     for(i=pSubList->Begin(); i!=pSubList->End(); ++i)
  2862.     {
  2863. char tmp[64];
  2864.         RTSPSubscription* pSub = (RTSPSubscription*)(*i);
  2865. SafeSprintf(tmp, 64, "stream=%d;rule=%ld", pSub->m_streamNumber,
  2866.     pSub->m_ruleNumber);
  2867. if (pSub->m_bIsSubscribe)
  2868. {
  2869.     if(!bFirstSub)
  2870.     {
  2871. SubString += "," + CHXString(tmp);
  2872.     }
  2873.     else
  2874.     {
  2875. SubString += tmp;
  2876. bFirstSub = FALSE;
  2877.     }
  2878. }
  2879. else
  2880. {
  2881.     if(!bFirstUnSub)
  2882.     {
  2883. UnSubString += "," + CHXString(tmp);
  2884.     }
  2885.     else
  2886.     {
  2887. UnSubString += tmp;
  2888. bFirstUnSub = FALSE;
  2889.     }
  2890. }
  2891.     }
  2892.     if (!bFirstSub)
  2893.     {
  2894. pMsg->addHeader("Subscribe", (const char*)SubString);
  2895.     }
  2896.     if (!bFirstUnSub)
  2897.     {
  2898. pMsg->addHeader("UnSubscribe", (const char*)UnSubString);
  2899.     }
  2900.     if (!m_sessionID.IsEmpty())
  2901.     {
  2902. pMsg->addHeader("Session", m_sessionID);
  2903.     }
  2904.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  2905.     HX_RESULT rc = sendRequest(pMsg, seqNo);
  2906.     m_pMutex->Unlock();
  2907.     return rc;
  2908. }
  2909. STDMETHODIMP
  2910. RTSPClientProtocol::Subscribe(CHXSimpleList* pSubList)
  2911. {
  2912.     return RuleChange(pSubList);
  2913. }
  2914. STDMETHODIMP
  2915. RTSPClientProtocol::Unsubscribe(CHXSimpleList* pUnsubList)
  2916. {
  2917.     return RuleChange(pUnsubList);
  2918. }
  2919. STDMETHODIMP
  2920. RTSPClientProtocol::BackChannelPacketReady(IHXPacket* pPacket)
  2921. {
  2922.     if (!m_pIsMethodSupported[SET_PARAM])
  2923.     {
  2924. return HXR_OK;
  2925.     }
  2926.     m_pMutex->Lock();
  2927.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  2928.     IHXBuffer* pBuffer = pPacket->GetBuffer();
  2929.     pMsg->setURL(m_url);
  2930.     char* pEncodedBuffer =
  2931. new char[pBuffer->GetSize() * 2 + 4]; // XXXSMP Overkill
  2932.     BinTo64(pBuffer->GetBuffer(), pBuffer->GetSize(), pEncodedBuffer);
  2933. int lenTmpBuf = strlen(pEncodedBuffer)+12;
  2934.     char* tmpBuf = new char[lenTmpBuf];
  2935.     SafeSprintf(tmpBuf, lenTmpBuf, ""%s"", pEncodedBuffer);
  2936.     pMsg->addHeader("BackChannel", tmpBuf);
  2937.     SafeSprintf(tmpBuf, lenTmpBuf, "%d", pPacket->GetStreamNumber());
  2938.     pMsg->addHeader("StreamNumber", tmpBuf);
  2939.     if (!m_sessionID.IsEmpty())
  2940.     {
  2941. pMsg->addHeader("Session", m_sessionID);
  2942.     }
  2943.     delete[] tmpBuf;
  2944.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  2945.     pBuffer->Release();
  2946.     delete[] pEncodedBuffer;
  2947.     HX_RESULT rc = sendRequest(pMsg, seqNo);
  2948.     m_pMutex->Unlock();
  2949.     return rc;
  2950. }
  2951. STDMETHODIMP
  2952. RTSPClientProtocol::SendRTTRequest()
  2953. {
  2954.     return DoSendRTTRequest();
  2955. }
  2956. STDMETHODIMP
  2957. RTSPClientProtocol::SendBWReport(INT32 aveBandwidth,
  2958. INT32 packetLoss,
  2959. INT32 bandwidthWanted)
  2960. {
  2961.     return DoSendBWReport(aveBandwidth, packetLoss, bandwidthWanted);
  2962. }
  2963. HX_RESULT
  2964. RTSPClientProtocol::DoSendRTTRequest(void)
  2965. {
  2966.     return HXR_OK;
  2967. }
  2968. HX_RESULT
  2969. RTSPClientProtocol::DoSendBWReport(INT32 aveBandwidth,
  2970.    INT32 packetLoss,
  2971.    INT32 bandwidthWanted)
  2972. {
  2973.     return HXR_OK;
  2974. }
  2975. HX_RESULT
  2976. RTSPClientProtocol::sendRequest(RTSPRequestMessage* pMsg,
  2977.                                 UINT32 seqNo)
  2978. {
  2979.     messageDebugFileOut((const char*)pMsg->asString(), FALSE); 
  2980.     // Our legacy timeout approach was to periodically send messages
  2981.     // to the server.  Currently, we only send a keep alive message
  2982.     // if we have not sent an rtsp message for the duration
  2983.     // of the timeout value.
  2984.     if (m_pSessionTimeout && !m_bUseLegacyTimeOutMsg)
  2985.     {
  2986.         m_pSessionTimeout->OnActivity();
  2987.     }
  2988.     return RTSPBaseProtocol::sendRequest(pMsg, seqNo);
  2989. }
  2990. HX_RESULT
  2991. RTSPClientProtocol::sendRequest(RTSPRequestMessage* pMsg,
  2992.                                 const char* pContent,
  2993.                                 const char* pMimeType,
  2994.                                 UINT32 seqNo)
  2995. {
  2996.     messageDebugFileOut((const char*)pMsg->asString(), FALSE); 
  2997.     if (m_pSessionTimeout && !m_bUseLegacyTimeOutMsg)
  2998.     {
  2999.         m_pSessionTimeout->OnActivity();
  3000.     }
  3001.     return RTSPBaseProtocol::sendRequest(pMsg, pContent, pMimeType, seqNo);
  3002. }
  3003. BOOL
  3004. RTSPClientProtocol::IsRealServer(void)
  3005. {
  3006.     return FALSE;
  3007. }
  3008. STDMETHODIMP
  3009. RTSPClientProtocol::SetFirstSeqNum(UINT16 uStreamNumber, UINT16 uSeqNum)
  3010. {
  3011.     m_pMutex->Lock();
  3012.     RTSPTransport* pTrans =
  3013. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  3014.     if(pTrans)
  3015.     {
  3016. pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
  3017. // pTrans->setFirstTimeStamp(uStreamNumber, ulTimeStamp);
  3018.     }
  3019.     m_pMutex->Unlock();
  3020.     return HXR_OK;
  3021. }
  3022. STDMETHODIMP
  3023. RTSPClientProtocol::SetRTPInfo(UINT16 uStreamNumber, UINT16 uSeqNum,
  3024.     UINT32 ulRTPTime, RTPInfoEnum info)
  3025. {
  3026.     m_pMutex->Lock();
  3027.     HX_ASSERT(RTPINFO_ERROR != info);
  3028.     RTSPTransport* pTrans =
  3029. (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  3030.     if(pTrans)
  3031.     {
  3032. /*
  3033. *  RTPTransport needs to know exactly what's in RTP-Info
  3034. */
  3035. if (RTPINFO_SEQ_RTPTIME == info)
  3036. {
  3037.     pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
  3038.     pTrans->setFirstTimeStamp(uStreamNumber, ulRTPTime);
  3039. }
  3040. else if (RTPINFO_SEQ == info)
  3041. {
  3042.     pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
  3043. }
  3044. else if (RTPINFO_RTPTIME == info)
  3045. {
  3046.     pTrans->setFirstTimeStamp(uStreamNumber, ulRTPTime);
  3047. }
  3048. else if (RTPINFO_EMPTY == info)
  3049. {
  3050.     pTrans->notifyEmptyRTPInfo();
  3051. }
  3052.     }
  3053.     m_pMutex->Unlock();
  3054.     return HXR_OK;
  3055. }
  3056. HX_RESULT
  3057. RTSPClientProtocol::ReadDoneWithToPort(HX_RESULT status, IHXBuffer* pBuffer,
  3058.        UINT32 ulAddr, UINT16 nFromPort, UINT16 nToPort)
  3059. {
  3060.     HX_RESULT hresult = HXR_OK;
  3061.     BOOL bMCastPort = FALSE;
  3062.     RTSPTransport* pTrans = NULL;
  3063.     /*
  3064.      * XXX HP: While handling the m_pData->done it's possible for the
  3065.      *         DispatchMessage call in CancelSelect to cause an
  3066.      *         asynchronous DoRead to occur. m_pTransportPortMap has
  3067.      *        been deleted inside Done() and we should add checkpoint
  3068.      *        here!!
  3069.      */
  3070.     if (m_bClientDone)
  3071.     {
  3072. return hresult;
  3073.     }
  3074.     m_pMutex->Lock();
  3075.     if(status == HXR_OK)
  3076.     {
  3077. //XXXBAB - need to get transport by port
  3078. pTrans = (RTSPTransport*)(*m_pTransportPortMap)[nToPort];
  3079. if (!pTrans)
  3080. {
  3081.     pTrans = (RTSPTransport*)(*m_pTransportMPortMap)[nToPort];
  3082.     bMCastPort = TRUE;
  3083.     m_currentTransport = MulticastMode;
  3084. }
  3085.         if (pTrans)
  3086.         {
  3087.             // make sure the unicast packets received are coming from the same server
  3088.             // we are connecting to
  3089.             if ((m_ulConnectToAddr == ulAddr) || bMCastPort)
  3090.             {
  3091.         if (!m_bReportedSuccessfulTransport)
  3092.         {
  3093.     m_bReportedSuccessfulTransport = TRUE;
  3094.     IHXPreferredTransportSink* pPreferredTransportSink = NULL;
  3095.     if (m_pResp &&
  3096.         HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
  3097.           (void**)&pPreferredTransportSink))
  3098.     {
  3099.         pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
  3100.     }
  3101.     HX_RELEASE(pPreferredTransportSink);
  3102.         }
  3103.                 // XXX HP we use PacketReady() to indicate the liveness of UDP connection
  3104.                 // for server timeout detection
  3105.                 PacketReady(HXR_OK, m_sessionID, NULL);
  3106.                 // drop all the scalable multicast packets when we are paused
  3107.                 if ((MulticastMode != m_currentTransport) || !m_bSDPInitiated || !m_bPaused)
  3108.                 {
  3109.             hresult = pTrans->handlePacket(pBuffer);
  3110.             if (m_bSplitterConsumer)
  3111.             {
  3112.         pTrans->releasePackets();
  3113.             }
  3114.                 }
  3115.             }
  3116.             else
  3117.             {
  3118.                 // XXX HP, invalid packets such as sent from 3rd party box
  3119.                 HX_ASSERT(FALSE);
  3120.             }
  3121.     if (hresult == HXR_OK || hresult == HXR_UNEXPECTED)
  3122.     {
  3123.         if (bMCastPort)
  3124.         {
  3125.     IHXUDPSocket* pSocket = pTrans->getMulticastSocket();
  3126.     hresult = pSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  3127.         }
  3128.         else
  3129.         {
  3130.     IHXUDPSocket* pSocket = pTrans->getUDPSocket();
  3131.     hresult = pSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  3132.         }
  3133.     }
  3134.         }
  3135.     }
  3136.     else
  3137.     {
  3138. hresult = PacketReady(HXR_FAIL, m_sessionID, 0);
  3139.     }
  3140.     m_pMutex->Unlock();
  3141.     return hresult;
  3142. }
  3143. STDMETHODIMP
  3144. RTSPClientProtocol::SetConnectionTimeout(UINT32 uSeconds)
  3145. {
  3146.     m_uConnectionTimeout = uSeconds;
  3147.     return HXR_OK;
  3148. }
  3149. STDMETHODIMP
  3150. RTSPClientProtocol::SetResendBufferDepth(UINT32 uSeconds)
  3151. {
  3152.     m_ulBufferDepth = uSeconds * 1000;
  3153.     return HXR_OK;
  3154. }
  3155. /*
  3156.  * IHXTransportSyncServer methods
  3157.  */
  3158. STDMETHODIMP
  3159. RTSPClientProtocol::DistributeSyncAnchor(ULONG32 ulHXTime,
  3160. ULONG32 ulNTPTime)
  3161. {
  3162.     m_pMutex->Lock();
  3163.     if (!m_transportRequestList.IsEmpty())
  3164.     {
  3165. RTSPTransportRequest* pRequest =
  3166.     (RTSPTransportRequest*)m_transportRequestList.GetHead();
  3167. RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
  3168. while(pTransInfo)
  3169. {
  3170.     pTransInfo->m_pTransport->anchorSync(ulHXTime, ulNTPTime);
  3171.     pTransInfo = pRequest->getNextTransportInfo();
  3172. }
  3173.     }
  3174.     m_pMutex->Unlock();
  3175.     return HXR_OK;
  3176. }
  3177. STDMETHODIMP
  3178. RTSPClientProtocol::DistributeSync(ULONG32 ulHXTime,
  3179.    LONG32 lHXTimeOffset)
  3180. {
  3181.     m_pMutex->Lock();
  3182.     if (!m_transportRequestList.IsEmpty())
  3183.     {
  3184. RTSPTransportRequest* pRequest =
  3185.     (RTSPTransportRequest*)m_transportRequestList.GetHead();
  3186. RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
  3187. while(pTransInfo)
  3188. {
  3189.     pTransInfo->m_pTransport->handleMasterSync(ulHXTime,
  3190.        lHXTimeOffset);
  3191.     pTransInfo = pRequest->getNextTransportInfo();
  3192. }
  3193.     }
  3194.     m_pMutex->Unlock();
  3195.     return HXR_OK;
  3196. }
  3197. STDMETHODIMP
  3198. RTSPClientProtocol::DistributeStartTime(ULONG32 ulHXRefTime)
  3199. {
  3200.     return HXR_NOTIMPL;
  3201. }
  3202. /*
  3203.  * IHXTransportBufferLimit methods
  3204.  */
  3205. /************************************************************************
  3206.  * Method:
  3207.  *     IHXTransportBufferLimit::SetByteLimit
  3208.  * Purpose:
  3209.  *      Sets the maximum number of bytes that can be buffered in the
  3210.  *      transport buffer. If incomming packets would put us over this
  3211.  *      limit, then they are replaced with lost packets. A byte limit
  3212.  *      of 0 means unlimited buffering.
  3213.  */
  3214. STDMETHODIMP
  3215. RTSPClientProtocol::SetByteLimit(UINT16 uStreamNumber, UINT32 uByteLimit)
  3216. {
  3217.     HX_RESULT res = HXR_FAILED;
  3218.     m_pMutex->Lock();
  3219.     RTSPTransportBuffer* pTransBuf = getTransportBuffer(uStreamNumber);
  3220.     if (pTransBuf)
  3221.     {
  3222. pTransBuf->SetByteLimit(uByteLimit);
  3223. res = HXR_OK;
  3224.     }
  3225.     m_pMutex->Unlock();
  3226.     return res;
  3227. }
  3228. /************************************************************************
  3229.  * Method:
  3230.  *     IHXTransportBufferLimit::GetByteLimit
  3231.  * Purpose:
  3232.  *      Returns the current byte limit in effect. A value of 0 means
  3233.  *      unlimited buffering is allowed
  3234.  */
  3235. STDMETHODIMP_(UINT32)
  3236. RTSPClientProtocol::GetByteLimit(UINT16 uStreamNumber)
  3237. {
  3238.     UINT32 ulRet = 0;
  3239.     m_pMutex->Lock();
  3240.     RTSPTransportBuffer* pTransBuf = getTransportBuffer(uStreamNumber);
  3241.     if (pTransBuf)
  3242.     {
  3243. ulRet = pTransBuf->GetByteLimit();
  3244.     }
  3245.     m_pMutex->Unlock();
  3246.     return ulRet;
  3247. }
  3248. /*
  3249.  * private RTSPClientProtocol methods
  3250.  */
  3251. HX_RESULT
  3252. RTSPClientProtocol::handleMessage(RTSPMessage* pMsg)
  3253. {
  3254.     HX_RESULT rc = HXR_OK;
  3255.     m_pMutex->Lock();
  3256.     messageDebugFileOut((const char*)pMsg->asString(), TRUE);
  3257.     if(pMsg->tag() != RTSPMessage::T_RESP)
  3258.     {
  3259. int majorVersion = pMsg->majorVersion();
  3260. int minorVersion = pMsg->minorVersion();
  3261. if((majorVersion == 0 && minorVersion == 0) ||
  3262.    (majorVersion > RTSPMessage::MAJ_VERSION))
  3263. {
  3264.     rc = HandleBadVersion(pMsg);
  3265.     goto exit;
  3266. }
  3267. else if(minorVersion > RTSPMessage::MIN_VERSION)
  3268. {
  3269.     rc = HandleBadVersion(pMsg);
  3270.     goto exit;
  3271. }
  3272.     }
  3273.     // XXX HP we use PacketReady() to indicate the liveness of TCP connection
  3274.     // for server timeout detection
  3275.     if (TCPMode == m_currentTransport ||
  3276.         HTTPCloakMode == m_currentTransport)
  3277.     {
  3278.         PacketReady(HXR_OK, m_sessionID, NULL);
  3279.     }
  3280.     switch(pMsg->tag())
  3281.     {
  3282. case RTSPMessage::T_OPTIONS:
  3283. {
  3284.     rc = HandleOptions((RTSPOptionsMessage*)pMsg);
  3285.     goto exit;
  3286. }
  3287. case RTSPMessage::T_SET_PARAM:
  3288. {
  3289.     rc = HandleSetParam((RTSPSetParamMessage*)pMsg);
  3290.     goto exit;
  3291. }
  3292. case RTSPMessage::T_REDIRECT:
  3293. {
  3294.     rc = HandleRedirect((RTSPRedirectMessage*)pMsg);
  3295.     goto exit;
  3296. }
  3297. case RTSPMessage::T_RESP:
  3298. {
  3299.     // check for proxy(305) redirect
  3300.     const char* pErrorCode = ((RTSPResponseMessage*)pMsg)->errorCode();
  3301.     if(strcmp(pErrorCode, "305") == 0)
  3302.     {
  3303. rc = HandleUseProxy((RTSPResponseMessage*)pMsg);
  3304. goto exit;
  3305.     }
  3306.     // check for URL redirect
  3307.     else if (strcmp(pErrorCode, "302") == 0 ||
  3308.      strcmp(pErrorCode, "303") == 0)
  3309.     {
  3310.      rc = HandleRedirectResponse((RTSPResponseMessage*)pMsg);
  3311.      goto exit;
  3312.     }
  3313.     RTSPMessage* pReqMsg = dequeueMessage(pMsg->seqNo());
  3314.     if(pReqMsg)
  3315.     {
  3316. switch(pReqMsg->tag())
  3317. {
  3318.     case RTSPMessage::T_OPTIONS:
  3319.     {
  3320. rc = handleOptionsResponse((RTSPResponseMessage*)pMsg);
  3321.     }
  3322.     break;
  3323.     case RTSPMessage::T_GET_PARAM:
  3324.     {
  3325. rc = handleGetParamResponse((RTSPResponseMessage*)pMsg);
  3326.     }
  3327.     break;
  3328.     case RTSPMessage::T_SET_PARAM:
  3329.     {
  3330. rc = handleSetParamResponse((RTSPResponseMessage*)pMsg);
  3331.     }
  3332.     break;
  3333.     case RTSPMessage::T_TEARDOWN:
  3334.     {
  3335. rc = handleTeardownResponse((RTSPResponseMessage*)pMsg);
  3336. m_state = RTSPClientProtocol::INIT;
  3337.     }
  3338.     break;
  3339.     case RTSPMessage::T_DESCRIBE:
  3340.     {
  3341. rc = handleDescribeResponse((RTSPResponseMessage*)pMsg);
  3342.     }
  3343.     break;
  3344.     case RTSPMessage::T_ANNOUNCE:
  3345.     {
  3346. rc = handleAnnounceResponse((RTSPResponseMessage*)pMsg);
  3347.     }
  3348.     break;
  3349.     default:
  3350.     {
  3351. switch(m_state)
  3352. {
  3353.     case RTSPClientProtocol::INIT:
  3354.     {
  3355. switch(pReqMsg->tag())
  3356. {
  3357.     case RTSPMessage::T_SETUP:
  3358.     {
  3359. rc = handleSetupResponse(
  3360.     (RTSPResponseMessage*)pMsg,
  3361.     (RTSPSetupMessage*)pReqMsg);
  3362. if(rc == HXR_OK)
  3363. {
  3364.     m_state = RTSPClientProtocol::READY;
  3365. }
  3366.     }
  3367.     break;
  3368.     default:
  3369.     {
  3370. rc = HandleUnexpected(pMsg);
  3371.     }
  3372.     break;
  3373. }
  3374.     }
  3375.     break;
  3376.     case RTSPClientProtocol::READY:
  3377.     {
  3378. switch(pReqMsg->tag())
  3379. {
  3380.     case RTSPMessage::T_SETUP:
  3381.     {
  3382. rc = handleSetupResponse(
  3383.     (RTSPResponseMessage*)pMsg,
  3384.     (RTSPSetupMessage*)pReqMsg);
  3385.     }
  3386.     break;
  3387.     case RTSPMessage::T_PLAY:
  3388.     {
  3389. rc = handlePlayResponse(
  3390.     (RTSPResponseMessage*)pMsg,
  3391.     (RTSPPlayMessage*)pReqMsg);
  3392. if(rc == HXR_OK)
  3393. {
  3394.     m_state =
  3395. RTSPClientProtocol::PLAYING;
  3396. }
  3397.     }
  3398.     break;
  3399.     case RTSPMessage::T_RECORD:
  3400.     {
  3401. rc = handleRecordResponse(
  3402.     (RTSPResponseMessage*)pMsg);
  3403. if(rc == HXR_OK)
  3404. {
  3405.     m_state =
  3406. RTSPClientProtocol::RECORDING;
  3407. }
  3408.     }
  3409.     break;
  3410.     default:
  3411.     {
  3412. rc = HandleUnexpected(pMsg);
  3413.     }
  3414.     break;
  3415. }
  3416.     }
  3417.     break;
  3418.     case RTSPClientProtocol::PLAYING:
  3419.     {
  3420. switch(pReqMsg->tag())
  3421. {
  3422.     case RTSPMessage::T_PLAY:
  3423.     {
  3424. rc = handlePlayResponse(
  3425.     (RTSPResponseMessage*)pMsg,
  3426.     (RTSPPlayMessage*)pReqMsg);
  3427.     }
  3428.     break;
  3429.     case RTSPMessage::T_PAUSE:
  3430.     {
  3431. rc = handlePauseResponse(
  3432.     (RTSPResponseMessage*)pMsg);
  3433. if(rc == HXR_OK)
  3434. {
  3435.     m_state =
  3436. RTSPClientProtocol::READY;
  3437. }
  3438.     }
  3439.     break;
  3440.     default:
  3441.     {
  3442. rc = HandleUnexpected(pMsg);
  3443.     }
  3444.     break;
  3445. }
  3446.     }
  3447.     break;
  3448.     case RTSPClientProtocol::RECORDING:
  3449.     {
  3450. switch(pReqMsg->tag())
  3451. {
  3452.     case RTSPMessage::T_RECORD:
  3453.     {
  3454. rc = handleRecordResponse(
  3455.     (RTSPResponseMessage*)pMsg);
  3456.     }
  3457.     break;
  3458.     case RTSPMessage::T_PAUSE:
  3459.     {
  3460. rc = handlePauseResponse(
  3461.     (RTSPResponseMessage*)pMsg);
  3462. if(rc == HXR_OK)
  3463. {
  3464.     m_state =
  3465. RTSPClientProtocol::READY;
  3466. }
  3467.     }
  3468.     break;
  3469.     default:
  3470.     {
  3471. rc = HandleUnexpected(pMsg);
  3472.     }
  3473.     break;
  3474. }
  3475.     }
  3476.     break;
  3477. }
  3478.     }
  3479.     break;
  3480. }
  3481.                 // Create and init out server timeout object
  3482.                 if (!m_pTimeoutCallback)
  3483.                 {
  3484.                     m_pTimeoutCallback = new TimeoutCallback(this);
  3485.                     m_pTimeoutCallback->AddRef();
  3486.                 }
  3487.                 UINT32 nTimeOut = 0;
  3488.                 // Set to server timeout value on creation
  3489.                 if (!m_pSessionTimeout)
  3490.                 {
  3491.                     m_pSessionTimeout = new CHXKeepAlive;
  3492.                     nTimeOut = m_ulServerTimeOut;
  3493.                 }
  3494.                 // Check for session timeout
  3495.                 CHXString sessionID = pMsg->getHeaderValue("Session");
  3496.                 if(sessionID != "")
  3497.                 {
  3498.             int i;
  3499.             if (-1 != (i = sessionID.Find('=')))
  3500.             {
  3501.                         // Wake up early for session timeout since servers will
  3502.                         // disconnect if they do not receive messages on time.
  3503.                         nTimeOut = atoi(sessionID.Right(sessionID.GetLength()-(i+1)));
  3504.                         // Some servers specify timeout in ms not secs
  3505.                         if (nTimeOut < 1000)
  3506.                             nTimeOut *= 1000;
  3507.                         // If session timeout is present, use options message to alert the
  3508.                         // server we are still alive.  If not, use setparam.
  3509.                         m_bUseLegacyTimeOutMsg = FALSE;
  3510.                         // If session timeout value differnt than our current value, we
  3511.                         // need to reinit the scheduer.
  3512.                         if (nTimeOut == m_ulCurrentTimeOut)
  3513.                         {
  3514.                             nTimeOut = 0;
  3515.                         }
  3516.                         // Use the lower of our default timeout and the session timeout
  3517.                         else if (m_ulServerTimeOut < nTimeOut)
  3518.                         {
  3519.                             nTimeOut = m_ulServerTimeOut;
  3520.                         }
  3521.             }
  3522.                 }
  3523. if (nTimeOut && m_pSessionTimeout)
  3524.                 {
  3525.                     m_pSessionTimeout->Init(m_pScheduler,
  3526.                                             nTimeOut/2,
  3527.                                             (IHXCallback*)m_pTimeoutCallback);
  3528.                     m_ulCurrentTimeOut = nTimeOut;
  3529.                 }
  3530.                 delete pReqMsg;
  3531.     }
  3532. }
  3533. break;
  3534. default:
  3535. {
  3536.     rc =  HandleUnexpected(pMsg);
  3537.     goto exit;
  3538. }
  3539.     }
  3540. exit:
  3541.     m_pMutex->Unlock();
  3542.     return rc;
  3543. }
  3544. const char*
  3545. RTSPClientProtocol::allowedMethods()
  3546. {
  3547.     return "OPTIONS";
  3548. }
  3549. HX_RESULT
  3550. RTSPClientProtocol::handleTCPData(BYTE* pData, UINT16 dataLen, UINT16 channel)
  3551. {
  3552.     if (!m_pTransportChannelMap)
  3553. return HXR_FAIL;
  3554.     m_pMutex->Lock();
  3555.     HX_RESULT rc = HXR_OK;
  3556.     CHXBuffer* pBuffer = new CHXBuffer;
  3557.     if(!pBuffer)
  3558.     {
  3559.         rc = HXR_OUTOFMEMORY;
  3560.         goto overandout;
  3561.     }
  3562.     pBuffer->AddRef();
  3563.     rc = pBuffer->Set(pData, dataLen);
  3564.     if( rc == HXR_OUTOFMEMORY )
  3565.     {
  3566.         pBuffer->Release();
  3567.         goto overandout;
  3568.     }
  3569.     RTSPTransport* pTrans;
  3570.     if (m_pTransportChannelMap->Lookup(channel, (void*&)pTrans))
  3571.     {
  3572.         if (!m_bReportedSuccessfulTransport)
  3573.         {
  3574.             m_bReportedSuccessfulTransport = TRUE;
  3575.             IHXPreferredTransportSink* pPreferredTransportSink = NULL;
  3576.             if (m_pResp &&
  3577.                 HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
  3578.                                                 (void**)&pPreferredTransportSink))
  3579.             {
  3580.                 pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
  3581.             }
  3582.             HX_RELEASE(pPreferredTransportSink);
  3583.         }
  3584.         
  3585. rc = pTrans->handlePacket(pBuffer);
  3586.     }
  3587. #ifdef _DEBUG
  3588.     else
  3589.     {
  3590. HX_ASSERT(!"make sure TransportChannelMap has been set up right...");
  3591.     }
  3592. #endif
  3593.     pBuffer->Release();
  3594. overandout:
  3595.     m_pMutex->Unlock();
  3596.     return rc;
  3597. }
  3598. /*
  3599.  */
  3600. SdpFileType
  3601. RTSPClientProtocol::GetSdpFileTypeWeNeed(IHXValues* pHeaders)
  3602. {
  3603.     IHXBuffer* pAgent = NULL;
  3604.     SdpFileType sdpType = NONE_SDP;
  3605.     /*
  3606.      * Better make sure to come up with a better way to check
  3607.      */
  3608.     if (FAILED(pHeaders->GetPropertyCString("Server", pAgent)))
  3609.     {
  3610. return NONE_SDP;
  3611.     }
  3612.     if (strstr((const char*)pAgent->GetBuffer(), "RealMedia"))
  3613.     {
  3614. sdpType = BACKWARD_COMP_SDP;
  3615.     }
  3616.     else
  3617.     {
  3618. sdpType = INTEROP_SDP;
  3619.     }
  3620.     HX_RELEASE(pAgent);
  3621.     return sdpType;
  3622. }
  3623. HX_RESULT
  3624. RTSPClientProtocol::GetStreamDescriptionInfo(IUnknown* pUnknown, CHXString& mimeTypes)
  3625. {
  3626.     HX_RESULT               rc = HXR_OK;
  3627.     const char*             pMimeType = NULL;
  3628.     BOOL                    bIsFirst = TRUE;
  3629.     IHXStreamDescription*   pStreamDesc = NULL;
  3630.     if (HXR_OK == pUnknown->QueryInterface(IID_IHXStreamDescription,(void**)&pStreamDesc) &&
  3631.         pStreamDesc)
  3632.     {
  3633. pStreamDesc->GetStreamDescriptionInfo(pMimeType);
  3634. if(bIsFirst)
  3635. {
  3636.     mimeTypes += pMimeType;
  3637.     bIsFirst = FALSE;
  3638. }
  3639. else
  3640. {
  3641.     mimeTypes += ", " + (CHXString)pMimeType;
  3642. }
  3643. pStreamDesc->Release();
  3644.     }
  3645.     return rc;
  3646. }
  3647. void
  3648. RTSPClientProtocol::SendMsgToTransport(TRANSPORT_MSG msg)
  3649. {
  3650.     RTSPTransportRequest*   pRequest = NULL;
  3651.     RTSPTransportInfo*     pTransInfo = NULL;
  3652.     if (!m_transportRequestList.IsEmpty())
  3653.     {
  3654.         pRequest = (RTSPTransportRequest*)m_transportRequestList.GetHead();
  3655.         pTransInfo = pRequest->getFirstTransportInfo();
  3656.         while(pTransInfo)
  3657.         {
  3658.             switch (msg)
  3659.             {
  3660.             case ENTER_PREFETCH:
  3661.         pTransInfo->m_pTransport->EnterPrefetch();
  3662.                 break;
  3663.             case LEAVE_PREFETCH:
  3664.                 pTransInfo->m_pTransport->LeavePrefetch();
  3665.                 break;
  3666.             case ENTER_FASTSTART:
  3667.                 pTransInfo->m_pTransport->EnterFastStart();
  3668.                 break;
  3669.             case LEAVE_FASTSTART:
  3670.                 pTransInfo->m_pTransport->LeaveFastStart();
  3671.                 break;
  3672.             case PAUSE_BUFFER:
  3673.                 pTransInfo->m_pTransport->pauseBuffers();
  3674.                 break;
  3675.             case RESUME_BUFFER:
  3676.                 pTransInfo->m_pTransport->resumeBuffers();
  3677.                 break;
  3678.             default:
  3679.                 break;
  3680.             }
  3681.     pTransInfo = pRequest->getNextTransportInfo();
  3682.         }
  3683.     }
  3684. }
  3685. void
  3686. RTSPClientProtocol::AddCommonHeaderToMsg(RTSPRequestMessage* pMsg)
  3687. {
  3688.     if (pMsg)
  3689.     {
  3690.         pMsg->addHeader("User-Agent", m_versionString);
  3691.         if (!m_sessionID.IsEmpty())
  3692.         {
  3693.     pMsg->addHeader("Session", m_sessionID);
  3694.         }
  3695.     }
  3696. }
  3697. HX_RESULT
  3698. RTSPClientProtocol::SendMsgToServer(RTSPMethod msg)
  3699. {
  3700.     HX_RESULT           rc = HXR_OK;
  3701.     RTSPRequestMessage* pMsg = NULL;
  3702.     switch(msg)
  3703.     {
  3704.     case RTSP_PLAY:
  3705.         pMsg = new RTSPPlayMessage;
  3706.         break;
  3707.     case RTSP_PAUSE:
  3708.         pMsg = new RTSPPauseMessage;
  3709.         break;
  3710.     case RTSP_OPTIONS:
  3711.         pMsg = new RTSPOptionsMessage;
  3712.         break;
  3713.     case RTSP_TEARDOWN:
  3714.         pMsg = new RTSPTeardownMessage;
  3715.         break;
  3716.     default:
  3717.         break;
  3718.     }
  3719.     if (pMsg)
  3720.     {
  3721.         pMsg->setURL(m_url);
  3722.         AddCommonHeaderToMsg(pMsg);
  3723.         UINT32 seqNo = m_pSession->getNextSeqNo(this);
  3724.         rc = sendRequest(pMsg, seqNo);
  3725.     }
  3726.     else
  3727.     {
  3728.         rc = HXR_OUTOFMEMORY;
  3729.     }
  3730.     return rc;
  3731. }
  3732. HX_RESULT
  3733. RTSPClientProtocol::handleOptionsResponse
  3734. (
  3735.     RTSPResponseMessage* pRTSPResponseMessageIncoming
  3736. )
  3737. {
  3738.     HX_RESULT   rc = HXR_OK;
  3739.     if (pRTSPResponseMessageIncoming->errorCodeAsUINT32() == 551)
  3740.     {
  3741. /* Quite poor, but the client only supports this one require for now */
  3742. return m_pResp->HandleOptionsResponse(HXR_LOADTEST_NOT_SUPPORTED,
  3743.     NULL);
  3744.     }
  3745.     else if(pRTSPResponseMessageIncoming->errorCodeAsUINT32() != 200)
  3746.     {
  3747. return m_pResp->HandleOptionsResponse(HXR_FAIL, NULL);
  3748.     }
  3749.     else
  3750.     {
  3751.         // Filter out session timeout message reponses
  3752.         if (m_bKeepAlivePending)
  3753.         {
  3754.     m_bKeepAlivePending = FALSE;
  3755.             return HXR_OK;
  3756.         }
  3757.         /*
  3758. * XXXGH...I added this just for the stats mask, but the
  3759. * authentication should be available from the 822 headers too
  3760. */
  3761. IHXValues* pRFC822Headers = NULL;
  3762. getRFC822Headers(pRTSPResponseMessageIncoming, pRFC822Headers);
  3763. if (pRFC822Headers)
  3764. {
  3765.     IHXKeyValueList* pRFC822List = NULL;
  3766.     if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
  3767.     {
  3768. m_pResponseHeaders->AppendAllListItems(pRFC822List);
  3769.     }
  3770.     HX_RELEASE(pRFC822List);
  3771. }
  3772. if (m_sessionID.IsEmpty())
  3773. {
  3774.          m_sessionID = pRTSPResponseMessageIncoming->getHeaderValue("Session");
  3775. }
  3776. // Respond to Client Challenge to prove that we are a RealClient
  3777. if (!m_pSession->m_bChallengeDone &&
  3778.     HXR_OK != RetrieveChallenge(pRTSPResponseMessageIncoming))
  3779. {
  3780.     IHXValues* pResponseHeaders = NULL;
  3781.     // check for supported RTSP methods if the server could be non-RS
  3782.             if (m_pResponseHeaders &&
  3783. HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  3784.     {
  3785.                 IHXBuffer* pCmds = NULL;
  3786.                 // Thanks IPTV for adding a space after Public
  3787.                 if (HXR_OK == pResponseHeaders->GetPropertyCString("Allow", pCmds) ||
  3788.                     HXR_OK == pResponseHeaders->GetPropertyCString("Public", pCmds) ||
  3789.                     HXR_OK == pResponseHeaders->GetPropertyCString("Public ", pCmds))
  3790.                 {
  3791.                     // all methods are supported by default
  3792.                     if (!strstr((char*)pCmds->GetBuffer(), "SETUP"))
  3793.                         m_pIsMethodSupported[SETUP] = FALSE;
  3794.                     // Is redirect supported
  3795.                     if (!strstr((char*)pCmds->GetBuffer(), "REDIRECT"))
  3796.                         m_pIsMethodSupported[REDIRECT] = FALSE;
  3797.                     // Is play supported
  3798.                     if (!strstr((char*)pCmds->GetBuffer(), "PLAY"))
  3799.                         m_pIsMethodSupported[PLAY] = FALSE;
  3800.                     // Is pause supported
  3801.                     if (!strstr((char*)pCmds->GetBuffer(), "PAUSE"))
  3802.                         m_pIsMethodSupported[PAUSE] = FALSE;
  3803.                     // Is set_param supported
  3804.                     if (!strstr((char*)pCmds->GetBuffer(), "SET_PARAMETER"))
  3805.                         m_pIsMethodSupported[SET_PARAM] = FALSE;
  3806.                     // Is get_param supported
  3807.                     if (!strstr((char*)pCmds->GetBuffer(), "GET_PARAMETER"))
  3808.                         m_pIsMethodSupported[GET_PARAM] = FALSE;
  3809.                     // Is describe supported
  3810.                     if (!strstr((char*)pCmds->GetBuffer(), "DESCRIBE"))
  3811.                         m_pIsMethodSupported[DESCRIBE] = FALSE;
  3812.                     // Is teardown supported
  3813.                     if (!strstr((char*)pCmds->GetBuffer(), "TEARDOWN"))
  3814.                         m_pIsMethodSupported[TEARDOWN] = FALSE;
  3815.                     // Is record supported
  3816.                     if (!strstr((char*)pCmds->GetBuffer(), "RECORD"))
  3817.                         m_pIsMethodSupported[RECORD] = FALSE;
  3818.                     // Is announce supported
  3819.                     if (!strstr((char*)pCmds->GetBuffer(), "ANNOUNCE"))
  3820.                         m_pIsMethodSupported[ANNOUNCE] = FALSE;
  3821.                 }
  3822.                 HX_RELEASE(pCmds);
  3823.             }
  3824.             HX_RELEASE(pResponseHeaders);
  3825.         }
  3826.         if (m_bSDPInitiated)
  3827.         {
  3828.     IHXValues* pResponseHeaders = NULL;
  3829.     if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  3830.     {
  3831. if (!IsRealServer())
  3832. {
  3833.     BOOL bForceRTP = TRUE;
  3834.                     ReadPrefBOOL(m_pPreferences, "NonRS", bForceRTP);
  3835.     if (bForceRTP)
  3836.     {
  3837. pResponseHeaders->SetPropertyULONG32("UseRTP", TRUE);
  3838.     }
  3839. }
  3840.                 m_url = m_headerControl;
  3841. rc = m_pResp->HandleStreamDescriptionResponse
  3842. (
  3843.     HXR_OK,
  3844.     m_pSDPFileHeader,
  3845.     m_pSDPStreamHeaders,
  3846.     pResponseHeaders
  3847. );
  3848.     }
  3849.     HX_RELEASE(pResponseHeaders);
  3850.             RemoveSDPHeaders();
  3851.         }
  3852.         else
  3853.         {
  3854.     rc = m_pResp->HandleOptionsResponse(HXR_OK, pRFC822Headers);
  3855.     HX_RELEASE(pRFC822Headers);
  3856.         }
  3857. return rc;
  3858.     }
  3859. }
  3860. HX_RESULT
  3861. RTSPClientProtocol::handleGetParamResponse(RTSPResponseMessage* pMsg)
  3862. {
  3863.     if(strcmp(pMsg->errorCode(), "200") != 0)
  3864.     {
  3865. return m_pResp->HandleGetParameterResponse(HXR_FAIL, 0);
  3866.     }
  3867.     CHXBuffer* pBuffer = new CHXBuffer;
  3868.     if(!pBuffer)
  3869.     {
  3870.         return HXR_OUTOFMEMORY;
  3871.     }
  3872.     pBuffer->AddRef();
  3873.     const char* pContent = (char*)pMsg->getContent();
  3874.     HX_RESULT ret = pBuffer->Set((BYTE*)pContent, strlen(pContent) + 1);