📄 rtspclnt.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"
#if defined _UNIX
#if defined _SOLARIS || defined _IRIX || defined _FREEBSD || defined _OPENBSD || defined _NETBSD
#include <sys/types.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef _BEOS
#include <arpa/inet.h>
#endif
#endif
#include <stdlib.h>
#include "hxtypes.h"
#include "timeval.h"
#include "hxstring.h"
#include "hxslist.h"
#include "hxmarsh.h"
#include "hxtick.h"
#include "netbyte.h"
#include "hxengin.h"
#include "hxcore.h"
#include "hxpnets.h"
#include "ihxpckts.h"
#include "hxcomm.h"
#include "hxprefs.h"
#include "hxpref.h"
#include "hxplugn.h"
#include "hxencod.h"
#include "hxrsdbf.h"
#include "plghand2.h"
#ifdef HELIX_FEATURE_SERVER
#include "plgnhand.h"
#endif
#include "hxplugn.h"
#include "hxsdesc.h"
#include "netbyte.h"
#include "chxpckts.h"
#include "asmrulep.h"
#include "growingq.h"
#include "mimehead.h"
#include "mimescan.h"
#include "timerep.h"
#include "hxthread.h"
#include "rtspmsg.h"
#include "rtsppars.h"
#include "rtspmdsc.h"
#include "basepkt.h"
#include "servrsnd.h"
#include "portaddr.h"
#include "chxkeepalive.h"
#include "rtspclnt.h"
#include "rtsputil.h"
#include "sdptools.h"
#include "hxurl.h"
#include "hxstrutl.h"
#include "trmimemp.h"
#include "rtptypes.h"
#include "stream_desc_hlpr.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define RN_COMMON_MIME_TYPE_FRAGMENT "x-pn-"
#ifndef BUFFER_DEPTH_UNDEFINED
#define BUFFER_DEPTH_UNDEFINED 0xffffffff
#endif
#define MULTICAST_ADDRESS_RANGE_LOW 3758096384 // 224.0.0.0
#define MULTICAST_ADDRESS_RANGE_HIGH 4026531839 // 239.255.255.255
#define DEFAULT_SERVER_TIMEOUT 90 // in seconds
#define MINIMUM_TIMEOUT 5 // in seconds
const RTSPTableEntry RTSPClientProtocol::zm_pRTSPTable[RTSP_TABLE_SIZE] =
{
{ "SETUP", SETUP },
{ "REDIRECT", REDIRECT },
{ "PLAY", PLAY },
{ "PAUSE", PAUSE },
{ "SET_PARAMETER", SET_PARAM },
{ "GET_PARAMETER", GET_PARAM },
{ "OPTIONS", OPTIONS },
{ "DESCRIBE", DESCRIBE },
{ "TEARDOWN", TEARDOWN },
{ "RECORD", RECORD },
{ "ANNOUNCE", ANNOUNCE }
};
/*
* RTSPTransportInfo methods
*/
RTSPTransportInfo::RTSPTransportInfo():
m_pTransport(0),
m_pRTCPTransport(0)
{
}
RTSPTransportInfo::~RTSPTransportInfo()
{
if(m_pTransport)
{
m_pTransport->Done();
}
if(m_pRTCPTransport)
{
m_pRTCPTransport->Done();
}
HX_RELEASE(m_pTransport);
HX_RELEASE(m_pRTCPTransport);
}
void
RTSPTransportInfo::addStreamNumber(UINT16 streamNumber)
{
m_streamNumberList.AddTail((void*)streamNumber);
}
BOOL
RTSPTransportInfo::containsStreamNumber(UINT16 streamNumber)
{
CHXSimpleList::Iterator i;
for(i=m_streamNumberList.Begin();i!=m_streamNumberList.End();++i)
{
UINT16 sNumber = (UINT16)(PTR_INT)(*i);
if(sNumber == streamNumber)
{
return TRUE;
}
}
return FALSE;
}
/*
* RTSPTransportRequest methods
*/
RTSPTransportRequest::RTSPTransportRequest(RTSPTransportTypeEnum tType,
UINT16 sPort):
m_lTransportType(tType),
m_sPort(sPort),
m_bDelete(FALSE)
{
}
RTSPTransportRequest::~RTSPTransportRequest()
{
CHXSimpleList::Iterator i;
for(i=m_transportInfoList.Begin();i!=m_transportInfoList.End();++i)
{
RTSPTransportInfo* pInfo = (RTSPTransportInfo*)(*i);
delete pInfo;
}
}
RTSPTransportInfo*
RTSPTransportRequest::getTransportInfo(UINT16 streamNumber)
{
CHXSimpleList::Iterator i;
for(i=m_transportInfoList.Begin();i!=m_transportInfoList.End();++i)
{
RTSPTransportInfo* pInfo = (RTSPTransportInfo*)(*i);
if(pInfo->containsStreamNumber(streamNumber))
{
return pInfo;
}
}
return 0;
}
RTSPTransportInfo*
RTSPTransportRequest::getFirstTransportInfo()
{
m_lListPos = m_transportInfoList.GetHeadPosition();
if(m_lListPos)
{
return (RTSPTransportInfo*)m_transportInfoList.GetNext(m_lListPos);
}
return 0;
}
RTSPTransportInfo*
RTSPTransportRequest::getNextTransportInfo()
{
if(m_lListPos)
{
return (RTSPTransportInfo*)m_transportInfoList.GetNext(m_lListPos);
}
return 0;
}
HX_RESULT
RTSPTransportRequest::addTransportInfo(RTSPTransport* pTrans,
RTCPBaseTransport* pRTCPTrans, UINT16 streamNumber, UINT16 sPort)
{
HX_RESULT retVal = HXR_OK;
RTSPTransportInfo* pTransInfo = new RTSPTransportInfo;
if(pTransInfo)
{
pTransInfo->m_pTransport = pTrans; // already AddRef'd
pTransInfo->m_pRTCPTransport = pRTCPTrans;
pTransInfo->addStreamNumber(streamNumber);
pTransInfo->m_sPort = sPort;
LISTPOSITION listRet = m_transportInfoList.AddTail(pTransInfo);
if( listRet == NULL )
{
HX_DELETE(pTransInfo);
retVal = HXR_OUTOFMEMORY;
}
}
else
{
retVal = HXR_OUTOFMEMORY;
}
return retVal;
}
// static initializations
RTSPClientSessionManagerType RTSPClientSessionManager::zm_pSessionManager = 0;
/*
* RTSPClientProtocol methods
*/
/*
* IUnknown methods
*/
STDMETHODIMP
RTSPClientProtocol::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IUnknown), this },
{ GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*) this },
{ GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*) this },
{ GET_IIDHANDLE(IID_IHXResolverResponse), (IHXResolverResponse*) this },
{ GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
{ GET_IIDHANDLE(IID_IHXResendBufferControl), (IHXResendBufferControl*) this },
{ GET_IIDHANDLE(IID_IHXThinnableSource), (IHXThinnableSource*) this },
{ GET_IIDHANDLE(IID_IHXTransportSyncServer), (IHXTransportSyncServer*) this },
};
if(QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj) == HXR_OK)
{
return HXR_OK;
}
else if (m_pTransportStreamMap &&
!m_pTransportStreamMap->IsEmpty() &&
((void *)((*m_pTransportStreamMap)[0])) &&
(HXR_OK == ((RTSPTransport*)(*m_pTransportStreamMap)[0])->
QueryInterface(riid, ppvObj)))
{
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
STDMETHODIMP_(UINT32)
RTSPClientProtocol::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(UINT32)
RTSPClientProtocol::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
/*
* RTSPClientProtocol methods
*/
RTSPClientProtocol::RTSPClientProtocol():
m_foreignPort(0),
m_pTransportStreamMap(0),
m_pTransportPortMap(0),
m_pTransportMPortMap(0),
m_pTransportChannelMap(0),
m_pControlToStreamNoMap(0),
m_foreignAddr(0),
m_ulConnectToAddr(0),
m_lRefCount(0),
m_pResp(0),
m_pFileHeader(0),
m_bSetupRecord(FALSE),
m_setupResponseCount(0),
m_pSessionHeaders(0),
m_pResponseHeaders(0),
m_pCloakValues(NULL),
m_pSession(0),
m_pRegistry(0),
m_bClientDone(FALSE),
m_bMessageDebug(FALSE),
m_bUseProxy(FALSE),
m_bHTTPOnly(FALSE),
m_pUDPSocketStreamMap(0),
m_pRTCPSocketStreamMap(0),
m_pResolver(0),
m_bSeqValueReceived(FALSE),
m_bNoReuseConnection(FALSE),
m_bLoadTest(FALSE),
m_bEntityRequired(TRUE),
m_pMutex(NULL),
m_uProtocolType(0),
m_pConnectionlessControl(0),
m_bConnectionlessControl(FALSE),
m_pConnectionCheckCallback(0),
m_uConnectionCheckCallbackHandle(0),
m_bConnectionAlive(FALSE),
m_uConnectionTimeout(DEFAULT_CONN_TIMEOUT),
m_ulBufferDepth(BUFFER_DEPTH_UNDEFINED),
m_pInterruptState(NULL),
m_pScheduler(NULL),
m_bUseHTTPProxy(FALSE),
m_bKeepLiveResponsed(TRUE),
m_bSplitterConsumer(FALSE),
m_pPacketFilter(NULL),
// workaround...
m_bNonRSRTP(FALSE),
m_pSetupRequestHeader(NULL),
m_bPlayJustSent(FALSE),
m_bIPTV(FALSE),
m_bColumbia(FALSE),
m_bNoKeepAlive(FALSE),
m_bForceUCaseTransportMimeType(FALSE),
m_bPrefetch(FALSE),
m_bFastStart(FALSE),
m_pCloakPorts(NULL),
m_nCloakPorts(0),
m_currentTransport(TCPMode),
m_bReportedSuccessfulTransport(FALSE),
m_bSDPInitiated(FALSE),
m_bMulticast(FALSE),
m_ulMulticastAddress(0),
m_pSDPFileHeader(NULL),
m_pSDPStreamHeaders(NULL),
m_bSessionSucceeded(FALSE),
m_bHasSyncMasterStream(FALSE),
m_pNetworkServices(NULL),
m_pPreferences(NULL),
m_pSessionTimeout(NULL),
m_pTimeoutCallback(NULL),
m_bUseLegacyTimeOutMsg(TRUE),
m_bKeepAlivePending(FALSE),
m_bPaused(FALSE),
m_ulServerTimeOut(DEFAULT_SERVER_TIMEOUT),
m_ulCurrentTimeOut(0),
m_pUAProfURI(NULL),
m_pUAProfDiff(NULL)
#if defined(_MACINTOSH)
, m_pCallback(NULL)
#endif /* _MACINTOSH */
{
/*
* Byte queue must be as large as possible because messages may be
* bigger than MAX_RTSP_MSG
*/
m_state = RTSPClientProtocol::INIT;
// all methods supported...
memset(m_pIsMethodSupported, 1, sizeof(BOOL) * RTSP_TABLE_SIZE);
#ifdef THREADS_SUPPORTED
HXMutex::MakeMutex(m_pMutex);
#else
HXMutex::MakeStubMutex(m_pMutex);
#endif
}
RTSPClientProtocol::~RTSPClientProtocol()
{
clearStreamInfoList();
clearTransportRequestList();
clearUDPResponseHelperList();
reset();
HX_DELETE(m_pMutex);
HX_RELEASE(m_pUAProfDiff);
HX_RELEASE(m_pUAProfURI);
HX_RELEASE(m_pPreferences);
HX_RELEASE(m_pNetworkServices);
HX_RELEASE(m_pRegistry);
HX_RELEASE(m_pFileHeader);
HX_RELEASE(m_pSessionHeaders);
HX_RELEASE(m_pResponseHeaders);
HX_RELEASE(m_pCloakValues);
HX_RELEASE(m_pInterruptState);
HX_RELEASE(m_pScheduler);
}
/*
* IHXRTSPClientProtocol methods
*/
void
RTSPClientProtocol::SetSplitterConsumer(BOOL b)
{
m_bSplitterConsumer = b;
}
STDMETHODIMP
RTSPClientProtocol::Init(IUnknown* pContext,
const char* pHostName,
UINT16 foreignPort,
IHXRTSPClientProtocolResponse* pClient,
UINT32 initializationType,
IHXValues* pSessionHeaders,
IHXValues* pInfo,
BOOL bHTTPCloak,
UINT16 uCloakPort,
BOOL bNoReuseConnection)
{
m_pSessionManager = RTSPClientSessionManager::instance();
return InitExt(pContext,
pHostName,
foreignPort,
pClient,
initializationType,
pSessionHeaders,
pInfo,
bHTTPCloak,
uCloakPort,
bNoReuseConnection);
}
HX_RESULT
RTSPClientProtocol::InitExt(IUnknown* pContext,
const char* pHostName,
UINT16 foreignPort,
IHXRTSPClientProtocolResponse* pClient,
UINT32 initializationType,
IHXValues* pSessionHeaders,
IHXValues* pInfo,
BOOL bHTTPCloak,
UINT16 uCloakPort,
BOOL bNoReuseConnection)
{
HX_RESULT hresult = HXR_OK;
IUnknown* pUnknown = NULL;
IHXResolver* pResolver = NULL;
IHXBuffer* pBuffer = NULL;
IHXBuffer* pSrcBuffer = NULL;
IHXValues* pURLProps = NULL;
CHXURL* pURL = NULL;
if (!m_pContext)
{
m_pContext = pContext;
m_pContext->AddRef();
}
if (!m_pResp)
{
m_pResp = pClient;
m_pResp->AddRef();
}
HX_RELEASE(m_pCommonClassFactory);
hresult = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**) &m_pCommonClassFactory);
if (HXR_OK != hresult)
{
goto cleanup;
}
HX_RELEASE(m_pInterruptState);
hresult = m_pContext->QueryInterface(IID_IHXInterruptState,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -