rtspclnt.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:217k
源码类别:

Symbian

开发平台:

C/C++

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