rtspprotocol.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:81k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: rtspprotocol.cpp,v 1.27.2.3 2004/07/13 17:12:04 ping Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include "hlxclib/stdio.h"
  51. #include "hlxclib/stdlib.h"
  52. #include "hxver.h"
  53. #include "hxtypes.h"
  54. #include "hxresult.h"
  55. #include "hxstrutl.h"
  56. #include "hxcomm.h"
  57. #include "ihxpckts.h"
  58. #include "hxfiles.h"
  59. #include "hxengin.h"
  60. #include "hxasm.h"
  61. #include "hxsdesc.h"
  62. #include "chxpckts.h"
  63. #include "hxcore.h"
  64. #include "hxprefs.h" 
  65. #include "hxpref.h"
  66. #include "hxsdesc.h"
  67. #include "hxpends.h"
  68. #include "hxrsdbf.h"
  69. #include "hxengin.h"
  70. #include "hxstring.h"
  71. #include "hxslist.h"
  72. #include "hxstat.h"
  73. #include "hxtick.h"
  74. #include "chxeven.h"
  75. #include "hxcleng.h"
  76. //#include "rtmlpars.h"
  77. #include "rtspclnt.h"
  78. #include "rtspclntext.h"
  79. #include "rtsputil.h"
  80. #include "mimehead.h"
  81. #include "rtspmsg.h"
  82. #include "rtsppars.h"
  83. #include "rtspmdsc.h"
  84. #include "statinfo.h"
  85. #include "hxntsrc.h"
  86. #include "hxprotocol.h"
  87. #include "hxauthn.h"
  88. #include "hxplgns.h"
  89. #include "hxauth.h"
  90. #include "hxdate.h"
  91. #include "hxurl.h"
  92. #include "platform.h"
  93. #include "clntcore.ver"
  94. #include "hxplugn.h"
  95. #include "dtrvtcon.h"
  96. #include "rmfftype.h"
  97. #include "rtspprotocol.h"
  98. #include "hxcomsp.h"
  99. #include "hxpktsp.h"
  100. #include "hxplnsp.h"
  101. #include "miscsp.h"
  102. #include "hxxrsmg.h"
  103. #include "hxresmgr.h"
  104. #include "dcoreres.h"
  105. #ifdef _MACINTOSH
  106. #include "hxmm.h"
  107. #endif
  108. #include "hxheap.h"
  109. #ifdef _DEBUG
  110. #undef HX_THIS_FILE
  111. static const char HX_THIS_FILE[] = __FILE__;
  112. #endif
  113. #define PRAGMA  "initiate-session"
  114. #define MINIMUM_STATS_INTERVAL      15000 // 15 seconds
  115. #define MAX_DEFAULT_STATS_SIZE      512
  116. #define MAX_TRANSPORT               10
  117. RTSPProtocol::RTSPProtocol(HXNetSource* owner, ULONG32 ulPlatformSpecific)
  118. : HXProtocol (owner, ulPlatformSpecific)
  119. , m_lRefCount(0)
  120. , m_uSecurityKey(0)
  121. , m_uStreamCount(0)
  122. , m_uCurrentStreamCount(0)
  123. , m_pProtocolLib(0)
  124. , m_pPendingStatus(0)
  125. , m_pStatistics(0)
  126. , m_bPlaying(FALSE)
  127. , m_bIsASMSource(FALSE)
  128. , m_bUseRTP(FALSE)
  129. , m_bReceivedData(FALSE)
  130. , m_bMulticastOnly(FALSE)
  131. , m_idleState(NULL_STATE)
  132. , m_pIDInfo(NULL)
  133. , m_pRequest(NULL)
  134. , m_bFirstAuthAttempt(TRUE)
  135. , mReceivedControl(FALSE)
  136. , m_bPendingSeek(FALSE)
  137. , m_ulSeekPos1(0)
  138. , m_ulSeekPos2(0)
  139. , m_bHandleWWWAuthentication(FALSE)
  140. , m_WWWResult(HXR_OK)
  141. , m_pWWWValues(NULL)
  142. #if defined(HELIX_FEATURE_REVERTER)
  143. , m_pDataRevert(0)
  144. #endif /* HELIX_FEATURE_REVERTER */
  145. {
  146.     m_pStreamInfoList = new CHXMapLongToObj;
  147.     
  148.     if (owner)
  149.     {
  150.         IHXPlayer* pPlayer = NULL;
  151.         IUnknown*   pUnknown = NULL;
  152.         owner->GetPlayer(pPlayer);
  153.         if (pPlayer)
  154.         {
  155.             pUnknown = (IUnknown*)pPlayer;
  156.         }
  157.         // auto. config doesn't have the player object
  158.         // use IHXClientEngine instead
  159.         else
  160.         {
  161.             owner->GetContext(pUnknown);
  162.         }
  163. #if defined(HELIX_FEATURE_REVERTER)
  164.         m_pDataRevert = new DataRevertController(pUnknown);
  165.         m_pDataRevert->AddRef();
  166.         m_pDataRevert->SetControlResponse(this);
  167. #endif /* HELIX_FEATURE_REVERTER */
  168.         HX_RELEASE(pUnknown);
  169.     }
  170.     /* Always allowed in RTSP - till we add some code to file format
  171.      * plugins to set this value in file header - XXXRA
  172.      */
  173.     m_bPerfectPlayAllowed = TRUE;
  174.     //
  175.     // get proxy info for RTSP protocol
  176.     //
  177.     initialize_members();
  178.     ReadPrefBOOL(m_pPreferences, "NonRS", m_bUseRTP);    
  179.     if (!m_bUseRTP)
  180.     {
  181.         ReadPrefBOOL(m_pPreferences, "UseRTP", m_bUseRTP);
  182.     }
  183. }
  184. RTSPProtocol::~RTSPProtocol ()
  185. {
  186.     if (m_pProtocolLib)
  187.     {
  188.         m_pProtocolLib->Done();
  189.         HX_RELEASE(m_pProtocolLib);
  190.     }
  191.     HX_RELEASE(m_pRequest);
  192.     HX_RELEASE(m_pPendingStatus);
  193.     HX_RELEASE(m_pStatistics);
  194.     HX_RELEASE(m_pIDInfo);
  195.     HX_RELEASE(m_pWWWValues);
  196. #if defined(HELIX_FEATURE_REVERTER)
  197.     HX_RELEASE(m_pDataRevert);
  198. #endif /* HELIX_FEATURE_REVERTER */
  199.     
  200.     HX_DELETE(m_pStreamInfoList);
  201. }
  202. /* IUnknown methods */
  203. STDMETHODIMP
  204. RTSPProtocol::QueryInterface(REFIID riid, void** ppvObj)
  205. {
  206.     QInterfaceList qiList[] =
  207.         {
  208.             { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
  209.             { GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*)this },
  210.             { GET_IIDHANDLE(IID_IHXBackChannel), (IHXBackChannel*)this },
  211.             { GET_IIDHANDLE(IID_IHXAtomicRuleChange), (IHXAtomicRuleChange*)this },
  212.             { GET_IIDHANDLE(IID_IHXPreferredTransportSink), (IHXPreferredTransportSink*)this },
  213.             { GET_IIDHANDLE(IID_IUnknown), this },
  214.         };
  215.     
  216.     if (HXR_OK == ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj))
  217.     {
  218.         return HXR_OK;
  219.     }    
  220.     else if (IsEqualIID(riid, IID_IHXASMSource) && m_bIsASMSource)
  221.     {
  222.         AddRef();
  223.         *ppvObj = (IHXASMSource*)this;
  224.         return HXR_OK;
  225.     }
  226.     else if (m_pProtocolLib &&
  227.             (HXR_OK == m_pProtocolLib->QueryInterface(riid, ppvObj)))
  228.     {
  229.         return HXR_OK;
  230.     }
  231.     *ppvObj = NULL;
  232.     return HXR_NOINTERFACE;
  233. }
  234. /////////////////////////////////////////////////////////////////////////
  235. //  Method:
  236. //      IUnknown::AddRef
  237. //  Purpose:
  238. //      Everyone usually implements this the same... feel free to use
  239. //      this implementation.
  240. //
  241. STDMETHODIMP_(ULONG32) RTSPProtocol::AddRef()
  242. {
  243.     return InterlockedIncrement(&m_lRefCount);
  244. }
  245. /////////////////////////////////////////////////////////////////////////
  246. //  Method:
  247. //      IUnknown::Release
  248. //  Purpose:
  249. //      Everyone usually implements this the same... feel free to use
  250. //      this implementation.
  251. //
  252. STDMETHODIMP_(ULONG32) RTSPProtocol::Release()
  253. {
  254.     if (InterlockedDecrement(&m_lRefCount) > 0)
  255.     {
  256.         return m_lRefCount;
  257.     }
  258.     delete this;
  259.     return 0;
  260. }
  261. /* IHXRTSPClientProtocolResponse methods */
  262. STDMETHODIMP
  263. RTSPProtocol::InitDone
  264. (
  265.     HX_RESULT status
  266. )
  267. {
  268.     if (status != HXR_OK)
  269.     {
  270.         /*
  271.          * XXX...Need to get proper errors from protocol library
  272.          */
  273.         mOwner->ReportError(status); //ConvertHResultToHXError(status));
  274.     }
  275.     if (m_pProtocolLib->HttpOnly())
  276.     {
  277.         mCurrentTransport = TCPMode;
  278.     }
  279.     return HXR_OK;
  280. }
  281. STDMETHODIMP
  282. RTSPProtocol::HandleWWWAuthentication
  283. (
  284.     HX_RESULT HX_RESULTStatus,
  285.     IHXValues* pIHXValuesHeaders
  286. )
  287. {
  288. #if defined(HELIX_FEATURE_AUTHENTICATION)
  289. #ifdef _MACINTOSH
  290.     /*
  291.      * We load a plugin for authetication. Can't do this at interrupt
  292.      * time on Mac
  293.      */
  294.     if (HXMM_ATINTERRUPT())
  295.     {
  296.         m_bHandleWWWAuthentication  = TRUE;
  297.         m_WWWResult                 = HX_RESULTStatus;
  298.         HX_RELEASE(m_pWWWValues);
  299.         m_pWWWValues                = pIHXValuesHeaders;
  300.         if (m_pWWWValues)
  301.         {
  302.             m_pWWWValues->AddRef();
  303.         }
  304.         if (mOwner)
  305.         {
  306.             mOwner->ScheduleProcessCallback();
  307.         }
  308.         return HXR_OK;
  309.     }
  310. #endif
  311.     return (handlePendingWWWAuthentication(HX_RESULTStatus, pIHXValuesHeaders));
  312. #else
  313.     return HXR_NOTIMPL;
  314. #endif /* HELIX_FEATURE_AUTHENTICATION */
  315. }
  316. #if defined(HELIX_FEATURE_AUTHENTICATION)
  317. // IHXClientAuthResponse
  318. STDMETHODIMP
  319. RTSPProtocol::ResponseReady
  320. (
  321.     HX_RESULT   HX_RESULTStatus,
  322.     IHXRequest* pIHXRequestResponse
  323. )
  324. {
  325.     HX_RESULT HX_RESULTErr;
  326.     IHXValues* pIHXValuesRequestHeaders = NULL;
  327.     if(SUCCEEDED(HX_RESULTStatus))
  328.     {
  329.         if (!m_pProtocolLib)
  330.         {
  331.             return HXR_OUTOFMEMORY;
  332.         }
  333.         pIHXRequestResponse->GetRequestHeaders
  334.         (
  335.             pIHXValuesRequestHeaders
  336.         );
  337.         if(!m_uStreamCount)
  338.         {
  339.             // We haven't received a successful Describe..
  340.             //
  341.             CHXHeader::mergeHeaders
  342.             (
  343.                 pIHXValuesRequestHeaders,
  344.                 m_spIHXValuesStoredHeaders
  345.             );
  346.             HX_RESULTErr = m_pProtocolLib->SendStreamDescriptionRequest
  347.             (
  348.                 mPath,
  349.                 pIHXValuesRequestHeaders
  350.             );
  351.         }
  352.         else if (m_uCurrentStreamCount == m_uStreamCount)
  353.         {
  354.             // We haven't received a successful Setup..
  355.             //
  356.             HX_RESULTErr = m_pProtocolLib->SendSetupRequest
  357.             (
  358.                 NULL,
  359.                 0,
  360.                 pIHXValuesRequestHeaders
  361.             );
  362.         }
  363.         HX_RELEASE(pIHXValuesRequestHeaders);
  364.     }
  365.     else
  366.     {
  367.         if (HXR_FAIL == HX_RESULTStatus)
  368.         {
  369.             HX_RESULTStatus = HXR_NOT_AUTHORIZED;
  370.         }
  371.         mOwner->ReportError(HX_RESULTStatus);
  372.     }
  373.     return HXR_OK;
  374. }
  375. HX_RESULT
  376. RTSPProtocol::handlePendingWWWAuthentication
  377. (
  378.     HX_RESULT HX_RESULTStatus,
  379.     IHXValues* pIHXValuesHeaders
  380. )
  381. {
  382.     HX_RESULT HX_RESULTRet = HXR_FAIL;
  383.     if(HXR_NOT_AUTHORIZED == HX_RESULTStatus)
  384.     {
  385.         IUnknown*   pIUnknownContext = NULL;
  386.         IHXPlayer* pIHXPlayerPlayer = NULL;
  387.         IHXAuthenticationManager* pIHXAuthenticationManager = NULL;
  388.         // Don't transport switch while we are waiting for authentication
  389.         mOwner->StopDataWait();
  390.         if
  391.         (
  392.             m_spIHXClientAuthConversationAuthenticator.IsValid()
  393.             &&
  394.             m_spIHXClientAuthConversationAuthenticator->IsDone()
  395.         )
  396.         {
  397.             // Well we tried to authenticate already,
  398.             // so it must have failed
  399.             m_spIHXClientAuthConversationAuthenticator->Authenticated(FALSE);
  400.             // Cleanup so that we can re-auth
  401.             m_spIHXClientAuthConversationAuthenticator.Release();
  402.         }
  403.         mOwner->GetPlayer(pIHXPlayerPlayer);
  404.         if (NULL == pIHXPlayerPlayer)
  405.         {
  406.             // in case of the Auto. Config
  407.             mOwner->GetContext(pIUnknownContext);
  408.         }
  409.         else
  410.         {
  411.             pIUnknownContext = (IUnknown*)pIHXPlayerPlayer;
  412.         }
  413.         if (!m_spIHXClientAuthConversationAuthenticator.IsValid())
  414.         {
  415.             DECLARE_SMART_POINTER_UNKNOWN spIUnknownAuthenticator;
  416.             DECLARE_SMART_POINTER
  417.             (
  418.                 IHXObjectConfiguration
  419.             ) spIHXObjectConfigurationAuthenticator;
  420.             DECLARE_SMART_POINTER
  421.             (
  422.                 IHXCommonClassFactory
  423.             ) spIHXCommonClassFactoryHXCore;
  424.             spIHXCommonClassFactoryHXCore = pIUnknownContext;
  425.             // Starting conversation
  426.             HX_RESULTRet = spIHXCommonClassFactoryHXCore->CreateInstance
  427.             (
  428.                 CLSID_CHXClientAuthenticator,
  429.                 (void**)&spIUnknownAuthenticator
  430.             );
  431.             if
  432.             (
  433.                 SUCCEEDED(HX_RESULTRet)
  434.                 &&
  435.                 spIUnknownAuthenticator.IsValid()
  436.             )
  437.             {
  438.                 spIHXObjectConfigurationAuthenticator =
  439.                 (
  440.                     spIUnknownAuthenticator
  441.                 );
  442.                 spIHXObjectConfigurationAuthenticator->SetContext
  443.                 (
  444.                     pIUnknownContext
  445.                 );
  446.                 m_spIHXClientAuthConversationAuthenticator =
  447.                 (
  448.                     spIUnknownAuthenticator
  449.                 );
  450.             }
  451.         }
  452.         if
  453.         (
  454.             m_spIHXClientAuthConversationAuthenticator.IsValid()
  455.             &&
  456.             !m_spIHXClientAuthConversationAuthenticator->IsDone()
  457.         )
  458.         {
  459.             HX_ASSERT(m_pRequest);
  460.             if (m_pRequest)
  461.             {
  462.                 m_pRequest->SetResponseHeaders
  463.                 (
  464.                     pIHXValuesHeaders
  465.                 );
  466.                 HX_RESULTRet =
  467.                 (
  468.                     m_spIHXClientAuthConversationAuthenticator->MakeResponse
  469.                     (
  470.                         this,
  471.                         m_pRequest
  472.                     )
  473.                 );
  474.             }
  475.             else
  476.             {
  477.                 // Auth Failed!
  478.                 m_spIHXClientAuthConversationAuthenticator->Authenticated(FALSE);
  479.                 mOwner->ReportError(HXR_NOT_AUTHORIZED);
  480.             }
  481.             // Flow continues in ResponseReady()
  482.         }
  483.         else
  484.         {
  485.             // Auth Failed!
  486.             if (m_spIHXClientAuthConversationAuthenticator.IsValid())
  487.             {
  488.                 m_spIHXClientAuthConversationAuthenticator->Authenticated(FALSE);
  489.             }
  490.             mOwner->ReportError(HXR_NOT_AUTHORIZED);
  491.         }
  492.         HX_RELEASE(pIUnknownContext);
  493.         return HXR_OK;
  494.     }
  495.     return HXR_OK;
  496. }
  497. STDMETHODIMP
  498. RTSPProtocol::AuthenticationRequestDone(HX_RESULT result,
  499.                                         const char* user,
  500.                                         const char* password)
  501. {
  502.     return HXR_NOTIMPL;
  503. }
  504. #endif /* HELIX_FEATURE_AUTHENTICATION */
  505. // XXXGo - IPTV_HACK
  506. void
  507. RTSPProtocol::hackCookie(IHXBuffer* pCookie)
  508. {
  509.     HX_ASSERT(m_bUseRTP);
  510.     // XXXGo - Interop Hack
  511.     // IP/TV send a spec incomplient cookie...take care of it for now while
  512.     // we get them to fix it.
  513.     // we will assume Set-Cookie has just NAME=VALUE paris.
  514.     IHXBuffer* pBuffer = new CHXBuffer();
  515.     pBuffer->AddRef();
  516.     pBuffer->Set((const BYTE*)pCookie->GetBuffer(),
  517.             strlen((const char*)pCookie->GetBuffer()) +1);
  518.     IHXBuffer* pBuf = NULL;
  519.     char* pcOneCookie = (char*)pBuffer->GetBuffer();
  520.     char* pc = pcOneCookie;
  521.     char* pcKey = NULL;
  522.     // go thorough each ';'
  523.     for (;;)
  524.     {
  525.         pc = strchr(pc, ';');
  526.         if (pc)
  527.         {
  528.             pBuf = new CHXBuffer();
  529.             pBuf->AddRef();
  530.             *pc = NULL;
  531.             pBuf->Set((const BYTE*)pcOneCookie, strlen(pcOneCookie) + 1);
  532.             mOwner->SetCookie(pBuf);
  533.             HX_RELEASE(pBuf);
  534.             pcOneCookie = ++pc;
  535.         }
  536.         else
  537.         {
  538.             // just set it
  539.             pBuf = new CHXBuffer();
  540.             pBuf->AddRef();
  541.             pBuf->Set((const BYTE*)pcOneCookie, strlen(pcOneCookie) + 1);
  542.             mOwner->SetCookie(pBuf);
  543.             HX_RELEASE(pBuf);
  544.             break;
  545.         }
  546.     }
  547. }
  548. HX_RESULT
  549. RTSPProtocol::SwitchToUnicast(void)
  550. {
  551.     HX_RESULT   rc = HXR_FAILED;
  552.     IHXBuffer* pBuffer = NULL;
  553.     if (mOwner && mOwner->m_pFileHeader)
  554.     {
  555.         // get a URL from the file header.  No URL, no Unicast!
  556.         if (HXR_OK == mOwner->m_pFileHeader->GetPropertyCString("UnicastURL", pBuffer) &&
  557.             pBuffer)
  558.         {
  559.             rc = HandleRedirectRequest((const char*)pBuffer->GetBuffer(), 0);
  560.         }
  561.         HX_RELEASE(pBuffer);
  562.     }
  563.     return rc;
  564. }
  565. STDMETHODIMP
  566. RTSPProtocol::HandleOptionsResponse(HX_RESULT status,
  567.     IHXValues* pHeader)
  568. {
  569.     if (FAILED(status))
  570.     {
  571.         mOwner->ReportError(status);
  572.         return status;
  573.     }
  574.     else if (HXR_REDIRECTION == status)
  575.     {
  576.         // expect a redirection message soon!
  577.         m_idleState = NULL_STATE;
  578.         BOOL bHackCookie = FALSE;
  579.         IHXBuffer* pAgent = NULL;
  580.         if (pHeader->GetPropertyCString("User-Agent", pAgent) == HXR_OK)
  581.         {
  582.             if (strncasecmp((const char*)pAgent->GetBuffer(), "Cisco IP/TV",
  583.                 11) == 0)
  584.             {
  585.                 bHackCookie = TRUE;
  586.             }
  587.         }
  588.         HX_RELEASE(pAgent);
  589.         // retrieve cookies from the response header
  590.         IHXKeyValueList* pKeyValueList = NULL;
  591.         if (HXR_OK == pHeader->QueryInterface(IID_IHXKeyValueList,
  592.                                         (void**)&pKeyValueList))
  593.         {
  594.             IHXKeyValueListIterOneKey* pListIter = NULL;
  595.             IHXBuffer* pCookie = NULL;
  596.             pKeyValueList->GetIterOneKey("Set-Cookie",pListIter);
  597.             while (pListIter->GetNextString(pCookie) == HXR_OK)
  598.             {
  599.                 // XXXGo - IPTV_HACK
  600.                 if (bHackCookie)
  601.                 {
  602.                     hackCookie(pCookie);
  603.                 }
  604.                 else
  605.                 {
  606.                     mOwner->SetCookie(pCookie);
  607.                 }
  608.                 HX_RELEASE(pCookie);
  609.             }
  610.             HX_RELEASE(pListIter);
  611.         }
  612.         HX_RELEASE(pKeyValueList);
  613.         return HXR_OK;
  614.     }
  615.     m_bConnectDone = TRUE;
  616.     HX_RESULT result = HXR_OK;
  617.     result = m_pProtocolLib->SendStreamDescriptionRequest
  618.     (
  619.         mPath,
  620.         m_spIHXValuesStoredHeaders
  621.     );
  622.     return result;
  623. }
  624. STDMETHODIMP
  625. RTSPProtocol::HandleStreamDescriptionResponse(HX_RESULT      status,
  626.                                                 IHXValues*    pFileHeader,
  627.                                                 CHXSimpleList* pHeaderList,
  628.                                                 IHXValues*    pResponseHeaders)
  629. {
  630.     HX_RESULT   hr = HXR_OK;
  631.     if (FAILED(status))
  632.     {
  633.         if (!pFileHeader || !pHeaderList)
  634.         {
  635.             /*
  636.              * XXX...Need to get proper errors from protocol library
  637.              */
  638.             mOwner->ReportError(status);//ConvertHResultToHXError(status));
  639.             return (status != (UINT32)HXR_OK) ? status : (UINT32)HXR_FAIL;
  640.         }
  641.     }
  642.     else if (!pFileHeader || !pHeaderList)
  643.     {
  644.         // Not a severe failure, need to try again.
  645.         return m_pProtocolLib->SendStreamDescriptionRequest(mPath,
  646.                                                 m_spIHXValuesStoredHeaders);
  647.     }
  648. #if defined(HELIX_FEATURE_REVERTER)
  649.     // DESCRIBE Succeeded!
  650.     //
  651.     m_pDataRevert->RevertHeaders(pFileHeader, pHeaderList, pResponseHeaders);
  652. #else
  653.     RevertHeadersDone(pFileHeader,
  654.                       pHeaderList,
  655.                       pResponseHeaders,
  656.                       FALSE);
  657. #endif /* HELIX_FEATURE_REVERTER */
  658.     return HXR_OK;
  659. }
  660. /*
  661.  * IHXPreferredTransportSink methods
  662.  */
  663. STDMETHODIMP
  664. RTSPProtocol::TransportSucceeded(TransportMode  /* IN */   prefTransportType,
  665.                                  UINT16         /* IN */   uCloakPort)
  666. {
  667.     if (m_bHTTPOnly)
  668.     {
  669.         return mOwner->TransportSucceeded(HTTPCloakMode, uCloakPort);
  670.     }
  671.     // we ignore the TCP control channel succeeded message if we are attempting
  672.     // Multicast or UDP
  673.     else if (mCurrentTransport == prefTransportType)
  674.     {
  675.         return mOwner->TransportSucceeded(prefTransportType, uCloakPort);
  676.     }
  677.     else
  678.     {
  679.         HX_ASSERT(mCurrentTransport == UDPMode || mCurrentTransport == MulticastMode);
  680.     }
  681.     return HXR_OK;
  682. }
  683. STDMETHODIMP
  684. RTSPProtocol::TransportFailed()
  685. {
  686.     return mOwner->TransportFailed();
  687. }
  688. void
  689. RTSPProtocol::RevertHeadersDone(IHXValues* pFileHeader,
  690.                                 CHXSimpleList* pHeaderList,
  691.                                 IHXValues* pResponseHeaders,
  692.                                 BOOL bUseReverter)
  693. {
  694.     HX_RESULT status = HXR_OK;
  695.     ULONG32 tempLiveStream = 0;
  696.     pFileHeader->GetPropertyULONG32("LiveStream", tempLiveStream);
  697.     mLiveStream = (tempLiveStream > 0)?TRUE:FALSE;
  698. #if defined(HELIX_FEATURE_REVERTER)
  699.     if (bUseReverter && m_pDataRevert)
  700.     {
  701.         m_pProtocolLib->InitPacketFilter(m_pDataRevert);
  702.     }
  703. #endif /* HELIX_FEATURE_REVERTER */
  704.     ULONG32 ulFlags = 0;
  705.     pFileHeader->GetPropertyULONG32("Flags", ulFlags);
  706.     mSaveAsAllowed = ulFlags & HX_SAVE_ENABLED ? TRUE : FALSE;
  707.     IHXBuffer* pBuffer = NULL;
  708.     if (HXR_OK == pResponseHeaders->GetPropertyCString("StatsMask", pBuffer))
  709.     {
  710.         mSendStatsMask = atoi((const char*)pBuffer->GetBuffer());
  711.         mOwner->SetOption(HX_STATS_MASK, &mSendStatsMask);
  712.     }
  713.     HX_RELEASE(pBuffer);
  714.     if (HXR_OK == pResponseHeaders->GetPropertyCString("StatsInterval", pBuffer))
  715.     {
  716.         UINT32 ulStatsInterval = 1000* atoi((const char*)pBuffer->GetBuffer());
  717.         // ulStatsInterval = 0 to disable the stats
  718.         if (ulStatsInterval && ulStatsInterval < MINIMUM_STATS_INTERVAL)
  719.         {
  720.             ulStatsInterval = MINIMUM_STATS_INTERVAL;
  721.         }
  722.         mOwner->SetOption(HX_STATS_INTERVAL, &ulStatsInterval);
  723.     }
  724.     HX_RELEASE(pBuffer);
  725.     if (HXR_OK == pResponseHeaders->GetPropertyCString("MaxBandwidth", pBuffer))
  726.     {
  727.         UINT32 ulMaxBandwidth = atoi((const char*)pBuffer->GetBuffer());
  728.         // ulMaxBandwidth = 0 to disable the faststart
  729.         mOwner->SetOption(HX_MAX_BANDWIDTH, &ulMaxBandwidth);
  730.     }
  731.     HX_RELEASE(pBuffer);
  732.     if (HXR_OK == pResponseHeaders->GetPropertyCString("TurboPlay", pBuffer))
  733.     {
  734.         BOOL bTurboPlay = (BOOL)atoi((const char*)pBuffer->GetBuffer());
  735.         mOwner->SetOption(HX_TURBO_PLAY, &bTurboPlay);
  736.     }
  737.     HX_RELEASE(pBuffer);
  738.     // UseRTP was set from RTSPClientProtocol::handleDescribeResponse when
  739.     // it detected we were not playing a stream from a RealServer.
  740.     ULONG32 ulTemp = 0;
  741.     if (HXR_OK == pResponseHeaders->GetPropertyULONG32("UseRTP", ulTemp))
  742.     {
  743.         m_bUseRTP = ulTemp;
  744.     }
  745.     // retrieve cookies from the response header
  746.     IHXKeyValueList* pKeyValueList = NULL;
  747.     if (HXR_OK == pResponseHeaders->QueryInterface(IID_IHXKeyValueList,
  748.                                                     (void**)&pKeyValueList))
  749.     {
  750.         IHXKeyValueListIterOneKey* pListIter = NULL;
  751.         IHXBuffer* pCookie = NULL;
  752.         pKeyValueList->GetIterOneKey("Set-Cookie",pListIter);
  753.         while (pListIter->GetNextString(pCookie) == HXR_OK)
  754.         {
  755.             mOwner->SetCookie(pCookie);
  756.             HX_RELEASE(pCookie);
  757.         }
  758.         HX_RELEASE(pListIter);
  759.     }
  760.     HX_RELEASE(pKeyValueList);
  761.     m_pRequest->SetResponseHeaders(pResponseHeaders);
  762.     // notify the source file header is ready
  763.     mOwner->FileHeaderReady(pFileHeader);
  764.     UINT32 ulNumHeaders = (UINT32) pHeaderList->GetCount();
  765.     HX_ASSERT(m_pStreamInfoList->IsEmpty() == TRUE);
  766.     if (m_pStreamInfoList->IsEmpty() && ulNumHeaders > 0 &&
  767.         ulNumHeaders < m_pStreamInfoList->GetHashTableSize())
  768.     {
  769.         m_pStreamInfoList->InitHashTable(ulNumHeaders);
  770.     }
  771.     CHXSimpleList::Iterator i;
  772.     for (i = pHeaderList->Begin(); i != pHeaderList->End(); ++i)
  773.     {
  774.         IHXValues* pHeader = (IHXValues*)(*i);
  775.         mOwner->HeaderCallback(pHeader);
  776.         if(!m_bIsASMSource)
  777.         {
  778.             // see if there's an ASMRuleBook in the stream header and set
  779.             //flag for QI. only need to get one rulebook to make this TRUE
  780.             IHXBuffer* pRuleBook = NULL;
  781.             pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);
  782.             if(pRuleBook)
  783.             {
  784.                 m_bIsASMSource = TRUE;
  785.                 pRuleBook->Release();
  786.             }
  787.         }
  788.         /*
  789.          * Need to maintain status for the streams
  790.          */
  791.         HX_RESULT result;
  792.         UINT32 ulStreamNumber = 0;
  793.         UINT32 ulClipBandwidth = 0;
  794.         IHXBuffer* pMimeType = NULL;
  795.         result = pHeader->GetPropertyULONG32("StreamNumber", ulStreamNumber);
  796.         if (result != HXR_OK)
  797.         {
  798.             return;
  799.         }
  800.         pHeader->GetPropertyCString("MimeType", pMimeType);
  801.         pHeader->GetPropertyULONG32("AvgBitRate", ulClipBandwidth);
  802.         RTSP_STREAM_INFO* pStreamInfo = new RTSP_STREAM_INFO;
  803.         pStreamInfo->m_uStreamNumber = (UINT16)ulStreamNumber;
  804.         pStreamInfo->m_ulClipBandwidth = ulClipBandwidth;
  805. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  806.         pStreamInfo->m_pStreamStats = create_statistics((UINT16)ulStreamNumber);
  807.         if (pStreamInfo->m_pStreamStats)
  808.         {
  809.             pStreamInfo->m_pStreamStats->m_pClipBandwidth->SetInt(0);
  810.             if (pMimeType)
  811.             {
  812.                 pStreamInfo->m_pStreamStats->m_pMimeType->SetStr((char*)pMimeType->GetBuffer());
  813.             }
  814.         }
  815. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  816.         HX_RELEASE(pMimeType);
  817.         (*m_pStreamInfoList)[ulStreamNumber] = pStreamInfo;
  818.         m_uStreamCount++;
  819.     }
  820.     mReceivedControl        = TRUE;
  821.     m_uCurrentStreamCount   = m_uStreamCount;
  822.     m_idleState             = INIT_SOCKETS_STATE;
  823. }
  824. void
  825. RTSPProtocol::SendControlBuffer(IHXBuffer* pBuffer)
  826. {
  827.     char* p64Buf = new char[pBuffer->GetSize() * 2 + 4];
  828.     BinTo64((const unsigned char*)pBuffer->GetBuffer(),
  829.             pBuffer->GetSize(), p64Buf);
  830.     m_pProtocolLib->SendSetParameterRequest("DataConvertBuffer", "1",
  831.             "base64", p64Buf);
  832.     delete[] p64Buf;
  833. }
  834. UINT16
  835. RTSPProtocol::GetRDTFeatureLevel(void)
  836. {
  837. #if defined(HELIX_FEATURE_RDT)
  838.     if (m_pProtocolLib)
  839.     {
  840.         return ((RTSPClientProtocolExt*)m_pProtocolLib)->GetRDTFeatureLevel();
  841.     }
  842.     else
  843. #endif /* HELIX_FEATURE_RDT */
  844.     {
  845.         return 0;
  846.     }
  847. }
  848. void
  849. RTSPProtocol::LeavePrefetch(void)
  850. {
  851.     m_bPrefetch = FALSE;
  852.     if (m_pProtocolLib)
  853.     {
  854.         ((RTSPClientProtocol*)m_pProtocolLib)->LeavePrefetch();
  855.     }
  856.     return;
  857. }
  858. void
  859. RTSPProtocol::EnterFastStart(void)
  860. {
  861.     m_bFastStart = TRUE;
  862.     if (m_pProtocolLib)
  863.     {
  864.         ((RTSPClientProtocol*)m_pProtocolLib)->EnterFastStart();
  865.     }
  866.     return;
  867. }
  868. void
  869. RTSPProtocol::LeaveFastStart(void)
  870. {
  871.     m_bFastStart = FALSE;
  872.     if (m_pProtocolLib)
  873.     {
  874.         ((RTSPClientProtocol*)m_pProtocolLib)->LeaveFastStart();
  875.     }
  876.     return;
  877. }
  878. /*
  879.  *  If this is multicast, make sure to send subscribe msg
  880.  */
  881. HX_RESULT
  882. RTSPProtocol::handle_multicast(void)
  883. {
  884. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  885.     HX_ASSERT(mCurrentTransport == MulticastMode);
  886.     STREAM_INFO* pStreamInfo = NULL;
  887.     IHXBuffer* pRuleBook = NULL;
  888.     for (UINT16 uStrmNum = 0; uStrmNum < m_uStreamCount; uStrmNum++)
  889.     {
  890.         pStreamInfo = NULL;
  891.         if (FAILED(mOwner->GetStreamInfo(uStrmNum, pStreamInfo)))
  892.         {
  893.             return HXR_OK;
  894.         }
  895.         HX_ASSERT(pStreamInfo);
  896.         // If there is an ASMRuleBook, subscription will be done eventually
  897.         // through RTSPClientProtocol::RuleChange()...
  898.         pRuleBook = NULL;
  899.         if (FAILED(pStreamInfo->m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook)))
  900.         {
  901.             HX_ASSERT(!pRuleBook);
  902.             Subscribe(uStrmNum, 0);
  903.         }
  904.         HX_RELEASE(pRuleBook);
  905.     }
  906.     return HXR_OK;
  907. #else
  908.     return HXR_NOTIMPL;
  909. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  910. }
  911. HX_RESULT
  912. RTSPProtocol::send_setup_request()
  913. {
  914.     HX_RESULT   rc = HXR_OK;
  915.     RTSPTransportType* pTransport = new RTSPTransportType[MAX_TRANSPORT];
  916.     int nTransports = 0;
  917.     switch (mCurrentTransport)
  918.     {
  919.         /*
  920.          * Port is omitted here, the transport layer will pick it.
  921.          */
  922. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  923.         case MulticastMode:
  924.             if (!m_bUseRTP)
  925.             {
  926.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_MCAST;
  927.                 pTransport[nTransports++].m_sPort = 0;
  928.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_UDP;
  929.                 pTransport[nTransports++].m_sPort = 0;
  930.                 pTransport[nTransports].m_lTransportType = RTSP_TR_TNG_UDP;
  931.                 pTransport[nTransports++].m_sPort = 0;
  932.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_UDP;
  933.                 pTransport[nTransports++].m_sPort = 0;
  934.                 if (m_ulTransportPrefMask & ATTEMPT_TCP)
  935.                 {
  936.                     pTransport[nTransports].m_lTransportType = RTSP_TR_TNG_TCP;
  937.                     pTransport[nTransports++].m_sPort = 0;
  938.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_TCP;
  939.                     pTransport[nTransports++].m_sPort = 0;
  940.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  941.                     pTransport[nTransports++].m_sPort = 0;
  942.                 }
  943.             }
  944.             else
  945.             {
  946.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_UDP;
  947.                 pTransport[nTransports++].m_sPort = 0;
  948.                 if (m_ulTransportPrefMask & ATTEMPT_TCP)
  949.                 {
  950.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  951.                     pTransport[nTransports++].m_sPort = 0;
  952.                 }
  953.             }
  954.             // tell the owner that we are using multicast...
  955.             // this is needed to display it on the stats dialog...
  956.             mOwner->TransportStarted(MulticastMode);
  957.             break;
  958. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  959.         case UDPMode:
  960.             if(!m_bUseRTP)
  961.             {
  962.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_UDP;
  963.                 pTransport[nTransports++].m_sPort = 0;
  964.                 pTransport[nTransports].m_lTransportType = RTSP_TR_TNG_UDP;
  965.                 pTransport[nTransports++].m_sPort = 0;
  966.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_UDP;
  967.                 pTransport[nTransports++].m_sPort = 0;
  968.                 if (m_ulTransportPrefMask & ATTEMPT_TCP)
  969.                 {
  970.                     pTransport[nTransports].m_lTransportType = RTSP_TR_TNG_TCP;
  971.                     pTransport[nTransports++].m_sPort = 0;
  972.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_TCP;
  973.                     pTransport[nTransports++].m_sPort = 0;
  974.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  975.                     pTransport[nTransports++].m_sPort = 0;
  976.                 }
  977.             }
  978.             else
  979.             {
  980.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_UDP;
  981.                 pTransport[nTransports++].m_sPort = 0;
  982.                 if (m_ulTransportPrefMask & ATTEMPT_TCP)
  983.                 {
  984.                     pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  985.                     pTransport[nTransports++].m_sPort = 0;
  986.                 }
  987.             }
  988.             // tell the owner that we are using UDP...
  989.             // this is needed to display it on the stats dialog...
  990.             mOwner->TransportStarted(UDPMode);
  991.             break;
  992.         case TCPMode:
  993.             if(!m_bUseRTP)
  994.             {
  995.                 pTransport[nTransports].m_lTransportType = RTSP_TR_TNG_TCP;
  996.                 pTransport[nTransports++].m_sPort = 0;
  997.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RDT_TCP;
  998.                 pTransport[nTransports++].m_sPort = 0;
  999.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  1000.                 pTransport[nTransports++].m_sPort = 0;
  1001.             }
  1002.             else
  1003.             {
  1004.                 pTransport[nTransports].m_lTransportType = RTSP_TR_RTP_TCP;
  1005.                 pTransport[nTransports++].m_sPort = 0;
  1006.             }
  1007.             // tell the owner that we are using TCPt...
  1008.             // this is needed to display it on the stats dialog...
  1009.             if (m_bHTTPOnly)
  1010.             {
  1011.                 mOwner->TransportStarted(HTTPCloakMode);
  1012.             }
  1013.             else
  1014.             {
  1015.                 mOwner->TransportStarted(TCPMode);
  1016.             }
  1017.             break;
  1018.         default:
  1019.             HX_VECTOR_DELETE(pTransport);
  1020. #if defined(_DEBUG) && defined(DEBUG_LOG_INFO)
  1021.             HXStaticStatLog::StatPrintf("SetTransport::wrong mode %dn", mCurrentTransport);
  1022. #endif
  1023.             return HXR_FAIL;
  1024.     }
  1025.     HX_ASSERT(nTransports <= MAX_TRANSPORT);
  1026.     // look for a cookie...
  1027.     // If we use pRequsetHeaders straight from m_pRequest, it will contain a
  1028.     // whole bunch of stuff that we don't need.  SO, just extract the "Cookie"
  1029.     // and create a new header right here.  If you need other headers, we might
  1030.     // need to come up with a better loginc.
  1031.     IHXValues* pRequestHeaders = NULL;
  1032.     IHXBuffer* pCookie = NULL;
  1033.     if (SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders)))
  1034.     {
  1035.         pRequestHeaders->GetPropertyCString("Cookie", pCookie);
  1036.         HX_RELEASE(pRequestHeaders);
  1037.         if (pCookie)
  1038.         {
  1039.             pRequestHeaders = new CHXHeader();
  1040.             pRequestHeaders->AddRef();
  1041.             pRequestHeaders->SetPropertyCString("Cookie", pCookie);
  1042.             HX_RELEASE(pCookie);
  1043.         }
  1044.     }
  1045.     rc = m_pProtocolLib->SendSetupRequest(pTransport, nTransports, pRequestHeaders);
  1046.     HX_RELEASE(pRequestHeaders);
  1047.     HX_VECTOR_DELETE(pTransport);
  1048.     return rc;
  1049. }
  1050. STDMETHODIMP
  1051. RTSPProtocol::HandleStreamRecordDescriptionResponse
  1052. (
  1053.     HX_RESULT   status,
  1054.     IHXValues* pResponseHeaders
  1055. )
  1056. {
  1057.     return HXR_NOTIMPL;
  1058. }
  1059. STDMETHODIMP
  1060. RTSPProtocol::HandleSetupResponse
  1061. (
  1062.     HX_RESULT status
  1063. )
  1064. {
  1065.     if (status != HXR_OK)
  1066.     {
  1067.         /*
  1068.          * XXX...Need to get proper errors from protocol library
  1069.          */
  1070.         mOwner->ReportError(status);
  1071.         return status;
  1072.     }
  1073.     switch(m_pProtocolLib->GetProtocolType())
  1074.     {
  1075.         case 1:
  1076.             mOwner->TransportStarted(MulticastMode);
  1077. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  1078.             // OK, this is multicast for sure...Make sure to send subscription.
  1079.             handle_multicast();
  1080. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  1081.             break;
  1082.         case 2:
  1083.             mOwner->TransportStarted(UDPMode);
  1084.             break;
  1085.         case 3:
  1086.             // notify that the server has selected TCP over UDP
  1087.             // when the player supports both
  1088.             if (!m_bHTTPOnly                        &&
  1089.                 mCurrentTransport != TCPMode        &&
  1090.                 HXR_OK == mOwner->TransportStarted(TCPMode))
  1091.             {
  1092.                 mOwner->TransportSucceeded(TCPMode, 0);
  1093.             }
  1094.             /* No need to report TCP success
  1095.              * We may be in TCP/HTTP Cloaking mode
  1096.              */
  1097.             break;
  1098.         default:
  1099.             HX_ASSERT(FALSE);
  1100.             break;
  1101.     }
  1102. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1103.     /*
  1104.      * Must wait until transport is established before initializing
  1105.      * statistics
  1106.      */
  1107.     CHXMapLongToObj::Iterator i;
  1108.     for (i = m_pStreamInfoList->Begin(); i != m_pStreamInfoList->End(); ++i)
  1109.     {
  1110.         RTSP_STREAM_INFO* pStreamInfo = (RTSP_STREAM_INFO*)(*i);
  1111.         if (m_pProtocolLib)
  1112.         {
  1113.             ((RTSPClientProtocol*)m_pProtocolLib)->SetStatistics(pStreamInfo->m_uStreamNumber,
  1114.                                                                  pStreamInfo->m_pStreamStats);
  1115.         }
  1116.     }
  1117. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1118.     mOwner->Initialize();
  1119. //    return m_pProtocolLib->SendPlayRequest(RTSP_PLAY_RANGE_BLANK, RTSP_PLAY_RANGE_BLANK, 0);
  1120.     return HXR_OK;
  1121. }
  1122. STDMETHODIMP
  1123. RTSPProtocol::HandlePlayResponse
  1124. (
  1125.     HX_RESULT status
  1126. )
  1127. {
  1128.     if (status != HXR_OK)
  1129.     {
  1130.         /*
  1131.          * XXX...Need to get proper errors from protocol library
  1132.          */
  1133.         mOwner->ReportError(status); //ConvertHResultToHXError(status));
  1134.         return status;
  1135.     }
  1136.     /* Mark the current state as Playing ONLY if we have called resume */
  1137.     if (!m_bIsFirstResume)
  1138.     {
  1139.         m_bPlaying = TRUE;
  1140.         // Start Waiting for data..
  1141.         mOwner->StartDataWait();
  1142.     }
  1143.     return HXR_OK;
  1144. }
  1145. STDMETHODIMP
  1146. RTSPProtocol::HandleRecordResponse
  1147. (
  1148.     HX_RESULT status
  1149. )
  1150. {
  1151.     return HXR_NOTIMPL;
  1152. }
  1153. STDMETHODIMP
  1154. RTSPProtocol::HandleTeardownResponse
  1155. (
  1156.     HX_RESULT status
  1157. )
  1158. {
  1159.     AddRef();
  1160.     if (m_pProtocolLib)
  1161.     {
  1162.         m_pProtocolLib->Done();
  1163.         m_pProtocolLib->Release();
  1164.         m_pProtocolLib = 0;
  1165.     }
  1166.     Release();
  1167.     return HXR_OK;
  1168. }
  1169. STDMETHODIMP
  1170. RTSPProtocol::HandleSetParameterRequest
  1171. (
  1172.     UINT32 lParamType,
  1173.     const char* pParamName,
  1174.     IHXBuffer* pParamValue
  1175. )
  1176. {
  1177.     IHXPlayer* pPlayer;
  1178.     IHXBandwidthManager * pBWM;
  1179.     if(!strcmp(pParamName,"MaximumASMBandwidth") &&
  1180.        (HXR_OK == mOwner->GetPlayer(pPlayer)) &&
  1181.        (HXR_OK == pPlayer->QueryInterface(IID_IHXBandwidthManager,
  1182.                                                   (void **)&pBWM)))
  1183.     {
  1184.         pBWM->ChangeBW((UINT32)atoi((const char *)pParamValue->GetBuffer()),
  1185.                 mOwner);
  1186.         return HXR_OK;
  1187.     }
  1188. #if defined(HELIX_FEATURE_REVERTER)
  1189.     else if (!strcmp(pParamName, "DataConvertBuffer"))
  1190.     {
  1191.         m_pDataRevert->ControlBufferReady(pParamValue);
  1192.         return HXR_OK;
  1193.     }
  1194. #endif /* HELIX_FEATURE_REVERTER */
  1195.     return HXR_NOTIMPL;
  1196. }
  1197. STDMETHODIMP
  1198. RTSPProtocol::HandleSetParameterRequest(const char* pParamName,
  1199.         const char* pParamValue, const char* pContent)
  1200. {
  1201. #if defined(HELIX_FEATURE_REVERTER)
  1202.     if (!strcmp(pParamName, "DataConvertBuffer"))
  1203.     {
  1204.         IHXBuffer* pBuffer = new CHXBuffer();
  1205.         int contentLen = strlen(pContent);
  1206.         pBuffer->SetSize(contentLen);
  1207.         int offset = BinFrom64(pContent, contentLen,
  1208.                 (unsigned char*)pBuffer->GetBuffer());
  1209.         pBuffer->SetSize(offset);
  1210.         pBuffer->AddRef();
  1211.         m_pDataRevert->ControlBufferReady(pBuffer);
  1212.         pBuffer->Release();
  1213.         return HXR_OK;
  1214.     }
  1215. #endif /* HELIX_FEATURE_REVERTER */
  1216.     return HXR_NOTIMPL;
  1217. }
  1218. STDMETHODIMP
  1219. RTSPProtocol::HandleSetParameterResponse
  1220. (
  1221.     HX_RESULT status
  1222. )
  1223. {
  1224.     return HXR_OK; // XXXSMP Just return OK for now.
  1225. }
  1226. STDMETHODIMP
  1227. RTSPProtocol::HandleSetParameterResponseWithValues
  1228. (
  1229.     HX_RESULT status,
  1230.     IHXValues* pValues
  1231. )
  1232. {
  1233.     if (status == HXR_OK && pValues)
  1234.     {
  1235.         UINT32 ulStatsInterval = 0;
  1236.         UINT32 ulValue = 0;
  1237.         if (pValues->GetPropertyULONG32("UpdateStatsInterval", ulStatsInterval) == HXR_OK)
  1238.         {
  1239.             ulStatsInterval = ulStatsInterval * 1000;
  1240.             // ulStatsInterval = 0 to disable the stats
  1241.             if (ulStatsInterval && ulStatsInterval < MINIMUM_STATS_INTERVAL)
  1242.             {
  1243.                 ulStatsInterval = MINIMUM_STATS_INTERVAL;
  1244.             }
  1245.             mOwner->SetOption(HX_STATS_INTERVAL, &ulStatsInterval);
  1246.         }
  1247.         if (pValues->GetPropertyULONG32("Reconnect", ulValue) == HXR_OK)
  1248.         {
  1249.             mOwner->SetReconnectInfo(pValues);
  1250.         }
  1251.     }
  1252.     return HandleSetParameterResponse(status);
  1253. }
  1254. STDMETHODIMP
  1255. RTSPProtocol::HandleGetParameterRequest
  1256. (
  1257.     UINT32 lParamType,
  1258.     const char* pParamName,
  1259.     IHXBuffer** pParamValue
  1260. )
  1261. {
  1262.     /*
  1263.      * XXX...Need to implement
  1264.      */
  1265.     return HXR_NOTIMPL;
  1266. }
  1267. STDMETHODIMP
  1268. RTSPProtocol::HandleGetParameterResponse
  1269. (
  1270.     HX_RESULT status,
  1271.     IHXBuffer* pParamValue
  1272. )
  1273. {
  1274.     /*
  1275.      * XXX...Need to implement
  1276.      */
  1277.     return HXR_NOTIMPL;
  1278. }
  1279. STDMETHODIMP
  1280. RTSPProtocol::HandleAlertRequest
  1281. (
  1282.     HX_RESULT status,
  1283.     INT32 lAlertNumber,
  1284.     const char* pAlertText
  1285. )
  1286. {
  1287.     HX_RESULT   theErr = HXR_OK;
  1288.     m_idleState = ALERT_STATE;
  1289.     m_ulLastAlert = (UINT32)lAlertNumber;
  1290.     HX_VECTOR_DELETE(m_pTextBuf);
  1291.     if (pAlertText)
  1292.     {
  1293.         m_pTextBuf = new char[::strlen(pAlertText) + 1];
  1294.         if(!m_pTextBuf)
  1295.         {
  1296.             theErr = HXR_OUTOFMEMORY;
  1297.             goto cleanup;
  1298.         }
  1299.         strcpy(m_pTextBuf, pAlertText); /* Flawfinder: ignore */
  1300.     }
  1301. cleanup:
  1302.     // Clear the authentication cache
  1303.     if (m_pRegistry)
  1304.     {
  1305.         m_pRegistry->DeleteByName("CredCache");
  1306.     }
  1307.     return theErr;
  1308. }
  1309. STDMETHODIMP
  1310. RTSPProtocol::HandleUseProxyRequest
  1311. (
  1312.     const char* pProxyURL
  1313. )
  1314. {
  1315.     HX_RESULT rc = HXR_OK;
  1316.     if(!pProxyURL)
  1317.     {
  1318.         mOwner->ReportError(HXR_DNR);
  1319.     }
  1320.     else
  1321.     {
  1322.         char* pProxyHost = NULL;
  1323.         UINT32 ulProxyPort = 0;
  1324.         // parse host name, port
  1325.         CHXURL proxyURL(pProxyURL);
  1326.         IHXValues* pProxyURLProps = proxyURL.GetProperties();
  1327.         IHXBuffer* pBuffer = NULL;
  1328.         if(HXR_OK == pProxyURLProps->GetPropertyBuffer(PROPERTY_HOST, pBuffer))
  1329.         {
  1330.             pProxyHost = new char[pBuffer->GetSize()+1];
  1331.             strcpy(pProxyHost, (char*)pBuffer->GetBuffer()); /* Flawfinder: ignore */
  1332.             HX_RELEASE(pBuffer);
  1333.         }
  1334.         pProxyURLProps->GetPropertyULONG32(PROPERTY_PORT, ulProxyPort);
  1335.         HX_RELEASE(pProxyURLProps);
  1336.         if(pProxyHost)
  1337.         {
  1338.             initialize_members();
  1339.             set_proxy(pProxyHost, (UINT16)ulProxyPort);
  1340.             // copy host/path so setup doesn't override
  1341.             char* pHost = new_string(mHost);
  1342.             char* pPath = new_string(mPath);
  1343.             rc = setup(pHost, pPath, mPort, mLossCorrection,
  1344.                        m_bHTTPOnly, m_bSDPInitiated, mCloakPort);
  1345.             delete[] pHost;
  1346.             delete[] pPath;
  1347.         }
  1348.         delete[] pProxyHost;
  1349.     }
  1350.     return rc;
  1351. }
  1352. STDMETHODIMP
  1353. RTSPProtocol::HandleRedirectRequest
  1354. (
  1355.     const char* pURL,
  1356.     UINT32 msFromNow
  1357. )
  1358. {
  1359.     HX_RESULT   rc = HXR_OK;
  1360.     char*       pHostStr = NULL;
  1361.     char*       pResource = NULL;
  1362.     UINT32      ulPort = 0;
  1363.     IHXValues*  pHeader = NULL;
  1364.     if(pURL)
  1365.     {
  1366.         CHXURL urlObj(pURL);
  1367.         pHeader = urlObj.GetProperties();
  1368.         IHXBuffer* pBuffer = 0;
  1369.         if (HXR_OK != pHeader->GetPropertyBuffer(PROPERTY_HOST, pBuffer))
  1370.         {
  1371.             rc = HXR_FAILED;
  1372.             goto cleanup;
  1373.         }
  1374.         pHostStr = new char[pBuffer->GetSize()+1];
  1375.         strcpy(pHostStr, (char*)pBuffer->GetBuffer()); /* Flawfinder: ignore */
  1376.         pBuffer->Release();
  1377.         if (HXR_OK != pHeader->GetPropertyBuffer(PROPERTY_RESOURCE, pBuffer))
  1378.         {
  1379.             rc = HXR_FAILED;
  1380.             goto cleanup;
  1381.         }
  1382.         pResource = (char*)pBuffer->GetBuffer();
  1383.         ulPort = 0;
  1384.         pHeader->GetPropertyULONG32(PROPERTY_PORT, ulPort);
  1385.         mOwner->SetRedirectURL(pHostStr, (UINT16)ulPort, pResource, &urlObj);
  1386.         m_LastError = HXR_REDIRECTION;
  1387.         pBuffer->Release();
  1388.         delete[] pHostStr;
  1389.     }
  1390.     else
  1391.     {
  1392.         mOwner->ReportError(HXR_DNR);
  1393.     }
  1394. cleanup:
  1395.     HX_RELEASE(pHeader);
  1396.     return rc;
  1397. }
  1398. STDMETHODIMP
  1399. RTSPProtocol::HandlePacket
  1400. (
  1401.     HX_RESULT   status,
  1402.     const char* pSessionID,
  1403.     IHXPacket* pPacket
  1404. )
  1405. {
  1406.     if (HXR_OK == status)
  1407.     {
  1408.         /*
  1409.          * These are flushed pre-seek packets
  1410.          */
  1411.         if (pPacket)
  1412.         {
  1413.             CHXEvent* pEvent = new CHXEvent(pPacket);
  1414.             pEvent->SetPreSeekEvent();
  1415.             mOwner->EventReady(pEvent);
  1416.         }
  1417.         // HandlePacket is called with pPacket=NULL to indicate
  1418.         // the liveness of TCP/UDP data connection in order to
  1419.         // detect the server timeout
  1420.         else
  1421.         {
  1422.             m_ulLastPacketReceivedTime = HX_GET_TICKCOUNT();
  1423.         }
  1424.     }
  1425.     return HXR_OK;
  1426. }
  1427. STDMETHODIMP
  1428. RTSPProtocol::HandleProtocolError
  1429. (
  1430.     HX_RESULT status
  1431. )
  1432. {
  1433.     /*
  1434.      * XXX...Need to get proper errors from protocol library
  1435.      */
  1436.     mOwner->ReportError(status);//ConvertHResultToHXError(status));
  1437.     m_bPlaying = FALSE;
  1438.     return status;
  1439. }
  1440. STDMETHODIMP
  1441. RTSPProtocol::HandleRTTResponse
  1442. (
  1443.     HX_RESULT status,
  1444.     const char* pSessionID,
  1445.     UINT32    ulSecs,
  1446.     UINT32    ulUSecs
  1447. )
  1448. {
  1449.     // we handle RTT response in order to detect
  1450.     // whether the UDP channel is still alive during PAUSE/RESUME
  1451.     return HXR_OK;
  1452. }
  1453. STDMETHODIMP
  1454. RTSPProtocol::HandleCongestion
  1455. (
  1456.     HX_RESULT status,
  1457.     const char* pSessionID,
  1458.     INT32     xmitMultiplier,
  1459.     INT32     recvMultiplier
  1460. )
  1461. {
  1462.     return HXR_NOTIMPL;
  1463. }
  1464. STDMETHODIMP
  1465. RTSPProtocol::HandleSourceDone(void)
  1466. {
  1467.     mSourceEnd = TRUE;
  1468.     if (mOwner)
  1469.     {
  1470.         mOwner->SetEndOfClip();
  1471.     }
  1472.     return HXR_OK;
  1473. }
  1474. STDMETHODIMP
  1475. RTSPProtocol::HandlePrerollChange(THIS_ 
  1476.   RTSPPrerollTypeEnum prerollType,
  1477.   UINT32 ulPreroll)
  1478. {
  1479.     if (RTSP_PREROLL_PREDECBUFPERIOD == prerollType)
  1480.     {
  1481. // Handle 3GPP 26.234 Annex G x-initpredecbufperiod field
  1482. // This field only updates the preroll for video streams
  1483. // Look through all the streams
  1484. for (UINT16 uStrmNum = 0; uStrmNum < m_uStreamCount; uStrmNum++)
  1485. {
  1486.     STREAM_INFO* pStreamInfo = NULL;
  1487.     IHXBuffer* pMimeType = NULL;
  1488.     // Look for video streams
  1489.     if ((HXR_OK == mOwner->GetStreamInfo(uStrmNum, pStreamInfo)) &&
  1490. (pStreamInfo->m_pHeader) &&
  1491. (HXR_OK == pStreamInfo->m_pHeader->GetPropertyCString("Mimetype",
  1492.       pMimeType)) &&
  1493. (!strncasecmp("video/", (char*)pMimeType->GetBuffer(), 6)))
  1494.     {
  1495. // Update the preroll value
  1496. pStreamInfo->BufferingState().UpdatePreroll(ulPreroll);
  1497.     }
  1498.     HX_RELEASE(pMimeType);
  1499. }
  1500.     }
  1501.     return HXR_OK;
  1502. }
  1503. STDMETHODIMP
  1504. RTSPProtocol::HandleStreamDone
  1505. (
  1506.     HX_RESULT status,
  1507.     UINT16    uStreamNumber
  1508. )
  1509. {
  1510.     STREAM_INFO* pStreamInfo;
  1511.     if (HXR_OK != mOwner->GetStreamInfo(uStreamNumber, pStreamInfo))
  1512.     {
  1513.         return HXR_FAIL;
  1514.     }
  1515.     HX_ASSERT(!pStreamInfo->m_bSrcStreamDone);
  1516.     if (!pStreamInfo->m_bSrcStreamDone)
  1517.     {
  1518.         pStreamInfo->m_bSrcStreamDone = TRUE;
  1519.         m_uCurrentStreamCount--;
  1520.         if (!m_uCurrentStreamCount)
  1521.         {
  1522.             mOwner->SetEndOfClip();
  1523.         }
  1524.     }
  1525.     return HXR_OK;
  1526. }
  1527. STDMETHODIMP
  1528. RTSPProtocol::GetStatus
  1529. (
  1530.     REF(UINT16) uStatusCode,
  1531.     REF(IHXBuffer*) pStatusDesc,
  1532.     REF(UINT16) ulPercentDone
  1533. )
  1534. {
  1535. // XXX HP
  1536. // we no longer care about the buffering at the transport layer
  1537. // playback starts as soon as we get enough data at BufferManager
  1538. #if 0
  1539.     /*
  1540.      * XXX...This needs to be properly implemented
  1541.      */
  1542.     CHXBuffer*          pStatus = NULL;
  1543.     IUnknown*           pContext = NULL;
  1544.     IHXClientEngine*    pEngine = NULL;
  1545.     uStatusCode = HX_STATUS_READY;
  1546.     ulPercentDone = 100;
  1547.     pStatusDesc = NULL;
  1548.     if (!m_bConnectDone)
  1549.     {
  1550.         uStatusCode     = HX_STATUS_CONTACTING;
  1551.         ulPercentDone   = 0;
  1552.         mOwner->GetContext(pContext);
  1553. #if defined(HELIX_FEATURE_RESOURCEMGR)
  1554.         if (pContext &&
  1555.             HXR_OK == pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine))
  1556.         {
  1557.             pStatus = ((HXClientEngine *)pEngine)->GetResMgr()->GetMiscString(IDS_STATUS_CONTACTING);
  1558.         }
  1559.         pStatusDesc     = new CHXBuffer;
  1560.         if (!pStatusDesc)
  1561.         {
  1562.             return HXR_OUTOFMEMORY;
  1563.         }
  1564.         pStatusDesc->AddRef();
  1565.         CHXString statusDesc = "";
  1566.         if (pStatus)
  1567.         {
  1568.             statusDesc += (const char*) pStatus->GetBuffer();
  1569.             statusDesc += " ";
  1570.         }
  1571.         statusDesc += mHost;
  1572.         statusDesc += "...";
  1573.         pStatusDesc->Set((UCHAR*)(const char*) statusDesc,
  1574.                          strlen((const char*)statusDesc)+1);
  1575.         HX_RELEASE(pStatus);
  1576.         HX_RELEASE(pEngine);
  1577. #endif /* HELIX_FEATURE_RESOURCEMGR */
  1578.         HX_RELEASE(pContext);
  1579.         return HXR_OK;
  1580.     }
  1581.     else if (m_pPendingStatus)
  1582.     {
  1583.         return m_pPendingStatus->GetStatus(uStatusCode,
  1584.                                            pStatusDesc,
  1585.                                            ulPercentDone);
  1586.     }
  1587.     else
  1588.     {
  1589.         uStatusCode = HX_STATUS_BUFFERING;
  1590.         ulPercentDone = 0;
  1591.     }
  1592.     return HXR_OK;
  1593. #else
  1594.     return HXR_NOTIMPL;
  1595. #endif
  1596. }
  1597. #if defined(HELIX_FEATURE_STATS)
  1598. /************************************************************************
  1599.  *      Method:
  1600.  *          IHXStatistics::InitializeStatistics
  1601.  *      Purpose:
  1602.  *          Pass registry ID to the caller
  1603.  */
  1604. STDMETHODIMP
  1605. RTSPProtocol::InitializeStatistics
  1606. (
  1607.     UINT32      /*IN*/ ulRegistryID
  1608. )
  1609. {
  1610.     m_ulRegistryID = ulRegistryID;
  1611.     return HXR_OK;
  1612. }
  1613. /************************************************************************
  1614.  *      Method:
  1615.  *          IHXStatistics::UpdateStatistics
  1616.  *      Purpose:
  1617.  *          Notify the user to updates its statistics registry
  1618.  */
  1619. STDMETHODIMP
  1620. RTSPProtocol::UpdateStatistics()
  1621. {
  1622.     if (!m_pStatistics)
  1623.     {
  1624.         return HXR_FAIL;
  1625.     }
  1626.     return m_pStatistics->UpdateStatistics();
  1627. }
  1628. #endif /* HELIX_FEATURE_STATS */
  1629. HX_RESULT
  1630. RTSPProtocol::GetStreamStatistics
  1631. (
  1632.     ULONG32 ulStreamNumber,
  1633.     STREAM_STATS** ppStreamStats
  1634. )
  1635. {
  1636. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1637.     RTSP_STREAM_INFO* pStreamInfo;
  1638.     if (!m_pStreamInfoList->Lookup(ulStreamNumber, (void*&)pStreamInfo))
  1639.     {
  1640.         *ppStreamStats = NULL;
  1641.         return HXR_FAIL;
  1642.     }
  1643.     *ppStreamStats = pStreamInfo->m_pStreamStats;
  1644.     return HXR_OK;
  1645. #else
  1646.     return HXR_NOTIMPL;
  1647. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1648. }
  1649. HX_RESULT
  1650. RTSPProtocol::UpdateRegistry(UINT32 ulStreamNumber,
  1651.                              UINT32 ulRegistryID)
  1652. {
  1653. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1654.     HX_RESULT result = HXR_OK;
  1655.     if (!m_pRegistry)
  1656.     {
  1657.         return HXR_FAIL;
  1658.     }
  1659.     CHXMapLongToObj::Iterator i;
  1660.     for (i = m_pStreamInfoList->Begin(); i != m_pStreamInfoList->End(); ++i)
  1661.     {
  1662.         RTSP_STREAM_INFO* pStreamInfo = (RTSP_STREAM_INFO*)(*i);
  1663.         if (pStreamInfo->m_uStreamNumber == (UINT16)ulStreamNumber)
  1664.         {
  1665.             STREAM_STATS* pTmpStreamStats = new STREAM_STATS(m_pRegistry, ulRegistryID);
  1666.             *pTmpStreamStats = *pStreamInfo->m_pStreamStats;
  1667.             HX_DELETE(pStreamInfo->m_pStreamStats);
  1668.             pStreamInfo->m_pStreamStats = pTmpStreamStats;
  1669.             if (m_pProtocolLib)
  1670.             {
  1671.                 ((RTSPClientProtocol*)m_pProtocolLib)->SetStatistics(pStreamInfo->m_uStreamNumber,
  1672.                                                                      pStreamInfo->m_pStreamStats);
  1673.             }
  1674.             break;
  1675.         }
  1676.     }
  1677.     return result;
  1678. #else
  1679.     return HXR_NOTIMPL;
  1680. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1681. }
  1682. STDMETHODIMP
  1683. RTSPProtocol::RuleChange(REF(CHXSimpleList) pList)
  1684. {
  1685.     return m_pProtocolLib->RuleChange(&pList);
  1686. }
  1687. /*
  1688.  * IHXASMSource methods
  1689.  */
  1690. /************************************************************************
  1691.  *      Method:
  1692.  *          IHXASMSource::Subscribe
  1693.  *      Purpose:
  1694.  *          Subscribe to a stream
  1695.  */
  1696. STDMETHODIMP
  1697. RTSPProtocol::Subscribe
  1698. (
  1699.     UINT16 streamNumber,
  1700.     UINT16 ruleNumber
  1701. )
  1702. {
  1703.     RTSPSubscription sub;
  1704.     sub.m_streamNumber = streamNumber;
  1705.     sub.m_ruleNumber = ruleNumber;
  1706.     sub.m_bIsSubscribe = TRUE;
  1707.     CHXSimpleList subList;
  1708.     subList.AddTail(&sub);
  1709.     return m_pProtocolLib->Subscribe(&subList);
  1710. }
  1711. /************************************************************************
  1712.  *      Method:
  1713.  *          IHXASMSource::Unsubscribe
  1714.  *      Purpose:
  1715.  *          Unsubscribe from a stream
  1716.  */
  1717. STDMETHODIMP
  1718. RTSPProtocol::Unsubscribe
  1719. (
  1720.     UINT16 streamNumber,
  1721.     UINT16 ruleNumber
  1722. )
  1723. {
  1724.     RTSPSubscription sub;
  1725.     sub.m_streamNumber = streamNumber;
  1726.     sub.m_ruleNumber = ruleNumber;
  1727.     sub.m_bIsSubscribe = FALSE;
  1728.     CHXSimpleList subList;
  1729.     subList.AddTail(&sub);
  1730.     return m_pProtocolLib->Unsubscribe(&subList);
  1731. }
  1732. /*
  1733.  * IHXBackChannel methods
  1734.  */
  1735. /************************************************************************
  1736.  *      Method:
  1737.  *          IHXBackChannel::PacketReady
  1738.  *      Purpose:
  1739.  *          Send a packet from renderer back to file format
  1740.  */
  1741. STDMETHODIMP
  1742. RTSPProtocol::PacketReady
  1743. (
  1744.     IHXPacket* pPacket
  1745. )
  1746. {
  1747.     /*
  1748.      * XXXSMP - We'll use the transport when available eventually, but
  1749.      * Control messages will do for now.
  1750.      */
  1751.     if(m_pProtocolLib)
  1752.     {
  1753.         return m_pProtocolLib->BackChannelPacketReady(pPacket);
  1754.     }
  1755.     return HXR_FAIL;
  1756. }
  1757. /* HXProtocol methods */
  1758. HX_RESULT
  1759. RTSPProtocol::server_hello(void)
  1760. {
  1761.     HX_RESULT   theErr = HXR_OK;
  1762.     IUnknown*   pContext = NULL;
  1763.     IHXBuffer*  pBuffer = NULL;
  1764.     IHXValues*  pInfo = NULL;
  1765.     pContext = (IUnknown*)(IHXStreamSource*)mOwner;
  1766.     pContext->AddRef();
  1767.     if (m_bSDPInitiated)
  1768.     {
  1769.         pInfo = new CHXHeader();
  1770.         if (pInfo)
  1771.         {
  1772.             pInfo->AddRef();
  1773.             pBuffer = new CHXBuffer();
  1774.             if (pBuffer)
  1775.             {
  1776.                 pBuffer->AddRef();
  1777.                 pBuffer->Set((UCHAR*)mPath, strlen(mPath) + 1);
  1778.                 pInfo->SetPropertyCString("helix-sdp", pBuffer);
  1779.                 pBuffer->Release();
  1780.             }
  1781.         }
  1782.     }
  1783.     theErr = m_pProtocolLib->Init((IUnknown*)pContext,
  1784.                                   mHost,
  1785.                                   mPort,
  1786.                                   (IHXRTSPClientProtocolResponse*)this,
  1787.                                   mUseProxy?RTSP_INIT_HXPRIVATE_AUTHORIZATION:0,
  1788.                                   m_pIDInfo,
  1789.                                   pInfo,
  1790.                                   m_bHTTPOnly,
  1791.                                   mCloakPort,
  1792.                                   FALSE);
  1793.     if (pInfo)
  1794.     {
  1795.         UINT32  ulMulticastOnly = 0;
  1796.         // "MulticastOnly" is set by the RTSPClientProtocol when it's scalable
  1797.         // multicast via SDP file.
  1798.         //
  1799.         // If "MulticastOnly" is set and the current transport is not multicast then
  1800.         // we will returns error immediately and won't waste time in transport switching
  1801.         pInfo->GetPropertyULONG32("MulticastOnly", ulMulticastOnly);
  1802.         m_bMulticastOnly = (ulMulticastOnly > 0)?TRUE:FALSE;
  1803.         if (m_bMulticastOnly && mCurrentTransport != MulticastMode)
  1804.         {
  1805.             theErr = HXR_SE_MULTICAST_DELIVERY_ONLY;
  1806.         }
  1807.     }
  1808.     HX_RELEASE(pInfo);
  1809.     HX_RELEASE(pContext);
  1810.     return theErr;
  1811. }
  1812. HX_RESULT
  1813. RTSPProtocol::proxy_hello(void)
  1814. {
  1815.     m_pProtocolLib->SetProxy(mProxy, mProxyPort);
  1816.     return server_hello();
  1817. }
  1818.     
  1819. HX_RESULT
  1820. RTSPProtocol::process(void)
  1821. {
  1822.     HX_RESULT theErr = HXR_OK;
  1823.     if (m_LastError != HXR_OK)
  1824.     {
  1825.         return m_LastError;
  1826.     }
  1827. #ifdef _MACINTOSH
  1828. #if defined(HELIX_FEATURE_AUTHENTICATION)
  1829.     if (m_bHandleWWWAuthentication)
  1830.     {
  1831.         /* Need to wait for system time */
  1832.         if (HXMM_ATINTERRUPT())
  1833.         {
  1834.             return HXR_OK;
  1835.         }
  1836.         m_bHandleWWWAuthentication = FALSE;
  1837.         handlePendingWWWAuthentication(m_WWWResult, m_pWWWValues);
  1838.         HX_RELEASE(m_pWWWValues);
  1839.     }
  1840. #endif
  1841. #endif
  1842.     switch(m_idleState)
  1843.     {
  1844.         case INIT_SOCKETS_STATE:
  1845.         {
  1846.             IUnknown*           pContext = NULL;
  1847.             IHXInterruptState*  pInterruptState = NULL;
  1848.             mOwner->GetContext(pContext);
  1849.             if (pContext)
  1850.             {
  1851.                 pContext->QueryInterface(IID_IHXInterruptState, (void**) &pInterruptState);
  1852.             }
  1853.             HX_RELEASE(pContext);
  1854.             /* We want to initialize sockets ONLY at system time */
  1855.             if (!pInterruptState ||
  1856.                 !pInterruptState->AtInterruptTime())
  1857.             {
  1858.                 // XXX HP: we should find better way to handle this
  1859.                 //             when the UseUDPPort option is selected
  1860.                 if (UDPMode == mCurrentTransport ||
  1861.                     MulticastMode == mCurrentTransport)
  1862.                 {
  1863.                     theErr = m_pProtocolLib->InitSockets();
  1864.                 }
  1865.                 m_idleState = SEND_SETUP_REQUEST_STATE;
  1866.             }
  1867.             HX_RELEASE(pInterruptState);
  1868.         }
  1869.         break;
  1870.         case SEND_SETUP_REQUEST_STATE:
  1871.         {
  1872.             // Make sure we are finished with the file header
  1873.             if (!mOwner->m_bContinueWithHeaders)
  1874.             {
  1875.                 theErr = send_setup_request();
  1876.                 m_idleState = NULL_STATE;
  1877.             }
  1878.         }
  1879.         break;
  1880.         case ALERT_STATE:
  1881.         {
  1882.             // Set theErr to the correct ServerAlert HXR_ code.
  1883.             theErr = MAKE_SA(m_ulLastAlert);
  1884.             if (!IS_SERVER_ALERT(theErr))
  1885.             {
  1886.                 theErr = HXR_SERVER_ALERT;
  1887.             }
  1888.             m_idleState = NULL_STATE;
  1889.         }
  1890.         break;
  1891.         default:
  1892.         break;
  1893.     }
  1894.     // check whether the connection has timed out
  1895.     if (!theErr && !m_bPaused)
  1896.     {
  1897.         ULONG32 ulNow = HX_GET_TICKCOUNT();
  1898.         if ((!mReceivedControl || (!m_bReceivedData && m_bPlaying))
  1899.             && mOwner->CheckTransportTimeout(ulNow))
  1900.         {
  1901.             /* Make sure that we have really not receioved any data.
  1902.              * If it is a sparse stream, transport may hold onto initial
  1903.              * data for around 2 seconds before releasing it to the next
  1904.              * layer.
  1905.              */
  1906.             if (!mReceivedControl)
  1907.             {
  1908.                 theErr = HXR_NET_CONNECT;
  1909.             }
  1910.             else
  1911.             {
  1912.                 if (m_pProtocolLib && m_pProtocolLib->IsDataReceived())
  1913.                 {
  1914.                     /* We haver received the data.. Transport will
  1915.                     * eventually give it to use (hopefully!)
  1916.                     */
  1917.                     m_bReceivedData = TRUE;
  1918.                 }
  1919.                 else
  1920.                 {
  1921.                     switch (mCurrentTransport)
  1922.                     {
  1923.                     case MulticastMode:
  1924.                         theErr = HXR_MULTICAST_UDP;
  1925.                         break;
  1926.                     case UDPMode:
  1927.                         theErr = HXR_NET_UDP;
  1928.                         break;
  1929.                     case TCPMode:
  1930.                         if (!m_bHTTPOnly)
  1931.                         {
  1932.                             theErr = HXR_NET_TCP;
  1933.                         }
  1934.                         else
  1935.                         {
  1936.                             theErr = HXR_DNR;
  1937.                         }
  1938.                         break;
  1939.                     default:
  1940.                         break;
  1941.                     }
  1942.                 }
  1943.             }
  1944.         }
  1945.         // The following logic is to force reconnect when in certain cases, the UDP
  1946.         // channel would be closed after a long pause. This solves the 50% phenomenon.
  1947.         if (HXR_OK == theErr && m_bReceivedData && m_bAreResuming && mCurrentTransport == UDPMode)
  1948.         {
  1949.             if (mSourceEnd || (m_pProtocolLib && m_pProtocolLib->IsDataReceived()))
  1950.             {
  1951.                 m_bAreResuming = FALSE;
  1952.             }
  1953.             else if (mOwner->CheckTransportTimeout(ulNow))
  1954.             {
  1955.                 m_bAreResuming = FALSE;
  1956.                 theErr = HXR_SERVER_TIMEOUT;
  1957.             }
  1958.         }
  1959.         // fallback to unicast if scalable multicast fails
  1960.         if (m_bSDPInitiated && HXR_MULTICAST_UDP == theErr && mLiveStream)
  1961.         {
  1962.             if (HXR_OK == SwitchToUnicast())
  1963.             {
  1964.                 theErr = HXR_OK;
  1965.             }
  1966.             else
  1967.             {
  1968.                 theErr = HXR_MULTICAST_JOIN;
  1969.             }
  1970.         }
  1971.     }
  1972.     // remember the last error so we won't proceed to the next
  1973.     // RTSP state in subsequent process() calls
  1974.     if (HXR_OK == m_LastError && HXR_OK != theErr)
  1975.     {
  1976.         m_LastError = theErr;
  1977.     }
  1978.     return theErr;
  1979. }
  1980. HX_RESULT
  1981. RTSPProtocol::abort(void)
  1982. {
  1983.     HX_RESULT theErr = HXR_OK;
  1984. //XXX...Currently unimplemented
  1985.     return theErr;
  1986. }
  1987. HX_RESULT
  1988. RTSPProtocol::GetEvent
  1989. (
  1990.     UINT16 uStreamNumber,
  1991.     CHXEvent*& pEvent
  1992. )
  1993. {
  1994.     HX_TRACE("RTSPProtocol::GetPacket");
  1995.     HX_RESULT result;
  1996.     IHXPacket* pPacket = NULL;
  1997.     pEvent = NULL;
  1998.     result = m_pProtocolLib->GetPacket(uStreamNumber, pPacket);
  1999. #ifdef _DEBUG
  2000.     if (result == HXR_AT_END)
  2001.     {
  2002.         STREAM_INFO* pStreamInfo;
  2003.         if (HXR_OK != mOwner->GetStreamInfo(uStreamNumber, pStreamInfo))
  2004.         {
  2005.             return HXR_FAIL;
  2006.         }
  2007.         HX_ASSERT(pStreamInfo->m_bSrcStreamDone);
  2008.     }
  2009. #endif
  2010.     if (pPacket)
  2011.     {
  2012.         // signal the raw data is received
  2013.         m_bReceivedData = TRUE;
  2014.         pEvent = new CHXEvent(pPacket);
  2015.         pPacket->Release();
  2016.     }
  2017.     return result;
  2018. }
  2019. HX_RESULT
  2020. RTSPProtocol::setup(const char* host, const char* path, UINT16 port,
  2021.                     BOOL LossCorrection, BOOL bHTTPCloak, 
  2022.                     BOOL bSDPInitiated, UINT16 cloakPort)
  2023. {
  2024.     HX_RESULT   theErr  = HXR_OK;
  2025.     IHXValues*  pRequestHeaders = NULL;
  2026.     IHXValues* pCloakValues = NULL;
  2027.     IHXBuffer*  pRegionData = NULL;
  2028.     m_bSDPInitiated = bSDPInitiated;
  2029.     mOwner->GetRequest(m_pRequest);
  2030.     // XXXkshoop store origional headers for use
  2031.     // in replaying Describe's.  This supports
  2032.     // authentication.
  2033.     HX_ASSERT(m_pRequest);
  2034.     if (m_pRequest)
  2035.     {
  2036.         m_spIHXValuesStoredHeaders.Release();
  2037.         theErr = m_pRequest->GetRequestHeaders(
  2038.             m_spIHXValuesStoredHeaders.ptr_reference());
  2039.         HX_VERIFY(SUCCEEDED(theErr) && m_spIHXValuesStoredHeaders.IsValid());
  2040.     }
  2041.     // setup base class members
  2042.     theErr = HXProtocol::setup(host, path, port, LossCorrection, bHTTPCloak,
  2043.                                m_bSDPInitiated, cloakPort);
  2044.     if (theErr)
  2045.     {
  2046.         return theErr;
  2047.     }
  2048.     if
  2049.     (
  2050.         m_pRequest
  2051.         &&
  2052.         SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders))
  2053.         &&
  2054.         pRequestHeaders
  2055.     )
  2056.     {
  2057.         pRequestHeaders->GetPropertyCString("RegionData", pRegionData);
  2058.     }
  2059.     HX_RELEASE(pRequestHeaders);
  2060.     // construct the IHXValues
  2061.     m_pIDInfo = new CHXHeader();
  2062.     m_pIDInfo->AddRef();
  2063.     IHXBuffer*  pGUID = new CHXBuffer();
  2064.     IHXBuffer*  pClientID = new CHXBuffer();
  2065.     IHXBuffer*  pPragma = new CHXBuffer();
  2066.     pGUID->AddRef();
  2067.     pClientID->AddRef();
  2068.     pPragma->AddRef();
  2069.     pGUID->Set((const UCHAR*)m_pszGUID, strlen(m_pszGUID)+1);
  2070.     pClientID->Set((const UCHAR*)m_pszClientID, strlen(m_pszClientID)+1);
  2071.     pPragma->Set((const UCHAR*)PRAGMA, strlen(PRAGMA)+1);
  2072.     m_pIDInfo->SetPropertyCString("GUID", pGUID);
  2073.     m_pIDInfo->SetPropertyCString("ClientID", pClientID);
  2074.     // server doesn't like this in SDP initiated playback
  2075.     if (!m_bSDPInitiated)
  2076.     {
  2077.         m_pIDInfo->SetPropertyCString("Pragma", pPragma);
  2078.     }
  2079. #if 0
  2080.     IHXBuffer* pPasswordBuffer;
  2081.     if (m_pPreferences && m_pPreferences->ReadPref("LoadTestPassword",
  2082.        pPasswordBuffer) == HXR_OK)
  2083.     {
  2084.         char szLoadTestPasswordKey[HX_COMPANY_ID_KEY_SIZE] = {0}; /* Flawfinder: ignore */
  2085.         // create the encrypted key
  2086.         CalcCompanyIDKey((const char*)pPasswordBuffer->GetBuffer(),
  2087.                         (const char*)szStarttime,
  2088.                         (const char*)"LoadTestID",
  2089.                         (const char*)pRCMagic1,
  2090.                         (const char*)pMagic2,
  2091.                         (UCHAR*) &szLoadTestPasswordKey[0]);
  2092.         char szEncodedLTP[HX_COMPANY_ID_KEY_SIZE * 2]; // probably overkill /* Flawfinder: ignore */
  2093.         BinTo64((const BYTE*)szLoadTestPasswordKey, HX_COMPANY_ID_KEY_SIZE,
  2094.             szEncodedLTP);
  2095.         IHXBuffer* pEncodedLTPBuffer = new CHXBuffer();
  2096.         pEncodedLTPBuffer->AddRef();
  2097.         pEncodedLTPBuffer->Set((const UCHAR*)szEncodedLTP,
  2098.             strlen(szEncodedLTP)+1);
  2099.         m_pIDInfo->SetPropertyCString("LoadTestPassword", pEncodedLTPBuffer);
  2100.         pEncodedLTPBuffer->Release();
  2101.         HX_RELEASE(pPasswordBuffer);
  2102.         /*
  2103.          * XXXSMP Very poor way to set a requirement.  This won't work
  2104.          * as soon rmartsp needs to send other requirements.  Comment
  2105.          * in rmartsp about this.
  2106.          */
  2107.         const UINT8 pRequireStr[] = "com.real.load-test-password-enabled";
  2108.         IHXBuffer* pReq = new CHXBuffer();
  2109.         pReq->AddRef();
  2110.         pReq->Set(pRequireStr, sizeof(pRequireStr) + 1);
  2111.         m_pIDInfo->SetPropertyCString("Require", pReq);
  2112.         pReq->Release();
  2113.     }
  2114. #endif
  2115.     if (pRegionData)
  2116.     {
  2117.         m_pIDInfo->SetPropertyCString("RegionData", pRegionData);
  2118.     }
  2119.     HX_RELEASE(pGUID);
  2120.     HX_RELEASE(pClientID);
  2121.     HX_RELEASE(pRegionData);
  2122.     HX_RELEASE(pPragma);
  2123.     /*
  2124.      * XXX...This had better get fixed under full IRMA (should
  2125.      *       be done with QueryInterface)
  2126.      */
  2127.     RTSPClientProtocol* pClientProtocol = NULL;
  2128. #if defined(HELIX_FEATURE_RDT)
  2129.     pClientProtocol = new RTSPClientProtocolExt();
  2130. #else
  2131.     pClientProtocol = new RTSPClientProtocol();
  2132. #endif /* HELIX_FEATURE_RDT */
  2133.     m_pProtocolLib = (IHXRTSPClientProtocol*)pClientProtocol;
  2134.     if (!m_pProtocolLib)
  2135.     {
  2136.         return HXR_OUTOFMEMORY;
  2137.     }
  2138.     m_pProtocolLib->AddRef();
  2139.     if (m_bHTTPOnly)
  2140.     {
  2141.         IHXBuffer* pBuffer = NULL;
  2142.         const char* pszURL = NULL;
  2143.         pCloakValues = new CHXHeader();
  2144.         pCloakValues->AddRef();
  2145.         if (HXR_OK == m_pIDInfo->GetPropertyCString("ClientID", pBuffer))
  2146.         {
  2147.             pCloakValues->SetPropertyCString("ClientID", pBuffer);
  2148.         }
  2149.         HX_RELEASE(pBuffer);
  2150.         if (m_pRequest)
  2151.         {
  2152.             if (HXR_OK == m_pRequest->GetURL(pszURL))
  2153.             {
  2154.                 pBuffer = new CHXBuffer();
  2155.                 pBuffer->AddRef();
  2156.                 pBuffer->Set((const UCHAR*)pszURL, strlen(pszURL)+1);
  2157.                 pCloakValues->SetPropertyCString("url", pBuffer);
  2158.                 HX_RELEASE(pBuffer);
  2159.             }
  2160.             if (HXR_OK == m_pRequest->GetRequestHeaders(pRequestHeaders))
  2161.             {
  2162.                 if (HXR_OK == pRequestHeaders->GetPropertyCString("Cookie", pBuffer))
  2163.                 {
  2164.                     pCloakValues->SetPropertyCString("Cookie", pBuffer);
  2165.                 }
  2166.                 HX_RELEASE(pBuffer);
  2167.             }
  2168.             HX_RELEASE(pRequestHeaders);
  2169.         }
  2170.         pClientProtocol->InitCloak(m_pCloakPorts, m_nCloakPorts, pCloakValues);
  2171.         HX_RELEASE(pCloakValues);
  2172.     }
  2173.     if (m_bPrefetch)
  2174.     {
  2175.         pClientProtocol->EnterPrefetch();
  2176.     }
  2177.     //USER_AGENT_STRING defined in hxver.h
  2178.     CHXString buildVersion = USER_AGENT_STRING +
  2179.         CHXString(TARVER_STRING_VERSION) + " (" +
  2180.         CHXString(TARVER_STR_PLATFORM) + ")";
  2181.     m_pProtocolLib->SetBuildVersion((const char*)buildVersion);
  2182.     m_pPendingStatus = m_pProtocolLib->GetPendingStatus();
  2183.     m_pStatistics = m_pProtocolLib->GetStatistics();
  2184.     // start communication with server
  2185.     if(mUseProxy)
  2186.     { 
  2187.         theErr = proxy_hello();
  2188.     }
  2189.     else
  2190.     {
  2191.         theErr = server_hello();
  2192.     }
  2193.     // Start Waiting for control channel..
  2194.     mOwner->StartDataWait(TRUE);
  2195.     return theErr;
  2196. }
  2197. // these get initialized every time we make a new connection with
  2198. // the server
  2199. void
  2200. RTSPProtocol::initialize_members(void)
  2201. {
  2202.     // intialize base class members
  2203.     HXProtocol::initialize_members();
  2204.     m_bPerfectPlayAllowed   = TRUE;
  2205.     // release any allocated local resources
  2206.     HX_RELEASE(m_pPendingStatus);
  2207.     HX_RELEASE(m_pStatistics);
  2208.     HX_RELEASE(m_pIDInfo);
  2209.     if (m_pProtocolLib)
  2210.     {
  2211.         m_pProtocolLib->Done();
  2212.         HX_RELEASE(m_pProtocolLib);
  2213.     }
  2214.     CHXMapLongToObj::Iterator i;
  2215.     for (i = m_pStreamInfoList->Begin(); i != m_pStreamInfoList->End(); ++i)
  2216.     {
  2217.         RTSP_STREAM_INFO* pStreamInfo = (RTSP_STREAM_INFO*)(*i);
  2218.         HX_DELETE(pStreamInfo);
  2219.     }
  2220.     m_pStreamInfoList->RemoveAll();
  2221. }
  2222. HX_RESULT
  2223. RTSPProtocol::seek
  2224. (
  2225.     ULONG32 posArg,
  2226.     ULONG32 posArg2,
  2227.     UINT16 seekFrom
  2228. )
  2229. {
  2230.     if (IsLive())
  2231.     {
  2232.         return m_pProtocolLib->SeekFlush();
  2233.     }
  2234.     HX_RESULT theErr = HXR_OK;
  2235.     m_uCurrentStreamCount = m_uStreamCount;
  2236.     mSourceEnd = FALSE;
  2237.     m_bPendingSeek = TRUE;
  2238.     m_ulSeekPos1 = posArg;
  2239.     m_ulSeekPos2 = posArg2;
  2240.     return theErr;
  2241. }
  2242. HX_RESULT
  2243. RTSPProtocol::resume(UINT32 ulEndTime)
  2244. {
  2245.     if (m_bPendingSeek)
  2246.     {
  2247.         m_bPendingSeek = FALSE;
  2248.         m_bIsFirstResume = FALSE;
  2249.         m_bPaused = FALSE;
  2250.         if (mCurrentTransport == UDPMode)
  2251.         {
  2252.             m_bAreResuming = TRUE;
  2253.             mOwner->StartDataWait();
  2254.         }
  2255.         return m_pProtocolLib->SendPlayRequest(m_ulSeekPos1, (!mLiveStream && ulEndTime > 0) ? ulEndTime : m_ulSeekPos2, 0);
  2256.     }
  2257.     if (m_bIsFirstResume)
  2258.     {
  2259.         m_bIsFirstResume = FALSE;
  2260.         m_bPaused = FALSE;
  2261.         return m_pProtocolLib->SendPlayRequest(0, (!mLiveStream && ulEndTime > 0) ? ulEndTime : RTSP_PLAY_RANGE_BLANK, 0);
  2262.     }
  2263.     else if (mCurrentTransport == UDPMode)
  2264.     {
  2265.         m_bAreResuming = TRUE;
  2266.         mOwner->StartDataWait();
  2267.     }
  2268.     if (!m_bPaused)
  2269.     {
  2270.         return HXR_OK;
  2271.     }
  2272.     m_bPaused = FALSE;
  2273.     return m_pProtocolLib->SendResumeRequest();
  2274. }
  2275. HX_RESULT
  2276. RTSPProtocol::stop(void)
  2277. {
  2278.     if (m_pProtocolLib)
  2279.     {
  2280.         m_pProtocolLib->SendTeardownRequest();
  2281.         m_pProtocolLib->Done();
  2282.         m_pProtocolLib->Release();
  2283.         m_pProtocolLib = 0;
  2284.     }
  2285.     HXProtocol::stop();
  2286. #if defined(HELIX_FEATURE_REVERTER)
  2287.     if (m_pDataRevert)
  2288.     {
  2289.         m_pDataRevert->Done();
  2290.         HX_RELEASE(m_pDataRevert);
  2291.     }
  2292. #endif /* HELIX_FEATURE_REVERTER */
  2293.     CHXMapLongToObj::Iterator i;
  2294.     for (i = m_pStreamInfoList->Begin(); i != m_pStreamInfoList->End(); ++i)
  2295.     {
  2296.         RTSP_STREAM_INFO* pStreamInfo = (RTSP_STREAM_INFO*)(*i);
  2297.         HX_DELETE(pStreamInfo);
  2298.     }
  2299.     m_pStreamInfoList->RemoveAll();
  2300.     m_bReceivedData = FALSE;
  2301.     m_bPlaying = FALSE;
  2302.     m_uStreamCount = 0;
  2303.     return HXR_OK;
  2304. }
  2305. HX_RESULT
  2306. RTSPProtocol::pause(void)
  2307. {
  2308.     HX_RESULT   rc = HXR_OK;
  2309.     // properly set the pause state for server timeout
  2310.     // calculation
  2311.     if (m_bIsFirstResume)
  2312.     {
  2313.         m_bPaused = TRUE;
  2314.     }
  2315.     else if (!m_bPaused)
  2316.     {
  2317.         m_bPaused = TRUE;
  2318.         rc = m_pProtocolLib->SendPauseRequest();
  2319.     }
  2320.     return rc;
  2321. }
  2322. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2323. void
  2324. RTSPProtocol::send_statistics
  2325. (
  2326.     UINT32      ulStatsMask
  2327. )
  2328. {
  2329.     UINT32  ulStats123 = 0;
  2330.     UINT32  ulStats4 = 0;
  2331.     char*   pszStats123 = NULL;
  2332.     char*   pszStats4 = NULL;
  2333.     char*   pszStats = NULL;
  2334.     prepare_statistics(ulStatsMask, pszStats123);
  2335.     if (pszStats123)
  2336.     {
  2337.         ulStats123 = strlen(pszStats123);
  2338.     }
  2339.     if (ulStatsMask & 8UL)
  2340.     {
  2341.         prepare_stats4(pszStats4, ulStats4);
  2342.     }
  2343.     if (pszStats123 && pszStats4)
  2344.     {
  2345.         pszStats = new char[ulStats123 + ulStats4 + 1];
  2346.         strcpy(pszStats, pszStats123); /* Flawfinder: ignore */
  2347.         strcat(pszStats, pszStats4); /* Flawfinder: ignore */
  2348.         HX_VECTOR_DELETE(pszStats123);
  2349.         HX_VECTOR_DELETE(pszStats4);
  2350.     }
  2351.     else if (pszStats123 && !pszStats4)
  2352.     {
  2353.         pszStats = pszStats123;
  2354.     }
  2355.     else if (!pszStats123 && pszStats4)
  2356.     {
  2357.         pszStats = pszStats4;
  2358.     }
  2359.     if (pszStats)
  2360.     {
  2361.         m_pProtocolLib->SendPlayerStats(pszStats);
  2362.     }
  2363.     HX_VECTOR_DELETE(pszStats);
  2364.     return;
  2365. }
  2366. HX_RESULT
  2367. RTSPProtocol::prepare_stats4(char*& pszStats, UINT32& ulStats)
  2368. {
  2369.     HX_RESULT           rc = HXR_OK;
  2370.     UINT32              i = 0;
  2371.     UINT32              ulAllocatedBufferSize = MAX_DEFAULT_STATS_SIZE;
  2372.     UINT32              ulValue = 0;
  2373.     char                szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  2374.     char*               pszValue = NULL;
  2375.     char*               pszTempStats = NULL;
  2376.     RTSP_STREAM_INFO*   pStreamInfo = NULL;
  2377.     STREAM_STATS*       pStreamStats = NULL;
  2378.     IHXBuffer*          pParentName = NULL;
  2379.     IHXBuffer*          pValue = NULL;
  2380.     CHXMapLongToObj::Iterator j;
  2381.     pszStats = new char[ulAllocatedBufferSize];
  2382.     ulStats = 0;
  2383.     SafeStrCpy(pszStats, "[Stat4:", MAX_DISPLAY_NAME);
  2384.     ulStats += 7;
  2385.     statistics_cat_ext(pszStats, ulAllocatedBufferSize, m_uStreamCount, " ", ulStats);
  2386.     // per stream stats
  2387.     if (m_pStreamInfoList->GetCount())
  2388.     {
  2389.         for (j = m_pStreamInfoList->Begin(); j != m_pStreamInfoList->End(); ++j)
  2390.         {
  2391.             pStreamInfo = (RTSP_STREAM_INFO*)(*j);
  2392.             pStreamStats = pStreamInfo->m_pStreamStats;
  2393.             if (!pStreamStats || !pStreamStats->m_bInitialized)
  2394.             {
  2395.                 continue;
  2396.             }
  2397.             // mime type
  2398.             if (pStreamStats->m_pMimeType &&
  2399.                 (pszValue = pStreamStats->m_pMimeType->GetStr()))
  2400.             {
  2401.                 ulStats += strlen(pszValue);
  2402.                 if (ulStats > (ulAllocatedBufferSize - MAX_DISPLAY_NAME))
  2403.                 {
  2404.                     ulAllocatedBufferSize += MAX_DEFAULT_STATS_SIZE;
  2405.                     pszTempStats = new char[ulAllocatedBufferSize];
  2406.                     SafeStrCpy(pszTempStats, pszStats, ulAllocatedBufferSize);
  2407.                     HX_VECTOR_DELETE(pszStats);
  2408.                     pszStats = pszTempStats;
  2409.                 }
  2410.                 SafeStrCat(pszStats, pszValue, ulAllocatedBufferSize);
  2411.                 HX_VECTOR_DELETE(pszValue);
  2412.             }
  2413.             else
  2414.             {
  2415.                 SafeStrCat(pszStats, "N/A", ulAllocatedBufferSize);
  2416.                 ulStats += 3;
  2417.             }
  2418.             SafeStrCat(pszStats, "|", ulAllocatedBufferSize);
  2419.             ulStats++;
  2420.             // codec
  2421.             if (HXR_OK == m_pRegistry->GetPropName(pStreamStats->m_pRenderer->m_ulRegistryID, pParentName))
  2422.             {
  2423.                 SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.Codec", pParentName->GetBuffer());
  2424.                 if (HXR_OK == m_pRegistry->GetStrByName(szRegKeyName, pValue) && pValue)
  2425.                 {
  2426.                     ulValue = pValue->GetSize();
  2427.                     pszValue = new char[ulValue+1];
  2428.                     strcpy(pszValue, (const char*)pValue->GetBuffer()); /* Flawfinder: ignore */
  2429.                     // replace space with underscore
  2430.                     for (i = 0; i < ulValue; i++)
  2431.                     {
  2432.                         if (pszValue[i] == ' ')
  2433.                         {
  2434.                             pszValue[i] = '_';
  2435.                         }
  2436.                     }
  2437.                 }
  2438.                 HX_RELEASE(pValue);
  2439.             }
  2440.             HX_RELEASE(pParentName);
  2441.             if (pszValue)
  2442.             {
  2443.                 ulStats += strlen(pszValue);
  2444.                 if (ulStats > (ulAllocatedBufferSize - MAX_DISPLAY_NAME))
  2445.                 {
  2446.                     ulAllocatedBufferSize += MAX_DEFAULT_STATS_SIZE;
  2447.                     pszTempStats = new char[ulAllocatedBufferSize];
  2448.                     SafeStrCpy(pszTempStats, pszStats, ulAllocatedBufferSize);
  2449.                     HX_VECTOR_DELETE(pszStats);
  2450.                     pszStats = pszTempStats;
  2451.                 }
  2452.                 SafeStrCat(pszStats, pszValue, ulAllocatedBufferSize);
  2453.                 HX_VECTOR_DELETE(pszValue);
  2454.             }
  2455.             else
  2456.             {
  2457.                 SafeStrCat(pszStats, "N/A", ulAllocatedBufferSize);
  2458.                 ulStats += 3;
  2459.             }
  2460.             SafeStrCat(pszStats, "|", ulAllocatedBufferSize);
  2461.             ulStats++;
  2462.             // bandwidth stats
  2463.             statistics_cat_ext(pszStats, ulAllocatedBufferSize, pStreamStats->m_pReceived->GetInt(), "|", ulStats);
  2464.             statistics_cat_ext(pszStats, ulAllocatedBufferSize, pStreamStats->m_pLost->GetInt(), "|", ulStats);
  2465.             statistics_cat_ext(pszStats, ulAllocatedBufferSize, pStreamStats->m_pReceived->GetInt() - pStreamStats->m_pNormal->GetInt(), "|", ulStats);
  2466.             statistics_cat_ext(pszStats, ulAllocatedBufferSize, pStreamStats->m_pAvgBandwidth->GetInt(), "|", ulStats);
  2467.             statistics_cat_ext(pszStats, ulAllocatedBufferSize, pStreamStats->m_pCurBandwidth->GetInt(), "|", ulStats);
  2468.             SafeStrCat(pszStats, ";", ulAllocatedBufferSize);
  2469.             ulStats++;
  2470.         }
  2471.     }
  2472.     else
  2473.     {
  2474.         statistics_cat_ext(pszStats, ulAllocatedBufferSize, 0, " ", ulStats);
  2475.     }
  2476.     pszStats[ulStats-1] = ' ';
  2477.     // Transport
  2478.     statistics_cat_ext(pszStats, ulAllocatedBufferSize, mCurrentTransport, " ", ulStats);
  2479.     // TurboPlay
  2480.     statistics_cat_ext(pszStats, ulAllocatedBufferSize, m_bFastStart, "|", ulStats);
  2481.     if (m_bFastStart)
  2482.     {
  2483.         statistics_cat_ext(pszStats, ulAllocatedBufferSize, mOwner->m_turboPlayStats.ulAcceleratedBW, "|", ulStats);
  2484.         statistics_cat_ext(pszStats, ulAllocatedBufferSize, mOwner->m_turboPlayStats.ulBufferedTime, "|", ulStats);
  2485.     }
  2486.     else
  2487.     {
  2488.         statistics_cat_ext(pszStats, ulAllocatedBufferSize, mOwner->m_turboPlayStats.tpOffReason, "|", ulStats);
  2489.         statistics_cat_ext(pszStats, ulAllocatedBufferSize, 0, "|", ulStats);
  2490.     }
  2491.     SafeStrCat(pszStats, " ", ulAllocatedBufferSize);
  2492.     ulStats++;
  2493.     // Startup latency, first data packet arrives!
  2494.     statistics_cat_ext(pszStats, ulAllocatedBufferSize, mOwner->GetFirstDataArriveTime(), " ", ulStats);
  2495.     // Reason of clip end
  2496.     statistics_cat_ext(pszStats, ulAllocatedBufferSize, mOwner->m_srcEndCode, NULL, ulStats);
  2497.     SafeStrCat(pszStats, "]", ulAllocatedBufferSize);
  2498.     ulStats++;
  2499.     return rc;
  2500. }
  2501. STREAM_STATS*
  2502. RTSPProtocol::create_statistics(UINT16 uStreamNumber)
  2503. {
  2504.     HX_RESULT       result = HXR_OK;
  2505.     STREAM_STATS*   pStats = NULL;
  2506.     IHXBuffer*      pParentName = NULL;
  2507.     CHAR            RegKeyName[MAX_DISPLAY_NAME] = {0};
  2508.     if (!m_pRegistry)
  2509.     {
  2510.         goto cleanup;
  2511.     }
  2512.     if (HXR_OK == m_pRegistry->GetPropName(m_ulRegistryID, pParentName) && pParentName)
  2513.     {
  2514.         SafeSprintf(RegKeyName, MAX_DISPLAY_NAME, "%s.Stream%d", pParentName->GetBuffer(), uStreamNumber);
  2515.         /*
  2516.          * This the location where the first STREAM_STATS for the stream
  2517.          * is instantiated. The protocol library may make another to fill
  2518.          * the fields in the registry, but it must use the keys created
  2519.          * here
  2520.          */
  2521.         //ASSERT(!m_pRegistry->GetId(RegKeyName));
  2522.         UINT32 uStreamId = 0;
  2523.         if (!m_pRegistry->GetId(RegKeyName))
  2524.         {
  2525.             uStreamId = m_pRegistry->AddComp(RegKeyName);
  2526.         }
  2527.         else
  2528.         {
  2529.             uStreamId = m_pRegistry->GetId(RegKeyName);
  2530.         }
  2531.         pStats = new STREAM_STATS(m_pRegistry, uStreamId);
  2532.     }
  2533.     HX_RELEASE(pParentName);
  2534. cleanup:
  2535.     return pStats;
  2536. }
  2537. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2538. BOOL
  2539. RTSPProtocol::IsSourceDone(void)
  2540. {
  2541.     return mSourceEnd;
  2542. }
  2543. HX_RESULT
  2544. RTSPProtocol::GetCurrentBuffering(UINT16  uStreamNumber,
  2545.                                   INT64&  llLowestTimestamp,
  2546.                                   INT64&  llHighestTimestamp,
  2547.                                   UINT32& ulNumBytes,
  2548.                                   BOOL&   bDone)
  2549. {
  2550.     HX_RESULT   theErr  = HXR_OK;
  2551.     llLowestTimestamp   = 0;
  2552.     llHighestTimestamp  = 0;
  2553.     ulNumBytes          = 0;
  2554.     bDone               = FALSE;
  2555.     if (m_pProtocolLib)
  2556.     {
  2557.         theErr = m_pProtocolLib->GetCurrentBuffering(uStreamNumber,
  2558.                                                      llLowestTimestamp,
  2559.                                                      llHighestTimestamp,
  2560.                                                      ulNumBytes,
  2561.                                                      bDone);
  2562.         if (!theErr && ulNumBytes > 0)
  2563.         {
  2564.             m_bReceivedData = TRUE;
  2565.         }
  2566.     }
  2567.     return theErr;
  2568. }