📄 rtspclnt.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: rtspclnt.cpp,v 1.63.2.9 2004/12/01 23:56:37 bobclark Exp $ * * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (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. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * 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_FILEstatic 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 secondsconst 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);}voidRTSPTransportInfo::addStreamNumber(UINT16 streamNumber){ m_streamNumberList.AddTail((void*)streamNumber);}BOOLRTSPTransportInfo::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_RESULTRTSPTransportRequest::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 initializationsRTSPClientSessionManagerType RTSPClientSessionManager::zm_pSessionManager = 0;/* * RTSPClientProtocol methods *//* * IUnknown methods */STDMETHODIMPRTSPClientProtocol::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 }, { GET_IIDHANDLE(IID_IHXTransportBufferLimit), (IHXTransportBufferLimit*) 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_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 */voidRTSPClientProtocol::SetSplitterConsumer(BOOL b){ m_bSplitterConsumer = b;}STDMETHODIMPRTSPClientProtocol::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_RESULTRTSPClientProtocol::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* pHostBuffer = 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, (void**) &m_pInterruptState);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -