📄 hxprotocol.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxcom.h"
#include "hlxclib/string.h"
#include "hxresult.h"
#include "hxtypes.h"
#include "hxassert.h"
#if defined(_WINDOWS) || defined(WIN32)
#include "platform/win/win_net.h"
#endif
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxfiles.h"
#include "hxengin.h"
#include "chxpckts.h"
#include "hxcore.h"
#include "hxprefs.h"
#include "hxpref.h"
#include "hxpends.h"
#include "hxslist.h"
#include "hxstring.h"
#include "chxelst.h"
#include "chxeven.h"
#include "strminfo.h"
#include "hxntsrc.h"
#include "hxtick.h"
#include "hxmangle.h"
#include "hxprotocol.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
HXProtocol::HXProtocol(HXNetSource* owner, ULONG32 ulPlatformData) :
mOwner (owner)
, m_pPreferences(0)
, m_bConnectDone (FALSE)
, mProtocolValid (FALSE)
, mSendStatsMask (1)
, mLocked (0)
, mAtInterrupt (0)
, m_bPaused (FALSE)
, mSourceEnd (FALSE)
, mLocale (0)
, mUseUDPPort (FALSE)
, m_uUDPPort (0)
, mHost (0)
, mPath (0)
, mLossCorrection (FALSE)
, m_pszClientID (NULL)
, m_pszGUID (NULL)
, mServerAddr (0)
, mServerTimeout (0)
, mPort (0)
, mUseProxy (FALSE)
, mProxy (0)
, mProxyPort (0)
, mProxyVersion (0)
, mFlowControl (FALSE)
, mProtocolVersion (0)
, m_bPerfectPlay (FALSE)
, m_bPrefetch(FALSE)
, m_bFastStart(FALSE)
, mMulticastAddr (0)
, mMulticastPort (0)
, mUsingMulticast (FALSE)
, mCurrentTransport(UnknownMode)
, m_ulTransportPrefMask(0)
, mLiveStream(FALSE)
, mSaveAsAllowed(FALSE)
, m_bPerfectPlayAllowed(FALSE)
, mNumFlowControl(0)
, m_ulRegistryID (0)
, m_pRegistry (0)
, m_lRefCount(0)
, m_bIsFirstResume(TRUE)
, m_bHTTPOnly(FALSE)
, mCloakPort(0)
, m_pCredentialsCache(NULL)
, m_LastError(HXR_OK)
, m_pTextBuf(NULL)
, m_bHTTPvProxy(FALSE)
, m_pCloakPorts(NULL)
, m_nCloakPorts(0)
, m_bAreResuming(FALSE)
, m_ulLastAlert(0)
, m_bSDPInitiated(FALSE)
{
if (mOwner)
{
mOwner->AddRef();
mOwner->QueryInterface(IID_IHXPreferences, (void **) &m_pPreferences);
m_pRegistry = mOwner->m_pRegistry;
if (HXR_OK != mOwner->QueryInterface(IID_IHXCredentialsCache, (void**)&m_pCredentialsCache))
{
m_pCredentialsCache = NULL;
}
}
}
HXProtocol::~HXProtocol(void)
{
HX_RELEASE(m_pPreferences);
HX_RELEASE(m_pCredentialsCache);
HX_RELEASE(mOwner);
HX_VECTOR_DELETE(mHost);
HX_VECTOR_DELETE(mPath);
HX_VECTOR_DELETE(m_pszClientID);
HX_VECTOR_DELETE(m_pszGUID);
HX_VECTOR_DELETE(mProxy);
HX_VECTOR_DELETE(m_pTextBuf);
}
// these get initialized every time we make a new connection with
// the server
void HXProtocol::initialize_members()
{
IHXBuffer* pBuffer = NULL;
mProtocolValid = FALSE;
mFlowControl = FALSE;
mLiveStream = FALSE;
mSaveAsAllowed = FALSE;
m_bPerfectPlayAllowed = FALSE;
mNumFlowControl = 0;
HX_VECTOR_DELETE(m_pszGUID);
BOOL bCanSendGUID = FALSE;
ReadPrefBOOL(m_pPreferences, "AllowAuthID", bCanSendGUID);
if(bCanSendGUID &&
m_pPreferences && m_pPreferences->ReadPref(CLIENT_GUID_REGNAME, pBuffer) == HXR_OK)
{
m_pszGUID = DeCipher((char*)pBuffer->GetBuffer());
}
else
{
m_pszGUID = new char[sizeof(CLIENT_ZERO_GUID) + 1];
::strcpy(m_pszGUID, CLIENT_ZERO_GUID); /* Flawfinder: ignore */
}
HX_ASSERT(m_pszGUID);
HX_RELEASE(pBuffer);
}
HX_RESULT
HXProtocol::setup(const char *host, const char *path, UINT16 port, BOOL LossCorrection,
BOOL bHTTPCloak, BOOL bSDPInitiated, UINT16 cloakPort)
{
HX_RESULT theErr = HXR_OK;
if (bSDPInitiated)
{
mPath = new char[::strlen(path) + 1];
::strcpy(mPath, path);
}
else
{
// get out immediately if we have bogus parameters
if(!host || !*host)
theErr = HXR_DNR;
if(!theErr && !path)
theErr = HXR_INVALID_PATH;
if(!theErr)
{
HX_VECTOR_DELETE(mHost);
HX_VECTOR_DELETE(mPath);
// Save a copy of the parameters
mHost = new char[::strlen(host) + 1];
mPath = new char[::strlen(path) + 1];
if(!mHost || !mPath)
theErr = HXR_OUTOFMEMORY;
}
// initialize member variables
if(!theErr)
{
::strcpy(mHost, host); /* Flawfinder: ignore */
::strcpy(mPath, path); /* Flawfinder: ignore */
// strip off fragment
char* pFragment = strchr(mPath, '#');
if(pFragment)
{
*pFragment = '\0';
}
mPort = port;
mLossCorrection = LossCorrection;
m_bHTTPOnly = bHTTPCloak;
mCloakPort = cloakPort;
}
}
return(theErr);
}
HX_RESULT
HXProtocol::process_idle (BOOL atInterrupt)
{
HX_RESULT theErr = HXR_OK;
if(mLocked) // process is locked
return HXR_OK;
mLocked = 1; // lock out interrupt processing
if (atInterrupt)
{
mAtInterrupt = 1;
}
theErr = process();
mAtInterrupt = 0;
mLocked = 0; // enable interrupt processing
return(theErr);
}
HX_RESULT
HXProtocol::set_client_id(char *clientID)
{
HX_VECTOR_DELETE(m_pszClientID);
// check if the clientID is not null
if(clientID == 0) return HXR_OK;
m_pszClientID = new char[::strlen(clientID) + 1];
if(m_pszClientID == 0) return HXR_OUTOFMEMORY;
::strcpy(m_pszClientID, clientID); /* Flawfinder: ignore */
return HXR_OK;
}
// sets up HXProtocol to use a RealAudio proxy
HX_RESULT
HXProtocol::set_proxy(const char* proxy, UINT16 port)
{
HX_RESULT theErr = HXR_OK;
if(proxy == 0 || *proxy == 0) return HXR_OK;
HX_VECTOR_DELETE(mProxy);
mProxy = new char[::strlen(proxy) + 1];
if(mProxy == NULL) theErr = HXR_OUTOFMEMORY;
if(!theErr)
{
::strcpy(mProxy, proxy); /* Flawfinder: ignore */
mProxyPort = port;
}
mUseProxy = theErr == HXR_OK;
return(theErr);
}
void
HXProtocol::LeavePrefetch(void)
{
m_bPrefetch = FALSE;
return;
}
void
HXProtocol::SetCloakPortAttempted(UINT16* pCloakPorts, UINT8 nCloakPorts)
{
m_pCloakPorts = pCloakPorts;
m_nCloakPorts = nCloakPorts;
}
HX_RESULT
HXProtocol::stop(void)
{
mSourceEnd = TRUE;
HX_RELEASE(mOwner);
return HXR_OK;
}
#if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
void
HXProtocol::statistics_cat(char* pStats, UINT32 ulBufLen, LONG32 lData)
{
char numb[12]; /* Flawfinder: ignore */
SafeSprintf(numb, 12, "%10lu ", lData); /* Flawfinder: ignore */
SafeStrCat(pStats,numb, ulBufLen);
}
void
HXProtocol::statistics_cat_ext(char* pszStats, UINT32 ulBufLen, LONG32 lData, char* pszSep, UINT32& ulCount)
{
char numb[12]; /* Flawfinder: ignore */
if (pszSep)
{
SafeSprintf(numb, 12, "%lu%s", lData, pszSep);
}
else
{
SafeSprintf(numb,12, "%lu", lData);
}
SafeStrCat(pszStats, numb, ulBufLen);
ulCount += strlen(numb);
}
HX_RESULT
HXProtocol::prepare_statistics(UINT32 ulStatsMask, char*& pszStats)
{
HX_RESULT rc = HXR_OK;
char szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
char* pszCodec = NULL;
INT32 lRAStreamNumber = -1;
UINT32 i = 0;
UINT32 ulStatsLength = 0;
UINT32 ulTransport = 0;
UINT32 ulLength = 0;
STREAM_STATS* pStreamStats = NULL;
CHXSimpleList* pLogInfoList = NULL;
IHXBuffer* pParentName = NULL;
IHXBuffer* pValue = NULL;
pszStats = NULL;
// collect level 3 stats info.
ulStatsLength = MAX_DISPLAY_NAME + mOwner->GetLogInfo(pLogInfoList);
if (!(ulStatsMask & 8UL))
{
// get the RA stream number
// Level 1,2 pszStats only apply to RealAudio
lRAStreamNumber = mOwner->GetRAStreamNumber();
if (lRAStreamNumber >= 0)
{
// retrieve the pszStats
if (HXR_OK != GetStreamStatistics((UINT32)lRAStreamNumber, &pStreamStats))
{
goto cleanup;
}
if (!pStreamStats || !pStreamStats->m_bInitialized)
{
goto cleanup;
}
// retreive the pszStats set by the renderer
if (m_pRegistry &&
HXR_OK == m_pRegistry->GetPropName(pStreamStats->m_pRenderer->m_ulRegistryID, pParentName))
{
SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.Codec", pParentName->GetBuffer());
if (HXR_OK == m_pRegistry->GetStrByName(szRegKeyName, pValue) && pValue)
{
ulLength = pValue->GetSize();
pszCodec = new char[ulLength + 1];
strcpy(pszCodec, (const char*)pValue->GetBuffer()); /* Flawfinder: ignore */
// replace space with underscore
for (i = 0; i < ulLength; i++)
{
if (pszCodec[i] == ' ')
{
pszCodec[i] = '_';
}
}
HX_RELEASE(pValue);
}
}
HX_RELEASE(pParentName);
if (pszCodec)
{
ulStatsLength += 2 * strlen(pszCodec);
}
pszStats = new CHAR[ulStatsLength];
memset(pszStats, 0, ulStatsLength);
if (ulStatsMask & 1UL)
{
SafeStrCat(pszStats, "Stat1:", ulStatsLength);
// build statistics string
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pReceived->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pReceived->GetInt() -
pStreamStats->m_pNormal->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pLost->GetInt());
statistics_cat(pszStats, ulStatsLength, 0); // no packets sent early in 6.0
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pLate->GetInt());
if (!pszCodec)
{
SafeStrCat(pszStats, "N/A", ulStatsLength);
}
else
{
SafeStrCat(pszStats, pszCodec, ulStatsLength);
}
}
if (ulStatsMask & 2UL)
{
// divide pszStats levels if necessary
if (ulStatsMask & 1UL)
{
SafeStrCat(pszStats, "][", ulStatsLength);
}
SafeStrCat(pszStats, "Stat2:", ulStatsLength);
// Bandwidth info
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pClipBandwidth->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pAvgBandwidth->GetInt());
// Latency info
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pHighLatency->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pLowLatency->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pAvgLatency->GetInt());
// Resend info
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pResendRequested->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pResendReceived->GetInt());
statistics_cat(pszStats, ulStatsLength, pStreamStats->m_pLate->GetInt());
// rebuffer info (in percent)
statistics_cat(pszStats, ulStatsLength, 0);
// Transport
// 0 or UDP, 1 for TCP, 2 for Multicast...
if (mCurrentTransport == UDPMode)
{
ulTransport = 0L;
}
else if (mCurrentTransport == TCPMode)
{
ulTransport = 1L;
}
else if (mCurrentTransport == MulticastMode)
{
ulTransport = 2L;
}
statistics_cat(pszStats, ulStatsLength, ulTransport);
// Startup latency, first data packet arrives!
statistics_cat(pszStats, ulStatsLength, mOwner->GetFirstDataArriveTime());
if (!pszCodec)
{
SafeStrCat(pszStats, "N/A", ulStatsLength);
}
else
{
SafeStrCat(pszStats, pszCodec, ulStatsLength);
}
}
}
}
if ((ulStatsMask & 4UL) && pLogInfoList && pLogInfoList->GetCount())
{
if (!pszStats)
{
pszStats = new CHAR[ulStatsLength];
memset(pszStats, 0, ulStatsLength);
}
// divide stats levels if necessary
if((lRAStreamNumber >= 0) && ((ulStatsMask & 1UL) || (ulStatsMask & 2UL)))
{
SafeStrCat(pszStats, "][", ulStatsLength);
}
SafeStrCat(pszStats, "Stat3:", ulStatsLength);
CHXSimpleList::Iterator ndx = pLogInfoList->Begin();
for (; ndx != pLogInfoList->End(); ++ndx)
{
char* pszInfo = (char*) (*ndx);
SafeStrCat(pszStats, pszInfo, ulStatsLength);
}
}
if (!pszStats || strlen(pszStats) == 0)
{
// nothing to send
goto cleanup;
}
else
{
SafeStrCat(pszStats, "]", ulStatsLength);
}
cleanup:
HX_VECTOR_DELETE(pszCodec);
return HXR_OK;
}
#endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -