rtspclnt.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:217k
- /* ***** 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,
- (void**) &m_pInterruptState);
- if (HXR_OK != m_pContext->QueryInterface(IID_IHXNetworkServices, (void**)&m_pNetworkServices) ||
- HXR_OK != m_pContext->QueryInterface(IID_IHXPreferences, (void**)&m_pPreferences))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- if (NULL == pHostName &&
- NULL != pInfo &&
- HXR_OK == pInfo->GetPropertyCString("helix-sdp", pSrcBuffer))
- {
- m_bSDPInitiated = TRUE;
- if (HXR_OK != ParseSDP("application/sdp", pSrcBuffer))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- if (!m_sessionHost.IsEmpty())
- {
- UINT32 addr = HXinet_addr((const char*)m_sessionHost);
- UINT32 ulHostAddr = DwToHost(addr);
- if (ulHostAddr >= MULTICAST_ADDRESS_RANGE_LOW &&
- ulHostAddr <= MULTICAST_ADDRESS_RANGE_HIGH)
- {
- m_bMulticast = TRUE;
- m_ulMulticastAddress = ulHostAddr;
- pHostName = (const char*)m_sessionHost;
- pInfo->SetPropertyULONG32("MulticastOnly", 1);
- m_pSDPFileHeader->SetPropertyULONG32("LiveStream", 1);
- }
- }
- if (!m_bMulticast)
- {
- pURL = new CHXURL(m_headerControl);
- if (!(pURLProps = pURL->GetProperties()))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- pURLProps->GetPropertyULONG32(PROPERTY_PORT, (UINT32&)foreignPort);
- if (HXR_OK != pURLProps->GetPropertyBuffer(PROPERTY_HOST, pBuffer))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- pHostName = (char*)pBuffer->GetBuffer();
- }
- HX_RELEASE(pBuffer);
- }
- ReadPrefINT32(m_pPreferences, "ConnectionTimeOut", m_uConnectionTimeout);
- ReadPrefINT32(m_pPreferences, "ServerTimeOut", m_ulServerTimeOut);
- if (m_ulServerTimeOut < MINIMUM_TIMEOUT)
- {
- m_ulServerTimeOut = MINIMUM_TIMEOUT;
- }
- m_ulServerTimeOut *= MILLISECS_PER_SECOND;
- if (bHTTPCloak && m_bUseProxy)
- {
- m_bUseHTTPProxy = TRUE;
- }
- ReadPrefBOOL(m_pPreferences, "RTSPMessageDebug", m_bMessageDebug);
- if (m_bMessageDebug)
- {
- if (HXR_OK == m_pPreferences->ReadPref("RTSPMessageDebugFile", pBuffer))
- {
- if (pBuffer->GetSize() <= 0)
- {
- // no file name, no log
- m_bMessageDebug = FALSE;
- }
- else
- {
- m_messageDebugFileName = (const char*)pBuffer->GetBuffer();
- }
- }
- HX_RELEASE(pBuffer);
- }
- // XXXGo - Interop workaround
- ReadPrefBOOL(m_pPreferences, "NonRS", m_bNonRSRTP);
- if (m_bNonRSRTP)
- {
- m_pIsMethodSupported[SET_PARAM] = FALSE;
- m_pIsMethodSupported[GET_PARAM] = FALSE;
- m_pIsMethodSupported[RECORD] = FALSE;
- m_pIsMethodSupported[ANNOUNCE] = FALSE;
- }
- ReadPrefBOOL(m_pPreferences, "RTSPNoReuseConnection", bNoReuseConnection);
- ReadPrefBOOL(m_pPreferences, "LoadTest", m_bLoadTest);
- if (!m_pTransportStreamMap)
- {
- m_pTransportStreamMap = new CHXMapLongToObj;
- if(!m_pTransportStreamMap)
- {
- hresult = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- }
- if (!m_pTransportPortMap)
- {
- m_pTransportPortMap = new CHXMapLongToObj;
- if(!m_pTransportPortMap)
- {
- hresult = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- }
- if (!m_pTransportMPortMap)
- {
- m_pTransportMPortMap = new CHXMapLongToObj;
- if(!m_pTransportMPortMap)
- {
- hresult = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- }
- m_hostName = pHostName;
- m_foreignPort = foreignPort;
- m_bHTTPOnly = bHTTPCloak;
- m_uCloakPort = uCloakPort;
- m_bNoReuseConnection = bNoReuseConnection;
- if (m_bHTTPOnly)
- {
- m_currentTransport = HTTPCloakMode;
- }
- if(pSessionHeaders && !m_pSessionHeaders)
- {
- m_pSessionHeaders = pSessionHeaders;
- m_pSessionHeaders->AddRef();
- }
- HX_RELEASE(m_pResponseHeaders);
- if (HXR_OK != m_pCommonClassFactory->CreateInstance(CLSID_IHXKeyValueList, (void**)&pUnknown))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- if (HXR_OK != pUnknown->QueryInterface(IID_IHXKeyValueList, (void**)&m_pResponseHeaders))
- {
- hresult = HXR_FAILED;
- goto cleanup;
- }
- if(!m_pRegistry)
- {
- #if defined(HELIX_FEATURE_REGISTRY)
- // get registry ptr
- IHXRegistry* pRegistry = 0;
- hresult = m_pContext->QueryInterface(IID_IHXRegistry,
- (void**)&pRegistry);
- HX_VERIFY(HXR_OK == hresult);
- if(hresult == HXR_OK)
- {
- m_pRegistry = pRegistry;
- }
- #endif /* HELIX_FEATURE_REGISTRY */
- }
- if(!m_pResolver)
- {
- m_pNetworkServices->CreateResolver(&pResolver);
- if(!pResolver)
- {
- hresult = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- HX_RELEASE(m_pResolver);
- m_pResolver = pResolver;
- m_pResolver->Init(this);
- CHXString pHost;
- if (m_bUseHTTPProxy || m_bUseProxy)
- {
- pHost = m_proxyHost;
- }
- else
- {
- pHost = m_hostName;
- }
- if(IsNumericAddr(pHost, pHost.GetLength()))
- {
- UINT32 addr = HXinet_addr((const char*)pHost);
- UINT32 ulHostAddr = DwToHost(addr);
- hresult = GetHostByNameDone(HXR_OK, ulHostAddr);
- }
- else
- {
- hresult = m_pResolver->GetHostByName(pHost);
- }
- }
- HX_RELEASE(m_pScheduler);
- if (HXR_OK != m_pContext->QueryInterface(IID_IHXScheduler,
- (void**)&m_pScheduler))
- {
- hresult = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- // check for UAProf headers
- if (m_pPreferences)
- {
- HX_RELEASE(m_pUAProfURI);
- HX_RELEASE(m_pUAProfDiff);
- m_pPreferences->ReadPref("XWapProfileURI", m_pUAProfURI);
- m_pPreferences->ReadPref("XWapProfileDiff", m_pUAProfDiff);
- }
- #if defined(_MACINTOSH)
- if (m_pCallback &&
- m_pCallback->m_bIsCallbackPending &&
- m_pScheduler)
- {
- m_pCallback->m_bIsCallbackPending = FALSE;
- m_pScheduler->Remove(m_pCallback->m_Handle);
- }
- #endif /* _MACINTOSH */
- cleanup:
- HX_RELEASE(pSrcBuffer);
- HX_RELEASE(pURLProps);
- HX_RELEASE(pUnknown);
- HX_DELETE(pURL);
- return hresult;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetProxy(const char* pProxyHost, UINT16 uProxyPort)
- {
- m_bUseProxy = TRUE;
- m_proxyHost = pProxyHost;
- m_proxyPort = uProxyPort;
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetResponse(IHXRTSPClientProtocolResponse* pResp)
- {
- HX_RELEASE(m_pResp);
- m_pResp = pResp;
- m_pResp->AddRef();
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetBuildVersion(const char* pVersionString)
- {
- m_versionString = pVersionString;
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::Done()
- {
- m_bClientDone = TRUE;
- if (m_pMutex)
- {
- m_pMutex->Lock();
- }
- #if defined(_MACINTOSH)
- if (m_pCallback &&
- m_pCallback->m_bIsCallbackPending &&
- m_pScheduler)
- {
- m_pCallback->m_bIsCallbackPending = FALSE;
- m_pScheduler->Remove(m_pCallback->m_Handle);
- }
- HX_RELEASE(m_pCallback);
- #endif /* _MACINTOSH */
- while (!m_sessionList.IsEmpty())
- {
- RTSPClientSession* pTempSession = (RTSPClientSession*)m_sessionList.RemoveHead();
- m_pSessionManager->removeFromSession(this, pTempSession);
- }
- HX_ASSERT(m_pSessionManager && m_pSessionManager->isValid());
- if (m_pSession)
- {
- m_pSessionManager->removeFromSession(this, m_pSession);
- m_pSession = NULL;
- }
- HX_RELEASE(m_pSessionManager);
- clearSocketStreamMap(m_pUDPSocketStreamMap);
- clearSocketStreamMap(m_pRTCPSocketStreamMap);
- reset();
- if (m_pMutex)
- {
- m_pMutex->Unlock();
- }
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendStreamDescriptionRequest(const char* pURL,
- IHXValues* pRequestHeaders)
- {
- #ifdef _MACINTOSH
- if (m_pInterruptState && m_pInterruptState->AtInterruptTime())
- {
- /*
- * We cannot load DLLs (Stream Desc Plugins) at deferred time.
- * Also, encodeURL calls HXIsLeadByte->CharType->...internally
- * calls GetPort. Mac does not like that either at deferred time.
- * Schedule a callback and do this operation at system time
- */
- if (!m_pCallback)
- {
- m_pCallback = new RTSPClientProtocolCallback(this);
- if(!m_pCallback)
- {
- return HXR_OUTOFMEMORY;
- }
- m_pCallback->AddRef();
- }
- HX_ASSERT(m_pScheduler);
- if (!m_pCallback->m_bIsCallbackPending)
- {
- m_pCallback->m_bIsCallbackPending = TRUE;
- m_pCallback->m_Handle =
- m_pScheduler->RelativeEnter(m_pCallback, 0);
- }
- /*
- * If we receive a SendStreamDescriptionRequest when
- * one is already pending, we do not queue them up.
- * The last one wins
- */
- m_pCallback->m_PendingDescURL = pURL;
- HX_RELEASE(m_pCallback->m_pPendingRequestHeaders);
- m_pCallback->m_pPendingRequestHeaders = pRequestHeaders;
- m_pCallback->m_pPendingRequestHeaders->AddRef();
- return HXR_OK;
- }
- HX_ASSERT(m_pScheduler);
- /* remove any previously scheduled callback */
- if (m_pCallback &&
- m_pCallback->m_bIsCallbackPending)
- {
- m_pCallback->m_bIsCallbackPending = FALSE;
- m_pScheduler->Remove(m_pCallback->m_Handle);
- }
- #endif
- return sendPendingStreamDescription(pURL, pRequestHeaders);
- }
- HX_RESULT
- RTSPClientProtocol::sendPendingStreamDescription(const char* pURL,
- IHXValues* pRequestHeaders)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- if (HXR_OUTOFMEMORY == extractExistingAuthorizationInformation(pRequestHeaders))
- {
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- RTSPDescribeMessage* pMsg = new RTSPDescribeMessage;
- if(!pMsg)
- {
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- CHXString encodedURL;
- CHXURL::encodeURL(pURL, encodedURL);
- UINT32 stringSize = 7 + m_hostName.GetLength() + 1 + 5 + 1 + encodedURL.GetLength() + 1;
- char* pURLBuffer = new char[ stringSize ];
- if(!pURLBuffer)
- {
- HX_DELETE(pMsg);
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- SafeSprintf( pURLBuffer, stringSize, "rtsp://%s:%u/%s", (const char*)m_hostName, m_foreignPort, (const char*)encodedURL ); /* Flawfinder: ignore */
- m_url = pURLBuffer;
- delete [] pURLBuffer;
- pMsg->setURL(m_url);
- IHXValues* pValuesRequestHeaders = NULL;
- pValuesRequestHeaders = new CHXHeader();
- if(!pValuesRequestHeaders)
- {
- HX_DELETE(pMsg);
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- pValuesRequestHeaders->AddRef();
- if (m_bEntityRequired)
- {
- CHXString CHXStringRequireValue
- (
- RTSPClientProtocol::RTSPRequireOptionsTable
- [
- RTSPClientProtocol::RTSP_REQUIRE_ENTITY
- ].pcharOption
- );
- IHXBuffer* pBufferRequireValue = NULL;
- CHXBuffer::FromCharArray
- (
- CHXStringRequireValue.GetBuffer(0),
- &pBufferRequireValue
- );
- // Set require header
- pValuesRequestHeaders->SetPropertyCString
- (
- "Require",
- pBufferRequireValue
- );
- HX_RELEASE(pBufferRequireValue);
- }
- addUAProfHeaders(pValuesRequestHeaders);
- CHXHeader::mergeHeaders
- (
- pValuesRequestHeaders,
- pRequestHeaders
- );
- // get all StreamDescription plugin mime types
- CHXString mimeTypes;
- IHXCommonClassFactory* pClassFactory = NULL;
- IHXPluginGroupEnumerator* pPluginGroupEnum = NULL;
- // ok we are going to get an IRMA PluginGroupEnumerator from the core.
- if
- (
- SUCCEEDED
- (
- m_pContext->QueryInterface
- (
- IID_IHXCommonClassFactory,
- (void**) &pClassFactory
- )
- )
- )
- {
- pClassFactory->CreateInstance
- (
- CLSID_IHXPluginGroupEnumerator,
- (void**)&pPluginGroupEnum
- );
- HX_RELEASE(pClassFactory);
- }
- if(pPluginGroupEnum &&
- (HXR_OK == pPluginGroupEnum->Init(IID_IHXStreamDescription)))
- {
- IUnknown* pUnknown = NULL;
- ULONG32 ulNumPlugins = pPluginGroupEnum->GetNumOfPlugins();
- for(ULONG32 i=0;i<ulNumPlugins;++i)
- {
- if (SUCCEEDED(pPluginGroupEnum->GetPlugin(i, pUnknown)))
- {
- GetStreamDescriptionInfo(pUnknown, mimeTypes);
- HX_RELEASE(pUnknown);
- }
- }
- }
- else
- {
- // if we don't have a CCF or we don't have a pluginGroupEnumerator
- // then we will have to use a plugin Enumerator.
- IHXPluginEnumerator* pPluginEnumerator = NULL;
- m_pContext->QueryInterface
- (
- IID_IHXPluginEnumerator,
- (void**)&pPluginEnumerator
- );
- if(pPluginEnumerator)
- {
- IUnknown* pUnknown = NULL;
- ULONG32 ulNumPlugins = pPluginEnumerator->GetNumOfPlugins();
- for(ULONG32 i=0;i<ulNumPlugins;++i)
- {
- if(SUCCEEDED(pPluginEnumerator->GetPlugin(i, pUnknown)))
- {
- GetStreamDescriptionInfo(pUnknown, mimeTypes);
- HX_RELEASE(pUnknown);
- }
- }
- pPluginEnumerator->Release();
- }
- }
- HX_RELEASE(pPluginGroupEnum);
- pMsg->addHeader("Accept", (const char*)mimeTypes);
- AddCommonHeaderToMsg(pMsg);
- addRFC822Headers(pMsg, pValuesRequestHeaders);
- appendAuthorizationHeaders(pMsg);
- HX_RELEASE(pValuesRequestHeaders);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendStreamRecordDescriptionRequest(
- const char* pURL,
- IHXValues* pFileHeader,
- CHXSimpleList* pStreams,
- IHXValues* pRequestHeaders)
- {
- HX_RESULT rc = HXR_OK;
- IHXBuffer* pDescription = 0;
- if (!m_pIsMethodSupported[ANNOUNCE])
- {
- return HXR_OK;
- }
- // Let's make sure we have enough mem before we do the mutex lock.
- RTSPAnnounceMessage* pMsg = new RTSPAnnounceMessage;
- if(!pMsg)
- {
- return HXR_OUTOFMEMORY;
- }
- m_pMutex->Lock();
- pMsg->setURL(pURL);
- m_url = pURL;
- const char* pDesc = 0;
- addRFC822Headers(pMsg, pRequestHeaders);
- clearStreamInfoList();
- // use the first stream description plugin found...
- char* pMimeType = 0;
- if(HXR_OK == getStreamDescriptionMimeType(pMimeType))
- {
- IHXStreamDescription* pSD =
- getStreamDescriptionInstance(pMimeType);
- if(pSD)
- {
- UINT32 streamNumber;
- UINT32 needReliable;
- UINT32 rtpPayloadType;
- UINT32 ulIsLive;
- IHXBuffer* pControlString;
- UINT32 ulIsSessionLive = 0;
- // if we are talking to a realserver, we will make an old sdpfile
- // for now...We need to check version and send the spec complient
- // sdp!
- IHXValues* pResponseHeaders = NULL;
- if (HXR_OK ==
- m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- pFileHeader->SetPropertyULONG32("SdpFileType",
- GetSdpFileTypeWeNeed(pResponseHeaders));
- }
- HX_RELEASE(pResponseHeaders);
- UINT16 nStreams = pStreams->GetCount();
- IHXValues** ppValues = new IHXValues*[nStreams+2];
- if(!ppValues)
- {
- rc = HXR_OUTOFMEMORY;
- HX_DELETE(pMsg);
- goto overandout;
- }
- ppValues[0] = pFileHeader;
- ppValues[1] = 0; // no options
- pFileHeader->GetPropertyULONG32("LiveStream", ulIsSessionLive);
- CHXSimpleList::Iterator i;
- INT16 j=2;
- for(i=pStreams->Begin();i!=pStreams->End();++i,++j)
- {
- // reset...
- streamNumber = 0;
- needReliable = 0;
- rtpPayloadType = (UINT32)-1;
- ulIsLive = ulIsSessionLive;
- pControlString = 0;
- ppValues[j] = (IHXValues*)(*i);
- // build stream info list
- RTSPStreamInfo* pInfo = new RTSPStreamInfo;
- if(!pInfo)
- {
- rc = HXR_OUTOFMEMORY;
- HX_DELETE(pMsg);
- HX_VECTOR_DELETE(ppValues);
- goto overandout;
- }
- ppValues[j]->GetPropertyULONG32("StreamNumber",
- streamNumber);
- ppValues[j]->GetPropertyULONG32("NeedReliablePackets",
- needReliable);
- ppValues[j]->GetPropertyULONG32("RTPPayloadType",
- rtpPayloadType);
- ppValues[j]->GetPropertyCString("Control",
- pControlString);
- ppValues[j]->GetPropertyULONG32("LiveStream", ulIsLive);
- pInfo->m_streamNumber = (UINT16)streamNumber;
- pInfo->m_bNeedReliablePackets = needReliable? TRUE: FALSE;
- pInfo->m_rtpPayloadType = (INT16)rtpPayloadType;
- pInfo->m_bIsLive = ulIsLive ? TRUE : FALSE;
- pInfo->m_sPort = 0;
- if(pControlString)
- {
- pInfo->m_streamControl = pControlString->GetBuffer();
- // done with the buffer
- pControlString->Release();
- pControlString = NULL;
- }
- else
- {
- char tmp[32];
- SafeSprintf(tmp,32, "streamid=%u", (UINT16)streamNumber);
- pInfo->m_streamControl = tmp;
- }
- m_streamInfoList.AddTail(pInfo);
- }
- pSD->GetDescription(nStreams+2, ppValues, pDescription);
- pDesc = (const char*)pDescription->GetBuffer();
- pSD->Release();
- delete[] ppValues;
- }
- }
- if(pDesc)
- {
- m_bSetupRecord = TRUE;
- #ifdef _MACINTOSH
- // someday, someone in core should look at why m_pSession is NULL when
- // an invalid port is used, and yet m_pSession is assumed to be valid, and subsequently
- // crashes macs HARD. I would attempt to investigate this further, however
- // the core deferred task keeps crashing the debugger while I am attempting
- // to trace through why m_pSession never gets assigned. since Mac Producer goes
- // beta in 2 weeks, I'm putting this 'fix' in here now.. rlovejoy 2/16/00
- if (m_pSession == NULL) {
- rc = HXR_PORT_IN_USE;
- } else
- #endif
- {
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, pDesc, pMimeType, seqNo);
- }
- // done with the description, we need to clean it up
- pDescription->Release();
- }
- else
- {
- rc = HXR_FAIL;
- }
- overandout:
- delete[] pMimeType;
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendSetupRequest
- (
- RTSPTransportType* pTransType,
- UINT16 nTransTypes,
- IHXValues* pIHXValuesRequestHeaders
- )
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- IHXUDPSocket* pUDPSocket = NULL;
- IHXUDPSocket* pRTCPUDPSocket = NULL;
- RTSPTransport* pTrans = NULL;
- RTCPUDPTransport* pRTCPTrans = NULL;
- RTSPStreamInfo* pStreamInfo = NULL;
- IHXSetSocketOption* pSockOpt = NULL;
- CHXSimpleList::Iterator i;
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if (m_bSDPInitiated && m_bMulticast)
- {
- RTSPTransportRequest* pRequest = new RTSPTransportRequest(RTSP_TR_RTP_MCAST, 0);
- if(pRequest)
- {
- m_transportRequestList.AddTail(pRequest);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- for (i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
- {
- pStreamInfo = (RTSPStreamInfo*)(*i);
- pUDPSocket = (IHXUDPSocket*)(*m_pUDPSocketStreamMap)[pStreamInfo->m_streamNumber];
- pRTCPUDPSocket = (IHXUDPSocket*)(*m_pRTCPSocketStreamMap)[pStreamInfo->m_streamNumber];
- // create a new transport for each setup
- pTrans = new RTPUDPTransport(m_bSetupRecord);
- if(!pTrans)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pTrans->AddRef();
- if (HXR_OK != ((RTPUDPTransport*)pTrans)->init(m_pContext,
- pUDPSocket,
- (IHXRTSPTransportResponse*)this))
- {
- rc = HXR_BAD_TRANSPORT;
- goto cleanup;
- }
- pTrans->notifyEmptyRTPInfo();
- // create an RTCP transport for this stream
- pRTCPTrans = new RTCPUDPTransport(m_bSetupRecord);
- if (!pRTCPTrans)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pRTCPTrans->AddRef();
- if (HXR_OK != pRTCPTrans->init(m_pContext, pRTCPUDPSocket, (RTPUDPTransport*)pTrans,
- (IHXRTSPTransportResponse*) this, pStreamInfo->m_streamNumber))
- {
- rc = HXR_BAD_TRANSPORT;
- goto cleanup;
- }
- pRTCPTrans->notifyEmptyRTPInfo();
- ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTrans);
- pTrans->addStreamInfo(pStreamInfo);
- (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
- (*m_pTransportMPortMap)[pStreamInfo->m_sPort] = pTrans;
- pTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort, pUDPSocket);
- (*m_pTransportMPortMap)[pStreamInfo->m_sPort+1] = pRTCPTrans;
- pRTCPTrans->JoinMulticast(m_ulConnectToAddr, pStreamInfo->m_sPort + 1, pRTCPUDPSocket);
- if ((!m_bHasSyncMasterStream) &&
- (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
- {
- pStreamInfo->m_bIsSyncMaster = TRUE;
- m_bHasSyncMasterStream = TRUE;
- }
- mapControlToStreamNo(pStreamInfo->m_streamControl, pStreamInfo->m_streamNumber);
- rc = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTrans, pStreamInfo->m_streamNumber, 0);
- if( rc == HXR_OUTOFMEMORY )
- {
- goto cleanup;
- }
-
- rc = pUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- if( rc == HXR_OUTOFMEMORY )
- {
- goto cleanup;
- }
- rc = pRTCPUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- if( rc == HXR_OUTOFMEMORY )
- {
- goto cleanup;
- }
- }
- m_uProtocolType = 1;
- m_pResp->HandleSetupResponse(HXR_OK);
- goto cleanup;
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- if( HXR_OUTOFMEMORY == extractExistingAuthorizationInformation(pIHXValuesRequestHeaders))
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- if(pTransType)
- {
- for(int i=0;i<nTransTypes;++i)
- {
- RTSPTransportRequest* pRequest =
- new RTSPTransportRequest(pTransType[i].m_lTransportType,
- pTransType[i].m_sPort);
- if(pRequest)
- {
- m_transportRequestList.AddTail(pRequest);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- break;
- }
- }
- }
- if (m_bIPTV && rc == HXR_OK)
- {
- // we are going to keep this around for now to send cookie in all SETUP.
- m_pSetupRequestHeader = pIHXValuesRequestHeaders;
- m_pSetupRequestHeader->AddRef();
- }
- if (rc == HXR_OK)
- {
- rc = sendFirstSetupRequest(pIHXValuesRequestHeaders);
- }
- cleanup:
- if (HXR_OK != rc)
- {
- HX_RELEASE(pRTCPTrans);
- HX_RELEASE(pTrans);
- }
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::sendFirstSetupRequest
- (
- IHXValues* pIHXValuesRequestHeaders
- )
- {
- m_setupResponseCount = 0;
- if (!m_streamInfoList.IsEmpty())
- {
- RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)m_streamInfoList.GetHead();
- if(pStreamInfo)
- {
- return sendSetupRequestMessage
- (
- pStreamInfo,
- pIHXValuesRequestHeaders,
- TRUE
- );
- }
- }
- return HXR_FAIL;
- }
- HX_RESULT
- RTSPClientProtocol::sendRemainingSetupRequests()
- {
- HX_RESULT status = HXR_OK;
- CHXSimpleList::Iterator i;
- BOOL bFirst = TRUE;
- for(i=m_streamInfoList.Begin();
- status == HXR_OK && (i!=m_streamInfoList.End());++i)
- {
- if(bFirst)
- {
- bFirst = FALSE;
- }
- else
- {
- RTSPStreamInfo* pStreamInfo = (RTSPStreamInfo*)(*i);
- status = sendSetupRequestMessage(pStreamInfo, NULL, FALSE);
- }
- }
- return status;
- }
- HX_RESULT
- RTSPClientProtocol::sendSetupRequestMessage(RTSPStreamInfo* pStreamInfo,
- IHXValues* pIHXValuesRequestHeaders, BOOL bFirstSetup)
- {
- m_pMutex->Lock();
- RTSPSetupMessage* pMsg = new RTSPSetupMessage;
- if(!pMsg)
- {
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- HX_RESULT status = HXR_OK;
- status = sendSetupRequestMessageExt(pStreamInfo,
- pIHXValuesRequestHeaders,
- bFirstSetup,
- pMsg);
- pMsg->addHeader("User-Agent", m_versionString);
- if (bFirstSetup && !m_sessionID.IsEmpty())
- {
- pMsg->addHeader("If-Match", m_sessionID);
- }
- else if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- // append stream control string to request
- setSetupRequestURL(pMsg, pStreamInfo);
- if (pIHXValuesRequestHeaders)
- {
- addUAProfHeaders(pIHXValuesRequestHeaders);
- addRFC822Headers(pMsg, pIHXValuesRequestHeaders);
- }
- UINT32 seqNo;
- seqNo = m_pSession->getNextSeqNo(this);
- /* Why are we not checking for any error code from above ??? */
- status = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return status;
- }
- HX_RESULT
- RTSPClientProtocol::sendSetupRequestMessageExt(RTSPStreamInfo* pStreamInfo,
- IHXValues*& pIHXValuesRequestHeaders,
- BOOL bFirstSetup,
- RTSPSetupMessage*& pMsg)
- {
- MIMEHeader* pHeader = new MIMEHeader("Transport");
- if(!pHeader)
- {
- return HXR_OUTOFMEMORY;
- }
- HX_RESULT status = HXR_OK;
- CHXSimpleList::Iterator i;
- for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
- {
- RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
- UINT16 streamNumber = pStreamInfo->m_streamNumber;
- UINT16 nUDPPort = 0;
- #if defined(HELIX_FEATURE_RTP)
- switch(pRequest->m_lTransportType)
- {
- case RTSP_TR_RTP_UDP:
- {
- // create a new transport for each setup
- RTSPTransport* pTrans =
- new RTPUDPTransport(m_bSetupRecord);
- if(!pTrans)
- {
- HX_DELETE(pHeader);
- return HXR_OUTOFMEMORY;
- }
- pTrans->AddRef();
- if (m_bPrefetch)
- {
- pTrans->EnterPrefetch();
- }
- IHXUDPSocket* pUDPSocket = (IHXUDPSocket*)
- (*m_pUDPSocketStreamMap)[streamNumber];
- pUDPSocket->GetLocalPort(nUDPPort);
- IHXUDPSocket* pRTCPSocket = (IHXUDPSocket*)
- (*m_pRTCPSocketStreamMap)[streamNumber];
- if (HXR_OK !=
- ((RTPUDPTransport*)pTrans)->init(
- m_pContext,
- pUDPSocket,
- (IHXRTSPTransportResponse*) this))
- {
- pTrans->Release();
- return HXR_BAD_TRANSPORT;
- }
- // create an RTCP transport for this stream
- RTCPUDPTransport* pRTCPTran = new RTCPUDPTransport(m_bSetupRecord);
- if(!pRTCPTran)
- {
- HX_DELETE(pHeader);
- HX_RELEASE(pTrans);
- m_pMutex->Unlock();
- return HXR_OUTOFMEMORY;
- }
- pRTCPTran->AddRef();
- pRTCPTran->init(m_pContext,
- pRTCPSocket,
- (RTPUDPTransport*)pTrans,
- (IHXRTSPTransportResponse*) this,
- streamNumber);
- ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTran);
- status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
- nUDPPort);
- if (m_bIPTV && m_pSetupRequestHeader && status != HXR_OUTOFMEMORY)
- {
- addRFC822Headers(pMsg, m_pSetupRequestHeader);
- // don't add it twice...
- pIHXValuesRequestHeaders = NULL;
- }
- }
- break;
- case RTSP_TR_RTP_TCP:
- {
- RTSPTransport* pTrans = new RTPTCPTransport(m_bSetupRecord);
- if(!pTrans)
- {
- HX_DELETE(pHeader);
- return HXR_OUTOFMEMORY;
- }
- pTrans->AddRef();
- if (m_bPrefetch)
- {
- pTrans->EnterPrefetch();
- }
- if (HXR_OK != ((RTPTCPTransport*)pTrans)->init(
- m_pContext, m_pSocket, (IHXRTSPTransportResponse*)this))
- {
- status = HXR_BAD_TRANSPORT;
- }
- // create an RTCP transport for this stream
- RTCPTCPTransport* pRTCPTran = new RTCPTCPTransport(m_bSetupRecord);
- if(!pRTCPTran)
- {
- HX_DELETE(pHeader);
- HX_DELETE(pTrans);
- return HXR_OUTOFMEMORY;
- }
- pRTCPTran->AddRef();
- pRTCPTran->init(m_pContext,
- m_pSocket,
- (RTPTCPTransport*)pTrans,
- (IHXRTSPTransportResponse*)this,
- streamNumber);
- ((RTPTCPTransport*)pTrans)->setRTCPTransport((RTCPBaseTransport*)pRTCPTran);
- status = pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber,
- nUDPPort);
- if (m_bIPTV && m_pSetupRequestHeader)
- {
- addRFC822Headers(pMsg, m_pSetupRequestHeader);
- // don't add it twice...
- pIHXValuesRequestHeaders = NULL;
- }
- }
- break;
- default:
- {
- }
- break;
- }
- #endif /* HELIX_FEATURE_RTP */
- char* pModifiedMimeType = NULL;
- const char* pMimeType =
- RTSPTransportMimeMapper::getTransportMimeType
- (
- pRequest->m_lTransportType
- );
- // Accomodate incompliant servers that understand only upper case
- // transport mime-types
- if (m_bForceUCaseTransportMimeType)
- {
- ULONG32 ulMimeTypeLength = strlen(pMimeType);
- if (ulMimeTypeLength != 0)
- {
- pModifiedMimeType = new char [ulMimeTypeLength + 1];
- if(!pModifiedMimeType)
- {
- HX_DELETE(pHeader);
- return HXR_OUTOFMEMORY;
- }
- }
- if (pModifiedMimeType)
- {
- strcpy(pModifiedMimeType, pMimeType); /* Flawfinder: ignore */
- StrToUpper(pModifiedMimeType);
- pMimeType = pModifiedMimeType;
- }
- }
- #if defined(HELIX_FEATURE_RTP)
- switch(pRequest->m_lTransportType)
- {
- case RTSP_TR_RTP_UDP:
- case RTSP_TR_RTP_TCP:
- {
- char portValue[32]; /* Flawfinder: ignore */
- MIMEHeaderValue* pHeaderValue = new MIMEHeaderValue(pMimeType);
- if(!pHeaderValue)
- {
- HX_DELETE(pHeader);
- HX_DELETE(pModifiedMimeType);
- return HXR_OUTOFMEMORY;
- }
- if (RTSP_TR_RTP_UDP == pRequest->m_lTransportType)
- {
- SafeSprintf(portValue, 32, "%u-%u", nUDPPort, nUDPPort+1);
- pHeaderValue->addParameter("client_port", (const char*)portValue);
- #ifdef XXXtbradleyTEST_RTSP_DESTINATION
- pHeaderValue->addParameter("destination", "127.0.0.1");
- #endif /* XXXtbradleyTEST_RTSP_DESTINATION */
- }
- if(m_bSetupRecord)
- {
- pHeaderValue->addParameter("mode", "record");
- }
- else
- {
- pHeaderValue->addParameter("mode", "play");
- }
- pHeader->addHeaderValue(pHeaderValue);
- }
- break;
- case RTSP_TR_RTP_MCAST:
- default:
- {
- }
- break;
- }
- #endif /* HELIX_FEATURE_RTP */
- HX_VECTOR_DELETE(pModifiedMimeType);
- }
- pMsg->addHeader(pHeader);
- return status;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendPlayRequest(UINT32 lFrom, UINT32 lTo,
- CHXSimpleList* pASMRules)
- {
- /*
- * Flush the data packets out of the transport buffers
- */
- m_pMutex->Lock();
- m_bPaused = FALSE;
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if (m_bSDPInitiated && m_bMulticast)
- {
- m_pMutex->Unlock();
- return m_pResp->HandlePlayResponse(HXR_OK);
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- /*
- * XXXGH...I believe we should be iterating through m_transportRequestList
- * here and for SendPauseRequest, SendResumeRequest, etc.
- */
- // only used when m_bNonRSRTP is TRUE
- m_bPlayJustSent = TRUE;
- if (!m_transportRequestList.IsEmpty())
- {
- RTSPTransportRequest* pRequest =
- (RTSPTransportRequest*)m_transportRequestList.GetHead();
- RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo)
- {
- pTransInfo->m_pTransport->playReset();
- // set the range in transport...only for RTP
- pTransInfo->m_pTransport->setPlayRange(lFrom, lTo);
- pTransInfo->m_pTransport->SetPlayRequestSent(TRUE);
- pTransInfo->m_pTransport->resumeBuffers();
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- HX_RESULT rc = HXR_OK;
- RTSPPlayMessage* pMsg = new RTSPPlayMessage;
- if(pMsg)
- {
- RTSPRange range(lFrom, lTo, RTSPRange::TR_NPT);
- pMsg->setURL(m_url);
- AddCommonHeaderToMsg(pMsg);
- pMsg->addHeader("Range", (const char*)range.asString());
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendRecordRequest()
- {
- if (!m_pIsMethodSupported[RECORD] || !m_pSession)
- {
- return HXR_OK;
- }
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- // Declaring these here so I can use a goto below!
- CHXString streamSequenceNumbers;
- BOOL bIsFirst = TRUE;
- CHXMapLongToObj::Iterator i;
- RTSPRecordMessage* pMsg = new RTSPRecordMessage;
- if(!pMsg)
- {
- rc = HXR_OUTOFMEMORY;
- goto overandout;
- }
- pMsg->setURL(m_url);
- AddCommonHeaderToMsg(pMsg);
- /*
- * Add header for sequence numbers
- */
- for(i=m_pTransportStreamMap->Begin(); i!=m_pTransportStreamMap->End(); ++i)
- {
- int lenTmpBuf = 100 + strlen(m_url);
- char* tmpBuf = new char[lenTmpBuf];
- if(!tmpBuf)
- {
- HX_DELETE(pMsg);
- rc = HXR_OUTOFMEMORY;
- goto overandout;
- }
- RTSPTransport* pTransport = (RTSPTransport*)(*i);
- pTransport->m_bHackedRecordFlag = TRUE;
- UINT16 streamNumber = (UINT16)i.get_key();
- UINT16 seqNum = pTransport->getSeqNum(streamNumber);
- UINT32 ulTimestamp = pTransport->getTimestamp(streamNumber);
- SafeSprintf(tmpBuf, lenTmpBuf, "url=" + m_url +
- "/streamid=%d;seq=%d;rtptime=%ld", streamNumber, seqNum,
- ulTimestamp);
- if(!bIsFirst)
- {
- streamSequenceNumbers += ", " + CHXString(tmpBuf);
- }
- else
- {
- bIsFirst = FALSE;
- streamSequenceNumbers = tmpBuf;
- }
- delete[] tmpBuf;
- }
- pMsg->addHeader("RTP-Info", streamSequenceNumbers);
- if( m_pSession )
- {
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- }
- overandout:
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendPauseRequest()
- {
- m_bPaused = TRUE;
- /*
- * Stop the internal buffer timers
- */
- if (!m_pIsMethodSupported[PAUSE] || m_transportRequestList.IsEmpty() ||
- !m_pSession)
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- // only used when m_bNonRSRTP is TRUE
- m_bPlayJustSent = FALSE;
- SendMsgToTransport(PAUSE_BUFFER);
- HX_RESULT rc = SendMsgToServer(RTSP_PAUSE);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendResumeRequest()
- {
- m_bPaused = FALSE;
- if (!m_pSession)
- {
- return HXR_OK;
- }
- /*
- * Restart the internal buffer timers
- */
- m_pMutex->Lock();
- SendMsgToTransport(RESUME_BUFFER);
- /*
- * Man, iptv, teracast, and darwin server don't like this even though
- * this is perfetly legal...
- */
- if (m_bNonRSRTP && m_bPlayJustSent)
- {
- m_pResp->HandlePlayResponse(HXR_OK);
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT rc = SendMsgToServer(RTSP_PLAY);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendTeardownRequest()
- {
- // make sure not to send a TEARDOWN unless SETUP succeeded
- if (m_setupResponseCount <= 0 || !m_pSession)
- {
- // no successful SETUP response received...
- return HXR_OK;
- }
- // it's ok if there is no session by spec.
- m_pMutex->Lock();
- HX_RESULT rc = SendMsgToServer(RTSP_TEARDOWN);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendPlayerStats(const char* pStats)
- {
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- if (!m_pIsMethodSupported[SET_PARAM])
- {
- return HXR_OK;
- }
- if(m_pSession && !m_sessionID.IsEmpty())
- {
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- if(pMsg)
- {
- pMsg->setURL(m_url);
- pMsg->addHeader("Session", m_sessionID);
- pMsg->addHeader("PlayerStats", pStats);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- m_pMutex->Unlock();
- return rc;
- }
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendKeepAlive()
- {
- HX_RESULT rc = HXR_OK;
- // XXXSMP - Not right! :-)
- m_pMutex->Lock();
- if (!m_pSession)
- {
- // just say alive!
- m_pMutex->Unlock();
- return HXR_OK;
- }
- // Handle server timeout
- if (!m_bKeepLiveResponsed)
- {
- m_pResp->HandleOptionsResponse(HXR_SERVER_TIMEOUT, NULL);
- m_pMutex->Unlock();
- return rc;
- }
- m_bKeepLiveResponsed = FALSE;
- // If using session timeout code, send an Options message,
- // otherwise, send a SetParam. The SetParam approach is
- // is for servers that do not specify a session timeout value.
- if (!m_bUseLegacyTimeOutMsg ||
- !m_pIsMethodSupported[SET_PARAM] ||
- m_bNoKeepAlive)
- {
- m_bKeepAlivePending = TRUE;
- rc = SendMsgToServer(RTSP_OPTIONS);
- }
- else
- {
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- if(pMsg)
- {
- pMsg->setURL("*");
- MIMEHeader* pAlertHeader = new MIMEHeader("Ping");
- if(pAlertHeader)
- {
- pAlertHeader->addHeaderValue("Pong");
- pMsg->addHeader(pAlertHeader);
- AddCommonHeaderToMsg(pMsg);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- sendRequest(pMsg, seqNo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendPacket(BasePacket* pPacket)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_UNEXPECTED;
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[pPacket->GetStreamNumber()];
- if(pTrans)
- {
- rc = pTrans->sendPacket(pPacket);
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendStreamDone(UINT16 streamNumber)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_UNEXPECTED;
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[streamNumber];
- if(pTrans)
- {
- rc = pTrans->streamDone(streamNumber);
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::GetPacket(UINT16 uStreamNumber, REF(IHXPacket*) pPacket)
- {
- m_pMutex->Lock();
- /*
- * Must not return HXR_FAIL because player may request a packet
- * before the transport is set up
- */
- HX_RESULT rc = HXR_NO_DATA;
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if (pTrans)
- {
- rc = pTrans->getPacket(uStreamNumber, pPacket);
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::StartPackets(UINT16 uStreamNumber)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_FAIL;
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if (pTrans)
- {
- rc = pTrans->startPackets(uStreamNumber);
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::StopPackets(UINT16 uStreamNumber)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_FAIL;
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if (pTrans)
- {
- /*
- * Must not return HXR_FAIL because player may request a packet
- * before the transport is set up
- */
- rc = pTrans->stopPackets(uStreamNumber);
- }
- m_pMutex->Unlock();
- return rc;
- }
- /*
- * XXX...This had BETTER GET FIXED when we go to full IRMA
- */
- STDMETHODIMP_(IHXPendingStatus*)
- RTSPClientProtocol::GetPendingStatus()
- {
- AddRef();
- return (IHXPendingStatus*)this;
- }
- STDMETHODIMP_(IHXStatistics*)
- RTSPClientProtocol::GetStatistics()
- {
- AddRef();
- return (IHXStatistics*)this;
- }
- STDMETHODIMP_(BOOL)
- RTSPClientProtocol::HttpOnly()
- {
- if(m_pSession)
- {
- return m_pSession->HttpOnly();
- }
- return FALSE;
- }
- /*
- * IHXResolverResponse methods
- */
- STDMETHODIMP
- RTSPClientProtocol::GetHostByNameDone(HX_RESULT status,
- UINT32 ulAddr)
- {
- UINT16 uPort = 0;
- BOOL bUseProxy = FALSE;
- CHXString host;
- HX_RELEASE(m_pResolver);
- /* We may have been deleted by now */
- if (!m_pResp)
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if (m_bSDPInitiated && m_bMulticast)
- {
- m_ulConnectToAddr = ulAddr;
- m_pResp->InitDone(HXR_OK);
- IHXValues* pResponseHeaders = NULL;
- if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- rc = m_pResp->HandleStreamDescriptionResponse
- (
- HXR_OK,
- m_pSDPFileHeader,
- m_pSDPStreamHeaders,
- pResponseHeaders
- );
- }
- HX_RELEASE(pResponseHeaders);
- RemoveSDPHeaders();
- goto exit;
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- if(status == HXR_OK)
- {
- if (!m_pSessionManager->isValid())
- {
- // just return, this puppy's going away...
- goto exit;
- }
- if (!m_pSession && !m_pSocket)
- {
- RTSPClientSession* pSession = 0;
- IUnknown* pContextToMatch = NULL;
- /* Do not reuse connection for connections coming from the
- * same player. Check for context (IHXPlayer) equality test
- * Context check is needed to simulate real-world scenario
- * for SMIL load testing
- */
- if (m_bNoReuseConnection && m_bLoadTest)
- {
- pContextToMatch = m_pContext;
- }
- /* We share established connections if
- * 1. m_bNoReuseConnection is FALSE OR
- * 2. m_bLoadTest is set to TRUE (in which case we share
- * connections ONLY for the same context (see above)
- * AND
- * 3. m_bHTTPOnly is FALSE OR
- * 4. m_pCloakPorts == NULL which means we *not* gonna
- * attempt cloakport scanning
- *
- * NOTE: Splitter Plugin uses m_bNoReuseConnection = TRUE
- */
- if ((!m_bHTTPOnly || !m_pCloakPorts) &&
- (!m_bNoReuseConnection || m_bLoadTest))
- {
- if(m_bUseProxy || m_bUseHTTPProxy)
- {
- uPort = m_proxyPort;
- }
- else if (m_bHTTPOnly)
- {
- uPort = m_uCloakPort;
- }
- else
- {
- uPort = m_foreignPort;
- }
- pSession = m_pSessionManager->findSession
- (
- ulAddr,
- uPort,
- (m_bUseProxy | m_bUseHTTPProxy),
- (const char*)m_hostName,
- (m_bUseHTTPProxy?m_uCloakPort:m_foreignPort),
- pContextToMatch
- );
- }
- if(pSession)
- {
- pSession->addProtocol(this);
- m_bSessionSucceeded = TRUE;
- m_pSession = pSession;
- m_pSocket = pSession->getSocket();
- sendInitialMessage(m_pSession, m_pSocket);
- IHXPreferredTransportSink* pPreferredTransportSink = NULL;
- if (m_pResp &&
- HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
- (void**)&pPreferredTransportSink))
- {
- pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
- }
- HX_RELEASE(pPreferredTransportSink);
- m_pResp->InitDone(HXR_OK);
- }
- else
- {
- if(m_bUseProxy || m_bUseHTTPProxy)
- {
- host = m_proxyHost;
- uPort = m_proxyPort;
- bUseProxy = TRUE;
- }
- else
- {
- host = m_hostName;
- uPort = m_foreignPort;
- }
- // XXX HP: the new session is created based on
- // the actual(foreign) host and port to
- // fix SMIL containing diff. servers
- // the better fix will be send a new
- // Challenge but still sharing the same
- //. session
- if (m_pCloakPorts)
- {
- HX_ASSERT(m_bHTTPOnly);
- // initiating cloakport scanning
- for (int i = 0; i < m_nCloakPorts; i++)
- {
- rc = m_pSessionManager->newSession(m_pContext,
- this,
- host,
- uPort,
- ulAddr,
- bUseProxy,
- m_bHTTPOnly,
- m_pCloakPorts[i]);
- HX_ASSERT(HXR_OK == rc);
- }
- goto exit;
- }
- else
- {
- rc = m_pSessionManager->newSession
- (
- m_pContext,
- this,
- host,
- uPort,
- ulAddr,
- bUseProxy,
- m_bHTTPOnly,
- m_uCloakPort
- );
- goto exit;
- }
- }
- }
- else
- {
- // being re-inited..
- //sendInitialMessage();
- m_pResp->InitDone(HXR_OK);
- }
- }
- else
- {
- m_pResp->InitDone(status);
- }
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendGetParameterRequest(UINT32 lParamType,
- const char* pParamName)
- {
- if (!m_pIsMethodSupported[GET_PARAM])
- {
- return HXR_OK;
- }
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- RTSPGetParamMessage* pMsg = new RTSPGetParamMessage;
- if(pMsg)
- {
- pMsg->setURL("*");
- AddCommonHeaderToMsg(pMsg);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, pParamName, "text/rtsp-parameters", seqNo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendSetParameterRequest(UINT32 lParamType,
- const char* pParamName, IHXBuffer* pParamValue)
- {
- if (!m_pIsMethodSupported[SET_PARAM])
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- pMsg->setURL(m_url);
- AddCommonHeaderToMsg(pMsg);
- pMsg->addHeader(pParamName, (const char*)pParamValue->GetBuffer());
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- HX_RESULT rc = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendSetParameterRequest(const char* pParamName,
- const char* pParamValue, const char* pMimeType,
- const char* pContent)
- {
- if (!m_pIsMethodSupported[SET_PARAM])
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- pMsg->setURL(m_url);
- AddCommonHeaderToMsg(pMsg);
- pMsg->addHeader(pParamName, pParamValue);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- HX_RESULT rc = sendRequest(pMsg, pContent, pMimeType, seqNo);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::PacketReady(HX_RESULT status, const char* pSessionID,
- IHXPacket* pPacket)
- {
- m_pMutex->Lock();
- HX_RESULT rc = m_pResp->HandlePacket(status, pSessionID, pPacket);
- m_pMutex->Unlock();
- return rc;
- }
- /*
- * OnRTTRequest() and OnBWReport() are server-side functions
- */
- STDMETHODIMP
- RTSPClientProtocol::OnRTTRequest(HX_RESULT status, const char* pSessionID)
- {
- return HXR_UNEXPECTED;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnRTTResponse(HX_RESULT status, const char* pSessionID,
- UINT32 ulSecs, UINT32 ulUSecs)
- {
- m_pMutex->Lock();
- HX_RESULT rc = m_pResp->HandleRTTResponse(status, pSessionID,
- ulSecs, ulUSecs);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnBWReport(HX_RESULT status, const char* pSessionID,
- INT32 aveBandwidth, INT32 packetLoss, INT32 bandwidthWanted)
- {
- return HXR_UNEXPECTED;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnCongestion(HX_RESULT status, const char* pSessionID,
- INT32 xmitMultiplier, INT32 recvMultiplier)
- {
- m_pMutex->Lock();
- HX_RESULT rc = m_pResp->HandleCongestion(status, pSessionID,
- xmitMultiplier, recvMultiplier);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnACK(HX_RESULT status, RTSPResendBuffer* pResendBuffer,
- UINT16 uStreamNumber, const char* pSessionID,
- UINT16* pAckList, UINT32 uAckListCount,
- UINT16* pNakList, UINT32 uNakListCount)
- {
- /*
- * While it's ACKing, remote client is alive
- */
- m_bConnectionAlive = TRUE;
- m_pMutex->Lock();
- HX_RESULT rc = handleACK((IHXPacketResend*)this, pResendBuffer,
- uStreamNumber,
- pAckList, uAckListCount,
- pNakList, uNakListCount,
- FALSE);
- m_pMutex->Unlock();
- return rc;
- };
- STDMETHODIMP
- RTSPClientProtocol::OnStreamDone(HX_RESULT status, UINT16 uStreamNumber)
- {
- m_pMutex->Lock();
- HX_RESULT rc = m_pResp->HandleStreamDone(status, uStreamNumber);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnSourceDone(void)
- {
- m_pMutex->Lock();
- HX_RESULT rc = m_pResp->HandleSourceDone();
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnProtocolError(HX_RESULT status)
- {
- HX_RESULT rc = HXR_OK;
- // called from transport layer
- m_pMutex->Lock();
- if (m_sessionList.IsEmpty() || m_bSessionSucceeded)
- {
- rc = m_pResp->HandleProtocolError(status);
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::GetStatus
- (
- REF(UINT16) uStatusCode,
- REF(IHXBuffer*) pStatusDesc,
- REF(UINT16) ulPercentDone
- )
- {
- #if 0
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
- if(i != m_pTransportStreamMap->End())
- {
- RTSPTransport* pTrans = (RTSPTransport*)(*i);
- rc = pTrans ? pTrans->getStatus(uStatusCode, pStatusDesc, ulPercentDone) : HXR_OK;
- }
- else
- {
- uStatusCode = HX_STATUS_BUFFERING;
- pStatusDesc = 0;
- ulPercentDone = 0;
- }
- m_pMutex->Unlock();
- return rc;
- #else
- return HXR_NOTIMPL;
- #endif
- }
- STDMETHODIMP
- RTSPClientProtocol::InitializeStatistics
- (
- UINT32 ulRegistryID
- )
- {
- HX_RESULT rc = HXR_FAIL;
- m_pMutex->Lock();
- CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
- if(i != m_pTransportStreamMap->End())
- {
- RTSPTransport* pTrans = (RTSPTransport*)(*i);
- rc = pTrans ? pTrans->initializeStatistics(ulRegistryID) : HXR_FAIL;
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::UpdateStatistics()
- {
- HX_RESULT rc = HXR_FAIL;
- m_pMutex->Lock();
- CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
- if(i != m_pTransportStreamMap->End())
- {
- RTSPTransport* pTrans = (RTSPTransport*)(*i);
- rc = pTrans ? pTrans->updateStatistics() : HXR_FAIL;
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::OnPacket(UINT16 uStreamNumber, BasePacket** ppPacket)
- {
- BasePacket* pPacket;
- m_pMutex->Lock();
- for (; (pPacket = *ppPacket); ppPacket++)
- {
- SendPacket(pPacket);
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- /*
- * RTSPClientProtocol methods
- */
- HX_RESULT
- RTSPClientProtocol::HandleUnexpected(RTSPMessage* pMsg)
- {
- m_pMutex->Lock();
- RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "405");
- pRspMsg->addHeader("Allow", allowedMethods());
- sendResponse(pRspMsg);
- delete pRspMsg;
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleBadVersion(RTSPMessage* pMsg)
- {
- m_pMutex->Lock();
- RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "505");
- sendResponse(pRspMsg);
- delete pRspMsg;
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleOptions(RTSPOptionsMessage* pMsg)
- {
- sendResponse(pMsg->seqNo(), "200");
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleTeardown(RTSPTeardownMessage* pMsg)
- {
- m_pMutex->Lock();
- RTSPResponseMessage* pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
- sendResponse(pRespMsg);
- delete pRespMsg;
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleGetParam(RTSPGetParamMessage* pMsg)
- {
- IHXBuffer* pBuffer = 0;
- m_pMutex->Lock();
- const char* pParamName = pMsg->getContent();
- HX_RESULT rc = m_pResp->HandleGetParameterRequest(
- RTSP_PARAM_STRING, pParamName, &pBuffer);
- RTSPResponseMessage* pRespMsg = 0;
- if(rc == HXR_OK)
- {
- pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
- sendResponse(pRespMsg, (const char*)pBuffer->GetBuffer(),
- "text/rtsp-parameters");
- }
- else
- {
- pRespMsg = makeResponseMessage(pMsg->seqNo(), "451");
- sendResponse(pRespMsg);
- }
- delete pRespMsg;
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleSetParam(RTSPSetParamMessage* pMsg)
- {
- RTSPResponseMessage* pRespMsg = 0;
- HX_RESULT rc = HXR_OK;
- IHXValues* pReconnectValues = NULL;
- BOOL paramOK = FALSE;
- m_pMutex->Lock();
- MIMEHeader* pAlert = pMsg->getHeader("Alert");
- MIMEHeader* pMaxASMBW = pMsg->getHeader("MaximumASMBandwidth");
- MIMEHeader* pDataConvert = pMsg->getHeader("DataConvertBuffer");
- MIMEHeader* pReconnect = pMsg->getHeader("Reconnect");
- MIMEHeader* pAlternateServer = pMsg->getHeader("Alternate-Server");
- MIMEHeader* pAlternateProxy = pMsg->getHeader("Alternate-Proxy");
- if(pAlert)
- {
- paramOK = TRUE;
- MIMEHeaderValue* pHeaderValue = pAlert->getFirstHeaderValue();
- if(pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if(pParam)
- {
- const char* pAlertNumber = (const char*)pParam->m_attribute;
- pParam = pHeaderValue->getNextParameter();
- if(pParam)
- {
- const char* pAlertText = (const char*)pParam->m_attribute;
- rc = m_pResp->HandleAlertRequest(HXR_OK,
- strtol(pAlertNumber, 0, 10), pAlertText);
- }
- }
- }
- }
- else if(pMaxASMBW)
- {
- paramOK = TRUE;
- MIMEHeaderValue* pHeaderValue = pMaxASMBW->getFirstHeaderValue();
- if(pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if(pParam)
- {
- IHXBuffer * pBuffer;
- pBuffer = new CHXBuffer();
- if(pBuffer)
- {
- rc = pBuffer->Set((const unsigned char *)(pParam->m_attribute).
- GetBuffer(1), strlen((const char*)pParam->
- m_attribute)+1);
- if( rc != HXR_OUTOFMEMORY )
- {
- pBuffer->AddRef();
- rc = m_pResp->HandleSetParameterRequest(
- RTSP_PARAM_STRING, "MaximumASMBandwidth", pBuffer);
- pBuffer->Release();
- }
- else
- {
- HX_DELETE(pBuffer);
- }
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- }
- }
- }
- else if (pDataConvert)
- {
- rc = m_pResp->HandleSetParameterRequest("DataConvertBuffer",
- "1", pMsg->getContent());
- }
- else if (pReconnect)
- {
- CHXString reconnectFlag = pMsg->getHeaderValue("Reconnect");
- if (reconnectFlag != "" && strcasecmp((const char*)reconnectFlag, "false") == 0)
- {
- pReconnectValues = new CHXHeader();
- pReconnectValues->AddRef();
- pReconnectValues->SetPropertyULONG32("Reconnect", 0);
- rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
- HX_RELEASE(pReconnectValues);
- }
- }
- else if (pAlternateServer)
- {
- rc = RetrieveReconnectInfo(pAlternateServer, ALTERNATE_SERVER, pReconnectValues);
- rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
- HX_RELEASE(pReconnectValues);
- }
- else if (pAlternateProxy)
- {
- rc = RetrieveReconnectInfo(pAlternateProxy, ALTERNATE_PROXY, pReconnectValues);
- rc = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
- HX_RELEASE(pReconnectValues);
- }
- else
- {
- rc = HXR_UNEXPECTED;
- }
- if(rc == HXR_OK)
- {
- pRespMsg = makeResponseMessage(pMsg->seqNo(), "200");
- }
- else
- {
- pRespMsg = makeResponseMessage(pMsg->seqNo(), "451");
- }
- sendResponse(pRespMsg);
- delete pRespMsg;
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::HandleUseProxy(RTSPResponseMessage* pMsg)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- MIMEHeader* pLocation = pMsg->getHeader("Location");
- if(pLocation)
- {
- MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
- if(pURLValue)
- {
- CHXString proxyURL = pURLValue->value();
- if(proxyURL.GetLength() > 0)
- {
- rc = m_pResp->HandleUseProxyRequest((const char*)proxyURL);
- goto exit;
- }
- }
- }
- // bad redirect, inform the response object
- rc = m_pResp->HandleUseProxyRequest(NULL);
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::HandleRedirect(RTSPRedirectMessage* pMsg)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- RTSPResponseMessage* pRspMsg = makeResponseMessage(pMsg->seqNo(), "200");
- sendResponse(pRspMsg);
- delete pRspMsg;
- UINT32 msFromNow = 0;
- MIMEHeader* pLocation = pMsg->getHeader("Location");
- if(pLocation)
- {
- MIMEHeader* pRangeHeader = pMsg->getHeader("Range");
- if(pRangeHeader)
- {
- RTSPRange* pRange = (RTSPRange*)pRangeHeader->getFirstHeaderValue();
- if(pRange)
- {
- msFromNow = pRange->m_begin;
- }
- }
- MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
- if(pURLValue)
- {
- CHXString redirectURL = pURLValue->value();
- if(redirectURL.GetLength() > 0)
- {
- rc = m_pResp->HandleRedirectRequest((const char*)redirectURL,
- msFromNow);
- goto exit;
- }
- }
- }
- rc = m_pResp->HandleRedirectRequest(0, 0);
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::HandleRedirectResponse(RTSPResponseMessage* pMsg)
- {
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- IHXValues* pRFC822Headers = NULL;
- getRFC822Headers(pMsg, pRFC822Headers);
- if(pRFC822Headers)
- {
- IHXKeyValueList* pRFC822List = NULL;
- if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
- {
- m_pResponseHeaders->AppendAllListItems(pRFC822List);
- }
- HX_RELEASE(pRFC822List);
- }
- HX_RELEASE(pRFC822Headers);
- // tell them this is a redirect...
- IHXValues* pResponseHeaders = NULL;
- if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- m_pResp->HandleOptionsResponse(HXR_REDIRECTION, pResponseHeaders);
- HX_RELEASE(pResponseHeaders);
- }
- else
- {
- HX_ASSERT(pResponseHeaders);
- m_pResp->HandleOptionsResponse(HXR_REDIRECTION, NULL);
- }
- UINT32 msFromNow;
- msFromNow = 0;
- MIMEHeader* pLocation;
- pLocation = pMsg->getHeader("Location");
- if(pLocation)
- {
- MIMEHeader* pRangeHeader = pMsg->getHeader("Range");
- if(pRangeHeader)
- {
- RTSPRange* pRange = (RTSPRange*)pRangeHeader->getFirstHeaderValue();
- if(pRange)
- {
- msFromNow = pRange->m_begin;
- }
- }
- MIMEHeaderValue* pURLValue = pLocation->getFirstHeaderValue();
- if(pURLValue)
- {
- CHXString redirectURL = pURLValue->value();
- if(redirectURL.GetLength() > 0)
- {
- rc = m_pResp->HandleRedirectRequest((const char*)redirectURL,
- msFromNow);
- goto exit;
- }
- }
- }
- rc = m_pResp->HandleRedirectRequest(0, 0);
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- void
- RTSPClientProtocol::SessionCreated(RTSPClientSession* pSession)
- {
- m_sessionList.AddTail(pSession);
- }
- void
- RTSPClientProtocol::SessionSucceeded(RTSPClientSession* pSession,
- IHXTCPSocket* pSocket)
- {
- RTSPClientSession* pTempSession = NULL;
- m_pMutex->Lock();
- m_bSessionSucceeded = TRUE;
- while (!m_sessionList.IsEmpty())
- {
- pTempSession = (RTSPClientSession*)m_sessionList.RemoveHead();
- if (pTempSession != pSession)
- {
- m_pSessionManager->removeFromSession(this, pTempSession);
- }
- }
- m_pSession = pSession;
- m_pSocket = pSocket;
- m_uCloakPort = pSession->m_uCloakPort;
- m_pMutex->Unlock();
- return;
- }
- void
- RTSPClientProtocol::SessionFailed(RTSPClientSession* pSession,
- IHXTCPSocket* pSocket)
- {
- LISTPOSITION lPos = NULL;
- m_pMutex->Lock();
- lPos = m_sessionList.Find((void*)pSession);
- if (lPos)
- {
- m_sessionList.RemoveAt(lPos);
- }
- m_pMutex->Unlock();
- return;
- }
- HX_RESULT
- RTSPClientProtocol::InitDone(HX_RESULT status)
- {
- HX_RESULT rc = HXR_OK;
- AddRef();
- m_pMutex->Lock();
- if (m_sessionList.IsEmpty() ||
- m_bSessionSucceeded ||
- HXR_OK == status)
- {
- rc = m_pResp->InitDone(status);
- }
- m_pMutex->Unlock();
- Release();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::InitSockets()
- {
- HX_RESULT hr = HXR_OK;
- UINT32 nMaxUDPPort = MAX_UDP_PORT;
- IHXBuffer* pBuffer = 0;
- RTSPStreamInfo* pStreamInfo = NULL;
- BOOL bGotSocket = FALSE;
- BOOL bUseUDPPort = FALSE;
- UINT16 datagramPort = 0;
- UDP_PORTS* pUDPPort = NULL;
- CHXSimpleList* pUDPPortList = new CHXSimpleList();
- CHXSimpleList::Iterator i;
- AddRef();
- if (!m_pNetworkServices || !m_pPreferences)
- {
- hr = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- m_pUDPSocketStreamMap = new CHXMapLongToObj;
- m_pRTCPSocketStreamMap = new CHXMapLongToObj;
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if (m_bSDPInitiated && m_bMulticast)
- {
- for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End() && HXR_OK == hr;++i)
- {
- pStreamInfo = (RTSPStreamInfo*)(*i);
- hr = CreateUDPSockets(pStreamInfo->m_streamNumber, pStreamInfo->m_sPort);
- }
- }
- else
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- {
- /////////////////////////////////////////////////////////////
- //
- // Handle Specific UDP Port Preferences here....
- //
- ReadPrefBOOL(m_pPreferences, "UseUDPPort", bUseUDPPort);
- if(!bUseUDPPort)
- {
- // If the MaxUDPPort Preference is set, use that instead of our defined limit
- if (HXR_OK == ReadPrefINT32(m_pPreferences, "MaxUDPPort", nMaxUDPPort))
- {
- if(nMaxUDPPort < MIN_UDP_PORT)
- {
- nMaxUDPPort = MAX_UDP_PORT;
- }
- }
- pUDPPort = new UDP_PORTS;
- pUDPPort->uFrom = MIN_UDP_PORT;
- pUDPPort->uTo = nMaxUDPPort;
- pUDPPortList->AddTail((void*)pUDPPort);
- }
- else
- {
- if(m_pPreferences->ReadPref("UDPPort", pBuffer) == HXR_OK)
- {
- ReadUDPPorts(pBuffer, pUDPPortList);
- }
- }
- HX_RELEASE(pBuffer);
- for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
- {
- pStreamInfo = (RTSPStreamInfo*)(*i);
- CHXSimpleList::Iterator lIterator = pUDPPortList->Begin();
- for (; lIterator != pUDPPortList->End(); ++lIterator)
- {
- pUDPPort = (UDP_PORTS*) (*lIterator);
- if ((pUDPPort->uTo - pUDPPort->uFrom + 1) < 2)
- {
- continue;
- }
- for (datagramPort = pUDPPort->uFrom; datagramPort <= pUDPPort->uTo; datagramPort += 2)
- {
- if (datagramPort % 2)
- {
- datagramPort = datagramPort + 1;
- }
- if ((pUDPPort->uTo - datagramPort + 1) < 2)
- {
- break;
- }
- if (HXR_OK == CreateUDPSockets(pStreamInfo->m_streamNumber, datagramPort))
- {
- bGotSocket = TRUE;
- break;
- }
- }
- if (bGotSocket)
- {
- break;
- }
- }
- }
- m_currentTransport = UDPMode;
- }
- cleanup:
- if (HXR_OK != hr)
- {
- HX_DELETE(m_pUDPSocketStreamMap);
- HX_DELETE(m_pRTCPSocketStreamMap);
- }
- while (pUDPPortList->GetCount())
- {
- pUDPPort = (UDP_PORTS*)pUDPPortList->RemoveHead();
- HX_DELETE(pUDPPort);
- }
- HX_DELETE(pUDPPortList);
- Release();
- return hr;
- }
- STDMETHODIMP
- RTSPClientProtocol::GetCurrentBuffering(UINT16 uStreamNumber,
- REF(INT64) llLowestTimestamp,
- REF(INT64) llHighestTimestamp,
- REF(UINT32) ulNumBytes,
- REF(BOOL) bDone)
- {
- llLowestTimestamp = 0;
- llHighestTimestamp = 0;
- ulNumBytes = 0;
- bDone = FALSE;
- HX_ASSERT(m_pTransportStreamMap);
- if (!m_pTransportStreamMap)
- {
- return HXR_OK;
- }
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- HX_ASSERT(pTrans);
- rc = pTrans ?
- pTrans->GetCurrentBuffering(uStreamNumber,
- llLowestTimestamp,
- llHighestTimestamp,
- ulNumBytes,
- bDone) : HXR_OK;
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SeekFlush()
- {
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- CHXMapLongToObj::Iterator i;
- for(i=m_pTransportStreamMap->Begin();
- (rc == HXR_OK) && i!=m_pTransportStreamMap->End(); ++i)
- {
- RTSPTransport* pTransport = (RTSPTransport*)(*i);
- UINT16 streamNumber = (UINT16)i.get_key();
- HX_ASSERT(pTransport);
- rc = pTransport ? pTransport->SeekFlush(streamNumber) : HXR_OK;
- }
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP_(BOOL)
- RTSPClientProtocol::IsDataReceived(void)
- {
- m_pMutex->Lock();
- BOOL bReceived = FALSE;
- CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
- if(i != m_pTransportStreamMap->End())
- {
- RTSPTransport* pTrans = (RTSPTransport*)(*i);
- bReceived = pTrans ? pTrans->IsDataReceived() : FALSE;
- }
- m_pMutex->Unlock();
- return bReceived;
- }
- STDMETHODIMP_(BOOL)
- RTSPClientProtocol::IsSourceDone(void)
- {
- m_pMutex->Lock();
- BOOL bDone = FALSE;
- CHXMapLongToObj::Iterator i = m_pTransportStreamMap->Begin();
- if(i != m_pTransportStreamMap->End())
- {
- RTSPTransport* pTrans = (RTSPTransport*)(*i);
- bDone = pTrans ? pTrans->IsSourceDone() : FALSE;
- }
- m_pMutex->Unlock();
- return bDone;
- }
- STDMETHODIMP
- RTSPClientProtocol::RuleChange(CHXSimpleList* pSubList)
- {
- if (!m_pIsMethodSupported[SET_PARAM] || !m_pSession)
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- pMsg->setURL(m_url);
- CHXString SubString;
- CHXString UnSubString;
- CHXSimpleList::Iterator i;
- BOOL bFirstSub = TRUE;
- BOOL bFirstUnSub = TRUE;
- for(i=pSubList->Begin(); i!=pSubList->End(); ++i)
- {
- char tmp[64];
- RTSPSubscription* pSub = (RTSPSubscription*)(*i);
- SafeSprintf(tmp, 64, "stream=%d;rule=%ld", pSub->m_streamNumber,
- pSub->m_ruleNumber);
- if (pSub->m_bIsSubscribe)
- {
- if(!bFirstSub)
- {
- SubString += "," + CHXString(tmp);
- }
- else
- {
- SubString += tmp;
- bFirstSub = FALSE;
- }
- }
- else
- {
- if(!bFirstUnSub)
- {
- UnSubString += "," + CHXString(tmp);
- }
- else
- {
- UnSubString += tmp;
- bFirstUnSub = FALSE;
- }
- }
- }
- if (!bFirstSub)
- {
- pMsg->addHeader("Subscribe", (const char*)SubString);
- }
- if (!bFirstUnSub)
- {
- pMsg->addHeader("UnSubscribe", (const char*)UnSubString);
- }
- if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- HX_RESULT rc = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::Subscribe(CHXSimpleList* pSubList)
- {
- return RuleChange(pSubList);
- }
- STDMETHODIMP
- RTSPClientProtocol::Unsubscribe(CHXSimpleList* pUnsubList)
- {
- return RuleChange(pUnsubList);
- }
- STDMETHODIMP
- RTSPClientProtocol::BackChannelPacketReady(IHXPacket* pPacket)
- {
- if (!m_pIsMethodSupported[SET_PARAM])
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- IHXBuffer* pBuffer = pPacket->GetBuffer();
- pMsg->setURL(m_url);
- char* pEncodedBuffer =
- new char[pBuffer->GetSize() * 2 + 4]; // XXXSMP Overkill
- BinTo64(pBuffer->GetBuffer(), pBuffer->GetSize(), pEncodedBuffer);
- int lenTmpBuf = strlen(pEncodedBuffer)+12;
- char* tmpBuf = new char[lenTmpBuf];
- SafeSprintf(tmpBuf, lenTmpBuf, ""%s"", pEncodedBuffer);
- pMsg->addHeader("BackChannel", tmpBuf);
- SafeSprintf(tmpBuf, lenTmpBuf, "%d", pPacket->GetStreamNumber());
- pMsg->addHeader("StreamNumber", tmpBuf);
- if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- delete[] tmpBuf;
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- pBuffer->Release();
- delete[] pEncodedBuffer;
- HX_RESULT rc = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return rc;
- }
- STDMETHODIMP
- RTSPClientProtocol::SendRTTRequest()
- {
- return DoSendRTTRequest();
- }
- STDMETHODIMP
- RTSPClientProtocol::SendBWReport(INT32 aveBandwidth,
- INT32 packetLoss,
- INT32 bandwidthWanted)
- {
- return DoSendBWReport(aveBandwidth, packetLoss, bandwidthWanted);
- }
- HX_RESULT
- RTSPClientProtocol::DoSendRTTRequest(void)
- {
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::DoSendBWReport(INT32 aveBandwidth,
- INT32 packetLoss,
- INT32 bandwidthWanted)
- {
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::sendRequest(RTSPRequestMessage* pMsg,
- UINT32 seqNo)
- {
- messageDebugFileOut((const char*)pMsg->asString(), FALSE);
- // Our legacy timeout approach was to periodically send messages
- // to the server. Currently, we only send a keep alive message
- // if we have not sent an rtsp message for the duration
- // of the timeout value.
- if (m_pSessionTimeout && !m_bUseLegacyTimeOutMsg)
- {
- m_pSessionTimeout->OnActivity();
- }
- return RTSPBaseProtocol::sendRequest(pMsg, seqNo);
- }
- HX_RESULT
- RTSPClientProtocol::sendRequest(RTSPRequestMessage* pMsg,
- const char* pContent,
- const char* pMimeType,
- UINT32 seqNo)
- {
- messageDebugFileOut((const char*)pMsg->asString(), FALSE);
- if (m_pSessionTimeout && !m_bUseLegacyTimeOutMsg)
- {
- m_pSessionTimeout->OnActivity();
- }
- return RTSPBaseProtocol::sendRequest(pMsg, pContent, pMimeType, seqNo);
- }
- BOOL
- RTSPClientProtocol::IsRealServer(void)
- {
- return FALSE;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetFirstSeqNum(UINT16 uStreamNumber, UINT16 uSeqNum)
- {
- m_pMutex->Lock();
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if(pTrans)
- {
- pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
- // pTrans->setFirstTimeStamp(uStreamNumber, ulTimeStamp);
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetRTPInfo(UINT16 uStreamNumber, UINT16 uSeqNum,
- UINT32 ulRTPTime, RTPInfoEnum info)
- {
- m_pMutex->Lock();
- HX_ASSERT(RTPINFO_ERROR != info);
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if(pTrans)
- {
- /*
- * RTPTransport needs to know exactly what's in RTP-Info
- */
- if (RTPINFO_SEQ_RTPTIME == info)
- {
- pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
- pTrans->setFirstTimeStamp(uStreamNumber, ulRTPTime);
- }
- else if (RTPINFO_SEQ == info)
- {
- pTrans->setFirstSeqNum(uStreamNumber, uSeqNum);
- }
- else if (RTPINFO_RTPTIME == info)
- {
- pTrans->setFirstTimeStamp(uStreamNumber, ulRTPTime);
- }
- else if (RTPINFO_EMPTY == info)
- {
- pTrans->notifyEmptyRTPInfo();
- }
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::ReadDoneWithToPort(HX_RESULT status, IHXBuffer* pBuffer,
- UINT32 ulAddr, UINT16 nFromPort, UINT16 nToPort)
- {
- HX_RESULT hresult = HXR_OK;
- BOOL bMCastPort = FALSE;
- RTSPTransport* pTrans = NULL;
- /*
- * XXX HP: While handling the m_pData->done it's possible for the
- * DispatchMessage call in CancelSelect to cause an
- * asynchronous DoRead to occur. m_pTransportPortMap has
- * been deleted inside Done() and we should add checkpoint
- * here!!
- */
- if (m_bClientDone)
- {
- return hresult;
- }
- m_pMutex->Lock();
- if(status == HXR_OK)
- {
- //XXXBAB - need to get transport by port
- pTrans = (RTSPTransport*)(*m_pTransportPortMap)[nToPort];
- if (!pTrans)
- {
- pTrans = (RTSPTransport*)(*m_pTransportMPortMap)[nToPort];
- bMCastPort = TRUE;
- m_currentTransport = MulticastMode;
- }
- if (pTrans)
- {
- // make sure the unicast packets received are coming from the same server
- // we are connecting to
- if ((m_ulConnectToAddr == ulAddr) || bMCastPort)
- {
- if (!m_bReportedSuccessfulTransport)
- {
- m_bReportedSuccessfulTransport = TRUE;
- IHXPreferredTransportSink* pPreferredTransportSink = NULL;
- if (m_pResp &&
- HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
- (void**)&pPreferredTransportSink))
- {
- pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
- }
- HX_RELEASE(pPreferredTransportSink);
- }
- // drop all the scalable multicast packets when we are paused
- if ((MulticastMode != m_currentTransport) || !m_bSDPInitiated || !m_bPaused)
- {
- hresult = pTrans->handlePacket(pBuffer);
- if (m_bSplitterConsumer)
- {
- pTrans->releasePackets();
- }
- }
- }
- else
- {
- // XXX HP, invalid packets such as sent from 3rd party box
- HX_ASSERT(FALSE);
- }
- if (hresult == HXR_OK || hresult == HXR_UNEXPECTED)
- {
- if (bMCastPort)
- {
- IHXUDPSocket* pSocket = pTrans->getMulticastSocket();
- hresult = pSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- }
- else
- {
- IHXUDPSocket* pSocket = pTrans->getUDPSocket();
- hresult = pSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- }
- }
- }
- }
- else
- {
- hresult = PacketReady(HXR_FAIL, m_sessionID, 0);
- }
- m_pMutex->Unlock();
- return hresult;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetConnectionTimeout(UINT32 uSeconds)
- {
- m_uConnectionTimeout = uSeconds;
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetResendBufferDepth(UINT32 uSeconds)
- {
- m_ulBufferDepth = uSeconds * 1000;
- return HXR_OK;
- }
- /*
- * IHXTransportSyncServer methods
- */
- STDMETHODIMP
- RTSPClientProtocol::DistributeSyncAnchor(ULONG32 ulHXTime,
- ULONG32 ulNTPTime)
- {
- m_pMutex->Lock();
- if (!m_transportRequestList.IsEmpty())
- {
- RTSPTransportRequest* pRequest =
- (RTSPTransportRequest*)m_transportRequestList.GetHead();
- RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo)
- {
- pTransInfo->m_pTransport->anchorSync(ulHXTime, ulNTPTime);
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::DistributeSync(ULONG32 ulHXTime,
- LONG32 lHXTimeOffset)
- {
- m_pMutex->Lock();
- if (!m_transportRequestList.IsEmpty())
- {
- RTSPTransportRequest* pRequest =
- (RTSPTransportRequest*)m_transportRequestList.GetHead();
- RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo)
- {
- pTransInfo->m_pTransport->handleMasterSync(ulHXTime,
- lHXTimeOffset);
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientProtocol::DistributeStartTime(ULONG32 ulHXRefTime)
- {
- return HXR_NOTIMPL;
- }
- /*
- * IHXTransportBufferLimit methods
- */
- /************************************************************************
- * Method:
- * IHXTransportBufferLimit::SetByteLimit
- * Purpose:
- * Sets the maximum number of bytes that can be buffered in the
- * transport buffer. If incomming packets would put us over this
- * limit, then they are replaced with lost packets. A byte limit
- * of 0 means unlimited buffering.
- */
- STDMETHODIMP
- RTSPClientProtocol::SetByteLimit(UINT16 uStreamNumber, UINT32 uByteLimit)
- {
- HX_RESULT res = HXR_FAILED;
- m_pMutex->Lock();
- RTSPTransportBuffer* pTransBuf = getTransportBuffer(uStreamNumber);
- if (pTransBuf)
- {
- pTransBuf->SetByteLimit(uByteLimit);
- res = HXR_OK;
- }
- m_pMutex->Unlock();
- return res;
- }
- /************************************************************************
- * Method:
- * IHXTransportBufferLimit::GetByteLimit
- * Purpose:
- * Returns the current byte limit in effect. A value of 0 means
- * unlimited buffering is allowed
- */
- STDMETHODIMP_(UINT32)
- RTSPClientProtocol::GetByteLimit(UINT16 uStreamNumber)
- {
- UINT32 ulRet = 0;
- m_pMutex->Lock();
- RTSPTransportBuffer* pTransBuf = getTransportBuffer(uStreamNumber);
- if (pTransBuf)
- {
- ulRet = pTransBuf->GetByteLimit();
- }
- m_pMutex->Unlock();
- return ulRet;
- }
- /*
- * private RTSPClientProtocol methods
- */
- HX_RESULT
- RTSPClientProtocol::handleMessage(RTSPMessage* pMsg)
- {
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- messageDebugFileOut((const char*)pMsg->asString(), TRUE);
- if(pMsg->tag() != RTSPMessage::T_RESP)
- {
- int majorVersion = pMsg->majorVersion();
- int minorVersion = pMsg->minorVersion();
- if((majorVersion == 0 && minorVersion == 0) ||
- (majorVersion > RTSPMessage::MAJ_VERSION))
- {
- rc = HandleBadVersion(pMsg);
- goto exit;
- }
- else if(minorVersion > RTSPMessage::MIN_VERSION)
- {
- rc = HandleBadVersion(pMsg);
- goto exit;
- }
- }
- switch(pMsg->tag())
- {
- case RTSPMessage::T_OPTIONS:
- {
- rc = HandleOptions((RTSPOptionsMessage*)pMsg);
- goto exit;
- }
- case RTSPMessage::T_SET_PARAM:
- {
- rc = HandleSetParam((RTSPSetParamMessage*)pMsg);
- goto exit;
- }
- case RTSPMessage::T_REDIRECT:
- {
- rc = HandleRedirect((RTSPRedirectMessage*)pMsg);
- goto exit;
- }
- case RTSPMessage::T_RESP:
- {
- // check for proxy(305) redirect
- const char* pErrorCode = ((RTSPResponseMessage*)pMsg)->errorCode();
- if(strcmp(pErrorCode, "305") == 0)
- {
- rc = HandleUseProxy((RTSPResponseMessage*)pMsg);
- goto exit;
- }
- // check for URL redirect
- else if (strcmp(pErrorCode, "302") == 0 ||
- strcmp(pErrorCode, "303") == 0)
- {
- rc = HandleRedirectResponse((RTSPResponseMessage*)pMsg);
- goto exit;
- }
- RTSPMessage* pReqMsg = dequeueMessage(pMsg->seqNo());
- if(pReqMsg)
- {
- switch(pReqMsg->tag())
- {
- case RTSPMessage::T_OPTIONS:
- {
- rc = handleOptionsResponse((RTSPResponseMessage*)pMsg);
- }
- break;
- case RTSPMessage::T_GET_PARAM:
- {
- rc = handleGetParamResponse((RTSPResponseMessage*)pMsg);
- }
- break;
- case RTSPMessage::T_SET_PARAM:
- {
- rc = handleSetParamResponse((RTSPResponseMessage*)pMsg);
- }
- break;
- case RTSPMessage::T_TEARDOWN:
- {
- rc = handleTeardownResponse((RTSPResponseMessage*)pMsg);
- m_state = RTSPClientProtocol::INIT;
- }
- break;
- case RTSPMessage::T_DESCRIBE:
- {
- rc = handleDescribeResponse((RTSPResponseMessage*)pMsg);
- }
- break;
- case RTSPMessage::T_ANNOUNCE:
- {
- rc = handleAnnounceResponse((RTSPResponseMessage*)pMsg);
- }
- break;
- default:
- {
- switch(m_state)
- {
- case RTSPClientProtocol::INIT:
- {
- switch(pReqMsg->tag())
- {
- case RTSPMessage::T_SETUP:
- {
- rc = handleSetupResponse(
- (RTSPResponseMessage*)pMsg,
- (RTSPSetupMessage*)pReqMsg);
- if(rc == HXR_OK)
- {
- m_state = RTSPClientProtocol::READY;
- }
- }
- break;
- default:
- {
- rc = HandleUnexpected(pMsg);
- }
- break;
- }
- }
- break;
- case RTSPClientProtocol::READY:
- {
- switch(pReqMsg->tag())
- {
- case RTSPMessage::T_SETUP:
- {
- rc = handleSetupResponse(
- (RTSPResponseMessage*)pMsg,
- (RTSPSetupMessage*)pReqMsg);
- }
- break;
- case RTSPMessage::T_PLAY:
- {
- rc = handlePlayResponse(
- (RTSPResponseMessage*)pMsg,
- (RTSPPlayMessage*)pReqMsg);
- if(rc == HXR_OK)
- {
- m_state =
- RTSPClientProtocol::PLAYING;
- }
- }
- break;
- case RTSPMessage::T_RECORD:
- {
- rc = handleRecordResponse(
- (RTSPResponseMessage*)pMsg);
- if(rc == HXR_OK)
- {
- m_state =
- RTSPClientProtocol::RECORDING;
- }
- }
- break;
- default:
- {
- rc = HandleUnexpected(pMsg);
- }
- break;
- }
- }
- break;
- case RTSPClientProtocol::PLAYING:
- {
- switch(pReqMsg->tag())
- {
- case RTSPMessage::T_PLAY:
- {
- rc = handlePlayResponse(
- (RTSPResponseMessage*)pMsg,
- (RTSPPlayMessage*)pReqMsg);
- }
- break;
- case RTSPMessage::T_PAUSE:
- {
- rc = handlePauseResponse(
- (RTSPResponseMessage*)pMsg);
- if(rc == HXR_OK)
- {
- m_state =
- RTSPClientProtocol::READY;
- }
- }
- break;
- default:
- {
- rc = HandleUnexpected(pMsg);
- }
- break;
- }
- }
- break;
- case RTSPClientProtocol::RECORDING:
- {
- switch(pReqMsg->tag())
- {
- case RTSPMessage::T_RECORD:
- {
- rc = handleRecordResponse(
- (RTSPResponseMessage*)pMsg);
- }
- break;
- case RTSPMessage::T_PAUSE:
- {
- rc = handlePauseResponse(
- (RTSPResponseMessage*)pMsg);
- if(rc == HXR_OK)
- {
- m_state =
- RTSPClientProtocol::READY;
- }
- }
- break;
- default:
- {
- rc = HandleUnexpected(pMsg);
- }
- break;
- }
- }
- break;
- }
- }
- break;
- }
- // Create and init out server timeout object
- if (!m_pTimeoutCallback)
- {
- m_pTimeoutCallback = new TimeoutCallback(this);
- m_pTimeoutCallback->AddRef();
- }
- UINT32 nTimeOut = 0;
- // Set to server timeout value on creation
- if (!m_pSessionTimeout)
- {
- m_pSessionTimeout = new CHXKeepAlive;
- nTimeOut = m_ulServerTimeOut;
- }
- // Check for session timeout
- CHXString sessionID = pMsg->getHeaderValue("Session");
- if(sessionID != "")
- {
- int i;
- if (-1 != (i = sessionID.Find('=')))
- {
- // Wake up early for session timeout since servers will
- // disconnect if they do not receive messages on time.
- nTimeOut = atoi(sessionID.Right(sessionID.GetLength()-(i+1))) / 2;
- // Some servers specify timeout in ms not secs
- if (nTimeOut < 1000)
- nTimeOut *= 1000;
- // If session timeout is present, use options message to alert the
- // server we are still alive. If not, use setparam.
- m_bUseLegacyTimeOutMsg = FALSE;
- // If session timeout value differnt than our current value, we
- // need to reinit the scheduer.
- if (nTimeOut == m_ulCurrentTimeOut)
- {
- nTimeOut = 0;
- }
- // Use the lower of our default timeout and the session timeout
- else if (m_ulServerTimeOut < nTimeOut)
- {
- nTimeOut = m_ulServerTimeOut;
- }
- }
- }
- if (nTimeOut && m_pSessionTimeout)
- {
- m_pSessionTimeout->Init(m_pScheduler,
- nTimeOut,
- (IHXCallback*)m_pTimeoutCallback);
- m_ulCurrentTimeOut = nTimeOut;
- }
- delete pReqMsg;
- }
- }
- break;
- default:
- {
- rc = HandleUnexpected(pMsg);
- goto exit;
- }
- }
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- const char*
- RTSPClientProtocol::allowedMethods()
- {
- return "OPTIONS";
- }
- HX_RESULT
- RTSPClientProtocol::handleTCPData(BYTE* pData, UINT16 dataLen, UINT16 channel)
- {
- if (!m_pTransportChannelMap)
- return HXR_FAIL;
- m_pMutex->Lock();
- HX_RESULT rc = HXR_OK;
- CHXBuffer* pBuffer = new CHXBuffer;
- if(!pBuffer)
- {
- rc = HXR_OUTOFMEMORY;
- goto overandout;
- }
- pBuffer->AddRef();
- rc = pBuffer->Set(pData, dataLen);
- if( rc == HXR_OUTOFMEMORY )
- {
- pBuffer->Release();
- goto overandout;
- }
- RTSPTransport* pTrans;
- if (m_pTransportChannelMap->Lookup(channel, (void*&)pTrans))
- {
- if (!m_bReportedSuccessfulTransport)
- {
- m_bReportedSuccessfulTransport = TRUE;
- IHXPreferredTransportSink* pPreferredTransportSink = NULL;
- if (m_pResp &&
- HXR_OK == m_pResp->QueryInterface(IID_IHXPreferredTransportSink,
- (void**)&pPreferredTransportSink))
- {
- pPreferredTransportSink->TransportSucceeded(m_currentTransport, m_uCloakPort);
- }
- HX_RELEASE(pPreferredTransportSink);
- }
-
- rc = pTrans->handlePacket(pBuffer);
- }
- #ifdef _DEBUG
- else
- {
- HX_ASSERT(!"make sure TransportChannelMap has been set up right...");
- }
- #endif
- pBuffer->Release();
- overandout:
- m_pMutex->Unlock();
- return rc;
- }
- /*
- */
- SdpFileType
- RTSPClientProtocol::GetSdpFileTypeWeNeed(IHXValues* pHeaders)
- {
- IHXBuffer* pAgent = NULL;
- SdpFileType sdpType = NONE_SDP;
- /*
- * Better make sure to come up with a better way to check
- */
- if (FAILED(pHeaders->GetPropertyCString("Server", pAgent)))
- {
- return NONE_SDP;
- }
- if (strstr((const char*)pAgent->GetBuffer(), "RealMedia"))
- {
- sdpType = BACKWARD_COMP_SDP;
- }
- else
- {
- sdpType = INTEROP_SDP;
- }
- HX_RELEASE(pAgent);
- return sdpType;
- }
- HX_RESULT
- RTSPClientProtocol::GetStreamDescriptionInfo(IUnknown* pUnknown, CHXString& mimeTypes)
- {
- HX_RESULT rc = HXR_OK;
- const char* pMimeType = NULL;
- BOOL bIsFirst = TRUE;
- IHXStreamDescription* pStreamDesc = NULL;
- if (HXR_OK == pUnknown->QueryInterface(IID_IHXStreamDescription,(void**)&pStreamDesc) &&
- pStreamDesc)
- {
- pStreamDesc->GetStreamDescriptionInfo(pMimeType);
- if(bIsFirst)
- {
- mimeTypes += pMimeType;
- bIsFirst = FALSE;
- }
- else
- {
- mimeTypes += ", " + (CHXString)pMimeType;
- }
- pStreamDesc->Release();
- }
- return rc;
- }
- void
- RTSPClientProtocol::SendMsgToTransport(TRANSPORT_MSG msg)
- {
- RTSPTransportRequest* pRequest = NULL;
- RTSPTransportInfo* pTransInfo = NULL;
- if (!m_transportRequestList.IsEmpty())
- {
- pRequest = (RTSPTransportRequest*)m_transportRequestList.GetHead();
- pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo)
- {
- switch (msg)
- {
- case ENTER_PREFETCH:
- pTransInfo->m_pTransport->EnterPrefetch();
- break;
- case LEAVE_PREFETCH:
- pTransInfo->m_pTransport->LeavePrefetch();
- break;
- case ENTER_FASTSTART:
- pTransInfo->m_pTransport->EnterFastStart();
- break;
- case LEAVE_FASTSTART:
- pTransInfo->m_pTransport->LeaveFastStart();
- break;
- case PAUSE_BUFFER:
- pTransInfo->m_pTransport->pauseBuffers();
- break;
- case RESUME_BUFFER:
- pTransInfo->m_pTransport->resumeBuffers();
- break;
- default:
- break;
- }
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- }
- void
- RTSPClientProtocol::AddCommonHeaderToMsg(RTSPRequestMessage* pMsg)
- {
- if (pMsg)
- {
- pMsg->addHeader("User-Agent", m_versionString);
- if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- }
- }
- HX_RESULT
- RTSPClientProtocol::SendMsgToServer(RTSPMethod msg)
- {
- HX_RESULT rc = HXR_OK;
- RTSPRequestMessage* pMsg = NULL;
- switch(msg)
- {
- case RTSP_PLAY:
- pMsg = new RTSPPlayMessage;
- break;
- case RTSP_PAUSE:
- pMsg = new RTSPPauseMessage;
- break;
- case RTSP_OPTIONS:
- pMsg = new RTSPOptionsMessage;
- break;
- case RTSP_TEARDOWN:
- pMsg = new RTSPTeardownMessage;
- break;
- default:
- break;
- }
- if (pMsg)
- {
- pMsg->setURL(m_url);
- AddCommonHeaderToMsg(pMsg);
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::handleOptionsResponse
- (
- RTSPResponseMessage* pRTSPResponseMessageIncoming
- )
- {
- HX_RESULT rc = HXR_OK;
- if (pRTSPResponseMessageIncoming->errorCodeAsUINT32() == 551)
- {
- /* Quite poor, but the client only supports this one require for now */
- return m_pResp->HandleOptionsResponse(HXR_LOADTEST_NOT_SUPPORTED,
- NULL);
- }
- else if(pRTSPResponseMessageIncoming->errorCodeAsUINT32() != 200)
- {
- return m_pResp->HandleOptionsResponse(HXR_FAIL, NULL);
- }
- else
- {
- // Filter out session timeout message reponses
- if (m_bKeepAlivePending)
- {
- m_bKeepAlivePending = FALSE;
- m_bKeepLiveResponsed = TRUE;
- return HXR_OK;
- }
- /*
- * XXXGH...I added this just for the stats mask, but the
- * authentication should be available from the 822 headers too
- */
- IHXValues* pRFC822Headers = NULL;
- getRFC822Headers(pRTSPResponseMessageIncoming, pRFC822Headers);
- if (pRFC822Headers)
- {
- IHXKeyValueList* pRFC822List = NULL;
- if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
- {
- m_pResponseHeaders->AppendAllListItems(pRFC822List);
- }
- HX_RELEASE(pRFC822List);
- }
- if (m_sessionID.IsEmpty())
- {
- m_sessionID = pRTSPResponseMessageIncoming->getHeaderValue("Session");
- }
- // Respond to Client Challenge to prove that we are a RealClient
- if (!m_pSession->m_bChallengeDone &&
- HXR_OK != RetrieveChallenge(pRTSPResponseMessageIncoming))
- {
- IHXValues* pResponseHeaders = NULL;
- // check for supported RTSP methods if the server could be non-RS
- if (m_pResponseHeaders &&
- HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- IHXBuffer* pCmds = NULL;
- // Thanks IPTV for adding a space after Public
- if (HXR_OK == pResponseHeaders->GetPropertyCString("Allow", pCmds) ||
- HXR_OK == pResponseHeaders->GetPropertyCString("Public", pCmds) ||
- HXR_OK == pResponseHeaders->GetPropertyCString("Public ", pCmds))
- {
- // all methods are supported by default
- if (!strstr((char*)pCmds->GetBuffer(), "SETUP"))
- m_pIsMethodSupported[SETUP] = FALSE;
- // Is redirect supported
- if (!strstr((char*)pCmds->GetBuffer(), "REDIRECT"))
- m_pIsMethodSupported[REDIRECT] = FALSE;
- // Is play supported
- if (!strstr((char*)pCmds->GetBuffer(), "PLAY"))
- m_pIsMethodSupported[PLAY] = FALSE;
- // Is pause supported
- if (!strstr((char*)pCmds->GetBuffer(), "PAUSE"))
- m_pIsMethodSupported[PAUSE] = FALSE;
- // Is set_param supported
- if (!strstr((char*)pCmds->GetBuffer(), "SET_PARAMETER"))
- m_pIsMethodSupported[SET_PARAM] = FALSE;
- // Is get_param supported
- if (!strstr((char*)pCmds->GetBuffer(), "GET_PARAMETER"))
- m_pIsMethodSupported[GET_PARAM] = FALSE;
- // Is describe supported
- if (!strstr((char*)pCmds->GetBuffer(), "DESCRIBE"))
- m_pIsMethodSupported[DESCRIBE] = FALSE;
- // Is teardown supported
- if (!strstr((char*)pCmds->GetBuffer(), "TEARDOWN"))
- m_pIsMethodSupported[TEARDOWN] = FALSE;
- // Is record supported
- if (!strstr((char*)pCmds->GetBuffer(), "RECORD"))
- m_pIsMethodSupported[RECORD] = FALSE;
- // Is announce supported
- if (!strstr((char*)pCmds->GetBuffer(), "ANNOUNCE"))
- m_pIsMethodSupported[ANNOUNCE] = FALSE;
- }
- HX_RELEASE(pCmds);
- }
- HX_RELEASE(pResponseHeaders);
- }
- if (m_bSDPInitiated)
- {
- IHXValues* pResponseHeaders = NULL;
- if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- if (!IsRealServer())
- {
- BOOL bForceRTP = TRUE;
- ReadPrefBOOL(m_pPreferences, "NonRS", bForceRTP);
- if (bForceRTP)
- {
- pResponseHeaders->SetPropertyULONG32("UseRTP", TRUE);
- }
- }
- m_url = m_headerControl;
- rc = m_pResp->HandleStreamDescriptionResponse
- (
- HXR_OK,
- m_pSDPFileHeader,
- m_pSDPStreamHeaders,
- pResponseHeaders
- );
- }
- HX_RELEASE(pResponseHeaders);
- RemoveSDPHeaders();
- }
- else
- {
- rc = m_pResp->HandleOptionsResponse(HXR_OK, pRFC822Headers);
- HX_RELEASE(pRFC822Headers);
- }
- return rc;
- }
- }
- HX_RESULT
- RTSPClientProtocol::handleGetParamResponse(RTSPResponseMessage* pMsg)
- {
- if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- return m_pResp->HandleGetParameterResponse(HXR_FAIL, 0);
- }
- CHXBuffer* pBuffer = new CHXBuffer;
- if(!pBuffer)
- {
- return HXR_OUTOFMEMORY;
- }
- pBuffer->AddRef();
- const char* pContent = (char*)pMsg->getContent();
- HX_RESULT ret = pBuffer->Set((BYTE*)pContent, strlen(pContent) + 1);
- if( ret != HXR_OUTOFMEMORY )
- {
- ret = m_pResp->HandleGetParameterResponse(HXR_OK, pBuffer);
- }
- pBuffer->Release();
- return ret;
- }