rtspclnt.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:217k
- HX_RESULT
- RTSPClientProtocol::handleSetParamResponse(RTSPResponseMessage* pMsg)
- {
- const char* pPIP = 0;
- const char* pPPort = 0;
- const char* pPSourcePort = 0;
- IHXValues* pValues = NULL;
- HX_RESULT theErr = HXR_FAIL;
- m_bKeepLiveResponsed = TRUE;
- if (m_pResp)
- {
- if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- if (m_bNonRSRTP)
- {
- return m_pResp->HandleSetParameterResponse(HXR_OK);
- }
- else
- {
- return m_pResp->HandleSetParameterResponse(HXR_FAIL);
- }
- }
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- MIMEHeader* pIP = pMsg->getHeader("MulticastIP");
- if (pIP)
- {
- MIMEHeaderValue* pHeaderValue = pIP->getFirstHeaderValue();
- if (pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if (pParam)
- {
- pPIP = (const char*)pParam->m_attribute;
- }
- }
- }
- MIMEHeader* pPort = pMsg->getHeader("MulticastPort");
- if (pPort)
- {
- MIMEHeaderValue* pHeaderValue = pPort->getFirstHeaderValue();
- if (pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if (pParam)
- {
- pPPort = (const char*)pParam->m_attribute;
- }
- }
- }
- MIMEHeader* pSourcePort = pMsg->getHeader("MulticastSourcePort");
- if (pSourcePort)
- {
- MIMEHeaderValue* pHeaderValue = pSourcePort->getFirstHeaderValue();
- if (pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if (pParam)
- {
- pPSourcePort = (const char*)pParam->m_attribute;
- }
- }
- }
- if (pPIP && pPPort && pPSourcePort)
- {
- // multicast!!!
- UINT16 nToPort = atoi(pPPort);
- (*m_pTransportMPortMap)[nToPort] =
- (*m_pTransportStreamMap)[0];
- IHXUDPSocket* pUDPSocket = 0;
- UDPResponseHelper* pUDPResponseHelper = NULL;
- IHXSetSocketOption* pSockOpt = NULL;
- if (!m_pNetworkServices)
- {
- return HXR_OUTOFMEMORY;
- }
- if (HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket))
- {
- return HXR_FAIL;
- }
- pUDPResponseHelper = new UDPResponseHelper(this, nToPort);
- if (!pUDPResponseHelper)
- {
- return HXR_OUTOFMEMORY;
- }
- pUDPResponseHelper->AddRef();
- m_UDPResponseHelperList.AddTail(pUDPResponseHelper);
- pUDPSocket->Init(0, nToPort, pUDPResponseHelper);
- // set option before it binds
- if (HXR_OK == pUDPSocket->QueryInterface(IID_IHXSetSocketOption,
- (void**)&pSockOpt))
- {
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
- HX_RELEASE(pSockOpt);
- }
- pUDPSocket->Bind(HXR_INADDR_ANY, nToPort);
- theErr = pUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- ((RTSPTransport*)((*m_pTransportMPortMap)[nToPort]))->
- JoinMulticast(DwToHost(HXinet_addr(pPIP)), nToPort, pUDPSocket);
- HX_RELEASE(pUDPSocket);
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- MIMEHeader* pStatsInterval = pMsg->getHeader("UpdateStatsInterval");
- if (pStatsInterval)
- {
- MIMEHeaderValue* pHeaderValue = pStatsInterval->getFirstHeaderValue();
- if (pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- if (pParam)
- {
- // stats interval
- UINT32 ulStatsInterval = (UINT32) atoi((const char*)pParam->m_attribute);
- pValues = new CHXHeader;
- if( pValues )
- {
- pValues->AddRef();
- pValues->SetPropertyULONG32("UpdateStatsInterval", ulStatsInterval);
- }
- else
- {
- theErr = HXR_OUTOFMEMORY;
- }
- }
- }
- }
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- if( theErr != HXR_OUTOFMEMORY )
- {
- theErr = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pValues);
- }
- HX_RELEASE(pValues);
- }
- return theErr;
- }
- HX_RESULT
- RTSPClientProtocol::handleTeardownResponse(RTSPResponseMessage* pMsg)
- {
- if(m_pResp)
- {
- if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- m_pResp->HandleTeardownResponse(HXR_FAIL);
- }
- else
- {
- m_pResp->HandleTeardownResponse(HXR_OK);
- }
- }
- /*
- * The control channel is now closed
- */
- return HXR_NET_SOCKET_INVALID;
- }
- HX_RESULT
- RTSPClientProtocol::handleRecordResponse(RTSPResponseMessage* pMsg)
- {
- if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- return m_pResp->HandleRecordResponse(HXR_FAIL);
- }
- if (m_bConnectionlessControl)
- {
- closeSocket();
- if (HXR_OK ==
- m_pResp->QueryInterface(IID_IHXConnectionlessControl,
- (void**)&m_pConnectionlessControl))
- {
- m_pConnectionCheckCallback = new ConnectionCheckCallback(this);
- m_pConnectionCheckCallback->AddRef();
- m_uConnectionCheckCallbackHandle =
- m_pScheduler->RelativeEnter(m_pConnectionCheckCallback,
- m_uConnectionTimeout * 1000);
- }
- }
- return m_pResp->HandleRecordResponse(HXR_OK);
- }
- HX_RESULT
- RTSPClientProtocol::handlePauseResponse(RTSPResponseMessage* pMsg)
- {
- /*
- * XXX...Bruce is there anything to do here?
- */
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientProtocol::handlePlayResponse(RTSPResponseMessage* pMsg,
- RTSPPlayMessage* pPlayMsg)
- {
- /* Message Format:
- * RTSP/0.5 200 302 OK
- * RTP-Info: url=foo/streamid=0;seq=32;rtptime=40182123,
- * url=foo/streamid=1;seq=410;rtptime=40199211
- */
- if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- HX_RESULT hr = HXR_FAIL;
- if(pMsg->errorCodeAsUINT32() == 456)
- hr = HXR_INVALID_OPERATION;
- return m_pResp->HandlePlayResponse(hr);
- }
- MIMEHeader* pSequence = pMsg->getHeader("RTP-Info");
- MIMEHeaderValue* pSeqValue = 0;
- UINT16 streamID = 0;
- UINT16 seqNum = 0;
- UINT32 ulRTPTime = 0;
- const char* pControl = 0;
- RTPInfoEnum RTPErr;
- BOOL bSomeRTPInfoSet = FALSE;
- if (pSequence)
- {
- pSeqValue = pSequence->getFirstHeaderValue();
- }
- // per spec., "RTP-Info" has to be present in the 1st Play
- // response header received, regardless whether the transport
- // is TNG or RTP
- if (!pSeqValue && !m_bSeqValueReceived)
- {
- // XXXGo - interop hack
- if ((!(m_bIPTV || m_bColumbia)) || (m_pControlToStreamNoMap == NULL))
- {
- return m_pResp->HandlePlayResponse(HXR_BAD_SERVER);
- }
- }
- if (pSeqValue)
- {
- do
- {
- RTPErr = parseRTPInfoHeader(pSeqValue, streamID, seqNum,
- ulRTPTime, pControl);
- // if m_pControlToStreamNoMap, don't trust the parseRTPInfoHeader
- // because RTP-Info url could be not what we expect and still be ok with
- // spec
- HX_ASSERT(pControl);
- RTSPStreamInfo* pInfo = getStreamInfoFromSetupRequestURL(pControl);
- if (pInfo)
- {
- streamID = pInfo->m_streamNumber;
- }
- pControl = 0;
- if (RTPINFO_ERROR != RTPErr)
- {
- SetRTPInfo(streamID, seqNum, ulRTPTime, RTPErr);
- bSomeRTPInfoSet = TRUE;
- }
- pSeqValue = pSequence->getNextHeaderValue();
- } while (pSeqValue);
- }
- // If we did not receive any RTP Info,
- // just tell all streams not to wait for it
- if (!bSomeRTPInfoSet && m_pControlToStreamNoMap)
- {
- CHXMapStringToOb::Iterator i;
- UINT32* pul;
- for (i = m_pControlToStreamNoMap->Begin();
- i != m_pControlToStreamNoMap->End();
- ++i)
- {
- pul = (UINT32*)(*i);
- streamID = (UINT16) (*pul);
- SetRTPInfo(streamID, 0, 0, RTPINFO_EMPTY);
- }
- }
- m_bSeqValueReceived = TRUE;
- if (m_bConnectionlessControl)
- {
- closeSocket();
- }
- MIMEHeader* pXPredecPeriod = pMsg->getHeader("x-initpredecbufperiod");
- if (pXPredecPeriod)
- {
- MIMEHeaderValue* pPrerollValue = pXPredecPeriod->getFirstHeaderValue();
- if (pPrerollValue)
- {
- const char* pStart = pPrerollValue->value();
- char* pEnd = 0;
- ULONG32 ulValue = strtoul(pStart, &pEnd, 10);
- if (*pStart && !*pEnd)
- {
- // Handle updated preroll condition
- m_pResp->HandlePrerollChange(RTSP_PREROLL_PREDECBUFPERIOD,
- ulValue);
- }
- }
- }
- // Update range entries
- MIMEHeader* pRange = pMsg->getHeader("Range");
- if (pRange)
- {
- pSeqValue = pRange->getFirstHeaderValue();
- INT32 nFrom = 0, nTo = 0;
- if (pSeqValue)
- {
- MIMEParameter* pParam = pSeqValue->getFirstParameter();
- if (pParam)
- {
- const char* pRange = (const char*) pParam->m_attribute;
- const char* pDash = NULL;
- char* pStopString;
- double dTemp;
- if (pRange)
- {
- dTemp = strtod(pRange, &pStopString);
- nFrom = (INT32)(dTemp * 1000);
- pDash = strrchr(pRange, '-');
- }
- if (pDash)
- {
- dTemp = strtod(pDash + 1, &pStopString);
- nTo = (INT32)(dTemp * 1000);
- }
- }
- }
- if (!m_transportRequestList.IsEmpty())
- {
- RTSPTransportRequest* pRequest =
- (RTSPTransportRequest*)m_transportRequestList.GetHead();
- RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo && nTo)
- {
- // set the range in transport...only for RTP
- pTransInfo->m_pTransport->RTSPTransport::setPlayRange(nFrom, nTo);
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- }
- return m_pResp->HandlePlayResponse(HXR_OK);
- }
- HX_RESULT
- RTSPClientProtocol::handleSetupResponse(RTSPResponseMessage* pMsg,
- RTSPSetupMessage* pSetupMsg)
- {
- HX_RESULT status = HXR_OK;
- UINT16 streamNumber = 0;
- IHXValues* pReconnectValues = NULL;
- RTSPStreamInfo* pStreamInfo = 0;
- if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
- {
- status = handleAuthentication(pMsg);
- return status;
- }
- else if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- return m_pResp->HandleSetupResponse(HXR_BAD_TRANSPORT);
- }
- /* SETUP succeeded */
- m_setupResponseCount++;
- // we need to find the right StreamInfo obj..
- pStreamInfo = getStreamInfoFromSetupRequestURL(pSetupMsg->url());
- if(!pStreamInfo)
- {
- return m_pResp->HandleSetupResponse(HXR_BAD_TRANSPORT);
- }
- else
- {
- streamNumber = pStreamInfo->m_streamNumber;
- }
- CHXString reconnectFlag = pMsg->getHeaderValue("Reconnect");
- if (reconnectFlag != "" && strcasecmp((const char*)reconnectFlag, "false") == 0)
- {
- pReconnectValues = new CHXHeader();
- pReconnectValues->AddRef();
- pReconnectValues->SetPropertyULONG32("Reconnect", 0);
- }
- else
- {
- MIMEHeader* pHeader = pMsg->getHeader("Alternate-Server");
- if (pHeader)
- {
- RetrieveReconnectInfo(pHeader, ALTERNATE_SERVER, pReconnectValues);
- }
- pHeader = pMsg->getHeader("Alternate-Proxy");
- if (pHeader)
- {
- RetrieveReconnectInfo(pHeader, ALTERNATE_PROXY, pReconnectValues);
- }
- }
- if (pReconnectValues)
- {
- m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
- }
- HX_RELEASE(pReconnectValues);
- CHXString sessionID = pMsg->getHeaderValue("Session");
- if(sessionID != "")
- {
- int i;
- if (-1 != (i = sessionID.Find(';')))
- {
- m_sessionID = sessionID.Left(i);
- }
- else
- {
- m_sessionID = sessionID;
- }
- }
- status = handleSetupResponseExt(pStreamInfo, pMsg, pSetupMsg);
- UINT16 nStreamCount = (UINT16)m_streamInfoList.GetCount();
- if(m_setupResponseCount == 1 && (nStreamCount > 1))
- {
- // first time, send the rest...
- sendRemainingSetupRequests();
- }
- if(m_setupResponseCount == nStreamCount)
- {
- // all done!
- CHXSimpleList::Iterator i;
- for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
- {
- RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
- RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
- while(pTransInfo)
- {
- if (BUFFER_DEPTH_UNDEFINED == m_ulBufferDepth)
- {
- break;
- }
- HX_RESULT hresult =
- pTransInfo->m_pTransport->SetResendBufferDepth
- (
- m_ulBufferDepth
- );
- if (HXR_OK != hresult)
- {
- return hresult;
- }
- pTransInfo = pRequest->getNextTransportInfo();
- }
- }
- // we don't need this anymore...
- HX_RELEASE(m_pSetupRequestHeader);
- return m_pResp->HandleSetupResponse(status);
- }
- else
- {
- return status;
- }
- }
- HX_RESULT
- RTSPClientProtocol::handleSetupResponseExt(RTSPStreamInfo* pStreamInfo,
- RTSPResponseMessage* pMsg,
- RTSPSetupMessage* pSetupMsg)
- {
- HX_RESULT status = HXR_OK;
- // get transport info
- CHXString transportType;
- UINT16 localPort = 0;
- UINT16 streamNumber = pStreamInfo->m_streamNumber;
- MIMEHeader* pTransport = pMsg->getHeader("Transport");
- if(pTransport)
- {
- MIMEHeaderValue* pValue = pTransport->getFirstHeaderValue();
- if(!pValue)
- {
- // return some awful error
- }
- RTSPTransportRequest* pRequest = getTransportRequest(pValue);
- if(!pRequest)
- {
- // return another awful error
- return HXR_FAIL;
- }
- m_pSession->m_bChallengeMet = TRUE;
- m_pSession->m_bChallengeDone = TRUE;
- RTSPTransportInfo* pTransInfo = pRequest->getTransportInfo(streamNumber);
- UINT16 resendPort = 0;
- // get the server address we are connecting to
- // used to filter out any UDP packets received from 3rd party
- if (m_pSocket->GetForeignAddress(m_ulConnectToAddr) != HXR_OK)
- {
- HX_ASSERT(FALSE);
- status = HXR_BAD_TRANSPORT;
- }
- UINT32 foreignAddr = 0;
- if (m_foreignAddr != 0)
- {
- foreignAddr = m_foreignAddr;
- }
- else
- {
- foreignAddr = m_ulConnectToAddr;
- }
- resendPort = pRequest->m_sResendPort;
- RTSPTransport* pTrans = pTransInfo->m_pTransport;
- RTCPBaseTransport* pRTCPTrans = pTransInfo->m_pRTCPTransport;
- pStreamInfo->m_sPort = pTransInfo->m_sPort;
- HX_ASSERT(pTrans);
- #if defined(HELIX_FEATURE_RTP)
- switch(pRequest->m_lTransportType)
- {
- case RTSP_TR_RTP_TCP:
- {
- if ((!m_bHasSyncMasterStream) &&
- (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
- {
- pStreamInfo->m_bIsSyncMaster = TRUE;
- m_bHasSyncMasterStream = TRUE;
- }
- pTrans->addStreamInfo(pStreamInfo);
- (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
- m_pSession->setProtocolInterleave(this,
- pRequest->m_tcpInterleave);
- m_pSession->setProtocolInterleave(this,
- pRequest->m_tcpInterleave+1);
- ((RTPTCPTransport*)pTrans)->
- setInterleaveChannel(pRequest->m_tcpInterleave);
- ((RTCPTCPTransport*)pRTCPTrans)->
- setInterleaveChannel(pRequest->m_tcpInterleave+1);
- if (!m_sessionID.IsEmpty())
- {
- pTrans->setSessionID(m_sessionID);
- }
- mapTransportChannel(pTrans, pRequest->m_tcpInterleave);
- mapTransportChannel(pRTCPTrans, pRequest->m_tcpInterleave+1);
- mapControlToStreamNo(pStreamInfo->m_streamControl,
- pStreamInfo->m_streamNumber);
- /* Temporary */
- m_uProtocolType = 3;
- }
- break;
- case RTSP_TR_RTP_UDP:
- {
- if ((!m_bHasSyncMasterStream) &&
- (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
- {
- pStreamInfo->m_bIsSyncMaster = TRUE;
- m_bHasSyncMasterStream = TRUE;
- }
- pTrans->addStreamInfo(pStreamInfo);
- (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
- (*m_pTransportPortMap)[pTransInfo->m_sPort] = pTrans;
- (*m_pTransportPortMap)[pTransInfo->m_sPort+1] = pRTCPTrans;
- mapControlToStreamNo(pStreamInfo->m_streamControl, pStreamInfo->m_streamNumber);
- ((RTPUDPTransport*)pTrans)->setForeignAddress(foreignAddr, resendPort);
- ((RTCPUDPTransport*)pRTCPTrans)->setForeignAddress(foreignAddr, resendPort+1);
- if (!m_sessionID.IsEmpty())
- {
- pTrans->setSessionID(m_sessionID);
- }
- /* Temporary */
- m_uProtocolType = 2;
- }
- break;
- default:
- {
- status = HXR_BAD_TRANSPORT;
- }
- break;
- }
- #endif /* HELIX_FEATURE_RTP */
- }
- return status;
- }
- HX_RESULT
- RTSPClientProtocol::handleAnnounceResponse(RTSPResponseMessage* pMsg)
- {
- HX_RESULT rc = HXR_OK;
- if(!m_bSetupRecord) // better only get one of these if recording...
- {
- return HXR_FAIL;
- }
- if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
- {
- rc = handleAuthentication(pMsg);
- return rc;
- }
- else if(strcmp(pMsg->errorCode(), "409") == 0)
- {
- return m_pResp->HandleStreamRecordDescriptionResponse(HXR_ALREADY_OPEN, 0);
- }
- else if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- return m_pResp->HandleStreamRecordDescriptionResponse(HXR_FAIL, 0);
- }
- 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);
- IHXValues* pResponseHeaders = NULL;
- if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
- {
- rc = m_pResp->HandleStreamRecordDescriptionResponse(HXR_OK,
- pResponseHeaders);
- }
- else
- {
- rc = m_pResp->HandleStreamRecordDescriptionResponse(HXR_FAILED,
- NULL);
- }
- HX_RELEASE(pResponseHeaders);
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::handleDescribeResponse(RTSPResponseMessage* pMsg)
- {
- HX_RESULT rc = HXR_OK;
- if(m_bSetupRecord) // better only get one of these if playing...
- {
- return HXR_FAIL;
- }
- if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
- {
- rc = handleAuthentication(pMsg);
- return rc;
- }
- else if(pMsg->errorCodeAsUINT32() == 551)
- {
- // A Require option was not supported.
- // We could check the Unsupported header
- // to see which one(s) failed, but
- // since we only support one right now..
- m_bEntityRequired = FALSE;
- // Re-Send the describe w/o the Require..
- return m_pResp->HandleStreamDescriptionResponse
- (
- HXR_OK,
- 0,
- 0,
- 0
- );
- }
- else if(strcmp(pMsg->errorCode(), "200") != 0)
- {
- return m_pResp->HandleStreamDescriptionResponse
- (
- HXR_DOC_MISSING,
- 0,
- 0,
- 0
- );
- }
- // We do not handle content-encoding
- MIMEHeader* pContentEncoding = pMsg->getHeader("Content-Encoding");
- if(pContentEncoding)
- {
- if (pContentEncoding->getFirstHeaderValue())
- {
- return HXR_UNEXPECTED_MSG;
- }
- }
- // Set Context for use by sendSetupRequestMessage()
- CHXString sessionID = pMsg->getHeaderValue("ETag");
- if(!sessionID.IsEmpty())
- {
- m_sessionID = sessionID;
- }
- IHXValues* pRFC822Headers = NULL;
- getRFC822Headers(pMsg, pRFC822Headers);
- if(pRFC822Headers)
- {
- // XXXGo - interop hack...It should be "Server", but IPTV put this
- // string in "User-Agent"...
- IHXBuffer* pAgent = NULL;
- if (pRFC822Headers->GetPropertyCString("Server", pAgent) != HXR_OK)
- {
- // try this...
- pRFC822Headers->GetPropertyCString("User-Agent", pAgent);
- }
- if (pAgent)
- {
- if (strncasecmp((const char*)pAgent->GetBuffer(), "Columbia RTSP Server",
- 20) == 0)
- {
- m_bColumbia = TRUE;
- m_bNoKeepAlive = TRUE;
- }
- else if (strncasecmp((const char*)pAgent->GetBuffer(), "Cisco IPTV",
- 10) == 0)
- {
- m_bIPTV = TRUE;
- }
- else if (strncasecmp((const char*)pAgent->GetBuffer(), "Cisco IP/TV",
- 11) == 0)
- {
- m_bIPTV = TRUE;
- }
- else if (strncasecmp((const char*)pAgent->GetBuffer(), "QTSS",
- 4) == 0)
- {
- // once we send SET_PARAM for a keep alive, QTS won't be
- // responsive for any other request...so don't send
- // keep alive.
- m_bNoKeepAlive = TRUE;
- m_bForceUCaseTransportMimeType = TRUE;
- }
- else if (strncasecmp((const char*)pAgent->GetBuffer(), "DSS",
- 3) == 0)
- {
- m_bForceUCaseTransportMimeType = TRUE;
- }
- HX_RELEASE(pAgent);
- }
- IHXKeyValueList* pRFC822List = NULL;
- if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
- {
- m_pResponseHeaders->AppendAllListItems(pRFC822List);
- }
- HX_RELEASE(pRFC822List);
- }
- HX_RELEASE(pRFC822Headers);
- // Respond to Client Challenge to prove that we are a RealClient
- if (!m_pSession->m_bChallengeDone)
- {
- RetrieveChallenge(pMsg);
- }
- // We need a content base entry to handle relative urls.
- // Check for one in the order specified in:
- // http://www.zvon.org/tmRFC/RFC2326/Output/chapter19.html
- MIMEHeader* pContentBaseHeader = pMsg->getHeader("Content-Base");
- if(pContentBaseHeader)
- {
- MIMEHeaderValue* pValue = pContentBaseHeader->getFirstHeaderValue();
- m_contentBase = pValue->value();
- }
- if (m_contentBase.IsEmpty())
- {
- pContentBaseHeader = pMsg->getHeader("Content-Location");
- if(pContentBaseHeader)
- {
- MIMEHeaderValue* pValue = pContentBaseHeader->getFirstHeaderValue();
- m_contentBase = pValue->value();
- }
- }
- if (m_contentBase.IsEmpty())
- {
- INT32 nOffset = m_url.ReverseFind('/');
- m_contentBase = m_url.Left(nOffset+1);
- }
- // Format the content base member
- if (m_contentBase[m_contentBase.GetLength()-1] != '/')
- {
- INT32 nOffset = m_contentBase.ReverseFind('/');
- m_contentBase.SetAt(nOffset+1, ' ');
- m_contentBase.GetBufferSetLength(nOffset+1);
- }
- MIMEHeader* pContentTypeHeader = pMsg->getHeader("Content-type");
- MIMEHeader* pContentLengthHeader = pMsg->getHeader("Content-length");
- if(pContentTypeHeader && pContentLengthHeader)
- {
- MIMEHeaderValue* pContentValue =
- pContentTypeHeader->getFirstHeaderValue();
- if(!pContentValue)
- {
- // error
- rc = HXR_FAIL;
- }
- else
- {
- CHXBuffer* pBuffer = new CHXBuffer;
- if(pBuffer)
- {
- pBuffer->AddRef();
- rc = pBuffer->Set((BYTE*)pMsg->getContent(), strlen(pMsg->getContent())+1);
- if( rc == HXR_OUTOFMEMORY )
- {
- HX_RELEASE(pBuffer);
- goto cleanup;
- }
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- rc = ParseSDP(pContentValue->value(), pBuffer);
- if (HXR_OK == rc)
- {
- 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);
- }
- }
- rc = m_pResp->HandleStreamDescriptionResponse
- (
- HXR_OK,
- m_pSDPFileHeader,
- m_pSDPStreamHeaders,
- pResponseHeaders
- );
- }
- HX_RELEASE(pResponseHeaders);
- RemoveSDPHeaders();
- }
- HX_RELEASE(pBuffer);
- }
- }
- else
- {
- rc = HXR_FAILED;
- }
- cleanup:
- if (HXR_OK != rc)
- {
- rc = m_pResp->HandleStreamDescriptionResponse
- (
- rc,
- 0,
- 0,
- 0
- );
- }
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::sendInitialMessage(RTSPClientSession* pSession,
- IHXTCPSocket* pSocket)
- {
- HX_RESULT rc = HXR_OK;
- UINT32 seqNo = 0;
- RTSPOptionsMessage* pMsg = NULL;
- IHXBuffer* pBuffer = NULL;
- m_pMutex->Lock();
- // Assumption is we will send no options messages while waiting
- // for our session time out options response.
- HX_ASSERT(!m_bKeepAlivePending);
- if (m_bNonRSRTP)
- {
- rc = m_pResp->HandleOptionsResponse(HXR_OK, NULL);
- goto cleanup;
- }
- if (!m_bSessionSucceeded)
- {
- HX_ASSERT(!m_pSession && !m_pSocket);
- m_pSession = pSession;
- m_pSocket = pSocket;
- }
- pMsg = new RTSPOptionsMessage;
- // construct "rtsp://%-.200s:%u"
- m_url = "rtsp://";
- m_url += m_hostName.Left(200);
- m_url += ':';
- m_url.AppendULONG(m_foreignPort);
- pMsg->setURL(m_url);
- pMsg->addHeader("User-Agent", m_versionString);
- /*
- * XXXSMP m_pSessionHeaders can include a "Require" tag from rmacore.
- * Yes this is ugly, and needs fixing when we want to send more options
- */
- if (m_pSessionHeaders &&
- HXR_OK == m_pSessionHeaders->GetPropertyCString("ConnectionlessControl",
- pBuffer))
- {
- m_bConnectionlessControl =
- (strcasecmp((const char*)pBuffer->GetBuffer(), "on") == 0) ?
- TRUE : FALSE;
- pBuffer->Release();
- }
- addRFC822Headers(pMsg, m_pSessionHeaders);
- seqNo = m_pSession->getNextSeqNo(this);
- rc = sendRequest(pMsg, seqNo);
- if (!m_bSessionSucceeded)
- {
- m_pSession = NULL;
- m_pSocket = NULL;
- }
- cleanup:
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::getStreamDescriptionMimeType(char*& pMimeType)
- {
- HX_RESULT rc = HXR_OK;
- IHXStreamDescription* pSD = 0;
- IHXPlugin2Handler* pPlugin2Handler = NULL;
- // we have to have either an IHXPluginHandler or an IHXPlugin2Handler
- m_pContext->QueryInterface(IID_IHXPlugin2Handler,
- (void**)&pPlugin2Handler);
- if(pPlugin2Handler)
- {
- UINT32 unIndex;
- if (HXR_OK == pPlugin2Handler->FindIndexUsingStrings(PLUGIN_CLASS,
- PLUGIN_STREAM_DESC_TYPE,
- NULL,
- NULL,
- NULL,
- NULL,
- unIndex))
- {
- IHXValues* pValues;
- pPlugin2Handler->GetPluginInfo(unIndex, pValues);
- IHXBuffer* pBuffer;
- pValues->GetPropertyCString(PLUGIN_STREAMDESCRIPTION, pBuffer);
- pValues->Release();
- const char* pTemp = (const char*)pBuffer->GetBuffer();
- pMimeType = new_string(pTemp);
- pBuffer->Release();
- }
- else
- {
- rc = HXR_FAIL;
- }
- HX_RELEASE(pPlugin2Handler);
- }
- #if defined(HELIX_FEATURE_SERVER)
- else
- {
- // ok we do not have an IHXPlugin2Handler (we must be in the server)
- // so get the PluginHandler
- PluginHandler* pPHandler = 0;
- m_pContext->QueryInterface(IID_IHXPluginHandler,
- (void**)&pPHandler);
- if(pPHandler)
- {
- PluginHandler::StreamDescription* pSDHandler;
- pSDHandler = pPHandler->m_stream_description_handler;
- UINT32 ulNumPlugins = pSDHandler->GetNumOfPlugins();
- if(ulNumPlugins > 0)
- {
- // get the first one...
- char* ppszDllPath = 0;
- char* ppszDescription = 0;
- char* ppszCopyright = 0;
- char* ppszMoreInfo = 0;
- BOOL pbMultiple = FALSE;
- char* ppszMimeType = 0;
- pSDHandler->GetPluginInfo(0, &ppszDllPath, &ppszDescription,
- &ppszCopyright, &ppszMoreInfo, &pbMultiple,
- &ppszMimeType);
- pMimeType = new_string(ppszMimeType);
- rc = HXR_OK;
- }
- else
- {
- rc = HXR_FAIL;
- }
- pPHandler->Release();
- }
- else
- {
- rc = HXR_FAIL;
- }
- }
- #endif /* HELIX_FEATURE_SERVER */
- return rc;
- }
- IHXStreamDescription*
- RTSPClientProtocol::getStreamDescriptionInstance(const char* pMimeType)
- {
- IHXStreamDescription* pSD =
- HXStreamDescriptionHelper::GetInstance(m_pContext, pMimeType);
- #if defined(HELIX_FEATURE_SERVER)
- if (!pSD)
- {
- // we don't have a plugin2handler ... we must be in the
- // server ... ask for a plugin handler
-
- PluginHandler* pPHandler = 0;
- m_pContext->QueryInterface(IID_IHXPluginHandler, (void**)&pPHandler);
-
- const char* pFindMimeType = pMimeType;
- if(pPHandler)
- {
- PluginHandler::StreamDescription* pSDHandler;
- PluginHandler::Errors pluginResult;
- PluginHandler::Plugin* pPlugin;
- pSDHandler = pPHandler->m_stream_description_handler;
- pluginResult = pSDHandler->Find(pFindMimeType, pPlugin);
- if(PluginHandler::NO_ERRORS == pluginResult)
- {
- IUnknown* pInstance = 0;
- pPlugin->GetInstance(&pInstance);
- if(pInstance)
- {
- HX_RESULT rc;
- rc = pInstance->QueryInterface(IID_IHXStreamDescription,
- (void**)&pSD);
- if(rc == HXR_OK)
- {
- IHXPlugin* pSDPlugin = 0;
- rc = pSD->QueryInterface(IID_IHXPlugin,
- (void**)&pSDPlugin);
- if(rc == HXR_OK)
- {
- pSDPlugin->InitPlugin(m_pContext);
- pSDPlugin->Release();
- }
- }
- pInstance->Release();
- }
- pPlugin->ReleaseInstance();
- }
- pPHandler->Release();
- }
- }
- #endif
- return pSD;
- }
- void
- RTSPClientProtocol::reset()
- {
- HX_DELETE(m_pTransportStreamMap);
- HX_DELETE(m_pTransportPortMap);
- HX_DELETE(m_pTransportMPortMap);
- HX_DELETE(m_pTransportChannelMap);
- if (m_pControlToStreamNoMap)
- {
- CHXMapStringToOb::Iterator i;
- for(i=m_pControlToStreamNoMap->Begin();i!=m_pControlToStreamNoMap->End();++i)
- {
- UINT32* pul = (UINT32*)(*i);
- delete pul;
- }
- m_pControlToStreamNoMap->RemoveAll();
- HX_DELETE(m_pControlToStreamNoMap);
- }
- CHXSimpleList::Iterator i;
- for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
- {
- RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
- delete pRequest;
- }
- m_transportRequestList.RemoveAll();
- HX_RELEASE(m_pSetupRequestHeader);
- HX_RELEASE(m_pResolver);
- HX_RELEASE(m_pResp);
- HX_RELEASE(m_pConnectionlessControl);
- HX_RELEASE(m_pConnectionCheckCallback);
- HX_RELEASE(m_pContext);
- if (m_uConnectionCheckCallbackHandle)
- {
- m_pScheduler->Remove(m_uConnectionCheckCallbackHandle);
- m_uConnectionCheckCallbackHandle = 0;
- }
- HX_RELEASE(m_pTimeoutCallback);
- HX_DELETE(m_pSessionTimeout);
- }
- void
- RTSPClientProtocol::clearStreamInfoList()
- {
- CHXSimpleList::Iterator i;
- for(i=m_streamInfoList.Begin();
- i!=m_streamInfoList.End();
- ++i)
- {
- RTSPStreamInfo* pInfo = (RTSPStreamInfo*)(*i);
- delete pInfo;
- }
- m_streamInfoList.RemoveAll();
- }
- void
- RTSPClientProtocol::clearTransportRequestList()
- {
- CHXSimpleList::Iterator i;
- for (i = m_transportRequestList.Begin(); i != m_transportRequestList.End(); ++i)
- {
- RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
- delete pRequest;
- }
- m_transportRequestList.RemoveAll();
- }
- void
- RTSPClientProtocol::clearUDPResponseHelperList()
- {
- CHXSimpleList::Iterator i;
- for(i=m_UDPResponseHelperList.Begin();
- i!=m_UDPResponseHelperList.End();
- ++i)
- {
- UDPResponseHelper* pHelper = (UDPResponseHelper*)(*i);
- HX_RELEASE(pHelper);
- }
- m_UDPResponseHelperList.RemoveAll();
- }
- void
- RTSPClientProtocol::clearSocketStreamMap(CHXMapLongToObj*& pSocketStreamMap)
- {
- if(pSocketStreamMap)
- {
- CHXMapLongToObj::Iterator i;
- for(i=pSocketStreamMap->Begin();
- i!=pSocketStreamMap->End();++i)
- {
- IHXUDPSocket* pSocket = (IHXUDPSocket*)(*i);
- pSocket->Release();
- }
- delete pSocketStreamMap;
- pSocketStreamMap = 0;
- }
- }
- RTSPTransportRequest*
- RTSPClientProtocol::getTransportRequest(MIMEHeaderValue* pValue)
- {
- RTSPTransportRequest* pTransportRequest = 0;
- if(pValue)
- {
- UINT16 requestPort = 0;
- UINT16 resendPort = 0;
- INT8 tcpInterleave = 0;
- MIMEParameter* pParam = pValue->getFirstParameter();
- char pTransValue[256]; /* Flawfinder: ignore */
- strncpy(pTransValue, pParam->m_attribute,255);
- pTransValue[255] = ' ';
- pParam = pValue->getNextParameter();
- while(pParam)
- {
- if(0 == pParam->m_attribute.CompareNoCase("client_port"))
- {
- // value range in rtp
- const char* portString = (const char*)pParam->m_value;
- char* pFirstValue = (char*)strchr(portString, '-');
- if(pFirstValue)
- {
- *pFirstValue = 0; // get rid of second port value
- }
- requestPort = (UINT16)strtol(portString, 0, 10);
- }
- else if(0 == pParam->m_attribute.CompareNoCase("server_port"))
- {
- // value range in rtp
- const char* portString = (const char*)pParam->m_value;
- char* pFirstValue = (char*)strchr(portString, '-');
- if(pFirstValue)
- {
- *pFirstValue = 0; // get rid of second port value
- }
- resendPort = (UINT16)strtol(portString, 0, 10);
- }
- else if(0 == pParam->m_attribute.CompareNoCase("source"))
- {
- const char* serverAddress = (const char*) pParam->m_value;
- if ((m_foreignAddr = HXinet_addr(serverAddress)) ==
- INADDR_NONE)
- {
- /*
- * XXXtbradley should log a warning about invalid source
- * address.
- */
- m_foreignAddr = 0;
- }
- else
- {
- m_foreignAddr = DwToHost(m_foreignAddr);
- }
- }
- else if(0 == pParam->m_attribute.CompareNoCase("interleaved"))
- {
- // it could be a range in RTP (i.e. RTP-RTCP)
- const char* channelString = (const char*)pParam->m_value;
- char* pFirstValue = (char*)strchr(channelString, '-');
- if (pFirstValue)
- {
- //get rid of second channel value since the second value is
- //always one higher than the first
- *pFirstValue = 0;
- }
- tcpInterleave = (UINT8)strtol(channelString, 0, 10);
- }
- else if(0 == pParam->m_attribute.CompareNoCase("unicast"))
- {
- SafeStrCat(pTransValue, ";unicast", 256);
- }
- else if(0 == pParam->m_attribute.CompareNoCase("multicast"))
- {
- SafeStrCat(pTransValue, ";multicast", 256);
- }
- pParam = pValue->getNextParameter();
- }
- RTSPTransportTypeEnum transportType =
- RTSPTransportMimeMapper::getTransportType(pTransValue);
- CHXSimpleList::Iterator i;
- for(i=m_transportRequestList.Begin();
- i!=m_transportRequestList.End();++i)
- {
- RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
- if(pRequest->m_lTransportType == transportType)
- {
- pRequest->m_sPort = requestPort;
- pRequest->m_sResendPort = resendPort;
- pRequest->m_tcpInterleave = tcpInterleave;
- pTransportRequest = pRequest;
- }
- else
- {
- pRequest->m_bDelete = TRUE;
- }
- }
- }
- // remove transport requests marked as delete
- LISTPOSITION pos = m_transportRequestList.GetTailPosition();
- while(pos)
- {
- RTSPTransportRequest* pRequest =
- (RTSPTransportRequest*)m_transportRequestList.GetAt(pos);
- if(pRequest->m_bDelete)
- {
- delete pRequest;
- pos = m_transportRequestList.RemoveAt(pos);
- }
- else
- {
- m_transportRequestList.GetPrev(pos);
- }
- }
- return pTransportRequest;
- }
- void
- RTSPClientProtocol::messageDebugFileOut(const char* pMsg, BOOL bInbound)
- {
- if(m_bMessageDebug)
- {
- FILE* fp = fopen(m_messageDebugFileName, "a");
- if(!fp)
- {
- return;
- }
- if(bInbound)
- {
- fprintf(fp, "IN:n");
- }
- else
- {
- fprintf(fp, "OUT:n");
- }
- fprintf(fp, "%sn", pMsg);
- fclose(fp);
- }
- }
- /*
- * IHXThinnableSource methods.
- */
- /************************************************************************
- * Method:
- * IHXThinnableSource::LimitBandwidthByDropping
- * Purpose:
- *
- * Implemented by protocols that allow infinite thinnability through
- * LimitBandwidthByDropping
- */
- STDMETHODIMP
- RTSPClientProtocol::LimitBandwidthByDropping(UINT32 ulStreamNo,
- UINT32 ulBandwidthLimit)
- {
- if (!m_pIsMethodSupported[SET_PARAM])
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- pMsg->setURL(m_url);
- char tmp[128];
- SafeSprintf(tmp, 128, "stream=%d;LimitBandwidthByDropping=%d", ulStreamNo,
- ulBandwidthLimit);
- pMsg->addHeader("FrameControl", tmp);
- if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- HX_RESULT hr = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return hr;
- }
- STDMETHODIMP
- RTSPClientProtocol::SetDeliveryBandwidth(UINT32 ulBandwidth, UINT32 ulMsBackOff)
- {
- if (!m_pIsMethodSupported[SET_PARAM] || !m_pSession)
- {
- return HXR_OK;
- }
- m_pMutex->Lock();
- RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
- pMsg->setURL(m_url);
- char tmp[64];
- SafeSprintf(tmp, 64, "Bandwidth=%d;BackOff=%d", ulBandwidth, ulMsBackOff);
- pMsg->addHeader("SetDeliveryBandwidth", tmp);
- if (!m_sessionID.IsEmpty())
- {
- pMsg->addHeader("Session", m_sessionID);
- }
- UINT32 seqNo = m_pSession->getNextSeqNo(this);
- HX_RESULT hr = sendRequest(pMsg, seqNo);
- m_pMutex->Unlock();
- return hr;
- }
- HX_RESULT
- RTSPClientProtocol::closeSocket()
- {
- m_pSocket = 0;
- return m_pSession->closeSocket();
- }
- HX_RESULT
- RTSPClientProtocol::reopenSocket()
- {
- m_pMutex->Lock();
- m_pSession->m_bReopenSocket = TRUE;
- HX_RESULT hr = m_pSession->reopenSocket(this);
- m_pMutex->Unlock();
- return hr;
- }
- HX_RESULT
- RTSPClientProtocol::ReopenSocketDone(HX_RESULT status)
- {
- m_pMutex->Lock();
- HX_RESULT hresult = HXR_OK;
- m_pSession->m_bReopenSocket = FALSE;
- if (HXR_OK != status)
- {
- hresult = m_pResp->HandleProtocolError(status);
- goto exit;
- }
- HX_ASSERT(m_pControlBuffer);
- if (!m_pControlBuffer)
- {
- hresult = HXR_FAIL;
- goto exit;
- }
- hresult = sendControlMessage(m_pControlBuffer);
- m_pControlBuffer->Release();
- m_pControlBuffer = 0;
- exit:
- m_pMutex->Unlock();
- return hresult;
- }
- void
- RTSPClientProtocol::DoConnectionCheck()
- {
- m_uConnectionCheckCallbackHandle = 0;
- HX_ASSERT(m_pConnectionlessControl);
- if (!m_bConnectionAlive)
- {
- m_pConnectionlessControl->ConnectionCheckFailed(HXR_SERVER_TIMEOUT);
- return;
- }
- m_bConnectionAlive = FALSE;
- m_uConnectionCheckCallbackHandle =
- m_pScheduler->RelativeEnter(m_pConnectionCheckCallback,
- m_uConnectionTimeout * 1000);
- }
- void
- RTSPClientProtocol::GetForeignHostPort(char*& pHost, UINT16* pPort)
- {
- pHost = NULL;
- *pPort = 0;
- if (m_bUseProxy | m_bUseHTTPProxy)
- {
- pHost = new_string(m_hostName);
- if (m_bHTTPOnly)
- {
- *pPort = m_uCloakPort;
- }
- else
- {
- *pPort = m_foreignPort;
- }
- }
- }
- void
- RTSPClientProtocol::mapTransportChannel(RTSPTransport* pTran, UINT16 nChannel)
- {
- if (!m_pTransportChannelMap)
- {
- m_pTransportChannelMap = new CHXMapLongToObj();
- }
- (*m_pTransportChannelMap)[nChannel] = pTran;
- }
- /* Interop */
- void
- RTSPClientProtocol::mapControlToStreamNo(const char* pControl, UINT16 uStreamNo)
- {
- if (!m_pControlToStreamNoMap)
- {
- m_pControlToStreamNoMap = new CHXMapStringToOb();
- }
- UINT16* pu = new UINT16;
- *pu = uStreamNo;
- (*m_pControlToStreamNoMap)[pControl] = pu;
- }
- BOOL
- RTSPClientProtocol::getStreamNoFromControl(const char* pControl, REF(UINT16) uStreamNo)
- {
- // don't call if there is no map
- HX_ASSERT(m_pControlToStreamNoMap);
- UINT16* ul = NULL;
- if (m_pControlToStreamNoMap->Lookup(pControl, (void*&)ul))
- {
- uStreamNo = (UINT16)*ul;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- void
- RTSPClientProtocol::setSetupRequestURL(RTSPSetupMessage* pMsg,
- RTSPStreamInfo* pStreamInfo)
- {
- HX_ASSERT(pMsg && pStreamInfo);
- if (pStreamInfo->m_streamControl.Find("rtsp:") != -1)
- {
- // absolute url....just use this!
- pMsg->setURL(pStreamInfo->m_streamControl);
- }
- else if (!m_contentBase.IsEmpty())
- {
- // we have Content-Base RTSP header
- pMsg->setURL(m_contentBase + pStreamInfo->m_streamControl);
- }
- else if(!m_headerControl.IsEmpty())
- {
- // this is a=control in session description...
- pMsg->setURL(m_headerControl);
- }
- else
- {
- int lenURL = m_url.GetLength()+pStreamInfo->m_streamControl.GetLength()+15;
- char* setupURL = new char[lenURL];
- SafeSprintf(setupURL, lenURL,"%s/%s", (const char*)m_url,
- (const char*)pStreamInfo->m_streamControl);
- pMsg->setURL(setupURL);
- delete[] setupURL;
- }
- }
- RTSPStreamInfo*
- RTSPClientProtocol::getStreamInfoFromSetupRequestURL(const char* pUrl)
- {
- HX_ASSERT(pUrl);
- // we've created a Setup request url above. this is a reverse
- char* setupURL = NULL;
- BOOL bFoundIt = FALSE;
- RTSPStreamInfo* pStreamInfo = NULL;
- CHXSimpleList::Iterator i;
- // If we do not have control URL,
- // we can still proceed as long there is only one stream
- if (pUrl == NULL)
- {
- if (m_streamInfoList.GetCount() == 1)
- {
- return (RTSPStreamInfo*) m_streamInfoList.GetHead();
- }
- return NULL;
- }
- for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
- {
- pStreamInfo = (RTSPStreamInfo*)(*i);
- if(pStreamInfo->m_streamControl == pUrl)
- {
- // well, this is my lucky day
- bFoundIt = TRUE;
- break;
- }
- // - get stream identifier by parsing URL
- char* pStream = (char*)strrchr(pUrl, '/');
- if(pStream)
- {
- ++pStream; // pass '/'
- if(pStreamInfo->m_streamControl == (const char*)pStream)
- {
- bFoundIt = TRUE;
- break;
- }
- }
- if (!m_contentBase.IsEmpty())
- {
- if ((m_contentBase + pStreamInfo->m_streamControl) == pUrl)
- {
- // not so bad...
- bFoundIt = TRUE;
- break;
- }
- }
- if (!m_headerControl.IsEmpty())
- {
- if (m_headerControl == pStreamInfo->m_streamControl)
- {
- // phew....
- bFoundIt = TRUE;
- break;
- }
- }
- // Compare each portion of the url w/ our control
- pStream = (char*)strchr(pUrl, '/');
- while (pStream)
- {
- ++pStream; // pass '/'
- if(pStreamInfo->m_streamControl == (const char*)pStream)
- {
- bFoundIt = TRUE;
- break;
- }
- pStream = (char*)strchr(pStream, '/');
- }
- if (bFoundIt)
- {
- break;
- }
- // following the recommendation posted at:
- // http://www1.ietf.org/mail-archive/working-groups/mmusic/current/msg01245.html
- int lenURL = m_url.GetLength()+strlen(pUrl)+2;
- setupURL = new char[lenURL];
- SafeSprintf(setupURL, lenURL, "%s/%s", (const char*)m_url, pUrl);
- if (pStreamInfo->m_streamControl == (const char*)setupURL)
- {
- delete[] setupURL;
- bFoundIt = TRUE;
- break;
- }
- delete[] setupURL;
- }
- if (bFoundIt)
- {
- return pStreamInfo;
- }
- else
- {
- HX_ASSERT(!"streaminfo not found from setup request url");
- return NULL;
- }
- }
- STDMETHODIMP
- RTSPClientProtocol::InitPacketFilter(RawPacketFilter* pFilter)
- {
- m_pPacketFilter = pFilter;
- return HXR_OK;
- }
- void
- RTSPClientProtocol::LeavePrefetch(void)
- {
- m_bPrefetch = FALSE;
- SendMsgToTransport(LEAVE_PREFETCH);
- return;
- }
- void
- RTSPClientProtocol::EnterFastStart(void)
- {
- m_bFastStart = TRUE;
- SendMsgToTransport(ENTER_FASTSTART);
- return;
- }
- void
- RTSPClientProtocol::LeaveFastStart(void)
- {
- m_bFastStart = FALSE;
- SendMsgToTransport(LEAVE_FASTSTART);
- return;
- }
- void
- RTSPClientProtocol::InitCloak(UINT16* pCloakPorts,
- UINT8 nCloakPorts,
- IHXValues* pValues)
- {
- m_pCloakPorts = pCloakPorts;
- m_nCloakPorts = nCloakPorts;
- if (pValues)
- {
- m_pCloakValues = pValues;
- m_pCloakValues->AddRef();
- }
- }
- UINT16
- RTSPClientProtocol::GetCloakPortSucceeded(void)
- {
- return m_uCloakPort;
- }
- HX_RESULT
- RTSPClientProtocol::RetrieveChallenge(RTSPResponseMessage* pMessage)
- {
- return HXR_FAILED;
- }
- HX_RESULT
- RTSPClientProtocol::SetStatistics(UINT16 uStreamNumber,
- STREAM_STATS* pStats)
- {
- HX_RESULT rc = HXR_OK;
- #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
- RTSPTransport* pTrans = (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if (pTrans)
- {
- rc = pTrans->SetStatistics(uStreamNumber, pStats);
- }
- #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
- return rc;
- }
- HX_RESULT
- RTSPClientProtocol::extractRealmInformation(RTSPResponseMessage* pMsg)
- {
- #if defined(HELIX_FEATURE_AUTHENTICATION)
- // this is called from several places where authentication errors
- // are likely to occur. It then pulls out the realm for future reference.
- IHXRegistry* pRegistry = NULL;
- HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if (SUCCEEDED(retVal))
- {
- CHXString authString;
- authString = pMsg->getHeaderValue("Proxy-Authenticate");
- if (m_bUseProxy && !authString.IsEmpty())
- {
- IHXBuffer* pBuffer = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- if (SUCCEEDED(retVal))
- {
- HX_ASSERT(pMsg->errorCodeAsUINT32() == 407);
- retVal = pBuffer->Set((const unsigned char*)(const char*)authString,
- authString.GetLength()+1);
- UINT32 regid = pRegistry->GetId("proxy-authentication.rtsp.realm.recent");
- if( retVal == HXR_OUTOFMEMORY )
- {
- HX_RELEASE(pBuffer);
- HX_RELEASE(pRegistry);
- return retVal;
- }
- if (!regid)
- {
- pRegistry->AddStr("proxy-authentication.rtsp.realm.recent", pBuffer);
- }
- else
- {
- pRegistry->SetStrByName("proxy-authentication.rtsp.realm.recent", pBuffer);
- }
- HX_RELEASE(pBuffer);
- }
- }
- authString = pMsg->getHeaderValue("WWW-Authenticate");
- if (!authString.IsEmpty())
- {
- IHXBuffer* pBuffer = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- if (SUCCEEDED(retVal))
- {
- HX_ASSERT(pMsg->errorCodeAsUINT32() == 401);
- retVal = pBuffer->Set((const unsigned char*)(const char*)authString,
- authString.GetLength()+1);
- if( retVal == HXR_OUTOFMEMORY )
- {
- HX_RELEASE(pBuffer);
- HX_RELEASE(pRegistry);
- return retVal;
- }
- UINT32 regid = pRegistry->GetId("authentication.rtsp.realm.recent");
- if (!regid)
- {
- pRegistry->AddStr("authentication.rtsp.realm.recent", pBuffer);
- }
- else
- {
- pRegistry->SetStrByName("authentication.rtsp.realm.recent", pBuffer);
- }
- HX_RELEASE(pBuffer);
- }
- }
- HX_RELEASE(pRegistry);
- }
- return retVal;
- #else
- return HXR_NOTIMPL;
- #endif /* HELIX_FEATURE_AUTHENTICATION */
- }
- HX_RESULT
- RTSPClientProtocol::extractExistingAuthorizationInformation(IHXValues* pIHXValuesRequestHeaders)
- {
- #if defined(HELIX_FEATURE_AUTHENTICATION)
- if (pIHXValuesRequestHeaders)
- {
- const char* pName = NULL;
- IHXBuffer* pValue = NULL;
- HX_RESULT result = pIHXValuesRequestHeaders->GetFirstPropertyCString(pName, pValue);
- while (SUCCEEDED(result))
- {
- // check for proxy and www authentication stuff separately because
- // it's plausible that one request will have both of these.
- if (m_bUseProxy && !strcasecmp(pName, "Proxy-Authorization"))
- {
- HX_RESULT retVal = HXR_OK;
- IHXRegistry* pRegistry = NULL;
- retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pBuffer = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- UINT32 regid = 0;
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pHeaderBuffer = NULL;
- CHXString key;
- CHXString recentRealmInfo = "";
- key = "proxy-authentication.rtsp:";
- retVal = pRegistry->GetStrByName("proxy-authentication.rtsp.realm.recent",
- pHeaderBuffer);
- if (SUCCEEDED(retVal))
- {
- HX_ASSERT(pHeaderBuffer);
- recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
- HX_RELEASE(pHeaderBuffer);
- }
- key += "proxy-host:";
- key += recentRealmInfo;
- HX_ASSERT(!key.IsEmpty());
- retVal = pBuffer->Set(pValue->GetBuffer(), pValue->GetSize());
- if( retVal == HXR_OUTOFMEMORY )
- {
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeaderBuffer);
- HX_RELEASE(pRegistry);
- return retVal;
- }
- regid = pRegistry->GetId((const char*)key);
- if (!regid)
- {
- pRegistry->AddStr((const char*)key, pBuffer);
- }
- else
- {
- pRegistry->SetStrByName((const char*)key, pBuffer);
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeaderBuffer);
- }
- HX_RELEASE(pRegistry);
- }
- }
- if (!strcasecmp(pName, "Authorization"))
- {
- HX_RESULT retVal = HXR_OK;
- IHXRegistry* pRegistry = NULL;
- retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pBuffer = NULL;
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- UINT32 regid = 0;
- if (SUCCEEDED(retVal))
- {
- IHXBuffer* pHeaderBuffer = NULL;
- CHXString key;
- CHXString recentRealmInfo = "";
- key = "authentication.rtsp:";
- retVal = pRegistry->GetStrByName("authentication.rtsp.realm.recent",
- pHeaderBuffer);
- if (SUCCEEDED(retVal))
- {
- HX_ASSERT(pHeaderBuffer);
- recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
- HX_RELEASE(pHeaderBuffer);
- }
- key += m_hostName;
- key += ":";
- key += recentRealmInfo;
- HX_ASSERT(!key.IsEmpty());
- retVal = pBuffer->Set(pValue->GetBuffer(), pValue->GetSize());
- if( retVal == HXR_OUTOFMEMORY )
- {
- return retVal;
- }
- regid = pRegistry->GetId((const char*)key);
- if (!regid)
- {
- pRegistry->AddStr((const char*)key, pBuffer);
- }
- else
- {
- pRegistry->SetStrByName((const char*)key, pBuffer);
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeaderBuffer);
- }
- HX_RELEASE(pRegistry);
- }
- }
- HX_RELEASE(pValue);
- result = pIHXValuesRequestHeaders->GetNextPropertyCString(pName, pValue);
- }
- }
- return HXR_OK;
- #else
- return HXR_NOTIMPL;
- #endif /* HELIX_FEATURE_AUTHENTICATION */
- }
- void
- RTSPClientProtocol::appendAuthorizationHeaders(RTSPMessage* pMsg)
- {
- #if defined(HELIX_FEATURE_AUTHENTICATION)
- // This is currently getting called from sendPendingStreamDescription
- // although it's feasible that other rtsp messages will need authentication.
- // At this writing none of our servers or proxies do anything other than
- // DESCRIBE, so I'm omitting scattered calls to this routine so I don't
- // waste bandwidth. It's plausible that calling this from everywhere it calls
- // addRFC822Headers would be fully compliant, if a touch wasteful.
- // xxxbobclark
- IHXRegistry* pRegistry = NULL;
- HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if (SUCCEEDED(retVal))
- {
- CHXString strExistingAuthorizationHeader = pMsg->getHeaderValue("Authorization");
- CHXString strExistingProxyAuthorizationHeader = pMsg->getHeaderValue("Proxy-Authorization");
- if (strExistingAuthorizationHeader.IsEmpty())
- {
- // if it doesn't exist, see if we've remembered one we can
- // plop down here.
- CHXString key = "authentication.rtsp:";
- IHXBuffer* pFoundRealmBuffer = NULL;
- IHXBuffer* pBuffer = NULL;
- key += m_hostName;
- key += ":";
- retVal = pRegistry->GetStrByName("authentication.rtsp.realm.recent",
- pBuffer);
- if (SUCCEEDED(retVal))
- {
- key += CHXString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
- retVal = pRegistry->GetStrByName((const char*)key, pFoundRealmBuffer);
- if (SUCCEEDED(retVal))
- {
- CHXString strAuthHeader((const char*)pFoundRealmBuffer->GetBuffer(),
- pFoundRealmBuffer->GetSize());
- pMsg->addHeader("Authorization", (const char*)strAuthHeader);
- }
- }
- }
- if (m_bUseProxy && strExistingProxyAuthorizationHeader.IsEmpty())
- {
- // if it doesn't exist, see if we've remembered one we can
- // plop down here.
- CHXString key = "proxy-authentication.rtsp:";
- IHXBuffer* pFoundRealmBuffer = NULL;
- IHXBuffer* pBuffer = NULL;
- key += "proxy-host:";
- retVal = pRegistry->GetStrByName("proxy-authentication.rtsp.realm.recent",
- pBuffer);
- if (SUCCEEDED(retVal))
- {
- key += CHXString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
- retVal = pRegistry->GetStrByName((const char*)key, pFoundRealmBuffer);
- if (SUCCEEDED(retVal))
- {
- CHXString strAuthHeader((const char*)pFoundRealmBuffer->GetBuffer(),
- pFoundRealmBuffer->GetSize());
- pMsg->addHeader("Proxy-Authorization", (const char*)strAuthHeader);
- }
- }
- }
- HX_RELEASE(pRegistry);
- }
- #endif /* HELIX_FEATURE_AUTHENTICATION */
- }
- HX_RESULT
- RTSPClientProtocol::handleAuthentication(RTSPResponseMessage* pMsg)
- {
- #if defined(HELIX_FEATURE_AUTHENTICATION)
- HX_RESULT rc = HXR_OK;
- rc = extractRealmInformation(pMsg);
- if( rc == HXR_OUTOFMEMORY )
- {
- return rc;
- }
- IHXValues* pIHXValuesResponseHeaders = NULL;
- pMsg->AsValues(pIHXValuesResponseHeaders);
- if(pIHXValuesResponseHeaders)
- {
- HX_RESULT retVal = HXR_OK;
- IHXBuffer* pServerHeaderBuffer = NULL;
- // Add the fake _server value that's used
- // in IHXAuthenticationManager2 implementations. xxxbobclark
- HX_ASSERT(!m_hostName.IsEmpty());
- if (!m_hostName.IsEmpty())
- {
- retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
- (void**)&pServerHeaderBuffer);
- if (SUCCEEDED(retVal))
- {
- if (pMsg->errorCodeAsUINT32() == 407 && m_proxyHost.GetLength() > 0)
- {
- rc = pServerHeaderBuffer->Set((UCHAR*)(const char*)m_proxyHost, m_proxyHost.GetLength()+1);
- }
- else
- {
- rc = pServerHeaderBuffer->Set((UCHAR*)(const char*)m_hostName, m_hostName.GetLength()+1);
- }
- pIHXValuesResponseHeaders->SetPropertyCString("_server", pServerHeaderBuffer);
- HX_RELEASE(pServerHeaderBuffer);
- }
- }
- rc = m_pResp->HandleWWWAuthentication
- (
- HXR_NOT_AUTHORIZED,
- pIHXValuesResponseHeaders
- );
- }
- else
- {
- rc = m_pResp->HandleWWWAuthentication
- (
- HXR_FAIL,
- NULL
- );
- }
- HX_RELEASE(pIHXValuesResponseHeaders);
- return rc;
- #else
- return HXR_NOTIMPL;
- #endif /* HELIX_FEATURE_AUTHENTICATION */
- }
- //
- // add x-wap-profile and x-wap-profile-diff headers if they exists
- //
- void
- RTSPClientProtocol::addUAProfHeaders(IHXValues* pHeaders)
- {
- if (pHeaders)
- {
- if (m_pUAProfURI && m_pUAProfURI->GetSize() > 0)
- {
- pHeaders->SetPropertyCString("x-wap-profile", m_pUAProfURI);
- if (m_pUAProfDiff && m_pUAProfDiff->GetSize() > 0)
- {
- pHeaders->SetPropertyCString("x-wap-profile-diff",
- m_pUAProfDiff);
- }
- }
- }
- }
- RTSPTransportBuffer*
- RTSPClientProtocol::getTransportBuffer(UINT16 uStreamNumber)
- {
- RTSPTransportBuffer* pRet = NULL;
- if (m_pTransportStreamMap)
- {
- RTSPTransport* pTrans =
- (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
- if (pTrans)
- {
- pRet = pTrans->getTransportBuffer(uStreamNumber);
- }
- }
- return pRet;
- }
- HX_RESULT
- RTSPClientProtocol::ParseSDP(const char* pszContentType, IHXBuffer* pSDPBuffer)
- {
- HX_RESULT rc = HXR_OK;
- UINT16 nValues = 0;
- UINT32 ulNumStreams = 0;
- IHXValues** ppValues = NULL;
- IHXValues** ppRealHeaders = NULL;;// headers of right BW
- UINT32* pulSubscriptionBW = NULL;
- IHXStreamDescription* pSD = getStreamDescriptionInstance(pszContentType);
- if (!pSD)
- {
- rc = HXR_FAIL;
- goto cleanup;
- }
- rc = pSD->GetValues(pSDPBuffer, nValues, ppValues);
- if(HXR_REQUEST_UPGRADE == rc)
- {
- // request upgrade...sdpplin has added itself for
- // upgradecollection
- // nothing to do...
- }
- else if (HXR_OK != rc)
- {
- // error
- HX_ASSERT(!"bad sdp file 0");
- }
- else if (nValues <= 1)
- {
- // clean up..
- for(UINT16 i=0;i<nValues;++i)
- {
- // don't need IHXValues anymore...
- ppValues[i]->Release();
- }
- HX_VECTOR_DELETE(ppValues);
- // error
- rc = HXR_FAIL;
- HX_ASSERT("!bad sdp file 1");
- }
- else
- {
- // get header info
- IHXBuffer* pControl = NULL;
- IHXBuffer* pIPAddress = NULL;
- UINT32 ulIsSessionLive = 0;
- UINT32 ulAvgBitRate = 0;
- UINT32 ulRtpRRBitRate = (ULONG32)-1;
- UINT32 ulRtpRSBitRate = (ULONG32)-1;
- UINT32 ulIPAddress = 0;
- BOOL bRealMedia = FALSE;
- m_pSDPFileHeader = ppValues[0];
- ppValues[0]->GetPropertyCString("Control", pControl);
- if(pControl)
- {
- if (!strcmp((const char*)pControl->GetBuffer(),"*"))
- m_headerControl = m_contentBase;
- else
- m_headerControl = pControl->GetBuffer();
- HX_RELEASE(pControl);
- }
- ppValues[0]->GetPropertyULONG32("LiveStream", ulIsSessionLive);
- ppValues[0]->GetPropertyULONG32("AvgBitRate", ulAvgBitRate);
- // Get session level RTP bandwidth modifiers
- ppValues[0]->GetPropertyULONG32("RtcpRRRate", ulRtpRRBitRate);
- ppValues[0]->GetPropertyULONG32("RtcpRSRate", ulRtpRSBitRate);
- /*
- * Get a number of streams in this presentation
- */
-
- // don't trust the "StreamCount"
- // cHeaders will represent a number of m= line in SDP
- // ulNumStreams is actual number of streams in this presentation
- // They will be different on sure stream presentation becacause we are
- // duplicating headers for each bandwidth.
- // we have to iterate over the stream headers...
- if (!m_bSDPInitiated || GetStreamCountNoTrust(&ppValues[1], nValues - 1, ulNumStreams) != TRUE)
- {
- // Well, This is not a SDP file generated by pplyfobj.cpp.
- // Trust the StreamCount!
- m_pSDPFileHeader->GetPropertyULONG32("StreamCount", ulNumStreams);
- ppRealHeaders = new IHXValues*[ulNumStreams];
- for (int i = 0; i < (int)ulNumStreams; i++)
- {
- ppRealHeaders[i] = ppValues[i+1];
- ppRealHeaders[i]->AddRef();
- }
- }
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- else
- {
- // we should have at least one stream
- HX_ASSERT(ulNumStreams > 0 && m_bSDPInitiated);
-
- // set the StreamCount
- m_pSDPFileHeader->SetPropertyULONG32("StreamCount", ulNumStreams);
-
- /*
- * Get a BW for each stream to "subscribe" to
- */
- pulSubscriptionBW = new UINT32[ulNumStreams];
- memset(pulSubscriptionBW, 0, sizeof(UINT32) * ulNumStreams);
- if (GetSubscriptionBW(m_pSDPFileHeader,
- &ppValues[1],
- nValues - 1,
- pulSubscriptionBW,
- ulNumStreams) != TRUE)
- {
- // this should never happen
- HX_ASSERT(FALSE);
- rc = HXR_UNEXPECTED;
- goto cleanup;
- }
-
- /**************************
- * Get right stream headers to pass to CPurePlaySource
- * We have figured out BW to use for each stream
- * This is expensive, but...hey, it's done only once
- * Iterate over all the stream headers AGAIN, and Get right stream headers
- * for each stream depending on subscription BW
- */
- if (GetRightHeaders(ppRealHeaders,
- ulNumStreams,
- &ppValues[1],
- nValues - 1,
- pulSubscriptionBW) != TRUE)
- {
- // this should never happen
- HX_ASSERT(FALSE);
- rc = HXR_UNEXPECTED;
- goto cleanup;
- }
- }
- if (HXR_OK == ppValues[0]->GetPropertyCString("MulticastAddress", pIPAddress))
- {
- m_sessionHost = pIPAddress->GetBuffer();
- }
- HX_RELEASE(pIPAddress);
- if (m_bSDPInitiated)
- {
- bRealMedia = DetermineIfRMPresentation(&ppRealHeaders[0], ulNumStreams);
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- for (int i=0;i<ulNumStreams;++i)
- {
- // reset...
- BOOL bHasMarkerRule = 0;
- UINT16 markerRule = 0;
- UINT32 streamNumber = 0;
- UINT32 needReliable = 0;
- UINT32 rtpPayloadType = (ULONG32)-1;
- UINT32 sampleSize = 0;
- UINT32 sampleRate = 0;
- UINT32 RTPFactor = 0;
- UINT32 HXFactor = 0;
- UINT32 ulIsLive = ulIsSessionLive;
- UINT32 ulHasOutOfOrderTS = 0;
- UINT32 ulPort = 0;
- IHXBuffer* pMimeType = NULL;
- IHXBuffer* pRawRules = NULL;
- RTSPMediaType eMediaType = RTSPMEDIA_TYPE_UNKNOWN;
- pControl = NULL;
- if (!m_pSDPStreamHeaders)
- {
- m_pSDPStreamHeaders = new CHXSimpleList();
- }
- // build header list
- m_pSDPStreamHeaders->AddTail(ppRealHeaders[i]);
- // determine stream type
- ppRealHeaders[i]->GetPropertyCString("MimeType", pMimeType);
- if (pMimeType)
- {
- eMediaType = SDPMapMimeToMediaType((const char*) pMimeType->GetBuffer());
- HX_RELEASE(pMimeType);
- }
- #if defined(HELIX_FEATURE_ASM)
- // deal with marker rule...
- ppRealHeaders[i]->GetPropertyCString("ASMRuleBook", pRawRules);
- if (pRawRules)
- {
- ASMRuleBook* pRuleBook = new ASMRuleBook((const char*)pRawRules->GetBuffer());
- BOOL bHasRule = FALSE;
- IHXValues* pRuleProps = NULL;
- IHXBuffer* pBuffer = NULL;
- for(UINT16 nRule=0; nRule < pRuleBook->GetNumRules(); ++nRule)
- {
- pRuleProps = NULL;
- pBuffer = NULL;
- pRuleBook->GetProperties(nRule, pRuleProps);
- pRuleProps->GetPropertyCString("marker", pBuffer);
- if(pBuffer)
- {
- int marker = atoi((const char*)pBuffer->GetBuffer());
- if (1 == marker)
- {
- /* we don't allow more than one marker rule */
- markerRule = (UINT16)nRule;
- bHasMarkerRule = TRUE;
- pBuffer->Release();
- pRuleProps->Release();
- break;
- }
- HX_RELEASE(pBuffer);
- }
- HX_RELEASE(pRuleProps);
- }
- HX_DELETE(pRuleBook);
- HX_RELEASE(pRawRules);
- }
- #endif /* HELIX_FEATURE_ASM */
- // build stream info list
- RTSPStreamInfo* pInfo = new RTSPStreamInfo;
- ppRealHeaders[i]->GetPropertyULONG32("StreamNumber", streamNumber);
- ppRealHeaders[i]->GetPropertyULONG32("NeedReliablePackets", needReliable);
- ppRealHeaders[i]->GetPropertyULONG32("SamplesPerSecond", sampleRate);
- ppRealHeaders[i]->GetPropertyULONG32("BitsPerSample", sampleSize);
- ppRealHeaders[i]->GetPropertyCString("Control", pControl);
- ppRealHeaders[i]->GetPropertyULONG32("RTPPayloadType", rtpPayloadType);
- ppRealHeaders[i]->GetPropertyULONG32("RTPTimestampConversionFactor", RTPFactor);
- ppRealHeaders[i]->GetPropertyULONG32("HXTimestampConversionFactor", HXFactor);
- ppRealHeaders[i]->GetPropertyULONG32("LiveStream", ulIsLive);
- ppRealHeaders[i]->GetPropertyULONG32("HasOutOfOrderTS", ulHasOutOfOrderTS);
- // Override session level average bitrate
- ppRealHeaders[i]->GetPropertyULONG32("AvgBitRate", ulAvgBitRate);
- // Overide session level RTP bandwidth modifiers
- // with media level modifiers
- ppRealHeaders[i]->GetPropertyULONG32("RtcpRRRate", ulRtpRRBitRate);
- ppRealHeaders[i]->GetPropertyULONG32("RtcpRSRate", ulRtpRSBitRate);
- ppRealHeaders[i]->GetPropertyULONG32("port", ulPort);
- if(pControl)
- {
- pInfo->m_streamControl = pControl->GetBuffer();
- HX_RELEASE(pControl);
- }
- else
- {
- char tmp[32];
- SafeSprintf(tmp, 32, "streamid=%u", (UINT16)streamNumber);
- pInfo->m_streamControl = tmp;
- }
- pInfo->m_streamNumber = (UINT16)streamNumber;
- pInfo->m_bNeedReliablePackets = needReliable ? TRUE: FALSE;
- pInfo->m_rtpPayloadType = (INT16)rtpPayloadType;
- pInfo->m_sampleRate = sampleRate;
- pInfo->m_sampleSize = sampleSize / 8;
- pInfo->m_RTPFactor = RTPFactor;
- pInfo->m_HXFactor = HXFactor;
- pInfo->m_bHasMarkerRule = bHasMarkerRule;
- pInfo->m_markerRule = markerRule;
- pInfo->m_sPort = (UINT16)ulPort;
- pInfo->m_bIsLive = ulIsLive ? TRUE : FALSE;
- pInfo->m_bHasOutOfOrderTS = ulHasOutOfOrderTS ? TRUE : FALSE;
- pInfo->m_eMediaType = eMediaType;
- pInfo->m_bIsSyncMaster = FALSE; // decison will be made on setup response
- pInfo->m_ulAvgBitRate = ulAvgBitRate;
- pInfo->m_ulRtpRRBitRate = ulRtpRRBitRate;
- pInfo->m_ulRtpRSBitRate = ulRtpRSBitRate;
- pInfo->m_bRealMedia = bRealMedia;
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if ((m_sessionHost.IsEmpty() || HXR_INADDR_ANY == HXinet_addr((const char*)m_sessionHost)) &&
- HXR_OK == ppRealHeaders[i]->GetPropertyCString("MulticastAddress", pIPAddress))
- {
- m_sessionHost = pIPAddress->GetBuffer();
- }
- HX_RELEASE(pIPAddress);
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- m_streamInfoList.AddTail(pInfo);
- }
- }
- cleanup:
- HX_VECTOR_DELETE(ppValues);
- HX_VECTOR_DELETE(pulSubscriptionBW);
- // release ppRealHeaders too
- if (NULL != ppRealHeaders)
- {
- for (int i = 0; i < (int)ulNumStreams; i++)
- {
- HX_RELEASE(ppRealHeaders[i]);
- }
- HX_VECTOR_DELETE(ppRealHeaders);
- }
- HX_RELEASE(pSD);
- return rc;
- }
- void
- RTSPClientProtocol::RemoveSDPHeaders(void)
- {
- HX_RELEASE(m_pSDPFileHeader);
- CHXSimpleList::Iterator i;
- for(i=m_pSDPStreamHeaders->Begin();i!=m_pSDPStreamHeaders->End();++i)
- {
- IHXValues* pStreamHeader = (IHXValues*)(*i);
- HX_RELEASE(pStreamHeader);
- }
- HX_DELETE(m_pSDPStreamHeaders);
- }
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- BOOL
- RTSPClientProtocol::DetermineIfRMPresentation(IHXValues** ppStrmHeaders,
- UINT32 ulNumStreams)
- {
- BOOL bIsRMPresentation = FALSE;
- if (ppStrmHeaders && ulNumStreams)
- {
- IHXValues* pStrmHdr = NULL;
- IHXBuffer* pASMRuleBook = NULL;
- IHXBuffer* pMimeType = NULL;
- UINT32 ulRTPPayload = RTP_PAYLOAD_RTSP + 1;
- BOOL bIsRMStream = FALSE;
- UINT32 ulIdx = 0;
- bIsRMPresentation = TRUE;
- for (ulIdx = 0; bIsRMPresentation && (ulIdx < ulNumStreams); ulIdx++)
- {
- pStrmHdr = ppStrmHeaders[ulIdx];
- bIsRMStream = FALSE;
- if (pStrmHdr)
- {
- if (HXR_OK == pStrmHdr->GetPropertyULONG32("RTPPayloadType", ulRTPPayload) &&
- ulRTPPayload == RTP_PAYLOAD_RTSP)
- {
- bIsRMStream = TRUE;
- }
- ulRTPPayload = RTP_PAYLOAD_RTSP + 1;
- if (bIsRMStream)
- {
- bIsRMStream = FALSE;
-
- if (HXR_OK == pStrmHdr->GetPropertyCString("ASMRuleBook", pASMRuleBook) &&
- pASMRuleBook)
- {
- bIsRMStream = TRUE;
- }
- }
- HX_RELEASE(pASMRuleBook);
- if (bIsRMStream)
- {
- bIsRMStream = FALSE;
- if (HXR_OK == pStrmHdr->GetPropertyCString("MimeType", pMimeType) &&
- pMimeType)
- {
- if (strstr((const char*) pMimeType->GetBuffer(), RN_COMMON_MIME_TYPE_FRAGMENT))
- {
- bIsRMStream = TRUE;
- }
- }
- }
- HX_RELEASE(pMimeType);
- }
- bIsRMPresentation = (bIsRMStream && bIsRMPresentation);
- }
- }
- return bIsRMPresentation;
- }
- BOOL
- RTSPClientProtocol::GetSubscriptionBW(IHXValues* pFileHeader,
- IHXValues** ppStrmHeaders,
- UINT16 unNumStrmHeaders,
- REF(UINT32*) pulSubscriptionBW,
- UINT32 ulNumStreams)
- {
- HX_ASSERT(pFileHeader);
- HX_ASSERT(ppStrmHeaders);
- HX_ASSERT(unNumStrmHeaders >= 1);
- HX_ASSERT(pulSubscriptionBW);
- HX_ASSERT(ulNumStreams >= 1);
- IHXBuffer* pRuleBuf = NULL;
- IHXBuffer* pBandwidth = NULL;
- pFileHeader->AddRef();
- if (!m_pPreferences || HXR_OK != m_pPreferences->ReadPref("Bandwidth", pBandwidth))
- {
- HX_ASSERT(FALSE);
- pBandwidth = new CHXBuffer();
- pBandwidth->AddRef();
- pBandwidth->Set((const unsigned char*)"64000", strlen("64000"));
- }
- if (HXR_OK != pFileHeader->GetPropertyCString("ASMRuleBook", pRuleBuf))
- {
- // OK, this is a single stream presentation. Take an ASMRuleBook from
- // any of stream headers (they are all the same), and use it to decide
- // which stream header to use depending on bit rate
- HX_ASSERT(1 == ulNumStreams);
- // get ASMRuleBook
- HX_ASSERT(NULL != ppStrmHeaders[0]);
- IHXValues* pHeader = ppStrmHeaders[0];
- pHeader->AddRef();
- if (HXR_OK == pHeader->GetPropertyCString("ASMRuleBook", pRuleBuf))
- {
- IHXBuffer* pBuffer = NULL;
- UINT16 unRules = 0;
- ASMRuleBook rules((char*)pRuleBuf->GetBuffer());
- unRules = rules.GetNumRules();
-
- // get subscriptions for this bandwidth
- BOOL bSubInfo[256];
- UINT16 unRuleNum = 0;
- IHXValues* pValues = new CHXHeader();
- pValues->AddRef();
-
- pValues->SetPropertyCString("Bandwidth", pBandwidth);
- rules.GetSubscription(bSubInfo, pValues);
-
- HX_RELEASE(pValues);
- // get a rule number that we are interested in
- int y;
- for (y = 0; y < (int)unRules; y++)
- {
- if (TRUE == bSubInfo[y])
- {
- IHXBuffer* pBw = 0;
- unRuleNum = y;
-
- // make sure AverageBandwidth != 0
- rules.GetProperties(y, pValues);
-
- if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth",
- pBw))
- {
- pulSubscriptionBW[0] += atol((const char*)pBw->GetBuffer());
- HX_RELEASE(pBw);
- }
- else
- {
- // TimeStampDelivery only stream
- pulSubscriptionBW[0] = 0;
- }
- HX_RELEASE(pValues);
- }
- }
- HX_RELEASE(pRuleBuf);
- }
- else
- {
- // There is no ASMRuleBook at all...
- // This should never happen.
- HX_RELEASE(pFileHeader);
- HX_RELEASE(pBandwidth);
- HX_RELEASE(pHeader);
- HX_ASSERT(FALSE);
- return FALSE;
- }
- HX_RELEASE(pHeader);
- }
- else
- {
- // this is a multiple stream presentation.
- // take ASMRuleBook for a file and figure out BW to use for
- // each stream
- IHXBuffer* pBuffer = NULL;
- UINT16 unRules = 0;
- ASMRuleBook rules((char*)pRuleBuf->GetBuffer());
- unRules = rules.GetNumRules();
- // get subscriptions for this bandwidth
- BOOL bSubInfo[256];
- UINT16 unRuleNum = 0;
- IHXValues* pValues = new CHXHeader();
- pValues->AddRef();
-
- pValues->SetPropertyCString("Bandwidth", pBandwidth);
- rules.GetSubscription(bSubInfo, pValues);
- HX_RELEASE(pValues);
-
- // get a rule number that we are interested in
- // Assuming there is only one TRUE
- int y;
- for (y = 0; y < (int)unRules; y++)
- {
- if (TRUE == bSubInfo[y])
- {
- // there should be only one
- unRuleNum = y;
- break;
- }
- }
- // Get a BW for each stream
- rules.GetProperties((int)unRuleNum, pValues);
- for (int i = 0; i < (int)ulNumStreams; i++)
- {
- char rgStreamBW[32];
- sprintf(rgStreamBW, "Stream%dBandwidth", i);
- if (HXR_OK == pValues->GetPropertyCString((const char*)rgStreamBW,
- pBuffer))
- {
- pulSubscriptionBW[i] = (UINT32)atol((const char*)pBuffer->GetBuffer());
- HX_RELEASE(pBuffer);
- }
- }
- HX_RELEASE(pValues);
- HX_RELEASE(pRuleBuf);
- }
- HX_RELEASE(pFileHeader);
- HX_RELEASE(pBandwidth);
- return TRUE;
- }
- BOOL
- RTSPClientProtocol::GetRightHeaders(REF(IHXValues**) ppRealHeaders, // out
- UINT32 ulNumStreams,
- IHXValues** ppHeaders,
- UINT32 cHeaders,
- UINT32* pulSubscriptionBW)
- {
- HX_ASSERT(ulNumStreams >= 1);
- HX_ASSERT(ppHeaders);
- HX_ASSERT(pulSubscriptionBW);
-
- ppRealHeaders = new IHXValues*[ulNumStreams];
- memset(ppRealHeaders, NULL, sizeof(IHXValues*) * ulNumStreams);
-
- for (int i = 0; i < (int)ulNumStreams; i++)
- {
- ULONG32 ulID = 0;
- ULONG32 ulBW = 0;;
- BOOL bFound = FALSE;
- for (int j = 0; j < (int)cHeaders; j++)
- {
- HX_ASSERT(NULL != ppHeaders[j]);
- IHXValues* pSrcH = ppHeaders[j];
- pSrcH->AddRef();
- if ((HXR_OK == pSrcH->GetPropertyULONG32("AvgBitRate", ulBW)) &&
- (ulBW == pulSubscriptionBW[i]))
- {
- // this one has the right BW, how about stream number?
- if ((HXR_OK == pSrcH->GetPropertyULONG32("StreamId", ulID)) &&
- ((int)ulID == i))
- {
- bFound = TRUE;
-
- // This is the right heaader,
- ppRealHeaders[i] = pSrcH;
- ppRealHeaders[i]->AddRef();
- HX_RELEASE(pSrcH);
- break; // we found for this stream, go to next one
- }
- }
- HX_RELEASE(pSrcH);
- }
- if (!bFound)
- {
- // this should never happen
- ppRealHeaders[i] = NULL;
- HX_ASSERT(FALSE);
- return FALSE;
- }
- }
- return TRUE;
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- BOOL
- RTSPClientProtocol::GetStreamCountNoTrust(IHXValues** ppHeaders,
- UINT16 unNumHeader,
- REF(UINT32) ulNumStreams)
- {
- HX_ASSERT(NULL != ppHeaders);
- UINT32 ulID = 0;
- BOOL rgFound[256];
-
- memset(rgFound, 0, 256);
- for (UINT16 i = 0; i < unNumHeader; i++)
- {
- HX_ASSERT(ppHeaders[i] != NULL);
- IHXValues* pSrcHeader = NULL;
- pSrcHeader = ppHeaders[i];
- pSrcHeader->AddRef();
- // "StreamId" is the field that ppfobj.cpp puts for a group of
- // streams
- if (HXR_OK == pSrcHeader->GetPropertyULONG32("StreamId", ulID))
- {
- if (!rgFound[ulID])
- {
- rgFound[ulID] = TRUE;
- ulNumStreams++;
- }
- }
- else
- {
- // OK, trust the "StreamCount". This is not a SDP file generated
- // by pplyfobj.cpp
- ulNumStreams = 0;
- HX_RELEASE(pSrcHeader);
- return FALSE;
- }
- HX_RELEASE(pSrcHeader);
- }
- return TRUE;
- }
- HX_RESULT
- RTSPClientProtocol::CreateUDPSockets(UINT32 ulStream, UINT16 ulPort)
- {
- HX_RESULT rc = HXR_OK;
- IHXUDPSocket* pUDPSocket1 = NULL;
- IHXUDPSocket* pUDPSocket2 = NULL;
- IHXSetSocketOption* pSockOpt = NULL;
- UDPResponseHelper* pUDPResponseHelper1 = NULL;
- UDPResponseHelper* pUDPResponseHelper2 = NULL;
- if((HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket1)) ||
- (HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket2)))
- {
- rc = HXR_FAIL;
- goto cleanup;
- }
- pUDPResponseHelper1 = new UDPResponseHelper(this, ulPort);
- pUDPResponseHelper2 = new UDPResponseHelper(this, ulPort+1);
- if (!pUDPResponseHelper1 || !pUDPResponseHelper2)
- {
- rc = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pUDPResponseHelper1->AddRef();
- pUDPResponseHelper2->AddRef();
- m_UDPResponseHelperList.AddTail(pUDPResponseHelper1);
- m_UDPResponseHelperList.AddTail(pUDPResponseHelper2);
- if((HXR_OK != pUDPSocket1->Init(0, 0, pUDPResponseHelper1)) ||
- (HXR_OK != pUDPSocket2->Init(0, 0, pUDPResponseHelper2)))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
- if (m_bMulticast)
- {
- if (HXR_OK != pUDPSocket1->QueryInterface(IID_IHXSetSocketOption, (void**)&pSockOpt))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
- HX_RELEASE(pSockOpt);
- if (HXR_OK != pUDPSocket2->QueryInterface(IID_IHXSetSocketOption, (void**)&pSockOpt))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
- pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
- HX_RELEASE(pSockOpt);
- }
- #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
- if (HXR_OK != pUDPSocket1->Bind(HXR_INADDR_ANY, ulPort) ||
- HXR_OK != pUDPSocket2->Bind(HXR_INADDR_ANY, ulPort+1))
- {
- rc = HXR_FAILED;
- goto cleanup;
- }
- cleanup:
- if (HXR_OK == rc)
- {
- (*m_pUDPSocketStreamMap)[ulStream] = pUDPSocket1;
- (*m_pRTCPSocketStreamMap)[ulStream] = pUDPSocket2;
- if (!m_bMulticast)
- {
- // hang a read on these guys...
- rc = pUDPSocket1->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- if( rc != HXR_OUTOFMEMORY )
- {
- rc = pUDPSocket2->Read(HX_SAFEUINT(MAX_UDP_PACKET));
- }
- }
- }
- else
- {
- HX_RELEASE(pUDPSocket1);
- HX_RELEASE(pUDPSocket2);
- }
- return rc;
- }
- void
- RTSPClientProtocol::ReportError(
- HX_RESULT theErr
- )
- {
- if( m_pSession )
- {
- m_pSession->ReportError(theErr);
- }
- }
- void
- RTSPClientSession::ReportError(
- HX_RESULT theErr
- )
- {
- IHXErrorMessages * pErrorNotifier = NULL;
- IUnknown * pPlayer = NULL;
- IHXClientEngine* pEngine = NULL;
- UINT32 nNumPlayers = 0;
- m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine);
- if( pEngine )
- {
- nNumPlayers = pEngine->GetPlayerCount();
- for( int ii=0; ii<nNumPlayers; ii++ )
- {
- pEngine->GetPlayer(ii,pPlayer);
- if( pPlayer )
- {
- pPlayer->QueryInterface( IID_IHXErrorMessages, (void**)&pErrorNotifier );
- }
- if( pErrorNotifier )
- {
- pErrorNotifier->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
- pErrorNotifier->Release();
- }
- HX_RELEASE( pPlayer );
- }
- }
- HX_RELEASE( pEngine );
- }
- HX_RESULT
- RTSPClientProtocol::RetrieveReconnectInfo(MIMEHeader* pHeader,
- ReconnectType reconnectType,
- IHXValues*& pReconnectValues)
- {
- HX_RESULT rc = HXR_OK;
- UINT32 ulRand = 0;
- IHXBuffer* pServer = NULL;
- MIMEHeaderValue* pHeaderValue = NULL;
- MIMEParameter* pParam0 = NULL;
- MIMEParameter* pParam1 = NULL;
- ReconnectInfo* pReconnectInfo = NULL;
- CHXSimpleList reconnectInfoList;
- CHXSimpleList::Iterator i;
- if (!pReconnectValues)
- {
- pReconnectValues = new CHXHeader();
- pReconnectValues->AddRef();
- }
- pReconnectValues->SetPropertyULONG32("Reconnect", 1);
- pHeaderValue = pHeader->getFirstHeaderValue();
- while (pHeaderValue)
- {
- pParam0 = pHeaderValue->getFirstParameter();
- pParam1 = pHeaderValue->getNextParameter();
- if (pParam0)
- {
- pReconnectInfo = new ReconnectInfo;
- pReconnectInfo->m_server = (const char*)pParam0->m_value;
- if (pParam1)
- {
- pReconnectInfo->m_ulPort = atoi((const char*)pParam1->m_value);
- }
- }
- reconnectInfoList.AddTail(pReconnectInfo);
- pHeaderValue = pHeader->getNextHeaderValue();
- }
- if (!reconnectInfoList.IsEmpty())
- {
- ulRand = (HX_GET_TICKCOUNT() % reconnectInfoList.GetCount()) + 1;
- // random select the alternate serverport AND cleanup the list
- for(i = reconnectInfoList.Begin(); i != reconnectInfoList.End(); ++i)
- {
- pReconnectInfo = (ReconnectInfo*)*i;
- switch (ulRand)
- {
- case 0:
- break;
- case 1:
- pServer = new CHXBuffer();
- pServer->AddRef();
- pServer->Set((const unsigned char*)(const char*)pReconnectInfo->m_server,
- pReconnectInfo->m_server.GetLength()+1);
- if (reconnectType == ALTERNATE_SERVER)
- {
- pReconnectValues->SetPropertyCString("Alternate-Server", pServer);
- pReconnectValues->SetPropertyULONG32("Alternate-ServerPort", pReconnectInfo->m_ulPort);
- }
- else if (reconnectType == ALTERNATE_PROXY)
- {
- pReconnectValues->SetPropertyCString("Alternate-Proxy", pServer);
- pReconnectValues->SetPropertyULONG32("Alternate-ProxyPort", pReconnectInfo->m_ulPort);
- }
- HX_RELEASE(pServer);
- ulRand--;
- break;
- default:
- ulRand--;
- break;
- }
- HX_DELETE(pReconnectInfo);
- }
- reconnectInfoList.RemoveAll();
- }
- return rc;
- }
- RTSPClientProtocol::UDPResponseHelper::UDPResponseHelper(RTSPClientProtocol* pParent, UINT16 nPort)
- {
- m_lRefCount = 0;
- m_nPort = nPort;
- m_pOwner = pParent;
- }
- RTSPClientProtocol::UDPResponseHelper::~UDPResponseHelper()
- {
- }
- STDMETHODIMP
- RTSPClientProtocol::UDPResponseHelper::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXUDPResponse), (IHXUDPResponse*) this },
- { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::AddRef
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::UDPResponseHelper::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::UDPResponseHelper::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- RTSPClientProtocol::UDPResponseHelper::ReadDone(HX_RESULT status, IHXBuffer* pBuffer,
- UINT32 ulAddr, UINT16 nPort)
- {
- HX_RESULT retVal = HXR_FAILED;
- if (m_pOwner)
- {
- retVal = m_pOwner->ReadDoneWithToPort(status,
- pBuffer,
- ulAddr,
- nPort,
- m_nPort);
- if( retVal == HXR_OUTOFMEMORY )
- {
- m_pOwner->ReportError( retVal );
- }
- }
- return retVal;
- }
- RTSPClientProtocol::ConnectionCheckCallback::ConnectionCheckCallback
- (
- RTSPClientProtocol* pOwner
- ) : m_lRefCount(0)
- , m_pOwner(pOwner)
- {
- if (m_pOwner)
- {
- m_pOwner->AddRef();
- }
- }
- RTSPClientProtocol::ConnectionCheckCallback::~ConnectionCheckCallback()
- {
- HX_RELEASE(m_pOwner);
- }
- STDMETHODIMP
- RTSPClientProtocol::ConnectionCheckCallback::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::AddRef
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::ConnectionCheckCallback::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::ConnectionCheckCallback::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- RTSPClientProtocol::ConnectionCheckCallback::Func()
- {
- m_pOwner->AddRef();
- m_pOwner->DoConnectionCheck();
- m_pOwner->Release();
- return HXR_OK;
- }
- RTSPClientProtocol::TimeoutCallback::TimeoutCallback
- (
- RTSPClientProtocol* pOwner
- ) : m_lRefCount(0)
- , m_pOwner(pOwner)
- {
- if (m_pOwner)
- {
- m_pOwner->AddRef();
- }
- }
- RTSPClientProtocol::TimeoutCallback::~TimeoutCallback()
- {
- // DON'T use HX_RELEASE
- // m_pOwner isn't derived from a COM interface
- if (m_pOwner)
- {
- m_pOwner->Release();
- m_pOwner = NULL;
- }
- }
- STDMETHODIMP
- RTSPClientProtocol::TimeoutCallback::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::TimeoutCallback::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::TimeoutCallback::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- RTSPClientProtocol::TimeoutCallback::Func()
- {
- m_pOwner->AddRef();
- IHXRTSPClientProtocol* pCP = (IHXRTSPClientProtocol*)m_pOwner;
- pCP->SendKeepAlive();
- m_pOwner->Release();
- return HXR_OK;
- }
- #if defined(_MACINTOSH)
- RTSPClientProtocol::RTSPClientProtocolCallback::RTSPClientProtocolCallback
- (
- RTSPClientProtocol* pOwner
- ) : m_lRefCount(0)
- , m_pOwner(pOwner)
- , m_bIsCallbackPending(FALSE)
- , m_Handle(0)
- , m_pPendingRequestHeaders(NULL)
- {
- if (m_pOwner)
- {
- m_pOwner->AddRef();
- }
- }
- RTSPClientProtocol::RTSPClientProtocolCallback::~RTSPClientProtocolCallback()
- {
- HX_RELEASE(m_pOwner);
- HX_RELEASE(m_pPendingRequestHeaders);
- }
- STDMETHODIMP
- RTSPClientProtocol::RTSPClientProtocolCallback::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::AddRef
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::RTSPClientProtocolCallback::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- /////////////////////////////////////////////////////////////////////////
- // Method:
- // IUnknown::Release
- // Purpose:
- // Everyone usually implements this the same... feel free to use
- // this implementation.
- //
- STDMETHODIMP_(ULONG32)
- RTSPClientProtocol::RTSPClientProtocolCallback::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- STDMETHODIMP
- RTSPClientProtocol::RTSPClientProtocolCallback::Func()
- {
- m_bIsCallbackPending = FALSE;
- m_Handle = 0;
- m_pOwner->AddRef();
- m_pOwner->sendPendingStreamDescription(m_PendingDescURL, m_pPendingRequestHeaders);
- HX_RELEASE(m_pPendingRequestHeaders);
- m_pOwner->Release();
- return HXR_OK;
- }
- #endif /* _MACINTOSH */
- RTSPClientSessionManager::RTSPClientSessionManager():
- m_lRefCount(0),
- m_pMutex(NULL)
- {
- #ifdef THREADS_SUPPORTED
- HXMutex::MakeMutex(m_pMutex);
- #else
- HXMutex::MakeStubMutex(m_pMutex);
- #endif
- }
- RTSPClientSessionManager::~RTSPClientSessionManager()
- {
- CHXSimpleList::Iterator i;
- for(i=m_sessionList.Begin();i!=m_sessionList.End();++i)
- {
- RTSPClientSession* pSession = (RTSPClientSession*)(*i);
- pSession->Release();
- }
- m_sessionList.RemoveAll();
- HX_DELETE(m_pMutex);
- }
- /*
- * IUnknown methods
- */
- STDMETHODIMP
- RTSPClientSessionManager::QueryInterface(REFIID riid, void** ppvObj)
- {
- if (IsEqualIID(riid, IID_IUnknown))
- {
- AddRef();
- *ppvObj = (IUnknown*)this;
- return HXR_OK;
- }
- *ppvObj = NULL;
- return HXR_NOINTERFACE;
- }
- STDMETHODIMP_(UINT32)
- RTSPClientSessionManager::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32)
- RTSPClientSessionManager::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- SessionManGlobal() = 0;
- return 0;
- }
- /*
- * RTSPClientSessionManager methods
- */
- RTSPClientSessionManager*& RTSPClientSessionManager::SessionManGlobal()
- {
- #if defined(HELIX_CONFIG_NOSTATICS)
- GlobalID globalID = (GlobalID)RTSPClientSessionManager::zm_pSessionManager;
- return (RTSPClientSessionManager*&)HXGlobalPtr::Get(globalID);
- #else
- return RTSPClientSessionManager::zm_pSessionManager;
- #endif
- }
- RTSPClientSessionManager*
- RTSPClientSessionManager::instance()
- {
- RTSPClientSessionManager*& pSessionManager = SessionManGlobal();
- if(!pSessionManager)
- {
- pSessionManager = new RTSPClientSessionManager;
- }
- pSessionManager->AddRef();
- return pSessionManager;
- }
- HX_RESULT
- RTSPClientSessionManager::newSession(IUnknown* pContext,
- RTSPClientProtocol* pProt,
- const char* pHostName,
- UINT16 uPort,
- UINT32 ulActualAddr,
- BOOL bUseProxy,
- BOOL bHTTPOnly,
- UINT16 uCloakPort)
- {
- m_pMutex->Lock();
- RTSPClientSession* pSession = new RTSPClientSession;
- pSession->AddRef();
- m_sessionList.AddTail(pSession);
- if (pProt)
- {
- pProt->SessionCreated(pSession);
- }
- HX_RESULT hr = pSession->Init(pContext,
- pProt,
- pHostName,
- uPort,
- ulActualAddr,
- bUseProxy,
- bHTTPOnly,
- uCloakPort);
- m_pMutex->Unlock();
- return hr;
- }
- int
- RTSPClientSessionManager::getSessionCount()
- {
- return m_sessionList.GetCount();
- }
- BOOL
- RTSPClientSessionManager::MatchPlayerContext(IUnknown* pNewContext,
- IUnknown* pKnownContext)
- {
- BOOL bResult = FALSE;
- IHXPlayer* pNewHXPlayer = NULL;
- IHXPlayer* pKnownHXPlayer = NULL;
- if (!pNewContext || !pKnownContext)
- {
- goto cleanup;
- }
- if (HXR_OK == pNewContext->QueryInterface(IID_IHXPlayer, (void**)&pNewHXPlayer) &&
- HXR_OK == pKnownContext->QueryInterface(IID_IHXPlayer, (void**)&pKnownHXPlayer))
- {
- if (pNewHXPlayer == pKnownHXPlayer)
- {
- bResult = TRUE;
- }
- }
- cleanup:
- HX_RELEASE(pNewHXPlayer);
- HX_RELEASE(pKnownHXPlayer);
- return bResult;
- }
- HX_RESULT
- RTSPClientSessionManager::removeFromSession(RTSPClientProtocol* pProt,
- RTSPClientSession* pSessionRemoved)
- {
- HX_RESULT hr = HXR_OK;
- LISTPOSITION pos = m_sessionList.GetHeadPosition();
- while(pos)
- {
- RTSPClientSession* pSession =
- (RTSPClientSession*)m_sessionList.GetAt(pos);
- if(pSession == pSessionRemoved &&
- HXR_OK == pSession->removeProtocol(pProt))
- {
- if(pSession->isEmpty())
- {
- pSession->Done();
- pSession->Release();
- pos = m_sessionList.RemoveAt(pos);
- }
- break;
- }
- m_sessionList.GetNext(pos);
- }
- return hr;
- }
- RTSPClientSession*
- RTSPClientSessionManager::findSession(UINT32 ulActualAddr,
- UINT16 uActualPort,
- BOOL bUseProxy,
- const char* pForeignHost,
- UINT16 uForeignPort,
- IUnknown* pContext /*= NULL*/)
- {
- m_pMutex->Lock();
- RTSPClientSession* pSession = NULL;
- CHXSimpleList::Iterator i;
- for(i=m_sessionList.Begin();i!=m_sessionList.End();++i)
- {
- pSession = (RTSPClientSession*)(*i);
- if((pSession->m_ulActualAddr == ulActualAddr) &&
- (pSession->m_uActualPort == uActualPort) &&
- /* Either the context passed in is NULL OR it matches
- * the current session context
- */
- (!pContext || MatchPlayerContext(pContext, pSession->m_pContext)))
- {
- if (bUseProxy && pForeignHost)
- {
- if (strcasecmp(pForeignHost, pSession->m_pForeignHost) != 0 ||
- uForeignPort != pSession->m_uForeignPort)
- {
- pSession = NULL;
- continue;
- }
- }
- goto exit;
- }
- pSession = NULL;
- }
- exit:
- m_pMutex->Unlock();
- return pSession;
- }
- #define QUEUE_START_SIZE 512
- /*
- * RTSPClientSession methods
- */
- RTSPClientSession::RTSPClientSession():
- m_lRefCount(0),
- m_pNetworkServices(0),
- m_pSessionSocket(0),
- m_bIgnoreSession(FALSE),
- m_bUseProxy(FALSE),
- m_pForeignHost(0),
- m_uForeignPort(0),
- m_ulActualAddr(0),
- m_pActualHost(NULL),
- m_uActualPort(0),
- m_uCloakPort(0),
- m_ulLastSeqNo(0),
- m_bSessionDone(FALSE),
- m_bHTTPOnly(FALSE),
- m_bReopenSocket(FALSE),
- m_pMutex(NULL),
- m_pContext(NULL),
- m_bChallengeDone(FALSE),
- m_bChallengeMet(FALSE),
- m_bIsValidChallengeT(FALSE),
- m_bSetSessionCalled(FALSE)
- {
- m_pInQueue = new CByteGrowingQueue(QUEUE_START_SIZE);
- m_pInQueue->SetMaxSize(MAX_QUEUE_SIZE);
- m_pParser = new RTSPParser;
- #ifdef THREADS_SUPPORTED
- HXMutex::MakeMutex(m_pMutex);
- #else
- HXMutex::MakeStubMutex(m_pMutex);
- #endif
- }
- RTSPClientSession::~RTSPClientSession()
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- delete pInfo;
- }
- delete m_pInQueue;
- delete m_pParser;
- HX_VECTOR_DELETE(m_pActualHost);
- HX_VECTOR_DELETE(m_pForeignHost);
- HX_RELEASE(m_pNetworkServices);
- HX_RELEASE(m_pSessionSocket);
- HX_RELEASE(m_pContext);
- HX_DELETE(m_pMutex);
- }
- HX_RESULT
- RTSPClientSession::Init(IUnknown* pContext,
- RTSPClientProtocol* pProt,
- const char* pHostName,
- UINT16 uPort,
- UINT32 ulActualAddr,
- BOOL bUseProxy,
- BOOL bHTTPOnly,
- UINT16 uCloakPort)
- {
- HX_RESULT hr = HXR_OK;
- m_ulActualAddr = ulActualAddr;
- m_pActualHost = new_string(pHostName);
- m_bUseProxy = bUseProxy;
- m_bHTTPOnly = bHTTPOnly;
- // this port assignment logic should matches to the logic in
- // finding session at ::GetHostByNameDone()
- if (m_bUseProxy)
- {
- // if there is proxy, we need to also get the foreign host/port
- // in order to find the RTSP session which shares not only the
- // proxy host/port but also the foreign host/port
- if (pProt)
- {
- pProt->GetForeignHostPort(m_pForeignHost, &(m_uForeignPort));
- }
- m_uActualPort = uPort; // proxy port
- }
- // if it is HTTP cloaking, we need to set the actual port
- // to the cloaking port
- else if (m_bHTTPOnly)
- {
- m_uActualPort = uCloakPort; // cloaking port
- }
- else
- {
- m_uActualPort = uPort; // server host port
- }
- m_bHTTPOnly = bHTTPOnly;
- addProtocol(pProt);
- m_pContext = pContext;
- if (m_pContext)
- {
- m_pContext->AddRef();
- }
- IHXTCPSocket* pSocket = 0;
- IHXCloakedNetworkServices* pCloakedNetServices = 0;
- IHXPreferences* pPreferences = 0;
- IHXBuffer* pBuffer = 0;
- if (HXR_OK != pContext->QueryInterface(IID_IHXPreferences,
- (void**)&pPreferences))
- {
- hr = HXR_INVALID_PARAMETER;
- goto cleanup;
- }
- if (HXR_OK != pContext->QueryInterface(IID_IHXNetworkServices,
- (void**)&m_pNetworkServices))
- {
- hr = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- if (m_bHTTPOnly)
- {
- m_uCloakPort = uCloakPort;
- if (HXR_OK != pContext->QueryInterface(IID_IHXCloakedNetworkServices,
- (void**)&pCloakedNetServices))
- {
- hr = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pCloakedNetServices->CreateClientCloakedSocket(&pSocket);
- if (!pSocket)
- {
- hr = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- IHXCloakedTCPSocket* pCloakedTCPSocket = NULL;
- if (HXR_OK == pSocket->QueryInterface(IID_IHXCloakedTCPSocket, (void**)&pCloakedTCPSocket))
- {
- pCloakedTCPSocket->InitCloak(pProt->m_pCloakValues, pContext);
- }
- HX_RELEASE(pCloakedTCPSocket);
- if (pProt->m_bUseHTTPProxy)
- {
- IHXHTTPProxy* pHTTPProxyInterface = NULL;
- if (HXR_OK == pSocket->QueryInterface(IID_IHXHTTPProxy, (void**) &pHTTPProxyInterface) &&
- pHTTPProxyInterface)
- {
- pHTTPProxyInterface->SetProxy(pProt->m_proxyHost, pProt->m_proxyPort);
- }
- HX_RELEASE(pHTTPProxyInterface);
- }
- // Connect() in HXClientCloakedTCPSocket requires the foreign host NOT
- // the proxy host
- pHostName = pProt->m_hostName;
- if (m_uCloakPort)
- uPort = m_uCloakPort;
- }
- else
- {
- m_pNetworkServices->CreateTCPSocket(&pSocket);
- }
- hr = pSocket->Init((IHXTCPResponse*)this);
- if (hr != HXR_OK)
- {
- goto cleanup;
- }
- // already AddRef()'d in CreateTCPSocket
- m_pSessionSocket = pSocket;
- m_pConnectingProt = pProt;
- hr = m_pSessionSocket->Connect(pHostName, uPort);
- if(FAILED(hr))
- {
- ConnectDone(hr);
- }
- cleanup:
- HX_RELEASE(pCloakedNetServices);
- HX_RELEASE(pPreferences);
- return hr;
- }
- HX_RESULT
- RTSPClientSession::Done()
- {
- m_pMutex->Lock();
- m_bSessionDone = TRUE;
- if(m_pSessionSocket)
- {
- m_pSessionSocket->Release();
- m_pSessionSocket = 0;
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientSession::handleInput(BYTE* pData, UINT32 dataLen)
- {
- INT32 ret = HXR_OK;
- if (dataLen)
- {
- ret = m_pInQueue->EnQueue(pData, (UINT16)dataLen);
- if( ret == 0 )
- {
- // Why ABORT? Why not OUTOFMEMORY?
- return HXR_ABORT;
- }
- }
- UINT16 bytesAvail = m_pInQueue->GetQueuedItemCount();
- UINT32 bytesUsed = 0;
- if(bytesAvail == 0)
- {
- return HXR_OK;
- }
- BYTE* pBuf = new BYTE[bytesAvail];
- if(!pBuf)
- {
- return HXR_OUTOFMEMORY;
- }
- for(;;)
- {
- RTSPClientProtocol* pProt = NULL;
- if (!bytesAvail || m_bSessionDone)
- {
- break;
- }
- m_pInQueue->DeQueue(pBuf, bytesAvail);
- if(pBuf[0] == '$')
- {
- bytesUsed = 0;
- BOOL bGotData = FALSE;
- if(bytesAvail >= 4)
- {
- // handle TCP data
- INT8 interleave = pBuf[1];
- UINT16 tcpDataLen = (UINT16)getshort(&pBuf[2]);
- UINT32 currentDataLen = bytesAvail - 4;
- if(currentDataLen >= tcpDataLen)
- {
- pProt = findProtocolFromInterleave(interleave);
- if(pProt)
- {
- ret = pProt->handleTCPData(&pBuf[4], tcpDataLen, interleave);
- }
- bytesUsed = tcpDataLen+4;
- bytesAvail -= (UINT16)bytesUsed;
- bGotData = TRUE;
- }
- }
- m_pInQueue->EnQueue(&pBuf[bytesUsed], (UINT16)bytesAvail);
- if(!bGotData)
- {
- break;
- }
- }
- else
- {
- bytesUsed = bytesAvail;
- RTSPMessage* pMsg = m_pParser->parse((const char*)pBuf,
- bytesUsed);
- bytesAvail -= (UINT16)bytesUsed;
- m_pInQueue->EnQueue(&pBuf[bytesUsed], (UINT16)bytesAvail);
- if (!pMsg)
- {
- break;
- }
- // first always find protocol based on its sessionID
- CHXString pszSessionID = "";
- getSessionID(pMsg, &pszSessionID);
- if (!pszSessionID.IsEmpty())
- {
- pProt = findProtocolFromSessionID(&pszSessionID);
- }
- // then, based on the seq No.
- if (!pProt)
- {
- pProt = findProtocolFromSeqNo(pMsg->seqNo());
- }
- // then, we just grab the head from our protocol list
- if (!pProt)
- {
- RTSPClientProtocolInfo* pInfo =
- (RTSPClientProtocolInfo*)m_protList.GetHead();
- pProt = pInfo?pInfo->m_pProt:NULL;
- }
- if(pProt)
- {
- AddRef();
- pProt->AddRef();
- ret = pProt->handleMessage(pMsg);
- if(ret == HXR_OK)
- {
- removeProtocolSeqNo(pProt, pMsg->seqNo());
- }
- pProt->Release();
- Release();
- }
- delete pMsg;
- }
- }
- delete[] pBuf;
- return ret;
- }
- UINT32
- RTSPClientSession::getNextSeqNo(RTSPClientProtocol* pProt)
- {
- m_pMutex->Lock();
- UINT32 seqNo = ++m_ulLastSeqNo;
- setProtocolSeqNo(pProt, seqNo);
- m_pMutex->Unlock();
- return seqNo;
- }
- RTSPClientProtocol*
- RTSPClientSession::findProtocolFromInterleave(INT8 interleave)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- void* pDummy;
- if(pInfo->m_interleaveMap.Lookup(interleave, pDummy))
- {
- return pInfo->m_pProt;
- }
- }
- return 0;
- }
- RTSPClientProtocol*
- RTSPClientSession::findProtocolFromSeqNo(UINT32 seqNo)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- LISTPOSITION pos = pInfo->m_seqNoList.Find((void*)seqNo);
- if(pos)
- {
- return pInfo->m_pProt;
- }
- }
- return 0;
- }
- RTSPClientProtocol*
- RTSPClientSession::findProtocolFromSessionID(CHXString* pszSessionID)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- if (pInfo->m_pProt &&
- !pInfo->m_pProt->m_sessionID.IsEmpty())
- {
- if(pszSessionID->CompareNoCase(pInfo->m_pProt->m_sessionID) == 0)
- {
- return pInfo->m_pProt;
- }
- }
- }
- return NULL;
- }
- void
- RTSPClientSession::getSessionID(RTSPMessage* pMsg, CHXString* pszSessionID)
- {
- MIMEHeader* pSessionID = pMsg->getHeader("Session");
- if(pSessionID)
- {
- MIMEHeaderValue* pHeaderValue = pSessionID->getFirstHeaderValue();
- if(pHeaderValue)
- {
- MIMEParameter* pParam = pHeaderValue->getFirstParameter();
- *pszSessionID = (const char*)pParam->m_attribute;
- }
- }
- return;
- }
- HX_RESULT
- RTSPClientSession::addProtocol(RTSPClientProtocol* pProt)
- {
- HX_RESULT rc = HXR_OK;
- m_pMutex->Lock();
- RTSPClientProtocolInfo* pInfo = new RTSPClientProtocolInfo;
- if(pInfo)
- {
- pInfo->m_pProt = pProt;
- m_protList.AddTail(pInfo);
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- m_pMutex->Unlock();
- return rc;
- }
- HX_RESULT
- RTSPClientSession::removeProtocol(RTSPClientProtocol* pProt)
- {
- m_pMutex->Lock();
- HX_RESULT hr = HXR_FAIL;
- LISTPOSITION pos = m_protList.GetHeadPosition();
- while(pos)
- {
- RTSPClientProtocolInfo* pInfo =
- (RTSPClientProtocolInfo*)m_protList.GetAt(pos);
- if(pInfo->m_pProt == pProt)
- {
- delete pInfo;
- m_protList.RemoveAt(pos);
- hr = HXR_OK;
- goto exit;
- }
- m_protList.GetNext(pos);
- }
- exit:
- m_pMutex->Unlock();
- return hr;
- }
- BOOL
- RTSPClientSession::isEmpty()
- {
- return (m_protList.GetCount() == 0);
- }
- BOOL
- RTSPClientSession::HttpOnly()
- {
- return m_bHTTPOnly;
- }
- HX_RESULT
- RTSPClientSession::setProtocolInterleave(
- RTSPClientProtocol* pProt, INT8 interleave)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- if(pInfo->m_pProt == pProt)
- {
- pInfo->m_interleaveMap[(UINT32)interleave] = pProt;
- return HXR_OK;
- }
- }
- return HXR_FAIL;
- }
- HX_RESULT
- RTSPClientSession::setProtocolSeqNo(RTSPClientProtocol* pProt,
- UINT32 seqNo)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- if(pInfo->m_pProt == pProt)
- {
- pInfo->m_seqNoList.AddTail((void*)seqNo);
- return HXR_OK;
- }
- }
- return HXR_FAIL;
- }
- HX_RESULT
- RTSPClientSession::removeProtocolSeqNo(RTSPClientProtocol* pProt,
- UINT32 seqNo)
- {
- CHXSimpleList::Iterator i;
- for(i=m_protList.Begin();i!=m_protList.End();++i)
- {
- RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
- if(pInfo->m_pProt == pProt)
- {
- LISTPOSITION pos = pInfo->m_seqNoList.Find((void*)seqNo);
- if(pos)
- {
- pInfo->m_seqNoList.RemoveAt(pos);
- return HXR_OK;
- }
- }
- }
- return HXR_FAIL;
- }
- IHXTCPSocket*
- RTSPClientSession::getSocket()
- {
- return m_pSessionSocket;
- }
- HX_RESULT
- RTSPClientSession::closeSocket()
- {
- m_pMutex->Lock();
- if(m_pSessionSocket)
- {
- m_pSessionSocket->Release();
- m_pSessionSocket = 0;
- }
- m_pMutex->Unlock();
- return HXR_OK;
- }
- HX_RESULT
- RTSPClientSession::reopenSocket(RTSPClientProtocol* pProt)
- {
- m_pMutex->Lock();
- IHXTCPSocket* pSocket = 0;
- HX_RESULT rc = HXR_OK;
- /*
- * Not checking for HTTP because connectionless control channel is not
- * currently slated to work with HTTP cloaking
- */
- m_pNetworkServices->CreateTCPSocket(&pSocket);
- if (!pSocket)
- {
- rc = HXR_OUTOFMEMORY;
- goto exit;
- }
- rc = pSocket->Init((IHXTCPResponse*)this);
- if (rc != HXR_OK)
- {
- goto exit;
- }
- HX_ASSERT(!m_pSessionSocket && !m_pConnectingProt);
- // already AddRef()'d in CreateTCPSocket
- m_pSessionSocket = pSocket;
- m_pConnectingProt = pProt;
- rc = m_pSessionSocket->Connect(m_pActualHost, m_uActualPort);
- exit:
- m_pMutex->Unlock();
- return rc;
- }
- /*
- * IUnknown methods
- */
- STDMETHODIMP
- RTSPClientSession::QueryInterface(REFIID riid, void** ppvObj)
- {
- QInterfaceList qiList[] =
- {
- { GET_IIDHANDLE(IID_IUnknown), this },
- { GET_IIDHANDLE(IID_IHXTCPResponse), (IHXTCPResponse*) this },
- { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
- };
- return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
- }
- STDMETHODIMP_(UINT32)
- RTSPClientSession::AddRef()
- {
- return InterlockedIncrement(&m_lRefCount);
- }
- STDMETHODIMP_(UINT32)
- RTSPClientSession::Release()
- {
- if (InterlockedDecrement(&m_lRefCount) > 0)
- {
- return m_lRefCount;
- }
- delete this;
- return 0;
- }
- /*
- * IHXTCPResponse methods
- */
- STDMETHODIMP
- RTSPClientSession::ConnectDone(HX_RESULT status)
- {
- HX_ASSERT(m_pConnectingProt);
- #ifdef _MACINTOSH
- if (!m_pConnectingProt)
- {
- return HXR_FAIL;
- }
- #endif
- if(HXR_OK == status)
- {
- if (!m_bHTTPOnly && !m_bUseProxy)
- {
- m_bSetSessionCalled = TRUE;
- m_pConnectingProt->SessionSucceeded(this, m_pSessionSocket);
- }
- if (m_bReopenSocket)
- {
- m_pConnectingProt->ReopenSocketDone(HXR_OK);
- }
- else
- {
- m_pConnectingProt->sendInitialMessage(this, m_pSessionSocket);
- m_pConnectingProt->InitDone(HXR_OK);
- }
- m_pConnectingProt = 0;
- // start handleInput process
- return m_pSessionSocket->Read(MAX_RTSP_MSG);
- }
- m_bSetSessionCalled = TRUE;
- m_pConnectingProt->SessionFailed(this, m_pSessionSocket);
- m_pConnectingProt->AddRef();
- if (m_bReopenSocket)
- {
- m_pConnectingProt->ReopenSocketDone(HXR_NET_CONNECT);
- }
- else
- {
- m_pConnectingProt->InitDone(HXR_NET_CONNECT);
- }
- m_pConnectingProt->Release();
- m_pConnectingProt = 0;
- return HXR_FAIL;
- }
- STDMETHODIMP
- RTSPClientSession::ReadDone(HX_RESULT status,
- IHXBuffer* pBuffer)
- {
- HX_RESULT hresult = HXR_OK;
- if (m_bIgnoreSession)
- {
- return HXR_OK;
- }
- if(status == HXR_OK)
- {
- AddRef();
- m_pMutex->Lock();
- if (!m_bSetSessionCalled)
- {
- m_bSetSessionCalled = TRUE;
- LISTPOSITION pos = m_protList.GetHeadPosition();
- while (pos)
- {
- RTSPClientProtocolInfo* pInfo =
- (RTSPClientProtocolInfo*)m_protList.GetNext(pos);
- if (pInfo->m_pProt->IsSessionSucceeded())
- {
- m_bIgnoreSession = TRUE;
- goto ignoreexit;
- }
- pInfo->m_pProt->SessionSucceeded(this, m_pSessionSocket);
- }
- }
- hresult = handleInput(pBuffer->GetBuffer(), pBuffer->GetSize());
- if( hresult == HXR_OUTOFMEMORY )
- {
- m_pMutex->Unlock();
- Release();
- return hresult;
- }
- if (m_pSessionSocket && !m_bSessionDone)
- {
- hresult = m_pSessionSocket->Read(MAX_RTSP_MSG);
- }
- ignoreexit:
- m_pMutex->Unlock();
- Release();
- }
- else
- {
- AddRef();
- m_pMutex->Lock();
- LISTPOSITION pos = m_protList.GetHeadPosition();
- while (pos)
- {
- RTSPClientProtocolInfo* pInfo =
- (RTSPClientProtocolInfo*)m_protList.GetNext(pos);
- if (!m_bSetSessionCalled)
- {
- pInfo->m_pProt->SessionFailed(this, m_pSessionSocket);
- }
- hresult = pInfo->m_pProt->OnProtocolError(status);
- }
- m_bSetSessionCalled = TRUE;
- m_pMutex->Unlock();
- Release();
- }
- if( hresult == HXR_OUTOFMEMORY )
- {
- ReportError( hresult );
- }
- // We have handled OOM errors, and it is not the responsibility of the
- // caller to handle our other errors, so we return HXR_OK.
- return HXR_OK;
- }
- STDMETHODIMP
- RTSPClientSession::WriteReady(HX_RESULT status)
- {
- return HXR_NOTIMPL;
- }
- STDMETHODIMP
- RTSPClientSession::Closed(HX_RESULT status)
- {
- return HXR_NOTIMPL;
- }