📄 rtspprotocol.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/stdio.h"
#include "hlxclib/stdlib.h"
#include "hxver.h"
#include "hxtypes.h"
#include "hxresult.h"
#include "hxstrutl.h"
#include "hxcomm.h"
#include "ihxpckts.h"
#include "hxfiles.h"
#include "hxengin.h"
#include "hxasm.h"
#include "hxsdesc.h"
#include "chxpckts.h"
#include "hxcore.h"
#include "hxprefs.h"
#include "hxpref.h"
#include "hxsdesc.h"
#include "hxpends.h"
#include "hxrsdbf.h"
#include "hxengin.h"
#include "hxstring.h"
#include "hxslist.h"
#include "hxstat.h"
#include "hxtick.h"
#include "chxeven.h"
#include "hxcleng.h"
//#include "rtmlpars.h"
#include "rtspclnt.h"
#include "rtspclntext.h"
#include "rtsputil.h"
#include "mimehead.h"
#include "rtspmsg.h"
#include "rtsppars.h"
#include "rtspmdsc.h"
#include "statinfo.h"
#include "hxntsrc.h"
#include "hxprotocol.h"
#include "hxauthn.h"
#include "hxplgns.h"
#include "hxauth.h"
#include "hxdate.h"
#include "hxurl.h"
#include "platform.h"
#include "clntcore.ver"
#include "hxplugn.h"
#include "dtrvtcon.h"
#include "rmfftype.h"
#include "rtspprotocol.h"
#include "hxcomsp.h"
#include "hxpktsp.h"
#include "hxplnsp.h"
#include "miscsp.h"
#include "hxxrsmg.h"
#include "hxresmgr.h"
#include "dcoreres.h"
#ifdef _MACINTOSH
#include "hxmm.h"
#endif
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
#define PRAGMA "initiate-session"
#define MINIMUM_STATS_INTERVAL 15000 // 15 seconds
#define MAX_DEFAULT_STATS_SIZE 512
#define MAX_TRANSPORT 10
RTSPProtocol::RTSPProtocol(HXNetSource* owner, ULONG32 ulPlatformSpecific)
: HXProtocol (owner, ulPlatformSpecific)
, m_lRefCount(0)
, m_uSecurityKey(0)
, m_uStreamCount(0)
, m_uCurrentStreamCount(0)
, m_pProtocolLib(0)
, m_pPendingStatus(0)
, m_pStatistics(0)
, m_bPlaying(FALSE)
, m_bIsASMSource(FALSE)
, m_bUseRTP(FALSE)
, m_bReceivedData(FALSE)
, m_bMulticastOnly(FALSE)
, m_idleState(NULL_STATE)
, m_pIDInfo(NULL)
, m_pRequest(NULL)
, m_bFirstAuthAttempt(TRUE)
, mReceivedControl(FALSE)
, m_bPendingSeek(FALSE)
, m_ulSeekPos1(0)
, m_ulSeekPos2(0)
, m_bHandleWWWAuthentication(FALSE)
, m_WWWResult(HXR_OK)
, m_pWWWValues(NULL)
#if defined(HELIX_FEATURE_REVERTER)
, m_pDataRevert(0)
#endif /* HELIX_FEATURE_REVERTER */
{
m_pStreamInfoList = new CHXMapLongToObj;
if (owner)
{
IHXPlayer* pPlayer = NULL;
IUnknown* pUnknown = NULL;
owner->GetPlayer(pPlayer);
if (pPlayer)
{
pUnknown = (IUnknown*)pPlayer;
}
// auto. config doesn't have the player object
// use IHXClientEngine instead
else
{
owner->GetContext(pUnknown);
}
#if defined(HELIX_FEATURE_REVERTER)
m_pDataRevert = new DataRevertController(pUnknown);
m_pDataRevert->AddRef();
m_pDataRevert->SetControlResponse(this);
#endif /* HELIX_FEATURE_REVERTER */
HX_RELEASE(pUnknown);
}
/* Always allowed in RTSP - till we add some code to file format
* plugins to set this value in file header - XXXRA
*/
m_bPerfectPlayAllowed = TRUE;
//
// get proxy info for RTSP protocol
//
initialize_members();
ReadPrefBOOL(m_pPreferences, "NonRS", m_bUseRTP);
if (!m_bUseRTP)
{
ReadPrefBOOL(m_pPreferences, "UseRTP", m_bUseRTP);
}
}
RTSPProtocol::~RTSPProtocol ()
{
if (m_pProtocolLib)
{
m_pProtocolLib->Done();
HX_RELEASE(m_pProtocolLib);
}
HX_RELEASE(m_pRequest);
HX_RELEASE(m_pPendingStatus);
HX_RELEASE(m_pStatistics);
HX_RELEASE(m_pIDInfo);
HX_RELEASE(m_pWWWValues);
#if defined(HELIX_FEATURE_REVERTER)
HX_RELEASE(m_pDataRevert);
#endif /* HELIX_FEATURE_REVERTER */
HX_DELETE(m_pStreamInfoList);
}
/* IUnknown methods */
STDMETHODIMP
RTSPProtocol::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
{ GET_IIDHANDLE(IID_IHXStatistics), (IHXStatistics*)this },
{ GET_IIDHANDLE(IID_IHXBackChannel), (IHXBackChannel*)this },
{ GET_IIDHANDLE(IID_IHXAtomicRuleChange), (IHXAtomicRuleChange*)this },
{ GET_IIDHANDLE(IID_IHXPreferredTransportSink), (IHXPreferredTransportSink*)this },
{ GET_IIDHANDLE(IID_IUnknown), this },
};
if (HXR_OK == ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj))
{
return HXR_OK;
}
else if (IsEqualIID(riid, IID_IHXASMSource) && m_bIsASMSource)
{
AddRef();
*ppvObj = (IHXASMSource*)this;
return HXR_OK;
}
else if (m_pProtocolLib &&
(HXR_OK == m_pProtocolLib->QueryInterface(riid, ppvObj)))
{
return HXR_OK;
}
*ppvObj = NULL;
return HXR_NOINTERFACE;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) RTSPProtocol::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) RTSPProtocol::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
/* IHXRTSPClientProtocolResponse methods */
STDMETHODIMP
RTSPProtocol::InitDone
(
HX_RESULT status
)
{
if (status != HXR_OK)
{
/*
* XXX...Need to get proper errors from protocol library
*/
mOwner->ReportError(status); //ConvertHResultToHXError(status));
}
if (m_pProtocolLib->HttpOnly())
{
mCurrentTransport = TCPMode;
}
return HXR_OK;
}
STDMETHODIMP
RTSPProtocol::HandleWWWAuthentication
(
HX_RESULT HX_RESULTStatus,
IHXValues* pIHXValuesHeaders
)
{
#if defined(HELIX_FEATURE_AUTHENTICATION)
#ifdef _MACINTOSH
/*
* We load a plugin for authetication. Can't do this at interrupt
* time on Mac
*/
if (HXMM_ATINTERRUPT())
{
m_bHandleWWWAuthentication = TRUE;
m_WWWResult = HX_RESULTStatus;
HX_RELEASE(m_pWWWValues);
m_pWWWValues = pIHXValuesHeaders;
if (m_pWWWValues)
{
m_pWWWValues->AddRef();
}
if (mOwner)
{
mOwner->ScheduleProcessCallback();
}
return HXR_OK;
}
#endif
return (handlePendingWWWAuthentication(HX_RESULTStatus, pIHXValuesHeaders));
#else
return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_AUTHENTICATION */
}
#if defined(HELIX_FEATURE_AUTHENTICATION)
// IHXClientAuthResponse
STDMETHODIMP
RTSPProtocol::ResponseReady
(
HX_RESULT HX_RESULTStatus,
IHXRequest* pIHXRequestResponse
)
{
HX_RESULT HX_RESULTErr;
IHXValues* pIHXValuesRequestHeaders = NULL;
if(SUCCEEDED(HX_RESULTStatus))
{
if (!m_pProtocolLib)
{
return HXR_OUTOFMEMORY;
}
pIHXRequestResponse->GetRequestHeaders
(
pIHXValuesRequestHeaders
);
if(!m_uStreamCount)
{
// We haven't received a successful Describe..
//
CHXHeader::mergeHeaders
(
pIHXValuesRequestHeaders,
m_spIHXValuesStoredHeaders
);
HX_RESULTErr = m_pProtocolLib->SendStreamDescriptionRequest
(
mPath,
pIHXValuesRequestHeaders
);
}
else if (m_uCurrentStreamCount == m_uStreamCount)
{
// We haven't received a successful Setup..
//
HX_RESULTErr = m_pProtocolLib->SendSetupRequest
(
NULL,
0,
pIHXValuesRequestHeaders
);
}
HX_RELEASE(pIHXValuesRequestHeaders);
}
else
{
if (HXR_FAIL == HX_RESULTStatus)
{
HX_RESULTStatus = HXR_NOT_AUTHORIZED;
}
mOwner->ReportError(HX_RESULTStatus);
}
return HXR_OK;
}
HX_RESULT
RTSPProtocol::handlePendingWWWAuthentication
(
HX_RESULT HX_RESULTStatus,
IHXValues* pIHXValuesHeaders
)
{
HX_RESULT HX_RESULTRet = HXR_FAIL;
if(HXR_NOT_AUTHORIZED == HX_RESULTStatus)
{
IUnknown* pIUnknownContext = NULL;
IHXPlayer* pIHXPlayerPlayer = NULL;
IHXAuthenticationManager* pIHXAuthenticationManager = NULL;
// Don't transport switch while we are waiting for authentication
mOwner->StopDataWait();
if
(
m_spIHXClientAuthConversationAuthenticator.IsValid()
&&
m_spIHXClientAuthConversationAuthenticator->IsDone()
)
{
// Well we tried to authenticate already,
// so it must have failed
m_spIHXClientAuthConversationAuthenticator->Authenticated(FALSE);
// Cleanup so that we can re-auth
m_spIHXClientAuthConversationAuthenticator.Release();
}
mOwner->GetPlayer(pIHXPlayerPlayer);
if (NULL == pIHXPlayerPlayer)
{
// in case of the Auto. Config
mOwner->GetContext(pIUnknownContext);
}
else
{
pIUnknownContext = (IUnknown*)pIHXPlayerPlayer;
}
if (!m_spIHXClientAuthConversationAuthenticator.IsValid())
{
DECLARE_SMART_POINTER_UNKNOWN spIUnknownAuthenticator;
DECLARE_SMART_POINTER
(
IHXObjectConfiguration
) spIHXObjectConfigurationAuthenticator;
DECLARE_SMART_POINTER
(
IHXCommonClassFactory
) spIHXCommonClassFactoryHXCore;
spIHXCommonClassFactoryHXCore = pIUnknownContext;
// Starting conversation
HX_RESULTRet = spIHXCommonClassFactoryHXCore->CreateInstance
(
CLSID_CHXClientAuthenticator,
(void**)&spIUnknownAuthenticator
);
if
(
SUCCEEDED(HX_RESULTRet)
&&
spIUnknownAuthenticator.IsValid()
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -