📄 rtspprotocol.cpp
字号:
RTSPSubscription sub; sub.m_streamNumber = streamNumber; sub.m_ruleNumber = ruleNumber; sub.m_bIsSubscribe = FALSE; CHXSimpleList subList; subList.AddTail(&sub); return m_pProtocolLib->Unsubscribe(&subList);}/* * IHXBackChannel methods *//************************************************************************ * Method: * IHXBackChannel::PacketReady * Purpose: * Send a packet from renderer back to file format */STDMETHODIMPRTSPProtocol::PacketReady( IHXPacket* pPacket){ /* * XXXSMP - We'll use the transport when available eventually, but * Control messages will do for now. */ if(m_pProtocolLib) { return m_pProtocolLib->BackChannelPacketReady(pPacket); } return HXR_FAIL;}/* HXProtocol methods */HX_RESULTRTSPProtocol::server_hello(void){ HX_RESULT theErr = HXR_OK; IUnknown* pContext = NULL; IHXBuffer* pBuffer = NULL; IHXValues* pInfo = NULL; pContext = (IUnknown*)(IHXStreamSource*)mOwner; pContext->AddRef(); if (m_bSDPInitiated) { pInfo = new CHXHeader(); if (pInfo) { pInfo->AddRef(); pBuffer = new CHXBuffer(); if (pBuffer) { pBuffer->AddRef(); pBuffer->Set((UCHAR*)mPath, strlen(mPath) + 1); pInfo->SetPropertyCString("helix-sdp", pBuffer); pBuffer->Release(); } } } theErr = m_pProtocolLib->Init((IUnknown*)pContext, mHost, mPort, (IHXRTSPClientProtocolResponse*)this, mUseProxy?RTSP_INIT_HXPRIVATE_AUTHORIZATION:0, m_pIDInfo, pInfo, m_bHTTPOnly, mCloakPort, FALSE); if (pInfo) { UINT32 ulMulticastOnly = 0; // "MulticastOnly" is set by the RTSPClientProtocol when it's scalable // multicast via SDP file. // // If "MulticastOnly" is set and the current transport is not multicast then // we will returns error immediately and won't waste time in transport switching pInfo->GetPropertyULONG32("MulticastOnly", ulMulticastOnly); m_bMulticastOnly = (ulMulticastOnly > 0)?TRUE:FALSE; if (m_bMulticastOnly && mCurrentTransport != MulticastMode) { theErr = HXR_SE_MULTICAST_DELIVERY_ONLY; } } HX_RELEASE(pInfo); HX_RELEASE(pContext); return theErr;}HX_RESULTRTSPProtocol::proxy_hello(void){ m_pProtocolLib->SetProxy(mProxy, mProxyPort); return server_hello();} HX_RESULTRTSPProtocol::process(void){ HX_RESULT theErr = HXR_OK; if (m_LastError != HXR_OK) { return m_LastError; }#ifdef _MACINTOSH#if defined(HELIX_FEATURE_AUTHENTICATION) if (m_bHandleWWWAuthentication) { /* Need to wait for system time */ if (HXMM_ATINTERRUPT()) { return HXR_OK; } m_bHandleWWWAuthentication = FALSE; handlePendingWWWAuthentication(m_WWWResult, m_pWWWValues); HX_RELEASE(m_pWWWValues); }#endif#endif switch(m_idleState) { case INIT_SOCKETS_STATE: { IUnknown* pContext = NULL; IHXInterruptState* pInterruptState = NULL; mOwner->GetContext(pContext); if (pContext) { pContext->QueryInterface(IID_IHXInterruptState, (void**) &pInterruptState); } HX_RELEASE(pContext); /* We want to initialize sockets ONLY at system time */ if (!pInterruptState || !pInterruptState->AtInterruptTime()) { // XXX HP: we should find better way to handle this // when the UseUDPPort option is selected if (UDPMode == mCurrentTransport || MulticastMode == mCurrentTransport) { theErr = m_pProtocolLib->InitSockets(); } m_idleState = SEND_SETUP_REQUEST_STATE; } HX_RELEASE(pInterruptState); } break; case SEND_SETUP_REQUEST_STATE: { // Make sure we are finished with the file header if (!mOwner->m_bContinueWithHeaders) { theErr = send_setup_request(); m_idleState = NULL_STATE; } } break; case ALERT_STATE: { // Set theErr to the correct ServerAlert HXR_ code. theErr = MAKE_SA(m_ulLastAlert); if (!IS_SERVER_ALERT(theErr)) { theErr = HXR_SERVER_ALERT; } m_idleState = NULL_STATE; } break; default: break; } // check whether the connection has timed out if (!theErr && !m_bPaused) { ULONG32 ulNow = HX_GET_TICKCOUNT(); if ((!mReceivedControl || (!m_bReceivedData && m_bPlaying)) && mOwner->CheckTransportTimeout(ulNow)) { /* Make sure that we have really not receioved any data. * If it is a sparse stream, transport may hold onto initial * data for around 2 seconds before releasing it to the next * layer. */ if (!mReceivedControl) { theErr = HXR_NET_CONNECT; } else { if (m_pProtocolLib && m_pProtocolLib->IsDataReceived()) { /* We haver received the data.. Transport will * eventually give it to use (hopefully!) */ m_bReceivedData = TRUE; } else { switch (mCurrentTransport) { case MulticastMode: theErr = HXR_MULTICAST_UDP; break; case UDPMode: theErr = HXR_NET_UDP; break; case TCPMode: if (!m_bHTTPOnly) { theErr = HXR_NET_TCP; } else { theErr = HXR_DNR; } break; default: break; } } } } // The following logic is to force reconnect when in certain cases, the UDP // channel would be closed after a long pause. This solves the 50% phenomenon. if (HXR_OK == theErr && m_bReceivedData && m_bAreResuming && mCurrentTransport == UDPMode) { if (mSourceEnd || (m_pProtocolLib && m_pProtocolLib->IsDataReceived())) { m_bAreResuming = FALSE; } else if (mOwner->CheckTransportTimeout(ulNow)) { m_bAreResuming = FALSE; theErr = HXR_SERVER_TIMEOUT; } } // fallback to unicast if scalable multicast fails if (m_bSDPInitiated && HXR_MULTICAST_UDP == theErr && mLiveStream) { if (HXR_OK == SwitchToUnicast()) { theErr = HXR_OK; } else { theErr = HXR_MULTICAST_JOIN; } } } // remember the last error so we won't proceed to the next // RTSP state in subsequent process() calls if (HXR_OK == m_LastError && HXR_OK != theErr) { m_LastError = theErr; } return theErr;}HX_RESULTRTSPProtocol::abort(void){ HX_RESULT theErr = HXR_OK;//XXX...Currently unimplemented return theErr;}HX_RESULTRTSPProtocol::GetEvent( UINT16 uStreamNumber, CHXEvent*& pEvent){ HX_TRACE("RTSPProtocol::GetPacket"); HX_RESULT result; IHXPacket* pPacket = NULL; pEvent = NULL; result = m_pProtocolLib->GetPacket(uStreamNumber, pPacket);#ifdef _DEBUG if (result == HXR_AT_END) { STREAM_INFO* pStreamInfo; if (HXR_OK != mOwner->GetStreamInfo(uStreamNumber, pStreamInfo)) { return HXR_FAIL; } HX_ASSERT(pStreamInfo->m_bSrcStreamDone); }#endif if (pPacket) { // signal the raw data is received m_bReceivedData = TRUE; pEvent = new CHXEvent(pPacket); pPacket->Release(); } return result;}HX_RESULTRTSPProtocol::setup(const char* host, const char* path, UINT16 port, BOOL LossCorrection, BOOL bHTTPCloak, BOOL bSDPInitiated, UINT16 cloakPort){ HX_RESULT theErr = HXR_OK; IHXValues* pRequestHeaders = NULL; IHXValues* pCloakValues = NULL; IHXBuffer* pRegionData = NULL; m_bSDPInitiated = bSDPInitiated; mOwner->GetRequest(m_pRequest); // XXXkshoop store origional headers for use // in replaying Describe's. This supports // authentication. HX_ASSERT(m_pRequest); if (m_pRequest) { m_spIHXValuesStoredHeaders.Release(); theErr = m_pRequest->GetRequestHeaders( m_spIHXValuesStoredHeaders.ptr_reference()); HX_VERIFY(SUCCEEDED(theErr) && m_spIHXValuesStoredHeaders.IsValid()); } // setup base class members theErr = HXProtocol::setup(host, path, port, LossCorrection, bHTTPCloak, m_bSDPInitiated, cloakPort); if (theErr) { return theErr; } if ( m_pRequest && SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders)) && pRequestHeaders ) { pRequestHeaders->GetPropertyCString("RegionData", pRegionData); } HX_RELEASE(pRequestHeaders); // construct the IHXValues m_pIDInfo = new CHXHeader(); m_pIDInfo->AddRef(); IHXBuffer* pGUID = new CHXBuffer(); IHXBuffer* pClientID = new CHXBuffer(); IHXBuffer* pPragma = new CHXBuffer(); pGUID->AddRef(); pClientID->AddRef(); pPragma->AddRef(); pGUID->Set((const UCHAR*)m_pszGUID, strlen(m_pszGUID)+1); pClientID->Set((const UCHAR*)m_pszClientID, strlen(m_pszClientID)+1); pPragma->Set((const UCHAR*)PRAGMA, strlen(PRAGMA)+1); m_pIDInfo->SetPropertyCString("GUID", pGUID); m_pIDInfo->SetPropertyCString("ClientID", pClientID); // server doesn't like this in SDP initiated playback if (!m_bSDPInitiated) { m_pIDInfo->SetPropertyCString("Pragma", pPragma); }#if 0 IHXBuffer* pPasswordBuffer; if (m_pPreferences && m_pPreferences->ReadPref("LoadTestPassword", pPasswordBuffer) == HXR_OK) { char szLoadTestPasswordKey[HX_COMPANY_ID_KEY_SIZE] = {0}; /* Flawfinder: ignore */ // create the encrypted key CalcCompanyIDKey((const char*)pPasswordBuffer->GetBuffer(), (const char*)szStarttime, (const char*)"LoadTestID", (const char*)pRCMagic1, (const char*)pMagic2, (UCHAR*) &szLoadTestPasswordKey[0]); char szEncodedLTP[HX_COMPANY_ID_KEY_SIZE * 2]; // probably overkill /* Flawfinder: ignore */ BinTo64((const BYTE*)szLoadTestPasswordKey, HX_COMPANY_ID_KEY_SIZE, szEncodedLTP); IHXBuffer* pEncodedLTPBuffer = new CHXBuffer(); pEncodedLTPBuffer->AddRef(); pEncodedLTPBuffer->Set((const UCHAR*)szEncodedLTP, strlen(szEncodedLTP)+1); m_pIDInfo->SetPropertyCString("LoadTestPassword", pEncodedLTPBuffer); pEncodedLTPBuffer->Release(); HX_RELEASE(pPasswordBuffer); /* * XXXSMP Very poor way to set a requirement. This won't work * as soon rmartsp needs to send other requirements. Comment * in rmartsp about this. */ const UINT8 pRequireStr[] = "com.real.load-test-password-enabled"; IHXBuffer* pReq = new CHXBuffer(); pReq->AddRef(); pReq->Set(pRequireStr, sizeof(pRequireStr) + 1); m_pIDInfo->SetPropertyCString("Require", pReq); pReq->Release(); }#endif if (pRegionData) { m_pIDInfo->SetPropertyCString("RegionData", pRegionData); } HX_RELEASE(pGUID); HX_RELEASE(pClientID); HX_RELEASE(pRegionData); HX_RELEASE(pPragma); /* * XXX...This had better get fixed under full IRMA (should * be done with QueryInterface) */ RTSPClientProtocol* pClientProtocol = NULL;#if defined(HELIX_FEATURE_RDT) pClientProtocol = new RTSPClientProtocolExt();#else pClientProtocol = new RTSPClientProtocol();#endif /* HELIX_FEATURE_RDT */ m_pProtocolLib = (IHXRTSPClientProtocol*)pClientProtocol; if (!m_pProtocolLib) { return HXR_OUTOFMEMORY; } m_pProtocolLib->AddRef(); if (m_bHTTPOnly) { IHXBuffer* pBuffer = NULL; const char* pszURL = NULL; pCloakValues = new CHXHeader(); pCloakValues->AddRef(); if (HXR_OK == m_pIDInfo->GetPropertyCString("ClientID", pBuffer)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -