rtspclnt.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,603 行 · 第 1/5 页

CPP
2,603
字号
/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: rtspclnt.cpp,v 1.63.2.8.2.1 2004/12/13 23:10:25 gwright 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_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 },
	{ 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
 */

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*      pHostBuffer = NULL;
    IHXBuffer*      pSrcBuffer = NULL;
    IHXValues*      pURLProps = NULL;
    CHXURL*         pURL = NULL;

    if (!m_pContext)
    {
	m_pContext = pContext;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?