📄 preftran.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 "hxtypes.h"
#include "hlxclib/string.h"
#include "hlxclib/stdio.h"
#ifdef _MACINTOSH
//#include <stat.mac.h> // Not needed on Mac and doesn't exist in CW Pro 7.
#else
#include "hlxclib/sys/types.h"
#include "hlxclib/sys/stat.h"
#endif
#include "hlxclib/time.h"
#if defined(_AIX)
#include <ctype.h>
#endif
#if defined(_WINDOWS)
#include <windows.h>
#ifndef _WINCE
#include <winsock2.h>
#include <ws2tcpip.h>
#endif /* _WINCE */
#endif /* _WINDOWS */
#include "hlxclib/sys/socket.h"
#include "hxresult.h"
#include "hxslist.h"
#include "ihxpckts.h"
#include "hxstrutl.h"
#include "dbcs.h"
#include "dllpath.h"
#include "hxprefs.h"
#include "hxprefutil.h"
#include "hxthread.h"
#include "netbyte.h"
#include "hxpxymgr.h"
#include "portaddr.h"
#include "prefdefs.h"
#include "hxengin.h"
#include "hxnetif.h"
#include "pacutil.h"
#include "preftran.h"
#ifdef _UNIX
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/socket.h>
#if defined _SOLARIS || defined _FREEBSD || defined _OPENBSD || defined _NETBSD
#include <sys/sockio.h>
#endif
#include <net/if.h>
#include <sys/ioctl.h>
#endif
#include "hlxclib/stdlib.h" // for i64toa
#if defined (_UNIX) && !defined(_SUN) && !defined(_SCO_UW) && !defined(_HPUX) && !defined(_IRIX) && !defined(_OSF1)
#include <sys/file.h>
#endif /* UNIX */
#define RM_PREFTRAN_CAPTION "# RealMedia Preferred Transport File\n# This is a generated file! Do not edit.\n\n"
#define RM_PREFTRAN_DIR_NAME "preftran/"
#define RM_PREFTRAN_FILE_LOCK "PrefTranFileLock"
#include "hxdir.h" /* for OS_SEPARATOR_CHAR and OS_SEPARATOR_STRING */
HXPreferredTransport::HXPreferredTransport(HXPreferredTransportManager* pOwner)
: m_lRefCount(0)
, m_pOwner(pOwner)
, m_bHTTPNG(FALSE)
, m_pHost(NULL)
, m_ulHost(0)
, m_ulParentPlaybacks(0)
, m_uPlaybacks(0)
, m_uCloakPort(0)
, m_state(PTS_UNKNOWN)
, m_lastUsedTime(0)
, m_prefTransportClass(PTC_UNKNOWN)
, m_prefTransportProtocol(PTP_UNKNOWN)
, m_prefTransportType(UnknownMode)
, m_pPrefTransportSinkList(NULL)
{
HX_ADDREF(m_pOwner);
}
HXPreferredTransport::~HXPreferredTransport()
{
Close();
}
STDMETHODIMP
HXPreferredTransport::QueryInterface(REFIID riid, void**ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IHXPreferredTransport), (IHXPreferredTransport*)this },
{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPreferredTransport*)this },
};
return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
HXPreferredTransport::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32)
HXPreferredTransport::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
/*
* IHXPreferredTransport methods
*/
STDMETHODIMP
HXPreferredTransport::GetTransport (REF(TransportMode) /* OUT */ prefTransportType,
REF(UINT16) /* OUT */ ulCloakPort)
{
HX_RESULT rc = HXR_OK;
prefTransportType = UnknownMode;
ulCloakPort = 0;
switch (m_state)
{
case PTS_CREATE:
m_state = PTS_PENDING;
prefTransportType = m_prefTransportType;
ulCloakPort = m_uCloakPort;
break;
case PTS_PENDING:
rc = HXR_WOULD_BLOCK;
break;
case PTS_READY:
prefTransportType = m_prefTransportType;
ulCloakPort = m_uCloakPort;
break;
default:
break;
}
return rc;
}
STDMETHODIMP
HXPreferredTransport::SetTransport(TransportMode /* IN */ prefTransportType,
UINT16 /* IN */ ulCloakPort)
{
HX_RESULT rc = HXR_OK;
BOOL bSave = FALSE;
UINT32 ulTransportMask = 0;
HX_ASSERT(UnknownMode != prefTransportType);
// we will mask UDP to Multicast if Multicast is selected given
// the fact the server will always try UDP along with Multicast request
if (UDPMode == prefTransportType && m_pOwner)
{
if (PTP_RTSP == m_prefTransportProtocol)
{
ulTransportMask = m_pOwner->m_ulRTSPTransportMask;
}
else
{
ulTransportMask = m_pOwner->m_ulPNMTransportMask;
}
if (ulTransportMask & ATTEMPT_MULTICAST)
{
prefTransportType = MulticastMode;
}
}
m_state = PTS_READY;
m_uCloakPort = ulCloakPort;
m_lastUsedTime = time(NULL);
if (m_prefTransportType != prefTransportType)
{
bSave = TRUE;
m_uPlaybacks = 0;
m_prefTransportType = prefTransportType;
}
if (m_pPrefTransportSinkList)
{
CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
for (; i != m_pPrefTransportSinkList->End(); ++i)
{
IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
pSink->TransportSucceeded(m_prefTransportType, m_uCloakPort);
}
}
if (m_pOwner)
{
m_pOwner->TransportSet(this, bSave);
}
return rc;
}
STDMETHODIMP
HXPreferredTransport::SwitchTransport(HX_RESULT /* IN */ error,
REF(TransportMode) /* INOUT */ prefTransportType)
{
if (m_pOwner)
{
return m_pOwner->DownShiftTransport(error, this, prefTransportType);
}
return HXR_FAILED;
}
STDMETHODIMP
HXPreferredTransport::RemoveTransport()
{
m_state = PTS_UNKNOWN;
m_uPlaybacks = 0;
m_uCloakPort = 0;
m_prefTransportType = UnknownMode;
m_lastUsedTime = 0;
if (m_pPrefTransportSinkList)
{
CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
for (; i != m_pPrefTransportSinkList->End(); ++i)
{
IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
pSink->TransportFailed();
}
}
return HXR_OK;
}
STDMETHODIMP_(BOOL)
HXPreferredTransport::ValidateTransport(TransportMode /* IN */ prefTransportType)
{
if (m_pOwner)
{
return m_pOwner->ValidateTransport(this, prefTransportType);
}
return FALSE;
}
STDMETHODIMP_(PreferredTransportState)
HXPreferredTransport::GetState()
{
return m_state;
}
STDMETHODIMP_(PreferredTransportClass)
HXPreferredTransport::GetClass()
{
return m_prefTransportClass;
}
STDMETHODIMP
HXPreferredTransport::AddTransportSink(IHXPreferredTransportSink* /* IN */ pPrefTransportSink)
{
LISTPOSITION lPosition = 0;
if (!pPrefTransportSink)
{
return HXR_FAILED;
}
if (!m_pPrefTransportSinkList)
{
m_pPrefTransportSinkList = new CHXSimpleList;
}
else
{
lPosition = m_pPrefTransportSinkList->Find(pPrefTransportSink);
}
if (!lPosition)
{
pPrefTransportSink->AddRef();
m_pPrefTransportSinkList->AddTail(pPrefTransportSink);
}
return HXR_OK;
}
STDMETHODIMP
HXPreferredTransport::RemoveTransportSink(IHXPreferredTransportSink* /* IN */ pPrefTransportSink)
{
if (!m_pPrefTransportSinkList)
{
return HXR_UNEXPECTED;
}
LISTPOSITION lPosition = m_pPrefTransportSinkList->Find(pPrefTransportSink);
if (!lPosition)
{
return HXR_UNEXPECTED;
}
m_pPrefTransportSinkList->RemoveAt(lPosition);
HX_RELEASE(pPrefTransportSink);
return HXR_OK;
}
STDMETHODIMP_(BOOL)
HXPreferredTransport::GetHTTPNG()
{
return m_bHTTPNG;
}
STDMETHODIMP
HXPreferredTransport::SetHTTPNG(BOOL bHTTPNG)
{
m_bHTTPNG = bHTTPNG;
return HXR_OK;
}
void
HXPreferredTransport::Initialize()
{
TransportMode upShiftToTransport = UnknownMode;
if (!m_pOwner)
{
return;
}
if (m_lastUsedTime && PTS_READY == m_state)
{
// detect whether the preferences has been changed
// since its last use
if (PTP_RTSP == m_prefTransportProtocol &&
m_lastUsedTime < m_pOwner->m_lastRTSPPreferencesModifiedTime)
{
m_state = PTS_CREATE;
m_uPlaybacks = 0;
m_prefTransportType = m_pOwner->m_rtspTransportTypeStartWith;
}
else if (PTP_PNM == m_prefTransportProtocol &&
m_lastUsedTime < m_pOwner->m_lastPNMPreferencesModifiedTime)
{
m_state = PTS_CREATE;
m_uPlaybacks = 0;
m_prefTransportType = m_pOwner->m_pnmTransportTypeStartWith;
}
else if (m_pOwner->m_ulPlaybacks != m_ulParentPlaybacks)
{
m_ulParentPlaybacks = m_pOwner->m_ulPlaybacks;
m_uPlaybacks++;
// save the playback counter for UpShift
if (PTP_RTSP == m_prefTransportProtocol &&
m_prefTransportType > m_pOwner->m_rtspTransportTypeStartWith)
{
m_pOwner->m_bSave = TRUE;
}
else if (PTP_PNM == m_prefTransportProtocol &&
m_prefTransportType > m_pOwner->m_pnmTransportTypeStartWith)
{
m_pOwner->m_bSave = TRUE;
}
// attempt transport upshift every 3rd play
m_uPlaybacks = m_uPlaybacks % 3;
if (0 == m_uPlaybacks)
{
upShiftToTransport = m_prefTransportType;
m_pOwner->UpShiftTransport(this, upShiftToTransport);
if (upShiftToTransport != m_prefTransportType)
{
m_state = PTS_CREATE;
m_prefTransportType = upShiftToTransport;
}
}
}
}
// this is the first use
else
{
if (PTS_CREATE == m_state)
{
m_uPlaybacks = 0;
m_prefTransportType = m_pOwner->GetTransportPreferred(this);
}
else
{
HX_ASSERT(PTS_PENDING == m_state);
m_prefTransportType = UnknownMode;
}
}
// sanity check
if (UnknownMode != m_prefTransportType)
{
if (PTP_RTSP == m_prefTransportProtocol)
{
HX_ASSERT(m_prefTransportType >= m_pOwner->m_rtspTransportTypeStartWith);
}
else if (PTP_PNM == m_prefTransportProtocol)
{
HX_ASSERT(m_prefTransportType >= m_pOwner->m_pnmTransportTypeStartWith);
}
}
return;
}
void
HXPreferredTransport::Close()
{
HX_DELETE(m_pHost);
if (m_pPrefTransportSinkList)
{
CHXSimpleList::Iterator i = m_pPrefTransportSinkList->Begin();
for (; i != m_pPrefTransportSinkList->End(); ++i)
{
IHXPreferredTransportSink* pSink = (IHXPreferredTransportSink*)*i;
HX_RELEASE(pSink);
}
HX_DELETE(m_pPrefTransportSinkList);
}
HX_RELEASE(m_pOwner);
}
HXPreferredTransportManager::HXPreferredTransportManager(IUnknown* pContext)
: m_lRefCount(0)
, m_bSave(FALSE)
, m_pszFile(NULL)
, m_ulRTSPTransportMask(ATTEMPT_AUTOTRANSPORT)
, m_ulPNMTransportMask(ATTEMPT_AUTOTRANSPORT)
, m_ulLocalHost(0)
, m_ulSubnetMask(0)
, m_ulSubnet(0)
, m_ulPlaybacks(0)
, m_lastRTSPPreferencesModifiedTime(0)
, m_lastPNMPreferencesModifiedTime(0)
, m_internalTransportType(MulticastMode)
, m_externalTransportType(MulticastMode)
, m_rtspTransportTypeStartWith(MulticastMode)
, m_pnmTransportTypeStartWith(MulticastMode)
, m_pPrefHostTransportList(NULL)
, m_pPrevPrefHostTransportList(NULL)
, m_pSubnetManager(NULL)
, m_pPreferences(NULL)
, m_pProxyManager(NULL)
, m_pHXNetInterface(NULL)
, m_bInitialized(FALSE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -