rtspclnt.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:217k
源码类别:

Symbian

开发平台:

C/C++

  1. HX_RESULT
  2. RTSPClientProtocol::handleSetParamResponse(RTSPResponseMessage* pMsg)
  3. {
  4.     const char* pPIP = 0;
  5.     const char* pPPort = 0;
  6.     const char* pPSourcePort = 0;
  7.     IHXValues* pValues = NULL;
  8.     HX_RESULT theErr = HXR_FAIL;
  9.     m_bKeepLiveResponsed = TRUE;
  10.     if (m_pResp)
  11.     {
  12. if(strcmp(pMsg->errorCode(), "200") != 0)
  13. {
  14.     if (m_bNonRSRTP)
  15.     {
  16. return m_pResp->HandleSetParameterResponse(HXR_OK);
  17.     }
  18.     else
  19.     {
  20.      return m_pResp->HandleSetParameterResponse(HXR_FAIL);
  21.     }
  22. }
  23. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  24.         MIMEHeader* pIP = pMsg->getHeader("MulticastIP");
  25. if (pIP)
  26. {
  27.     MIMEHeaderValue* pHeaderValue = pIP->getFirstHeaderValue();
  28.     if (pHeaderValue)
  29.     {
  30.         MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  31.         if (pParam)
  32. {
  33.     pPIP = (const char*)pParam->m_attribute;
  34. }
  35.     }
  36. }
  37.         MIMEHeader* pPort = pMsg->getHeader("MulticastPort");
  38. if (pPort)
  39. {
  40.     MIMEHeaderValue* pHeaderValue = pPort->getFirstHeaderValue();
  41.     if (pHeaderValue)
  42.     {
  43.         MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  44.         if (pParam)
  45. {
  46.     pPPort = (const char*)pParam->m_attribute;
  47. }
  48.     }
  49. }
  50. MIMEHeader* pSourcePort = pMsg->getHeader("MulticastSourcePort");
  51. if (pSourcePort)
  52. {
  53.     MIMEHeaderValue* pHeaderValue = pSourcePort->getFirstHeaderValue();
  54.     if (pHeaderValue)
  55.     {
  56.         MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  57.         if (pParam)
  58. {
  59.     pPSourcePort = (const char*)pParam->m_attribute;
  60. }
  61.     }
  62. }
  63. if (pPIP && pPPort && pPSourcePort)
  64. {
  65.     // multicast!!!
  66.     UINT16 nToPort = atoi(pPPort);
  67.     (*m_pTransportMPortMap)[nToPort] =
  68. (*m_pTransportStreamMap)[0];
  69.     IHXUDPSocket*     pUDPSocket = 0;
  70.     UDPResponseHelper*     pUDPResponseHelper = NULL;
  71.     IHXSetSocketOption*    pSockOpt = NULL;
  72.     if (!m_pNetworkServices)
  73.     {
  74. return HXR_OUTOFMEMORY;
  75.     }
  76.     if (HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket))
  77.     {
  78. return HXR_FAIL;
  79.     }
  80.     pUDPResponseHelper = new UDPResponseHelper(this, nToPort);
  81.     if (!pUDPResponseHelper)
  82.     {
  83. return HXR_OUTOFMEMORY;
  84.     }
  85.     pUDPResponseHelper->AddRef();
  86.     m_UDPResponseHelperList.AddTail(pUDPResponseHelper);
  87.     pUDPSocket->Init(0, nToPort, pUDPResponseHelper);
  88.     // set option before it binds
  89.          if (HXR_OK == pUDPSocket->QueryInterface(IID_IHXSetSocketOption,
  90.      (void**)&pSockOpt))
  91.          {
  92.      pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
  93.      pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
  94.      HX_RELEASE(pSockOpt);
  95.          }
  96.     pUDPSocket->Bind(HXR_INADDR_ANY, nToPort);
  97.     theErr = pUDPSocket->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  98.     ((RTSPTransport*)((*m_pTransportMPortMap)[nToPort]))->
  99. JoinMulticast(DwToHost(HXinet_addr(pPIP)), nToPort, pUDPSocket);
  100.     HX_RELEASE(pUDPSocket);
  101. }
  102. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  103. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  104.         MIMEHeader* pStatsInterval = pMsg->getHeader("UpdateStatsInterval");
  105. if (pStatsInterval)
  106. {
  107.     MIMEHeaderValue* pHeaderValue = pStatsInterval->getFirstHeaderValue();
  108.     if (pHeaderValue)
  109.     {
  110.         MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  111.         if (pParam)
  112. {
  113.     // stats interval
  114.     UINT32 ulStatsInterval = (UINT32) atoi((const char*)pParam->m_attribute);
  115.     pValues = new CHXHeader;
  116.                     if( pValues )
  117.                     {
  118.         pValues->AddRef();
  119.         pValues->SetPropertyULONG32("UpdateStatsInterval", ulStatsInterval);
  120.                     }
  121.                     else
  122.                     {
  123.                         theErr = HXR_OUTOFMEMORY;
  124.                     }
  125. }
  126.     }
  127. }
  128. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  129.         if( theErr != HXR_OUTOFMEMORY )
  130.         {
  131.     theErr = m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pValues);
  132.         }
  133. HX_RELEASE(pValues);
  134.     }
  135.     return theErr;
  136. }
  137. HX_RESULT
  138. RTSPClientProtocol::handleTeardownResponse(RTSPResponseMessage* pMsg)
  139. {
  140.     if(m_pResp)
  141.     {
  142. if(strcmp(pMsg->errorCode(), "200") != 0)
  143. {
  144.     m_pResp->HandleTeardownResponse(HXR_FAIL);
  145. }
  146. else
  147. {
  148.     m_pResp->HandleTeardownResponse(HXR_OK);
  149. }
  150.     }
  151.     /*
  152.      * The control channel is now closed
  153.      */
  154.     return HXR_NET_SOCKET_INVALID;
  155. }
  156. HX_RESULT
  157. RTSPClientProtocol::handleRecordResponse(RTSPResponseMessage* pMsg)
  158. {
  159.     if(strcmp(pMsg->errorCode(), "200") != 0)
  160.     {
  161. return m_pResp->HandleRecordResponse(HXR_FAIL);
  162.     }
  163.     if (m_bConnectionlessControl)
  164.     {
  165. closeSocket();
  166. if (HXR_OK ==
  167.     m_pResp->QueryInterface(IID_IHXConnectionlessControl,
  168.                             (void**)&m_pConnectionlessControl))
  169. {
  170.     m_pConnectionCheckCallback = new ConnectionCheckCallback(this);
  171.     m_pConnectionCheckCallback->AddRef();
  172.     m_uConnectionCheckCallbackHandle =
  173.         m_pScheduler->RelativeEnter(m_pConnectionCheckCallback,
  174.         m_uConnectionTimeout * 1000);
  175. }
  176.     }
  177.     return m_pResp->HandleRecordResponse(HXR_OK);
  178. }
  179. HX_RESULT
  180. RTSPClientProtocol::handlePauseResponse(RTSPResponseMessage* pMsg)
  181. {
  182.     /*
  183.      * XXX...Bruce is there anything to do here?
  184.      */
  185.     return HXR_OK;
  186. }
  187. HX_RESULT
  188. RTSPClientProtocol::handlePlayResponse(RTSPResponseMessage* pMsg,
  189.     RTSPPlayMessage* pPlayMsg)
  190. {
  191.     /*  Message Format:
  192.      *  RTSP/0.5 200 302 OK
  193.      *  RTP-Info: url=foo/streamid=0;seq=32;rtptime=40182123,
  194.      *    url=foo/streamid=1;seq=410;rtptime=40199211
  195.      */
  196.     if(strcmp(pMsg->errorCode(), "200") != 0)
  197.     {
  198. HX_RESULT hr = HXR_FAIL;
  199.         if(pMsg->errorCodeAsUINT32() == 456)
  200.             hr = HXR_INVALID_OPERATION;
  201.         return m_pResp->HandlePlayResponse(hr);
  202.     }
  203.     MIMEHeader* pSequence = pMsg->getHeader("RTP-Info");
  204.     MIMEHeaderValue* pSeqValue = 0;
  205.     UINT16 streamID = 0;
  206.     UINT16 seqNum = 0;
  207.     UINT32 ulRTPTime = 0;
  208.     const char* pControl = 0;
  209.     RTPInfoEnum RTPErr;
  210.     BOOL bSomeRTPInfoSet = FALSE;
  211.     if (pSequence)
  212.     {
  213. pSeqValue = pSequence->getFirstHeaderValue();
  214.     }
  215.     // per spec., "RTP-Info" has to be present in the 1st Play
  216.     // response header received, regardless whether the transport
  217.     // is TNG or RTP
  218.     if (!pSeqValue && !m_bSeqValueReceived)
  219.     {
  220. // XXXGo - interop hack
  221. if ((!(m_bIPTV || m_bColumbia)) || (m_pControlToStreamNoMap == NULL))
  222. {
  223.     return m_pResp->HandlePlayResponse(HXR_BAD_SERVER);
  224. }
  225.     }
  226.     if (pSeqValue)
  227.     {
  228. do
  229. {
  230.     RTPErr = parseRTPInfoHeader(pSeqValue, streamID, seqNum,
  231. ulRTPTime, pControl);
  232.     // if m_pControlToStreamNoMap, don't trust the parseRTPInfoHeader
  233.     // because RTP-Info url could be not what we expect and still be ok with
  234.     // spec
  235.     HX_ASSERT(pControl);
  236.             RTSPStreamInfo* pInfo = getStreamInfoFromSetupRequestURL(pControl);
  237.             if (pInfo)
  238.             {
  239.                 streamID = pInfo->m_streamNumber;
  240.             }
  241.     pControl = 0;
  242.     if (RTPINFO_ERROR != RTPErr)
  243.     {
  244. SetRTPInfo(streamID, seqNum, ulRTPTime, RTPErr);
  245. bSomeRTPInfoSet = TRUE;
  246.     }
  247.     pSeqValue = pSequence->getNextHeaderValue();
  248. } while (pSeqValue);
  249.     }
  250.     // If we did not receive any RTP Info, 
  251.     // just tell all streams not to wait for it
  252.     if (!bSomeRTPInfoSet && m_pControlToStreamNoMap)
  253.     {
  254. CHXMapStringToOb::Iterator i;
  255. UINT32* pul;
  256. for (i = m_pControlToStreamNoMap->Begin();
  257.      i != m_pControlToStreamNoMap->End();
  258.      ++i)
  259. {
  260.     pul = (UINT32*)(*i);
  261.     streamID = (UINT16) (*pul);
  262.     SetRTPInfo(streamID, 0, 0, RTPINFO_EMPTY);
  263. }
  264.     }
  265.     m_bSeqValueReceived = TRUE;
  266.     if (m_bConnectionlessControl)
  267.     {
  268. closeSocket();
  269.     }
  270.     MIMEHeader* pXPredecPeriod = pMsg->getHeader("x-initpredecbufperiod");
  271.     if (pXPredecPeriod)
  272.     {
  273. MIMEHeaderValue* pPrerollValue = pXPredecPeriod->getFirstHeaderValue();
  274. if (pPrerollValue)
  275. {
  276.     const char* pStart = pPrerollValue->value();
  277.     char* pEnd = 0;
  278.     ULONG32 ulValue = strtoul(pStart, &pEnd, 10);
  279.     if (*pStart && !*pEnd)
  280.     {
  281. // Handle updated preroll condition
  282. m_pResp->HandlePrerollChange(RTSP_PREROLL_PREDECBUFPERIOD,
  283.      ulValue);
  284.     }
  285. }
  286.     }
  287.     // Update range entries
  288.     MIMEHeader* pRange = pMsg->getHeader("Range");
  289.     if (pRange)
  290.     {
  291.         pSeqValue = pRange->getFirstHeaderValue();
  292.         INT32 nFrom = 0, nTo = 0;
  293.         if (pSeqValue)
  294.         {
  295.             MIMEParameter* pParam = pSeqValue->getFirstParameter();
  296.             if (pParam)
  297.             {
  298.         const char* pRange = (const char*) pParam->m_attribute;
  299.                 const char* pDash = NULL;
  300.                 char* pStopString;
  301.                 double dTemp;
  302.         if (pRange)
  303.                 {
  304.     dTemp = strtod(pRange, &pStopString);
  305.                     nFrom = (INT32)(dTemp * 1000);
  306.                     pDash  = strrchr(pRange, '-');
  307.                 }
  308.                 if (pDash)
  309.                 {
  310.                     dTemp = strtod(pDash + 1, &pStopString);
  311.                     nTo = (INT32)(dTemp * 1000);
  312.                 }
  313.             }
  314.         }
  315.         if (!m_transportRequestList.IsEmpty())
  316.         {
  317.     RTSPTransportRequest* pRequest =
  318.         (RTSPTransportRequest*)m_transportRequestList.GetHead();
  319.             RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
  320.             while(pTransInfo && nTo)
  321.     {
  322.                 // set the range in transport...only for RTP
  323.         pTransInfo->m_pTransport->RTSPTransport::setPlayRange(nFrom, nTo);
  324.         pTransInfo = pRequest->getNextTransportInfo();
  325.     }
  326.         }
  327.     }
  328.     return m_pResp->HandlePlayResponse(HXR_OK);
  329. }
  330. HX_RESULT
  331. RTSPClientProtocol::handleSetupResponse(RTSPResponseMessage* pMsg,
  332.     RTSPSetupMessage* pSetupMsg)
  333. {
  334.     HX_RESULT status = HXR_OK;
  335.     UINT16 streamNumber = 0;
  336.     IHXValues* pReconnectValues = NULL;
  337.     RTSPStreamInfo* pStreamInfo = 0;
  338.     if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
  339.     {
  340. status = handleAuthentication(pMsg);
  341. return status;
  342.     }
  343.     else if(strcmp(pMsg->errorCode(), "200") != 0)
  344.     {
  345. return m_pResp->HandleSetupResponse(HXR_BAD_TRANSPORT);
  346.     }
  347.     /* SETUP succeeded */
  348.     m_setupResponseCount++;
  349.     // we need to find the right StreamInfo obj..
  350.     pStreamInfo = getStreamInfoFromSetupRequestURL(pSetupMsg->url());
  351.     if(!pStreamInfo)
  352.     {
  353. return m_pResp->HandleSetupResponse(HXR_BAD_TRANSPORT);
  354.     }
  355.     else
  356.     {
  357. streamNumber = pStreamInfo->m_streamNumber;
  358.     }
  359.     CHXString reconnectFlag = pMsg->getHeaderValue("Reconnect");
  360.     if (reconnectFlag != "" && strcasecmp((const char*)reconnectFlag, "false") == 0)
  361.     {
  362. pReconnectValues = new CHXHeader();
  363. pReconnectValues->AddRef();
  364.      pReconnectValues->SetPropertyULONG32("Reconnect", 0);
  365.     }
  366.     else
  367.     {
  368. MIMEHeader* pHeader = pMsg->getHeader("Alternate-Server");
  369. if (pHeader)
  370. {
  371.     RetrieveReconnectInfo(pHeader, ALTERNATE_SERVER, pReconnectValues);
  372. }
  373. pHeader = pMsg->getHeader("Alternate-Proxy");
  374. if (pHeader)
  375. {
  376.     RetrieveReconnectInfo(pHeader, ALTERNATE_PROXY, pReconnectValues);
  377. }
  378.     }
  379.     if (pReconnectValues)
  380.     {
  381. m_pResp->HandleSetParameterResponseWithValues(HXR_OK, pReconnectValues);
  382.     }
  383.     HX_RELEASE(pReconnectValues);
  384.     CHXString sessionID = pMsg->getHeaderValue("Session");
  385.     if(sessionID != "")
  386.     {
  387. int i;
  388. if (-1 != (i = sessionID.Find(';')))
  389. {
  390.     m_sessionID = sessionID.Left(i);
  391. }
  392. else
  393. {
  394.     m_sessionID = sessionID;
  395. }
  396.     }
  397.     status = handleSetupResponseExt(pStreamInfo, pMsg, pSetupMsg);
  398.     UINT16 nStreamCount = (UINT16)m_streamInfoList.GetCount();
  399.     if(m_setupResponseCount == 1 && (nStreamCount > 1))
  400.     {
  401. // first time, send the rest...
  402. sendRemainingSetupRequests();
  403.     }
  404.     if(m_setupResponseCount == nStreamCount)
  405.     {
  406. // all done!
  407. CHXSimpleList::Iterator i;
  408. for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
  409. {
  410.     RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
  411.     RTSPTransportInfo* pTransInfo = pRequest->getFirstTransportInfo();
  412.     while(pTransInfo)
  413.     {
  414. if (BUFFER_DEPTH_UNDEFINED == m_ulBufferDepth)
  415. {
  416.     break;
  417. }
  418. HX_RESULT hresult =
  419.     pTransInfo->m_pTransport->SetResendBufferDepth
  420.     (
  421. m_ulBufferDepth
  422.     );
  423. if (HXR_OK != hresult)
  424. {
  425.     return hresult;
  426. }
  427. pTransInfo = pRequest->getNextTransportInfo();
  428.     }
  429. }
  430. // we don't need this anymore...
  431. HX_RELEASE(m_pSetupRequestHeader);
  432. return m_pResp->HandleSetupResponse(status);
  433.     }
  434.     else
  435.     {
  436. return status;
  437.     }
  438. }
  439. HX_RESULT
  440. RTSPClientProtocol::handleSetupResponseExt(RTSPStreamInfo* pStreamInfo,
  441.    RTSPResponseMessage* pMsg,
  442.    RTSPSetupMessage* pSetupMsg)
  443. {
  444.     HX_RESULT status = HXR_OK;
  445.     // get transport info
  446.     CHXString transportType;
  447.     UINT16 localPort = 0;
  448.     UINT16 streamNumber = pStreamInfo->m_streamNumber;
  449.     MIMEHeader* pTransport = pMsg->getHeader("Transport");
  450.     if(pTransport)
  451.     {
  452. MIMEHeaderValue* pValue = pTransport->getFirstHeaderValue();
  453. if(!pValue)
  454. {
  455.     // return some awful error
  456. }
  457. RTSPTransportRequest* pRequest = getTransportRequest(pValue);
  458. if(!pRequest)
  459. {
  460.     // return another awful error
  461.     return HXR_FAIL;
  462. }
  463. m_pSession->m_bChallengeMet = TRUE;
  464. m_pSession->m_bChallengeDone = TRUE;
  465. RTSPTransportInfo* pTransInfo = pRequest->getTransportInfo(streamNumber);
  466. UINT16 resendPort = 0;
  467.         // get the server address we are connecting to
  468.         // used to filter out any UDP packets received from 3rd party
  469.         if (m_pSocket->GetForeignAddress(m_ulConnectToAddr) != HXR_OK)
  470. {
  471.             HX_ASSERT(FALSE);
  472.     status = HXR_BAD_TRANSPORT;
  473. }
  474. UINT32 foreignAddr = 0;
  475.         if (m_foreignAddr != 0)
  476.         {
  477.             foreignAddr = m_foreignAddr;
  478.         }
  479.         else
  480. {
  481.             foreignAddr = m_ulConnectToAddr;
  482. }
  483. resendPort = pRequest->m_sResendPort;
  484. RTSPTransport* pTrans = pTransInfo->m_pTransport;
  485. RTCPBaseTransport* pRTCPTrans = pTransInfo->m_pRTCPTransport;
  486. pStreamInfo->m_sPort = pTransInfo->m_sPort;
  487. HX_ASSERT(pTrans);
  488. #if defined(HELIX_FEATURE_RTP)
  489. switch(pRequest->m_lTransportType)
  490. {
  491.     case RTSP_TR_RTP_TCP:
  492.     {
  493. if ((!m_bHasSyncMasterStream) &&
  494.     (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
  495. {
  496.     pStreamInfo->m_bIsSyncMaster = TRUE;
  497.     m_bHasSyncMasterStream = TRUE;
  498. }
  499. pTrans->addStreamInfo(pStreamInfo);
  500. (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
  501. m_pSession->setProtocolInterleave(this,
  502.     pRequest->m_tcpInterleave);
  503. m_pSession->setProtocolInterleave(this,
  504.     pRequest->m_tcpInterleave+1);
  505. ((RTPTCPTransport*)pTrans)->
  506.     setInterleaveChannel(pRequest->m_tcpInterleave);
  507. ((RTCPTCPTransport*)pRTCPTrans)->
  508.     setInterleaveChannel(pRequest->m_tcpInterleave+1);
  509. if (!m_sessionID.IsEmpty())
  510. {
  511.     pTrans->setSessionID(m_sessionID);
  512. }
  513. mapTransportChannel(pTrans, pRequest->m_tcpInterleave);
  514. mapTransportChannel(pRTCPTrans, pRequest->m_tcpInterleave+1);
  515. mapControlToStreamNo(pStreamInfo->m_streamControl,
  516.                                      pStreamInfo->m_streamNumber);
  517. /* Temporary */
  518. m_uProtocolType = 3;
  519.     }
  520.     break;
  521.     case RTSP_TR_RTP_UDP:
  522.     {
  523. if ((!m_bHasSyncMasterStream) &&
  524.     (pStreamInfo->m_eMediaType == RTSPMEDIA_TYPE_AUDIO))
  525. {
  526.     pStreamInfo->m_bIsSyncMaster = TRUE;
  527.     m_bHasSyncMasterStream = TRUE;
  528. }
  529. pTrans->addStreamInfo(pStreamInfo);
  530. (*m_pTransportStreamMap)[pStreamInfo->m_streamNumber] = pTrans;
  531. (*m_pTransportPortMap)[pTransInfo->m_sPort] = pTrans;
  532. (*m_pTransportPortMap)[pTransInfo->m_sPort+1] = pRTCPTrans;
  533. mapControlToStreamNo(pStreamInfo->m_streamControl, pStreamInfo->m_streamNumber);
  534. ((RTPUDPTransport*)pTrans)->setForeignAddress(foreignAddr, resendPort);
  535. ((RTCPUDPTransport*)pRTCPTrans)->setForeignAddress(foreignAddr, resendPort+1);
  536. if (!m_sessionID.IsEmpty())
  537. {
  538.     pTrans->setSessionID(m_sessionID);
  539. }
  540. /* Temporary */
  541. m_uProtocolType = 2;
  542.     }
  543.     break;
  544.     default:
  545.     {
  546. status = HXR_BAD_TRANSPORT;
  547.     }
  548.     break;
  549. }
  550. #endif /* HELIX_FEATURE_RTP */
  551.     }
  552.     return status;
  553. }
  554. HX_RESULT
  555. RTSPClientProtocol::handleAnnounceResponse(RTSPResponseMessage* pMsg)
  556. {
  557.     HX_RESULT rc = HXR_OK;
  558.     if(!m_bSetupRecord) // better only get one of these if recording...
  559.     {
  560. return HXR_FAIL;
  561.     }
  562.     if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
  563.     {
  564. rc = handleAuthentication(pMsg);
  565. return rc;
  566.     }
  567.     else if(strcmp(pMsg->errorCode(), "409") == 0)
  568.     {
  569. return m_pResp->HandleStreamRecordDescriptionResponse(HXR_ALREADY_OPEN, 0);
  570.     }
  571.     else if(strcmp(pMsg->errorCode(), "200") != 0)
  572.     {
  573. return m_pResp->HandleStreamRecordDescriptionResponse(HXR_FAIL, 0);
  574.     }
  575.     IHXValues* pRFC822Headers = NULL;
  576.     getRFC822Headers(pMsg, pRFC822Headers);
  577.     if(pRFC822Headers )
  578.     {
  579. IHXKeyValueList* pRFC822List = NULL;
  580. if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
  581. {
  582.     m_pResponseHeaders->AppendAllListItems(pRFC822List);
  583. }
  584. HX_RELEASE(pRFC822List);
  585.     }
  586.     HX_RELEASE(pRFC822Headers);
  587.     IHXValues* pResponseHeaders = NULL;
  588.     if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  589.     {
  590. rc = m_pResp->HandleStreamRecordDescriptionResponse(HXR_OK,
  591.     pResponseHeaders);
  592.     }
  593.     else
  594.     {
  595. rc = m_pResp->HandleStreamRecordDescriptionResponse(HXR_FAILED,
  596.     NULL);
  597.     }
  598.     HX_RELEASE(pResponseHeaders);
  599.     return rc;
  600. }
  601. HX_RESULT
  602. RTSPClientProtocol::handleDescribeResponse(RTSPResponseMessage* pMsg)
  603. {
  604.     HX_RESULT rc = HXR_OK;
  605.     if(m_bSetupRecord) // better only get one of these if playing...
  606.     {
  607. return HXR_FAIL;
  608.     }
  609.     if(pMsg->errorCodeAsUINT32() == 401 || pMsg->errorCodeAsUINT32() == 407)
  610.     {
  611. rc = handleAuthentication(pMsg);
  612. return rc;
  613.     }
  614.     else if(pMsg->errorCodeAsUINT32() == 551)
  615.     {
  616. // A Require option was not supported.
  617. // We could check the Unsupported header
  618. // to see which one(s) failed, but
  619. // since we only support one right now..
  620. m_bEntityRequired = FALSE;
  621. // Re-Send the describe w/o the Require..
  622. return m_pResp->HandleStreamDescriptionResponse
  623. (
  624.     HXR_OK,
  625.     0,
  626.     0,
  627.     0
  628. );
  629.     }
  630.     else if(strcmp(pMsg->errorCode(), "200") != 0)
  631.     {
  632. return m_pResp->HandleStreamDescriptionResponse
  633. (
  634.     HXR_DOC_MISSING,
  635.     0,
  636.     0,
  637.     0
  638. );
  639.     }
  640.     // We do not handle content-encoding
  641.     MIMEHeader* pContentEncoding = pMsg->getHeader("Content-Encoding");
  642.     if(pContentEncoding)
  643.     {
  644.         if (pContentEncoding->getFirstHeaderValue())
  645.         {
  646.             return HXR_UNEXPECTED_MSG;
  647.         }
  648.     }
  649.     // Set Context for use by sendSetupRequestMessage()
  650.     CHXString sessionID = pMsg->getHeaderValue("ETag");
  651.     if(!sessionID.IsEmpty())
  652.     {
  653. m_sessionID = sessionID;
  654.     }
  655.     IHXValues* pRFC822Headers = NULL;
  656.     getRFC822Headers(pMsg, pRFC822Headers);
  657.     if(pRFC822Headers)
  658.     {
  659. // XXXGo - interop hack...It should be "Server", but IPTV put this
  660. // string in "User-Agent"...
  661.      IHXBuffer* pAgent  = NULL;
  662.      if (pRFC822Headers->GetPropertyCString("Server", pAgent) != HXR_OK)
  663.      {
  664.          // try this...
  665.          pRFC822Headers->GetPropertyCString("User-Agent", pAgent);
  666.      }
  667.      if (pAgent)
  668.      {
  669.     if (strncasecmp((const char*)pAgent->GetBuffer(), "Columbia RTSP Server",
  670.      20) == 0)
  671.     {
  672. m_bColumbia = TRUE;
  673. m_bNoKeepAlive = TRUE;
  674.     }
  675.     else if (strncasecmp((const char*)pAgent->GetBuffer(), "Cisco IPTV",
  676.      10) == 0)
  677.     {
  678.      m_bIPTV = TRUE;
  679.     }
  680.     else if (strncasecmp((const char*)pAgent->GetBuffer(), "Cisco IP/TV",
  681.      11) == 0)
  682.     {
  683.      m_bIPTV = TRUE;
  684.     }
  685.     else if (strncasecmp((const char*)pAgent->GetBuffer(), "QTSS",
  686.      4) == 0)
  687.     {
  688. // once we send SET_PARAM for a keep alive, QTS won't be
  689. // responsive for any other request...so don't send
  690. // keep alive.
  691. m_bNoKeepAlive = TRUE;
  692. m_bForceUCaseTransportMimeType = TRUE;
  693.     }
  694.     else if (strncasecmp((const char*)pAgent->GetBuffer(), "DSS",
  695.      3) == 0)
  696.     {
  697. m_bForceUCaseTransportMimeType = TRUE;
  698.     }
  699.          HX_RELEASE(pAgent);
  700.      }
  701. IHXKeyValueList* pRFC822List = NULL;
  702. if (HXR_OK == pRFC822Headers->QueryInterface(IID_IHXKeyValueList, (void**)&pRFC822List))
  703. {
  704.     m_pResponseHeaders->AppendAllListItems(pRFC822List);
  705. }
  706. HX_RELEASE(pRFC822List);
  707.     }
  708.     HX_RELEASE(pRFC822Headers);
  709.     // Respond to Client Challenge to prove that we are a RealClient
  710.     if (!m_pSession->m_bChallengeDone)
  711.     {
  712. RetrieveChallenge(pMsg);
  713.     }
  714.     // We need a content base entry to handle relative urls.
  715.     // Check for one in the order specified in:
  716.     // http://www.zvon.org/tmRFC/RFC2326/Output/chapter19.html
  717.     MIMEHeader* pContentBaseHeader = pMsg->getHeader("Content-Base");
  718.     if(pContentBaseHeader)
  719.     {
  720.         MIMEHeaderValue* pValue = pContentBaseHeader->getFirstHeaderValue();
  721.         m_contentBase = pValue->value();
  722.     }
  723.     if (m_contentBase.IsEmpty())
  724.     {
  725.         pContentBaseHeader = pMsg->getHeader("Content-Location");
  726.         if(pContentBaseHeader)
  727.         {
  728.         MIMEHeaderValue* pValue = pContentBaseHeader->getFirstHeaderValue();
  729.         m_contentBase = pValue->value();
  730.         }
  731.     }
  732.     if (m_contentBase.IsEmpty())
  733.     {
  734.         INT32 nOffset = m_url.ReverseFind('/');
  735.         m_contentBase = m_url.Left(nOffset+1);
  736.     }
  737.     // Format the content base member
  738.     if (m_contentBase[m_contentBase.GetLength()-1] != '/')
  739.     {
  740.         INT32 nOffset = m_contentBase.ReverseFind('/');
  741.         m_contentBase.SetAt(nOffset+1, '');
  742.         m_contentBase.GetBufferSetLength(nOffset+1);
  743.     }
  744.     MIMEHeader* pContentTypeHeader = pMsg->getHeader("Content-type");
  745.     MIMEHeader* pContentLengthHeader = pMsg->getHeader("Content-length");
  746.     if(pContentTypeHeader && pContentLengthHeader)
  747.     {
  748. MIMEHeaderValue* pContentValue =
  749.     pContentTypeHeader->getFirstHeaderValue();
  750. if(!pContentValue)
  751. {
  752.     // error
  753.     rc = HXR_FAIL;
  754. }
  755. else
  756. {
  757.     CHXBuffer* pBuffer = new CHXBuffer;
  758.     if(pBuffer)
  759.     {
  760. pBuffer->AddRef();
  761. rc = pBuffer->Set((BYTE*)pMsg->getContent(), strlen(pMsg->getContent())+1);
  762.                 if( rc == HXR_OUTOFMEMORY )
  763.                 {
  764.                     HX_RELEASE(pBuffer);
  765.                     goto cleanup;
  766.                 }
  767.             }
  768.             else
  769.             {
  770.                 rc = HXR_OUTOFMEMORY;
  771.                 goto cleanup;
  772.             }
  773.             rc = ParseSDP(pContentValue->value(), pBuffer);
  774.             if (HXR_OK == rc)
  775.             {
  776. IHXValues* pResponseHeaders = NULL;
  777. if (HXR_OK == m_pResponseHeaders->QueryInterface(IID_IHXValues, (void**)&pResponseHeaders))
  778. {
  779.     if (!IsRealServer())
  780.     {
  781. BOOL bForceRTP = TRUE;
  782.                         ReadPrefBOOL(m_pPreferences, "NonRS", bForceRTP);
  783. if (bForceRTP)
  784. {
  785.     pResponseHeaders->SetPropertyULONG32("UseRTP", TRUE);
  786. }
  787.     }
  788.     rc = m_pResp->HandleStreamDescriptionResponse
  789.     (
  790. HXR_OK,
  791. m_pSDPFileHeader,
  792. m_pSDPStreamHeaders,
  793. pResponseHeaders
  794.     );
  795. }
  796. HX_RELEASE(pResponseHeaders);
  797.                 RemoveSDPHeaders();
  798.     }
  799.             HX_RELEASE(pBuffer);
  800. }
  801.     }
  802.     else
  803.     {
  804. rc = HXR_FAILED;
  805.     }
  806. cleanup:
  807.     if (HXR_OK != rc)
  808.     {
  809. rc = m_pResp->HandleStreamDescriptionResponse
  810. (
  811.     rc,
  812.     0,
  813.     0,
  814.     0
  815. );
  816.     }
  817.     return rc;
  818. }
  819. HX_RESULT
  820. RTSPClientProtocol::sendInitialMessage(RTSPClientSession* pSession,
  821.        IHXTCPSocket* pSocket)
  822. {
  823.     HX_RESULT rc = HXR_OK;
  824.     UINT32 seqNo = 0;
  825.     RTSPOptionsMessage* pMsg = NULL;
  826.     IHXBuffer* pBuffer = NULL;
  827.     m_pMutex->Lock();
  828.     // Assumption is we will send no options messages while waiting
  829.     // for our session time out options response.
  830.     HX_ASSERT(!m_bKeepAlivePending);
  831.     if (m_bNonRSRTP)
  832.     {
  833. rc = m_pResp->HandleOptionsResponse(HXR_OK, NULL);
  834. goto cleanup;
  835.     }
  836.     if (!m_bSessionSucceeded)
  837.     {
  838. HX_ASSERT(!m_pSession && !m_pSocket);
  839. m_pSession = pSession;
  840. m_pSocket = pSocket;
  841.     }
  842.     pMsg = new RTSPOptionsMessage;
  843.     // construct "rtsp://%-.200s:%u"
  844.     m_url = "rtsp://";
  845.     m_url += m_hostName.Left(200);
  846.     m_url += ':';
  847.     m_url.AppendULONG(m_foreignPort);
  848.     pMsg->setURL(m_url);
  849.     pMsg->addHeader("User-Agent", m_versionString);
  850.     /*
  851.      * XXXSMP m_pSessionHeaders can include a "Require" tag from rmacore.
  852.      * Yes this is ugly, and needs fixing when we want to send more options
  853.      */
  854.     if (m_pSessionHeaders &&
  855.         HXR_OK == m_pSessionHeaders->GetPropertyCString("ConnectionlessControl",
  856. pBuffer))
  857.     {
  858. m_bConnectionlessControl =
  859.     (strcasecmp((const char*)pBuffer->GetBuffer(), "on") == 0) ?
  860.     TRUE : FALSE;
  861. pBuffer->Release();
  862.     }
  863.     addRFC822Headers(pMsg, m_pSessionHeaders);
  864.     seqNo = m_pSession->getNextSeqNo(this);
  865.     rc = sendRequest(pMsg, seqNo);
  866.     if (!m_bSessionSucceeded)
  867.     {
  868. m_pSession = NULL;
  869. m_pSocket = NULL;
  870.     }
  871. cleanup:
  872.     m_pMutex->Unlock();
  873.     return rc;
  874. }
  875. HX_RESULT
  876. RTSPClientProtocol::getStreamDescriptionMimeType(char*& pMimeType)
  877. {
  878.     HX_RESULT rc = HXR_OK;
  879.     IHXStreamDescription* pSD = 0;
  880.     IHXPlugin2Handler* pPlugin2Handler = NULL;
  881.     // we have to have either an IHXPluginHandler or an IHXPlugin2Handler
  882.     m_pContext->QueryInterface(IID_IHXPlugin2Handler,
  883.                                (void**)&pPlugin2Handler);
  884.     if(pPlugin2Handler)
  885.     {
  886. UINT32 unIndex;
  887. if (HXR_OK == pPlugin2Handler->FindIndexUsingStrings(PLUGIN_CLASS,
  888.     PLUGIN_STREAM_DESC_TYPE,
  889.     NULL,
  890.     NULL,
  891.     NULL,
  892.     NULL,
  893.     unIndex))
  894. {
  895.     IHXValues* pValues;
  896.     pPlugin2Handler->GetPluginInfo(unIndex, pValues);
  897.     IHXBuffer* pBuffer;
  898.     pValues->GetPropertyCString(PLUGIN_STREAMDESCRIPTION, pBuffer);
  899.     pValues->Release();
  900.     const char* pTemp = (const char*)pBuffer->GetBuffer();
  901.     pMimeType = new_string(pTemp);
  902.     pBuffer->Release();
  903. }
  904. else
  905. {
  906.     rc = HXR_FAIL;
  907. }
  908. HX_RELEASE(pPlugin2Handler);
  909.     }
  910. #if defined(HELIX_FEATURE_SERVER)
  911.     else
  912.     {
  913. // ok we do not have an IHXPlugin2Handler (we must be in the server)
  914. // so get the PluginHandler
  915. PluginHandler* pPHandler = 0;
  916.         m_pContext->QueryInterface(IID_IHXPluginHandler,
  917.                                (void**)&pPHandler);
  918. if(pPHandler)
  919. {
  920.     PluginHandler::StreamDescription* pSDHandler;
  921.     pSDHandler = pPHandler->m_stream_description_handler;
  922.     UINT32 ulNumPlugins = pSDHandler->GetNumOfPlugins();
  923.     if(ulNumPlugins > 0)
  924.     {
  925. // get the first one...
  926. char* ppszDllPath = 0;
  927. char* ppszDescription = 0;
  928. char* ppszCopyright = 0;
  929. char* ppszMoreInfo = 0;
  930. BOOL  pbMultiple = FALSE;
  931. char* ppszMimeType = 0;
  932. pSDHandler->GetPluginInfo(0, &ppszDllPath, &ppszDescription,
  933.     &ppszCopyright, &ppszMoreInfo, &pbMultiple,
  934.     &ppszMimeType);
  935. pMimeType = new_string(ppszMimeType);
  936. rc = HXR_OK;
  937.     }
  938.     else
  939.     {
  940. rc = HXR_FAIL;
  941.     }
  942.     pPHandler->Release();
  943. }
  944. else
  945. {
  946.     rc = HXR_FAIL;
  947. }
  948.     }
  949. #endif /* HELIX_FEATURE_SERVER */
  950.     return rc;
  951. }
  952. IHXStreamDescription*
  953. RTSPClientProtocol::getStreamDescriptionInstance(const char* pMimeType)
  954. {
  955.     IHXStreamDescription* pSD = 
  956. HXStreamDescriptionHelper::GetInstance(m_pContext, pMimeType);
  957. #if defined(HELIX_FEATURE_SERVER)
  958.     if (!pSD)
  959.     {
  960. // we don't have a plugin2handler ... we must be in the
  961. // server ... ask for a plugin handler
  962. PluginHandler* pPHandler = 0;
  963. m_pContext->QueryInterface(IID_IHXPluginHandler, (void**)&pPHandler);
  964. const char* pFindMimeType = pMimeType;
  965. if(pPHandler)
  966. {
  967.     PluginHandler::StreamDescription* pSDHandler;
  968.     PluginHandler::Errors             pluginResult;
  969.     PluginHandler::Plugin*            pPlugin;
  970.     pSDHandler = pPHandler->m_stream_description_handler;
  971.     pluginResult = pSDHandler->Find(pFindMimeType, pPlugin);
  972.     if(PluginHandler::NO_ERRORS == pluginResult)
  973.     {
  974. IUnknown* pInstance = 0;
  975. pPlugin->GetInstance(&pInstance);
  976. if(pInstance)
  977. {
  978.     HX_RESULT rc;
  979.     rc = pInstance->QueryInterface(IID_IHXStreamDescription,
  980.    (void**)&pSD);
  981.     if(rc == HXR_OK)
  982.     {
  983. IHXPlugin* pSDPlugin = 0;
  984. rc = pSD->QueryInterface(IID_IHXPlugin,
  985.  (void**)&pSDPlugin);
  986. if(rc == HXR_OK)
  987. {
  988.     pSDPlugin->InitPlugin(m_pContext);
  989.     pSDPlugin->Release();
  990. }
  991.     }
  992.     pInstance->Release();
  993. }
  994. pPlugin->ReleaseInstance();
  995.     }
  996.     pPHandler->Release();
  997. }
  998.     }
  999. #endif
  1000.     return pSD;
  1001. }
  1002. void
  1003. RTSPClientProtocol::reset()
  1004. {
  1005.     HX_DELETE(m_pTransportStreamMap);
  1006.     HX_DELETE(m_pTransportPortMap);
  1007.     HX_DELETE(m_pTransportMPortMap);
  1008.     HX_DELETE(m_pTransportChannelMap);
  1009.     if (m_pControlToStreamNoMap)
  1010.     {
  1011.         CHXMapStringToOb::Iterator i;
  1012. for(i=m_pControlToStreamNoMap->Begin();i!=m_pControlToStreamNoMap->End();++i)
  1013. {
  1014.     UINT32* pul = (UINT32*)(*i);
  1015.     delete pul;
  1016. }
  1017. m_pControlToStreamNoMap->RemoveAll();
  1018. HX_DELETE(m_pControlToStreamNoMap);
  1019.     }
  1020.     CHXSimpleList::Iterator i;
  1021.     for(i=m_transportRequestList.Begin();i!=m_transportRequestList.End();++i)
  1022.     {
  1023. RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
  1024. delete pRequest;
  1025.     }
  1026.     m_transportRequestList.RemoveAll();
  1027.     HX_RELEASE(m_pSetupRequestHeader);
  1028.     HX_RELEASE(m_pResolver);
  1029.     HX_RELEASE(m_pResp);
  1030.     HX_RELEASE(m_pConnectionlessControl);
  1031.     HX_RELEASE(m_pConnectionCheckCallback);
  1032.     HX_RELEASE(m_pContext);
  1033.     if (m_uConnectionCheckCallbackHandle)
  1034.     {
  1035.         m_pScheduler->Remove(m_uConnectionCheckCallbackHandle);
  1036.         m_uConnectionCheckCallbackHandle = 0;
  1037.     }
  1038.     HX_RELEASE(m_pTimeoutCallback);
  1039.     HX_DELETE(m_pSessionTimeout);
  1040. }
  1041. void
  1042. RTSPClientProtocol::clearStreamInfoList()
  1043. {
  1044.     CHXSimpleList::Iterator i;
  1045.     for(i=m_streamInfoList.Begin();
  1046. i!=m_streamInfoList.End();
  1047. ++i)
  1048.     {
  1049. RTSPStreamInfo* pInfo = (RTSPStreamInfo*)(*i);
  1050. delete pInfo;
  1051.     }
  1052.     m_streamInfoList.RemoveAll();
  1053. }
  1054. void
  1055. RTSPClientProtocol::clearTransportRequestList()
  1056. {
  1057.     CHXSimpleList::Iterator i;
  1058.     for (i = m_transportRequestList.Begin(); i != m_transportRequestList.End();  ++i)
  1059.     {
  1060. RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
  1061. delete pRequest;
  1062.     }
  1063.     m_transportRequestList.RemoveAll();
  1064. }
  1065. void
  1066. RTSPClientProtocol::clearUDPResponseHelperList()
  1067. {
  1068.     CHXSimpleList::Iterator i;
  1069.     for(i=m_UDPResponseHelperList.Begin();
  1070. i!=m_UDPResponseHelperList.End();
  1071. ++i)
  1072.     {
  1073. UDPResponseHelper* pHelper = (UDPResponseHelper*)(*i);
  1074. HX_RELEASE(pHelper);
  1075.     }
  1076.     m_UDPResponseHelperList.RemoveAll();
  1077. }
  1078. void
  1079. RTSPClientProtocol::clearSocketStreamMap(CHXMapLongToObj*& pSocketStreamMap)
  1080. {
  1081.     if(pSocketStreamMap)
  1082.     {
  1083. CHXMapLongToObj::Iterator i;
  1084. for(i=pSocketStreamMap->Begin();
  1085.     i!=pSocketStreamMap->End();++i)
  1086. {
  1087.     IHXUDPSocket* pSocket = (IHXUDPSocket*)(*i);
  1088.     pSocket->Release();
  1089. }
  1090. delete pSocketStreamMap;
  1091. pSocketStreamMap = 0;
  1092.     }
  1093. }
  1094. RTSPTransportRequest*
  1095. RTSPClientProtocol::getTransportRequest(MIMEHeaderValue* pValue)
  1096. {
  1097.     RTSPTransportRequest* pTransportRequest = 0;
  1098.     if(pValue)
  1099.     {
  1100. UINT16 requestPort = 0;
  1101. UINT16 resendPort = 0;
  1102. INT8 tcpInterleave = 0;
  1103. MIMEParameter* pParam = pValue->getFirstParameter();
  1104. char pTransValue[256]; /* Flawfinder: ignore */
  1105. strncpy(pTransValue, pParam->m_attribute,255);
  1106. pTransValue[255] = '';
  1107. pParam = pValue->getNextParameter();
  1108. while(pParam)
  1109. {
  1110.     if(0 == pParam->m_attribute.CompareNoCase("client_port"))
  1111.     {
  1112. // value range in rtp
  1113. const char* portString = (const char*)pParam->m_value;
  1114. char* pFirstValue = (char*)strchr(portString, '-');
  1115. if(pFirstValue)
  1116. {
  1117.     *pFirstValue = 0;  // get rid of second port value
  1118. }
  1119. requestPort = (UINT16)strtol(portString, 0, 10);
  1120.     }
  1121.     else if(0 == pParam->m_attribute.CompareNoCase("server_port"))
  1122.     {
  1123. // value range in rtp
  1124. const char* portString = (const char*)pParam->m_value;
  1125. char* pFirstValue = (char*)strchr(portString, '-');
  1126. if(pFirstValue)
  1127. {
  1128.     *pFirstValue = 0;  // get rid of second port value
  1129. }
  1130. resendPort = (UINT16)strtol(portString, 0, 10);
  1131.     }
  1132.             else if(0 == pParam->m_attribute.CompareNoCase("source"))
  1133.             {
  1134.                 const char* serverAddress = (const char*) pParam->m_value;
  1135.                 if ((m_foreignAddr = HXinet_addr(serverAddress)) ==
  1136.                     INADDR_NONE)
  1137.                 {
  1138.                     /*
  1139.                      * XXXtbradley should log a warning about invalid source
  1140.                      * address.
  1141.                      */
  1142.                     m_foreignAddr = 0;
  1143.                 }
  1144.                 else
  1145.                 {
  1146.                     m_foreignAddr = DwToHost(m_foreignAddr);
  1147.                 }
  1148.             }
  1149.     else if(0 == pParam->m_attribute.CompareNoCase("interleaved"))
  1150.     {
  1151. // it could be a range in RTP (i.e. RTP-RTCP)
  1152. const char* channelString = (const char*)pParam->m_value;
  1153. char* pFirstValue = (char*)strchr(channelString, '-');
  1154. if (pFirstValue)
  1155. {
  1156.     //get rid of second channel value since the second value is
  1157.     //always one higher than the first
  1158.     *pFirstValue = 0;
  1159.      }
  1160. tcpInterleave = (UINT8)strtol(channelString, 0, 10);
  1161.     }
  1162.     else if(0 == pParam->m_attribute.CompareNoCase("unicast"))
  1163.     {
  1164. SafeStrCat(pTransValue, ";unicast", 256);
  1165.     }
  1166.     else if(0 == pParam->m_attribute.CompareNoCase("multicast"))
  1167.     {
  1168. SafeStrCat(pTransValue, ";multicast", 256);
  1169.     }
  1170.     pParam = pValue->getNextParameter();
  1171. }
  1172. RTSPTransportTypeEnum transportType =
  1173.     RTSPTransportMimeMapper::getTransportType(pTransValue);
  1174. CHXSimpleList::Iterator i;
  1175. for(i=m_transportRequestList.Begin();
  1176.     i!=m_transportRequestList.End();++i)
  1177. {
  1178.     RTSPTransportRequest* pRequest = (RTSPTransportRequest*)(*i);
  1179.     if(pRequest->m_lTransportType == transportType)
  1180.     {
  1181. pRequest->m_sPort = requestPort;
  1182. pRequest->m_sResendPort = resendPort;
  1183. pRequest->m_tcpInterleave = tcpInterleave;
  1184. pTransportRequest = pRequest;
  1185.     }
  1186.     else
  1187.     {
  1188. pRequest->m_bDelete = TRUE;
  1189.     }
  1190. }
  1191.     }
  1192.     // remove transport requests marked as delete
  1193.     LISTPOSITION pos = m_transportRequestList.GetTailPosition();
  1194.     while(pos)
  1195.     {
  1196. RTSPTransportRequest* pRequest =
  1197.     (RTSPTransportRequest*)m_transportRequestList.GetAt(pos);
  1198. if(pRequest->m_bDelete)
  1199. {
  1200.     delete pRequest;
  1201.     pos = m_transportRequestList.RemoveAt(pos);
  1202. }
  1203. else
  1204. {
  1205.     m_transportRequestList.GetPrev(pos);
  1206. }
  1207.     }
  1208.     return pTransportRequest;
  1209. }
  1210. void
  1211. RTSPClientProtocol::messageDebugFileOut(const char* pMsg, BOOL bInbound)
  1212. {
  1213.     if(m_bMessageDebug)
  1214.     {
  1215. FILE* fp = fopen(m_messageDebugFileName, "a");
  1216. if(!fp)
  1217. {
  1218.     return;
  1219. }
  1220. if(bInbound)
  1221. {
  1222.     fprintf(fp, "IN:n");
  1223. }
  1224. else
  1225. {
  1226.     fprintf(fp, "OUT:n");
  1227. }
  1228. fprintf(fp, "%sn", pMsg);
  1229. fclose(fp);
  1230.     }
  1231. }
  1232. /*
  1233.  * IHXThinnableSource methods.
  1234.  */
  1235. /************************************************************************
  1236.  * Method:
  1237.  *     IHXThinnableSource::LimitBandwidthByDropping
  1238.  * Purpose:
  1239.  *
  1240.  *     Implemented by protocols that allow infinite thinnability through
  1241.  *     LimitBandwidthByDropping
  1242.  */
  1243. STDMETHODIMP
  1244. RTSPClientProtocol::LimitBandwidthByDropping(UINT32 ulStreamNo,
  1245.     UINT32 ulBandwidthLimit)
  1246. {
  1247.     if (!m_pIsMethodSupported[SET_PARAM])
  1248.     {
  1249. return HXR_OK;
  1250.     }
  1251.     m_pMutex->Lock();
  1252.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  1253.     pMsg->setURL(m_url);
  1254.     char tmp[128];
  1255.     SafeSprintf(tmp, 128, "stream=%d;LimitBandwidthByDropping=%d", ulStreamNo,
  1256. ulBandwidthLimit);
  1257.     pMsg->addHeader("FrameControl", tmp);
  1258.     if (!m_sessionID.IsEmpty())
  1259.     {
  1260. pMsg->addHeader("Session", m_sessionID);
  1261.     }
  1262.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1263.     HX_RESULT hr = sendRequest(pMsg, seqNo);
  1264.     m_pMutex->Unlock();
  1265.     return hr;
  1266. }
  1267. STDMETHODIMP
  1268. RTSPClientProtocol::SetDeliveryBandwidth(UINT32 ulBandwidth, UINT32 ulMsBackOff)
  1269. {
  1270.     if (!m_pIsMethodSupported[SET_PARAM] || !m_pSession)
  1271.     {
  1272. return HXR_OK;
  1273.     }
  1274.     m_pMutex->Lock();
  1275.     RTSPSetParamMessage* pMsg = new RTSPSetParamMessage;
  1276.     pMsg->setURL(m_url);
  1277.     char tmp[64];
  1278.     SafeSprintf(tmp, 64, "Bandwidth=%d;BackOff=%d", ulBandwidth, ulMsBackOff);
  1279.     pMsg->addHeader("SetDeliveryBandwidth", tmp);
  1280.     if (!m_sessionID.IsEmpty())
  1281.     {
  1282. pMsg->addHeader("Session", m_sessionID);
  1283.     }
  1284.     UINT32 seqNo = m_pSession->getNextSeqNo(this);
  1285.     HX_RESULT hr = sendRequest(pMsg, seqNo);
  1286.     m_pMutex->Unlock();
  1287.     return hr;
  1288. }
  1289. HX_RESULT
  1290. RTSPClientProtocol::closeSocket()
  1291. {
  1292.     m_pSocket = 0;
  1293.     return m_pSession->closeSocket();
  1294. }
  1295. HX_RESULT
  1296. RTSPClientProtocol::reopenSocket()
  1297. {
  1298.     m_pMutex->Lock();
  1299.     m_pSession->m_bReopenSocket = TRUE;
  1300.     HX_RESULT hr = m_pSession->reopenSocket(this);
  1301.     m_pMutex->Unlock();
  1302.     return hr;
  1303. }
  1304. HX_RESULT
  1305. RTSPClientProtocol::ReopenSocketDone(HX_RESULT status)
  1306. {
  1307.     m_pMutex->Lock();
  1308.     HX_RESULT hresult = HXR_OK;
  1309.     m_pSession->m_bReopenSocket = FALSE;
  1310.     if (HXR_OK != status)
  1311.     {
  1312. hresult = m_pResp->HandleProtocolError(status);
  1313. goto exit;
  1314.     }
  1315.     HX_ASSERT(m_pControlBuffer);
  1316.     if (!m_pControlBuffer)
  1317.     {
  1318. hresult = HXR_FAIL;
  1319. goto exit;
  1320.     }
  1321.     hresult = sendControlMessage(m_pControlBuffer);
  1322.     m_pControlBuffer->Release();
  1323.     m_pControlBuffer = 0;
  1324. exit:
  1325.     m_pMutex->Unlock();
  1326.     return hresult;
  1327. }
  1328. void
  1329. RTSPClientProtocol::DoConnectionCheck()
  1330. {
  1331.     m_uConnectionCheckCallbackHandle = 0;
  1332.     HX_ASSERT(m_pConnectionlessControl);
  1333.     if (!m_bConnectionAlive)
  1334.     {
  1335. m_pConnectionlessControl->ConnectionCheckFailed(HXR_SERVER_TIMEOUT);
  1336. return;
  1337.     }
  1338.     m_bConnectionAlive = FALSE;
  1339.     m_uConnectionCheckCallbackHandle =
  1340.         m_pScheduler->RelativeEnter(m_pConnectionCheckCallback,
  1341. m_uConnectionTimeout * 1000);
  1342. }
  1343. void
  1344. RTSPClientProtocol::GetForeignHostPort(char*& pHost, UINT16* pPort)
  1345. {
  1346.     pHost = NULL;
  1347.     *pPort = 0;
  1348.     if (m_bUseProxy | m_bUseHTTPProxy)
  1349.     {
  1350. pHost = new_string(m_hostName);
  1351. if (m_bHTTPOnly)
  1352. {
  1353.     *pPort = m_uCloakPort;
  1354. }
  1355. else
  1356. {
  1357.     *pPort = m_foreignPort;
  1358. }
  1359.     }
  1360. }
  1361. void
  1362. RTSPClientProtocol::mapTransportChannel(RTSPTransport* pTran, UINT16 nChannel)
  1363. {
  1364.     if (!m_pTransportChannelMap)
  1365.     {
  1366. m_pTransportChannelMap = new CHXMapLongToObj();
  1367.     }
  1368.     (*m_pTransportChannelMap)[nChannel] = pTran;
  1369. }
  1370. /* Interop */
  1371. void
  1372. RTSPClientProtocol::mapControlToStreamNo(const char* pControl, UINT16 uStreamNo)
  1373. {
  1374.     if (!m_pControlToStreamNoMap)
  1375.     {
  1376. m_pControlToStreamNoMap = new CHXMapStringToOb();
  1377.     }
  1378.     UINT16* pu = new UINT16;
  1379.     *pu = uStreamNo;
  1380.     (*m_pControlToStreamNoMap)[pControl] = pu;
  1381. }
  1382. BOOL
  1383. RTSPClientProtocol::getStreamNoFromControl(const char* pControl, REF(UINT16) uStreamNo)
  1384. {
  1385.     // don't call if there is no map
  1386.     HX_ASSERT(m_pControlToStreamNoMap);
  1387.     UINT16* ul = NULL;
  1388.     if (m_pControlToStreamNoMap->Lookup(pControl, (void*&)ul))
  1389.     {
  1390. uStreamNo = (UINT16)*ul;
  1391. return TRUE;
  1392.     }
  1393.     else
  1394.     {
  1395. return FALSE;
  1396.     }
  1397. }
  1398. void
  1399. RTSPClientProtocol::setSetupRequestURL(RTSPSetupMessage* pMsg,
  1400.     RTSPStreamInfo* pStreamInfo)
  1401. {
  1402.     HX_ASSERT(pMsg && pStreamInfo);
  1403.     if (pStreamInfo->m_streamControl.Find("rtsp:") != -1)
  1404.     {
  1405. // absolute url....just use this!
  1406. pMsg->setURL(pStreamInfo->m_streamControl);
  1407.     }
  1408.     else if (!m_contentBase.IsEmpty())
  1409.     {
  1410. // we have Content-Base RTSP header
  1411. pMsg->setURL(m_contentBase + pStreamInfo->m_streamControl);
  1412.     }
  1413.     else if(!m_headerControl.IsEmpty())
  1414.     {
  1415. // this is a=control in session description...
  1416. pMsg->setURL(m_headerControl);
  1417.     }
  1418.     else
  1419.     {
  1420. int lenURL = m_url.GetLength()+pStreamInfo->m_streamControl.GetLength()+15;
  1421. char* setupURL = new char[lenURL];
  1422. SafeSprintf(setupURL, lenURL,"%s/%s", (const char*)m_url,
  1423. (const char*)pStreamInfo->m_streamControl);
  1424. pMsg->setURL(setupURL);
  1425. delete[] setupURL;
  1426.     }
  1427. }
  1428. RTSPStreamInfo*
  1429. RTSPClientProtocol::getStreamInfoFromSetupRequestURL(const char* pUrl)
  1430. {
  1431.     HX_ASSERT(pUrl);
  1432.     // we've created a Setup request url above.  this is a reverse
  1433.     char* setupURL = NULL;
  1434.     BOOL bFoundIt = FALSE;
  1435.     RTSPStreamInfo* pStreamInfo = NULL;
  1436.     CHXSimpleList::Iterator i;
  1437.     // If we do not have control URL, 
  1438.     // we can still proceed as long there is only one stream
  1439.     if (pUrl == NULL)
  1440.     {
  1441. if (m_streamInfoList.GetCount() == 1)
  1442. {
  1443.     return (RTSPStreamInfo*) m_streamInfoList.GetHead();
  1444. }
  1445. return NULL;
  1446.     }
  1447.     for(i=m_streamInfoList.Begin();i!=m_streamInfoList.End();++i)
  1448.     {
  1449. pStreamInfo = (RTSPStreamInfo*)(*i);
  1450. if(pStreamInfo->m_streamControl == pUrl)
  1451. {
  1452.     // well, this is my lucky day
  1453.     bFoundIt = TRUE;
  1454.     break;
  1455. }
  1456.         // - get stream identifier by parsing URL
  1457. char* pStream = (char*)strrchr(pUrl, '/');
  1458. if(pStream)
  1459. {
  1460.     ++pStream; // pass '/'
  1461.     if(pStreamInfo->m_streamControl == (const char*)pStream)
  1462.     {
  1463.         bFoundIt = TRUE;
  1464.         break;
  1465.     }
  1466. }
  1467. if (!m_contentBase.IsEmpty())
  1468. {
  1469.     if ((m_contentBase + pStreamInfo->m_streamControl) == pUrl)
  1470.     {
  1471. // not so bad...
  1472. bFoundIt = TRUE;
  1473. break;
  1474.     }
  1475. }
  1476. if (!m_headerControl.IsEmpty())
  1477. {
  1478.     if (m_headerControl == pStreamInfo->m_streamControl)
  1479.     {
  1480. // phew....
  1481. bFoundIt = TRUE;
  1482. break;
  1483.     }
  1484. }
  1485.         // Compare each portion of the url w/ our control
  1486.         pStream = (char*)strchr(pUrl, '/');
  1487.         while (pStream)
  1488.         {
  1489.             ++pStream; // pass '/'
  1490.             if(pStreamInfo->m_streamControl == (const char*)pStream)
  1491.             {
  1492.                 bFoundIt = TRUE;
  1493.                 break;
  1494.             }
  1495.             pStream = (char*)strchr(pStream, '/');
  1496.         }
  1497.         if (bFoundIt)
  1498.         {
  1499.             break;
  1500.         }
  1501.         // following the recommendation posted at:
  1502.         // http://www1.ietf.org/mail-archive/working-groups/mmusic/current/msg01245.html
  1503.         int lenURL = m_url.GetLength()+strlen(pUrl)+2;
  1504. setupURL = new char[lenURL];
  1505. SafeSprintf(setupURL, lenURL, "%s/%s", (const char*)m_url, pUrl);
  1506. if (pStreamInfo->m_streamControl == (const char*)setupURL)
  1507. {
  1508.          delete[] setupURL;
  1509.          bFoundIt = TRUE;
  1510.          break;
  1511. }
  1512. delete[] setupURL;
  1513.     }
  1514.     if (bFoundIt)
  1515.     {
  1516. return pStreamInfo;
  1517.     }
  1518.     else
  1519.     {
  1520. HX_ASSERT(!"streaminfo not found from setup request url");
  1521. return NULL;
  1522.     }
  1523. }
  1524. STDMETHODIMP
  1525. RTSPClientProtocol::InitPacketFilter(RawPacketFilter* pFilter)
  1526. {
  1527.     m_pPacketFilter = pFilter;
  1528.     return HXR_OK;
  1529. }
  1530. void
  1531. RTSPClientProtocol::LeavePrefetch(void)
  1532. {
  1533.     m_bPrefetch = FALSE;
  1534.     SendMsgToTransport(LEAVE_PREFETCH);
  1535.     return;
  1536. }
  1537. void
  1538. RTSPClientProtocol::EnterFastStart(void)
  1539. {
  1540.     m_bFastStart = TRUE;
  1541.     SendMsgToTransport(ENTER_FASTSTART);
  1542.     return;
  1543. }
  1544. void
  1545. RTSPClientProtocol::LeaveFastStart(void)
  1546. {
  1547.     m_bFastStart = FALSE;
  1548.     SendMsgToTransport(LEAVE_FASTSTART);
  1549.     return;
  1550. }
  1551. void
  1552. RTSPClientProtocol::InitCloak(UINT16*     pCloakPorts,
  1553.       UINT8     nCloakPorts,
  1554.       IHXValues*   pValues)
  1555. {
  1556.     m_pCloakPorts = pCloakPorts;
  1557.     m_nCloakPorts = nCloakPorts;
  1558.     if (pValues)
  1559.     {
  1560. m_pCloakValues = pValues;
  1561. m_pCloakValues->AddRef();
  1562.     }
  1563. }
  1564. UINT16
  1565. RTSPClientProtocol::GetCloakPortSucceeded(void)
  1566. {
  1567.     return m_uCloakPort;
  1568. }
  1569. HX_RESULT
  1570. RTSPClientProtocol::RetrieveChallenge(RTSPResponseMessage* pMessage)
  1571. {
  1572.     return HXR_FAILED;
  1573. }
  1574. HX_RESULT
  1575. RTSPClientProtocol::SetStatistics(UINT16 uStreamNumber,
  1576.   STREAM_STATS* pStats)
  1577. {
  1578.     HX_RESULT rc = HXR_OK;
  1579. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1580.     RTSPTransport* pTrans = (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  1581.     if (pTrans)
  1582.     {
  1583. rc = pTrans->SetStatistics(uStreamNumber, pStats);
  1584.     }
  1585. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1586.     return rc;
  1587. }
  1588. HX_RESULT
  1589. RTSPClientProtocol::extractRealmInformation(RTSPResponseMessage* pMsg)
  1590. {
  1591. #if defined(HELIX_FEATURE_AUTHENTICATION)
  1592.     // this is called from several places where authentication errors
  1593.     // are likely to occur. It then pulls out the realm for future reference.
  1594.     IHXRegistry* pRegistry = NULL;
  1595.     HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1596.     if (SUCCEEDED(retVal))
  1597.     {
  1598. CHXString authString;
  1599. authString = pMsg->getHeaderValue("Proxy-Authenticate");
  1600. if (m_bUseProxy && !authString.IsEmpty())
  1601. {
  1602.     IHXBuffer* pBuffer = NULL;
  1603.     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  1604.     if (SUCCEEDED(retVal))
  1605.     {
  1606. HX_ASSERT(pMsg->errorCodeAsUINT32() == 407);
  1607. retVal = pBuffer->Set((const unsigned char*)(const char*)authString,
  1608. authString.GetLength()+1);
  1609. UINT32 regid = pRegistry->GetId("proxy-authentication.rtsp.realm.recent");
  1610.                 if( retVal == HXR_OUTOFMEMORY )
  1611.                 {
  1612.                     HX_RELEASE(pBuffer);
  1613.                     HX_RELEASE(pRegistry);
  1614.                     return retVal;
  1615.                 }
  1616. if (!regid)
  1617. {
  1618.     pRegistry->AddStr("proxy-authentication.rtsp.realm.recent", pBuffer);
  1619. }
  1620. else
  1621. {
  1622.     pRegistry->SetStrByName("proxy-authentication.rtsp.realm.recent", pBuffer);
  1623. }
  1624. HX_RELEASE(pBuffer);
  1625.     }
  1626. }
  1627. authString = pMsg->getHeaderValue("WWW-Authenticate");
  1628. if (!authString.IsEmpty())
  1629. {
  1630.     IHXBuffer* pBuffer = NULL;
  1631.     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  1632.     if (SUCCEEDED(retVal))
  1633.     {
  1634. HX_ASSERT(pMsg->errorCodeAsUINT32() == 401);
  1635. retVal = pBuffer->Set((const unsigned char*)(const char*)authString,
  1636. authString.GetLength()+1);
  1637.                 if( retVal == HXR_OUTOFMEMORY )
  1638.                 {
  1639.                     HX_RELEASE(pBuffer);
  1640.                     HX_RELEASE(pRegistry);
  1641.                     return retVal;
  1642.                 }
  1643. UINT32 regid = pRegistry->GetId("authentication.rtsp.realm.recent");
  1644. if (!regid)
  1645. {
  1646.     pRegistry->AddStr("authentication.rtsp.realm.recent", pBuffer);
  1647. }
  1648. else
  1649. {
  1650.     pRegistry->SetStrByName("authentication.rtsp.realm.recent", pBuffer);
  1651. }
  1652. HX_RELEASE(pBuffer);
  1653.     }
  1654. }
  1655. HX_RELEASE(pRegistry);
  1656.     }
  1657.     return retVal;
  1658. #else
  1659.     return HXR_NOTIMPL;
  1660. #endif /* HELIX_FEATURE_AUTHENTICATION */
  1661. }
  1662. HX_RESULT
  1663. RTSPClientProtocol::extractExistingAuthorizationInformation(IHXValues* pIHXValuesRequestHeaders)
  1664. {
  1665. #if defined(HELIX_FEATURE_AUTHENTICATION)
  1666.     if (pIHXValuesRequestHeaders)
  1667.     {
  1668. const char* pName = NULL;
  1669. IHXBuffer* pValue = NULL;
  1670. HX_RESULT result = pIHXValuesRequestHeaders->GetFirstPropertyCString(pName, pValue);
  1671. while (SUCCEEDED(result))
  1672. {
  1673.     // check for proxy and www authentication stuff separately because
  1674.     // it's plausible that one request will have both of these.
  1675.     if (m_bUseProxy && !strcasecmp(pName, "Proxy-Authorization"))
  1676.     {
  1677. HX_RESULT retVal = HXR_OK;
  1678. IHXRegistry* pRegistry = NULL;
  1679. retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1680. if (SUCCEEDED(retVal))
  1681. {
  1682.     IHXBuffer* pBuffer = NULL;
  1683.     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  1684.     UINT32 regid = 0;
  1685.     if (SUCCEEDED(retVal))
  1686.     {
  1687. IHXBuffer* pHeaderBuffer = NULL;
  1688. CHXString key;
  1689. CHXString recentRealmInfo = "";
  1690. key = "proxy-authentication.rtsp:";
  1691. retVal = pRegistry->GetStrByName("proxy-authentication.rtsp.realm.recent",
  1692. pHeaderBuffer);
  1693. if (SUCCEEDED(retVal))
  1694. {
  1695.     HX_ASSERT(pHeaderBuffer);
  1696.     recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
  1697.     HX_RELEASE(pHeaderBuffer);
  1698. }
  1699. key += "proxy-host:";
  1700. key += recentRealmInfo;
  1701. HX_ASSERT(!key.IsEmpty());
  1702. retVal = pBuffer->Set(pValue->GetBuffer(), pValue->GetSize());
  1703.                         if( retVal == HXR_OUTOFMEMORY )
  1704.                         {
  1705.                             HX_RELEASE(pBuffer);
  1706.                             HX_RELEASE(pHeaderBuffer);
  1707.                             HX_RELEASE(pRegistry);
  1708.                             return retVal;
  1709.                         }
  1710. regid = pRegistry->GetId((const char*)key);
  1711. if (!regid)
  1712. {
  1713.     pRegistry->AddStr((const char*)key, pBuffer);
  1714. }
  1715. else
  1716. {
  1717.     pRegistry->SetStrByName((const char*)key, pBuffer);
  1718. }
  1719. HX_RELEASE(pBuffer);
  1720. HX_RELEASE(pHeaderBuffer);
  1721.     }
  1722.     HX_RELEASE(pRegistry);
  1723.      }
  1724.     }
  1725.     if (!strcasecmp(pName, "Authorization"))
  1726.     {
  1727. HX_RESULT retVal = HXR_OK;
  1728. IHXRegistry* pRegistry = NULL;
  1729. retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1730. if (SUCCEEDED(retVal))
  1731. {
  1732.     IHXBuffer* pBuffer = NULL;
  1733.     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  1734.     UINT32 regid = 0;
  1735.     if (SUCCEEDED(retVal))
  1736.     {
  1737. IHXBuffer* pHeaderBuffer = NULL;
  1738. CHXString key;
  1739. CHXString recentRealmInfo = "";
  1740. key = "authentication.rtsp:";
  1741. retVal = pRegistry->GetStrByName("authentication.rtsp.realm.recent",
  1742. pHeaderBuffer);
  1743. if (SUCCEEDED(retVal))
  1744. {
  1745.     HX_ASSERT(pHeaderBuffer);
  1746.     recentRealmInfo = CHXString((const char*)pHeaderBuffer->GetBuffer(), pHeaderBuffer->GetSize());
  1747.     HX_RELEASE(pHeaderBuffer);
  1748. }
  1749. key += m_hostName;
  1750. key += ":";
  1751. key += recentRealmInfo;
  1752. HX_ASSERT(!key.IsEmpty());
  1753. retVal = pBuffer->Set(pValue->GetBuffer(), pValue->GetSize());
  1754.                         if( retVal == HXR_OUTOFMEMORY )
  1755.                         {
  1756.                             return retVal;
  1757.                         }
  1758. regid = pRegistry->GetId((const char*)key);
  1759. if (!regid)
  1760. {
  1761.     pRegistry->AddStr((const char*)key, pBuffer);
  1762. }
  1763. else
  1764. {
  1765.     pRegistry->SetStrByName((const char*)key, pBuffer);
  1766. }
  1767. HX_RELEASE(pBuffer);
  1768. HX_RELEASE(pHeaderBuffer);
  1769.     }
  1770.     HX_RELEASE(pRegistry);
  1771.      }
  1772.     }
  1773.             HX_RELEASE(pValue);
  1774.     result = pIHXValuesRequestHeaders->GetNextPropertyCString(pName, pValue);
  1775. }
  1776.     }
  1777.     return HXR_OK;
  1778. #else
  1779.     return HXR_NOTIMPL;
  1780. #endif /* HELIX_FEATURE_AUTHENTICATION */
  1781. }
  1782. void
  1783. RTSPClientProtocol::appendAuthorizationHeaders(RTSPMessage* pMsg)
  1784. {
  1785. #if defined(HELIX_FEATURE_AUTHENTICATION)
  1786.     // This is currently getting called from sendPendingStreamDescription
  1787.     // although it's feasible that other rtsp messages will need authentication.
  1788.     // At this writing none of our servers or proxies do anything other than
  1789.     // DESCRIBE, so I'm omitting scattered calls to this routine so I don't
  1790.     // waste bandwidth. It's plausible that calling this from everywhere it calls
  1791.     // addRFC822Headers would be fully compliant, if a touch wasteful.
  1792.     // xxxbobclark
  1793.     IHXRegistry* pRegistry = NULL;
  1794.     HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1795.     if (SUCCEEDED(retVal))
  1796.     {
  1797. CHXString strExistingAuthorizationHeader = pMsg->getHeaderValue("Authorization");
  1798. CHXString strExistingProxyAuthorizationHeader = pMsg->getHeaderValue("Proxy-Authorization");
  1799. if (strExistingAuthorizationHeader.IsEmpty())
  1800. {
  1801.     // if it doesn't exist, see if we've remembered one we can
  1802.     // plop down here.
  1803.     CHXString key = "authentication.rtsp:";
  1804.     IHXBuffer* pFoundRealmBuffer = NULL;
  1805.     IHXBuffer* pBuffer = NULL;
  1806.     key += m_hostName;
  1807.     key += ":";
  1808.     retVal = pRegistry->GetStrByName("authentication.rtsp.realm.recent",
  1809.      pBuffer);
  1810.     if (SUCCEEDED(retVal))
  1811.     {
  1812. key += CHXString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
  1813. retVal = pRegistry->GetStrByName((const char*)key, pFoundRealmBuffer);
  1814. if (SUCCEEDED(retVal))
  1815. {
  1816.     CHXString strAuthHeader((const char*)pFoundRealmBuffer->GetBuffer(),
  1817.      pFoundRealmBuffer->GetSize());
  1818.     pMsg->addHeader("Authorization", (const char*)strAuthHeader);
  1819. }
  1820.     }
  1821. }
  1822. if (m_bUseProxy && strExistingProxyAuthorizationHeader.IsEmpty())
  1823. {
  1824.     // if it doesn't exist, see if we've remembered one we can
  1825.     // plop down here.
  1826.     CHXString key = "proxy-authentication.rtsp:";
  1827.     IHXBuffer* pFoundRealmBuffer = NULL;
  1828.     IHXBuffer* pBuffer = NULL;
  1829.     key += "proxy-host:";
  1830.     retVal = pRegistry->GetStrByName("proxy-authentication.rtsp.realm.recent",
  1831.      pBuffer);
  1832.     if (SUCCEEDED(retVal))
  1833.     {
  1834. key += CHXString((const char*)pBuffer->GetBuffer(), pBuffer->GetSize());
  1835. retVal = pRegistry->GetStrByName((const char*)key, pFoundRealmBuffer);
  1836. if (SUCCEEDED(retVal))
  1837. {
  1838.     CHXString strAuthHeader((const char*)pFoundRealmBuffer->GetBuffer(),
  1839.      pFoundRealmBuffer->GetSize());
  1840.     pMsg->addHeader("Proxy-Authorization", (const char*)strAuthHeader);
  1841. }
  1842.     }
  1843. }
  1844. HX_RELEASE(pRegistry);
  1845.     }
  1846. #endif /* HELIX_FEATURE_AUTHENTICATION */
  1847. }
  1848. HX_RESULT
  1849. RTSPClientProtocol::handleAuthentication(RTSPResponseMessage* pMsg)
  1850. {
  1851. #if defined(HELIX_FEATURE_AUTHENTICATION)
  1852.     HX_RESULT rc = HXR_OK;
  1853.     rc = extractRealmInformation(pMsg);
  1854.     if( rc == HXR_OUTOFMEMORY )
  1855.     {
  1856.         return rc;
  1857.     }
  1858.     IHXValues* pIHXValuesResponseHeaders = NULL;
  1859.     pMsg->AsValues(pIHXValuesResponseHeaders);
  1860.     if(pIHXValuesResponseHeaders)
  1861.     {
  1862. HX_RESULT retVal = HXR_OK;
  1863. IHXBuffer* pServerHeaderBuffer = NULL;
  1864. // Add the fake _server value that's used
  1865. // in IHXAuthenticationManager2 implementations. xxxbobclark
  1866. HX_ASSERT(!m_hostName.IsEmpty());
  1867. if (!m_hostName.IsEmpty())
  1868. {
  1869.     retVal = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
  1870.      (void**)&pServerHeaderBuffer);
  1871.     if (SUCCEEDED(retVal))
  1872.     {
  1873. if (pMsg->errorCodeAsUINT32() == 407 && m_proxyHost.GetLength() > 0)
  1874. {
  1875.     rc = pServerHeaderBuffer->Set((UCHAR*)(const char*)m_proxyHost, m_proxyHost.GetLength()+1);
  1876. }
  1877. else
  1878. {
  1879.     rc = pServerHeaderBuffer->Set((UCHAR*)(const char*)m_hostName, m_hostName.GetLength()+1);
  1880. }
  1881. pIHXValuesResponseHeaders->SetPropertyCString("_server", pServerHeaderBuffer);
  1882. HX_RELEASE(pServerHeaderBuffer);
  1883.     }
  1884. }
  1885. rc = m_pResp->HandleWWWAuthentication
  1886. (
  1887.     HXR_NOT_AUTHORIZED,
  1888.     pIHXValuesResponseHeaders
  1889. );
  1890.     }
  1891.     else
  1892.     {
  1893. rc = m_pResp->HandleWWWAuthentication
  1894. (
  1895.     HXR_FAIL,
  1896.     NULL
  1897. );
  1898.     }
  1899.     HX_RELEASE(pIHXValuesResponseHeaders);
  1900.     return rc;
  1901. #else
  1902.     return HXR_NOTIMPL;
  1903. #endif /* HELIX_FEATURE_AUTHENTICATION */
  1904. }
  1905. //
  1906. // add x-wap-profile and x-wap-profile-diff headers if they exists
  1907. //
  1908. void
  1909. RTSPClientProtocol::addUAProfHeaders(IHXValues* pHeaders)
  1910. {
  1911.     if (pHeaders)
  1912.     {
  1913. if (m_pUAProfURI && m_pUAProfURI->GetSize() > 0)
  1914. {
  1915.     pHeaders->SetPropertyCString("x-wap-profile", m_pUAProfURI);
  1916.     if (m_pUAProfDiff && m_pUAProfDiff->GetSize() > 0)
  1917.     {
  1918. pHeaders->SetPropertyCString("x-wap-profile-diff",
  1919.      m_pUAProfDiff);
  1920.     }
  1921. }
  1922.     }
  1923. }
  1924. RTSPTransportBuffer*
  1925. RTSPClientProtocol::getTransportBuffer(UINT16 uStreamNumber)
  1926. {
  1927.     RTSPTransportBuffer* pRet = NULL;
  1928.     if (m_pTransportStreamMap)
  1929.     {
  1930. RTSPTransport* pTrans =
  1931.     (RTSPTransport*)(*m_pTransportStreamMap)[uStreamNumber];
  1932. if (pTrans)
  1933. {
  1934.     pRet = pTrans->getTransportBuffer(uStreamNumber);
  1935. }
  1936.     }
  1937.     return pRet;
  1938. }
  1939. HX_RESULT
  1940. RTSPClientProtocol::ParseSDP(const char* pszContentType, IHXBuffer* pSDPBuffer)
  1941. {
  1942.     HX_RESULT   rc = HXR_OK;
  1943.     UINT16      nValues = 0;
  1944.     UINT32      ulNumStreams = 0;
  1945.     IHXValues** ppValues = NULL;
  1946.     IHXValues** ppRealHeaders = NULL;;// headers of right BW
  1947.     UINT32*     pulSubscriptionBW = NULL;
  1948.     IHXStreamDescription* pSD = getStreamDescriptionInstance(pszContentType);
  1949.     if (!pSD)
  1950.     {
  1951. rc = HXR_FAIL;
  1952.         goto cleanup;
  1953.     }
  1954.     rc = pSD->GetValues(pSDPBuffer, nValues, ppValues);
  1955.     if(HXR_REQUEST_UPGRADE == rc)
  1956.     {
  1957. // request upgrade...sdpplin has added itself for
  1958. // upgradecollection
  1959. // nothing to do...
  1960.     }
  1961.     else if (HXR_OK != rc)
  1962.     {
  1963. // error
  1964. HX_ASSERT(!"bad sdp file 0");
  1965.     }
  1966.     else if (nValues <= 1)
  1967.     {
  1968. // clean up..
  1969. for(UINT16 i=0;i<nValues;++i)
  1970. {
  1971.     // don't need IHXValues anymore...
  1972.     ppValues[i]->Release();
  1973. }
  1974. HX_VECTOR_DELETE(ppValues);
  1975. // error
  1976. rc = HXR_FAIL;
  1977. HX_ASSERT("!bad sdp file 1");
  1978.     }
  1979.     else
  1980.     {
  1981. // get header info
  1982. IHXBuffer*  pControl = NULL;
  1983.         IHXBuffer*  pIPAddress = NULL;
  1984. UINT32      ulIsSessionLive = 0;
  1985. UINT32      ulAvgBitRate   = 0;
  1986. UINT32      ulRtpRRBitRate = (ULONG32)-1;
  1987. UINT32      ulRtpRSBitRate = (ULONG32)-1;
  1988.         UINT32      ulIPAddress = 0;
  1989.         BOOL        bRealMedia = FALSE;
  1990.         m_pSDPFileHeader = ppValues[0];
  1991. ppValues[0]->GetPropertyCString("Control", pControl);
  1992. if(pControl)
  1993. {
  1994.     if (!strcmp((const char*)pControl->GetBuffer(),"*"))
  1995.                 m_headerControl = m_contentBase;
  1996.             else
  1997.                 m_headerControl = pControl->GetBuffer();
  1998.             HX_RELEASE(pControl);
  1999.         }
  2000. ppValues[0]->GetPropertyULONG32("LiveStream", ulIsSessionLive);
  2001. ppValues[0]->GetPropertyULONG32("AvgBitRate", ulAvgBitRate);
  2002. // Get session level RTP bandwidth modifiers
  2003. ppValues[0]->GetPropertyULONG32("RtcpRRRate", ulRtpRRBitRate);
  2004. ppValues[0]->GetPropertyULONG32("RtcpRSRate", ulRtpRSBitRate);
  2005.         /*
  2006.          * Get a number of streams in this presentation
  2007.          */
  2008.     
  2009.         // don't trust the "StreamCount"
  2010.         // cHeaders will represent a number of m= line in SDP
  2011.         // ulNumStreams is actual number of streams in this presentation
  2012.         // They will be different on sure stream presentation becacause we are
  2013.         // duplicating headers for each bandwidth.    
  2014.         // we have to iterate over the stream headers...        
  2015.         if (!m_bSDPInitiated || GetStreamCountNoTrust(&ppValues[1], nValues - 1, ulNumStreams) != TRUE)
  2016.         {
  2017.     // Well, This is not a SDP file generated by pplyfobj.cpp.
  2018.     // Trust the StreamCount!
  2019.     m_pSDPFileHeader->GetPropertyULONG32("StreamCount", ulNumStreams);     
  2020.     ppRealHeaders = new IHXValues*[ulNumStreams];
  2021.     for (int i = 0; i < (int)ulNumStreams; i++)
  2022.     {
  2023.         ppRealHeaders[i] = ppValues[i+1];
  2024.         ppRealHeaders[i]->AddRef();
  2025.     }
  2026.         }
  2027. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  2028.         else
  2029.         {
  2030.          // we should have at least one stream
  2031.          HX_ASSERT(ulNumStreams > 0 && m_bSDPInitiated);
  2032.     
  2033.             // set the StreamCount
  2034.     m_pSDPFileHeader->SetPropertyULONG32("StreamCount", ulNumStreams);     
  2035.     
  2036.          /*
  2037.            * Get a BW for each stream to "subscribe" to
  2038.            */
  2039.          pulSubscriptionBW = new UINT32[ulNumStreams];
  2040.          memset(pulSubscriptionBW, 0, sizeof(UINT32) * ulNumStreams);
  2041.     if (GetSubscriptionBW(m_pSDPFileHeader, 
  2042.           &ppValues[1], 
  2043.           nValues - 1, 
  2044.           pulSubscriptionBW, 
  2045.           ulNumStreams) != TRUE)
  2046.     {              
  2047.         // this should never happen
  2048.                 HX_ASSERT(FALSE);
  2049.         rc = HXR_UNEXPECTED;
  2050.         goto cleanup;
  2051.     }
  2052.          /**************************
  2053.           * Get right stream headers to pass to CPurePlaySource
  2054.           * We have figured out BW to use for each stream
  2055.           * This is expensive, but...hey, it's done only once
  2056.           * Iterate over all the stream headers AGAIN, and Get right stream headers
  2057.           * for each stream depending on subscription BW
  2058.           */
  2059.           if (GetRightHeaders(ppRealHeaders,
  2060.               ulNumStreams,
  2061.               &ppValues[1],
  2062.               nValues - 1,
  2063.               pulSubscriptionBW) != TRUE)
  2064.           {
  2065.               // this should never happen
  2066.                 HX_ASSERT(FALSE);
  2067.         rc = HXR_UNEXPECTED;
  2068.         goto cleanup;
  2069.          }
  2070.        }
  2071.        if (HXR_OK == ppValues[0]->GetPropertyCString("MulticastAddress", pIPAddress))
  2072.         {
  2073.             m_sessionHost = pIPAddress->GetBuffer();
  2074.         }
  2075.         HX_RELEASE(pIPAddress);
  2076.         if (m_bSDPInitiated)
  2077.         {
  2078.             bRealMedia = DetermineIfRMPresentation(&ppRealHeaders[0], ulNumStreams);
  2079.         }
  2080. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  2081. for (int i=0;i<ulNumStreams;++i)
  2082. {
  2083.     // reset...
  2084.     BOOL    bHasMarkerRule = 0;
  2085.             UINT16  markerRule = 0;
  2086.     UINT32  streamNumber = 0;
  2087.     UINT32  needReliable = 0;
  2088.     UINT32  rtpPayloadType = (ULONG32)-1;
  2089.     UINT32  sampleSize = 0;
  2090.     UINT32  sampleRate = 0;
  2091.     UINT32  RTPFactor = 0;
  2092.     UINT32  HXFactor = 0;
  2093.     UINT32  ulIsLive = ulIsSessionLive;
  2094.     UINT32  ulHasOutOfOrderTS = 0;
  2095.             UINT32  ulPort = 0;
  2096.     IHXBuffer*      pMimeType = NULL;
  2097.     IHXBuffer*      pRawRules = NULL;
  2098.     RTSPMediaType   eMediaType = RTSPMEDIA_TYPE_UNKNOWN;
  2099.             pControl = NULL;
  2100.             if (!m_pSDPStreamHeaders)
  2101.             {
  2102.                 m_pSDPStreamHeaders = new CHXSimpleList();
  2103.             }
  2104.     // build header list
  2105.     m_pSDPStreamHeaders->AddTail(ppRealHeaders[i]);
  2106.     // determine stream type
  2107.     ppRealHeaders[i]->GetPropertyCString("MimeType", pMimeType);
  2108.     if (pMimeType)
  2109.     {
  2110. eMediaType = SDPMapMimeToMediaType((const char*) pMimeType->GetBuffer());
  2111. HX_RELEASE(pMimeType);
  2112.     }
  2113. #if defined(HELIX_FEATURE_ASM)
  2114.     // deal with marker rule...
  2115.     ppRealHeaders[i]->GetPropertyCString("ASMRuleBook", pRawRules);
  2116.     if (pRawRules)
  2117.     {
  2118. ASMRuleBook* pRuleBook = new ASMRuleBook((const char*)pRawRules->GetBuffer());
  2119.           BOOL bHasRule = FALSE;
  2120.           IHXValues* pRuleProps = NULL;
  2121.           IHXBuffer* pBuffer = NULL;
  2122.           for(UINT16 nRule=0; nRule < pRuleBook->GetNumRules(); ++nRule)
  2123.           {
  2124.          pRuleProps = NULL;
  2125.          pBuffer = NULL;
  2126.          pRuleBook->GetProperties(nRule, pRuleProps);
  2127.          pRuleProps->GetPropertyCString("marker", pBuffer);
  2128.          if(pBuffer)
  2129.          {
  2130.           int marker = atoi((const char*)pBuffer->GetBuffer());
  2131.           if (1 == marker)
  2132.           {
  2133.          /* we don't allow more than one marker rule */
  2134.          markerRule = (UINT16)nRule;
  2135.          bHasMarkerRule = TRUE;
  2136.          pBuffer->Release();
  2137.          pRuleProps->Release();
  2138.          break;
  2139.           }
  2140.                         HX_RELEASE(pBuffer);
  2141.          }
  2142.                     HX_RELEASE(pRuleProps);
  2143.           }
  2144. HX_DELETE(pRuleBook);
  2145. HX_RELEASE(pRawRules);
  2146.     }
  2147. #endif /* HELIX_FEATURE_ASM */
  2148.     // build stream info list
  2149.     RTSPStreamInfo* pInfo = new RTSPStreamInfo;
  2150.     ppRealHeaders[i]->GetPropertyULONG32("StreamNumber", streamNumber);
  2151.     ppRealHeaders[i]->GetPropertyULONG32("NeedReliablePackets", needReliable);
  2152.     ppRealHeaders[i]->GetPropertyULONG32("SamplesPerSecond", sampleRate);
  2153.     ppRealHeaders[i]->GetPropertyULONG32("BitsPerSample", sampleSize);
  2154.     ppRealHeaders[i]->GetPropertyCString("Control", pControl);
  2155.     ppRealHeaders[i]->GetPropertyULONG32("RTPPayloadType", rtpPayloadType);
  2156.     ppRealHeaders[i]->GetPropertyULONG32("RTPTimestampConversionFactor", RTPFactor);
  2157.     ppRealHeaders[i]->GetPropertyULONG32("HXTimestampConversionFactor", HXFactor);
  2158.     ppRealHeaders[i]->GetPropertyULONG32("LiveStream", ulIsLive);
  2159.     ppRealHeaders[i]->GetPropertyULONG32("HasOutOfOrderTS", ulHasOutOfOrderTS);
  2160.     // Override session level average bitrate
  2161.     ppRealHeaders[i]->GetPropertyULONG32("AvgBitRate", ulAvgBitRate);
  2162.     // Overide session level RTP bandwidth modifiers
  2163.     // with media level modifiers
  2164.     ppRealHeaders[i]->GetPropertyULONG32("RtcpRRRate", ulRtpRRBitRate);
  2165.     ppRealHeaders[i]->GetPropertyULONG32("RtcpRSRate", ulRtpRSBitRate);
  2166.          ppRealHeaders[i]->GetPropertyULONG32("port", ulPort);
  2167.             if(pControl)
  2168.     {
  2169. pInfo->m_streamControl = pControl->GetBuffer();
  2170.                 HX_RELEASE(pControl);
  2171.     }
  2172.     else
  2173.     {
  2174. char tmp[32];
  2175. SafeSprintf(tmp, 32, "streamid=%u", (UINT16)streamNumber);
  2176. pInfo->m_streamControl = tmp;
  2177.     }
  2178.     pInfo->m_streamNumber = (UINT16)streamNumber;
  2179.     pInfo->m_bNeedReliablePackets = needReliable ? TRUE: FALSE;
  2180.     pInfo->m_rtpPayloadType = (INT16)rtpPayloadType;
  2181.     pInfo->m_sampleRate = sampleRate;
  2182.     pInfo->m_sampleSize = sampleSize / 8;
  2183.     pInfo->m_RTPFactor = RTPFactor;
  2184.     pInfo->m_HXFactor = HXFactor;
  2185.     pInfo->m_bHasMarkerRule = bHasMarkerRule;
  2186.     pInfo->m_markerRule = markerRule;
  2187.     pInfo->m_sPort = (UINT16)ulPort;
  2188.     pInfo->m_bIsLive = ulIsLive ? TRUE : FALSE;
  2189.     pInfo->m_bHasOutOfOrderTS = ulHasOutOfOrderTS ? TRUE : FALSE;
  2190.     pInfo->m_eMediaType = eMediaType;
  2191.     pInfo->m_bIsSyncMaster = FALSE; // decison will be made on setup response
  2192.     pInfo->m_ulAvgBitRate = ulAvgBitRate;
  2193.     pInfo->m_ulRtpRRBitRate = ulRtpRRBitRate;
  2194.     pInfo->m_ulRtpRSBitRate = ulRtpRSBitRate;
  2195.             pInfo->m_bRealMedia = bRealMedia;
  2196. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  2197.             if ((m_sessionHost.IsEmpty() || HXR_INADDR_ANY == HXinet_addr((const char*)m_sessionHost)) &&
  2198.                 HXR_OK == ppRealHeaders[i]->GetPropertyCString("MulticastAddress", pIPAddress))
  2199.             {
  2200.                 m_sessionHost = pIPAddress->GetBuffer();
  2201.             }
  2202.             HX_RELEASE(pIPAddress);
  2203. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  2204.     m_streamInfoList.AddTail(pInfo);
  2205. }
  2206.     }
  2207. cleanup:
  2208.     HX_VECTOR_DELETE(ppValues);
  2209.     HX_VECTOR_DELETE(pulSubscriptionBW);
  2210.     // release ppRealHeaders too
  2211.     if (NULL != ppRealHeaders)
  2212.     {
  2213. for (int i = 0; i < (int)ulNumStreams; i++)
  2214. {
  2215.     HX_RELEASE(ppRealHeaders[i]);
  2216. }
  2217. HX_VECTOR_DELETE(ppRealHeaders);
  2218.     }
  2219.     HX_RELEASE(pSD);
  2220.     return rc;
  2221. }
  2222. void
  2223. RTSPClientProtocol::RemoveSDPHeaders(void)
  2224. {
  2225.     HX_RELEASE(m_pSDPFileHeader);
  2226.     CHXSimpleList::Iterator i;
  2227.     for(i=m_pSDPStreamHeaders->Begin();i!=m_pSDPStreamHeaders->End();++i)
  2228.     {
  2229. IHXValues* pStreamHeader = (IHXValues*)(*i);
  2230.         HX_RELEASE(pStreamHeader);
  2231.     }
  2232.     HX_DELETE(m_pSDPStreamHeaders);
  2233. }
  2234. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  2235. BOOL
  2236. RTSPClientProtocol::DetermineIfRMPresentation(IHXValues** ppStrmHeaders,
  2237.               UINT32 ulNumStreams)
  2238. {
  2239.     BOOL bIsRMPresentation = FALSE;
  2240.     if (ppStrmHeaders && ulNumStreams)
  2241.     {
  2242. IHXValues* pStrmHdr = NULL;
  2243. IHXBuffer* pASMRuleBook = NULL;
  2244. IHXBuffer* pMimeType = NULL;
  2245. UINT32 ulRTPPayload = RTP_PAYLOAD_RTSP + 1;
  2246. BOOL bIsRMStream = FALSE;
  2247. UINT32 ulIdx = 0;
  2248. bIsRMPresentation = TRUE;
  2249. for (ulIdx = 0; bIsRMPresentation && (ulIdx < ulNumStreams); ulIdx++)
  2250. {
  2251.     pStrmHdr = ppStrmHeaders[ulIdx];
  2252.     bIsRMStream = FALSE;
  2253.     if (pStrmHdr)
  2254.     {
  2255. if (HXR_OK == pStrmHdr->GetPropertyULONG32("RTPPayloadType", ulRTPPayload) &&
  2256.     ulRTPPayload == RTP_PAYLOAD_RTSP)
  2257. {
  2258.     bIsRMStream = TRUE;
  2259. }
  2260. ulRTPPayload = RTP_PAYLOAD_RTSP + 1;
  2261. if (bIsRMStream)
  2262. {
  2263.     bIsRMStream = FALSE;
  2264.     
  2265.     if (HXR_OK == pStrmHdr->GetPropertyCString("ASMRuleBook", pASMRuleBook) &&
  2266.         pASMRuleBook)
  2267.     {
  2268. bIsRMStream = TRUE;
  2269.     }
  2270. }
  2271. HX_RELEASE(pASMRuleBook);
  2272. if (bIsRMStream)
  2273. {
  2274.     bIsRMStream = FALSE;
  2275.     if (HXR_OK == pStrmHdr->GetPropertyCString("MimeType", pMimeType) &&
  2276.         pMimeType)
  2277.     {
  2278. if (strstr((const char*) pMimeType->GetBuffer(), RN_COMMON_MIME_TYPE_FRAGMENT))
  2279. {
  2280.     bIsRMStream = TRUE;
  2281. }
  2282.     }
  2283. }
  2284. HX_RELEASE(pMimeType);
  2285.     }
  2286.     bIsRMPresentation = (bIsRMStream && bIsRMPresentation);
  2287. }
  2288.     }
  2289.     return bIsRMPresentation;
  2290. }
  2291. BOOL
  2292. RTSPClientProtocol::GetSubscriptionBW(IHXValues*    pFileHeader, 
  2293.       IHXValues**   ppStrmHeaders,
  2294.       UINT16        unNumStrmHeaders,
  2295.       REF(UINT32*)  pulSubscriptionBW,
  2296.       UINT32        ulNumStreams)   
  2297. {
  2298.     HX_ASSERT(pFileHeader);
  2299.     HX_ASSERT(ppStrmHeaders);
  2300.     HX_ASSERT(unNumStrmHeaders >= 1);
  2301.     HX_ASSERT(pulSubscriptionBW);
  2302.     HX_ASSERT(ulNumStreams >= 1);
  2303.     IHXBuffer* pRuleBuf = NULL;
  2304.     IHXBuffer* pBandwidth = NULL;
  2305.     pFileHeader->AddRef();
  2306.     if (!m_pPreferences || HXR_OK != m_pPreferences->ReadPref("Bandwidth", pBandwidth))
  2307.     {
  2308. HX_ASSERT(FALSE);
  2309. pBandwidth = new CHXBuffer();
  2310. pBandwidth->AddRef();
  2311. pBandwidth->Set((const unsigned char*)"64000", strlen("64000"));
  2312.     }
  2313.     if (HXR_OK != pFileHeader->GetPropertyCString("ASMRuleBook", pRuleBuf))
  2314.     {
  2315. // OK, this is a single stream presentation.  Take an ASMRuleBook from 
  2316. // any of stream headers (they are all the same), and use it to decide
  2317. // which stream header to use depending on bit rate
  2318. HX_ASSERT(1 == ulNumStreams);
  2319. // get ASMRuleBook
  2320. HX_ASSERT(NULL != ppStrmHeaders[0]);
  2321. IHXValues* pHeader = ppStrmHeaders[0];
  2322. pHeader->AddRef();
  2323. if (HXR_OK == pHeader->GetPropertyCString("ASMRuleBook", pRuleBuf))
  2324. {
  2325.     IHXBuffer*     pBuffer = NULL;
  2326.     UINT16     unRules = 0;
  2327.          ASMRuleBook     rules((char*)pRuleBuf->GetBuffer());
  2328.     unRules = rules.GetNumRules();
  2329.     
  2330.     // get subscriptions for this bandwidth
  2331.     BOOL bSubInfo[256];
  2332.     UINT16 unRuleNum = 0;
  2333.     IHXValues* pValues = new CHXHeader();
  2334.          pValues->AddRef();
  2335.     
  2336.     pValues->SetPropertyCString("Bandwidth", pBandwidth);
  2337.     rules.GetSubscription(bSubInfo, pValues);
  2338.     
  2339.     HX_RELEASE(pValues);
  2340.     // get a rule number that we are interested in
  2341.     int y;
  2342.     for (y = 0; y < (int)unRules; y++)
  2343.     {
  2344.      if (TRUE == bSubInfo[y])
  2345.      {
  2346.          IHXBuffer* pBw = 0;
  2347.     unRuleNum = y;
  2348.     
  2349.     // make sure AverageBandwidth != 0
  2350.     rules.GetProperties(y, pValues);     
  2351.     
  2352.     if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth", 
  2353.       pBw))
  2354.     {
  2355.      pulSubscriptionBW[0] += atol((const char*)pBw->GetBuffer());
  2356.      HX_RELEASE(pBw);     
  2357.     }
  2358.     else
  2359.     {
  2360. // TimeStampDelivery only stream
  2361. pulSubscriptionBW[0] = 0;
  2362.     }
  2363.     HX_RELEASE(pValues);
  2364.      }
  2365.     }
  2366.             HX_RELEASE(pRuleBuf);
  2367. }
  2368. else
  2369. {
  2370.     // There is no ASMRuleBook at all...
  2371.     // This should never happen.
  2372.     HX_RELEASE(pFileHeader);
  2373.     HX_RELEASE(pBandwidth);
  2374.     HX_RELEASE(pHeader);
  2375.     HX_ASSERT(FALSE);
  2376.     return FALSE;
  2377. }
  2378. HX_RELEASE(pHeader);
  2379.     }
  2380.     else
  2381.     {
  2382. // this is a multiple stream presentation.
  2383. // take ASMRuleBook for a file and figure out BW to use for 
  2384. // each stream
  2385. IHXBuffer* pBuffer     = NULL;
  2386. UINT16 unRules     = 0;
  2387. ASMRuleBook rules((char*)pRuleBuf->GetBuffer());
  2388. unRules = rules.GetNumRules();    
  2389. // get subscriptions for this bandwidth
  2390. BOOL bSubInfo[256];
  2391. UINT16 unRuleNum = 0;
  2392. IHXValues* pValues = new CHXHeader();
  2393.      pValues->AddRef();
  2394. pValues->SetPropertyCString("Bandwidth", pBandwidth);
  2395. rules.GetSubscription(bSubInfo, pValues);
  2396. HX_RELEASE(pValues);
  2397. // get a rule number that we are interested in
  2398. // Assuming there is only one TRUE
  2399. int y;
  2400. for (y = 0; y < (int)unRules; y++)
  2401. {
  2402.     if (TRUE == bSubInfo[y])
  2403.     {
  2404.      // there should be only one
  2405. unRuleNum = y;
  2406. break;
  2407.     }
  2408. }
  2409. // Get a BW for each stream
  2410.         rules.GetProperties((int)unRuleNum, pValues);
  2411.         for (int i = 0; i < (int)ulNumStreams; i++)
  2412.         {
  2413.             char rgStreamBW[32];
  2414.             sprintf(rgStreamBW, "Stream%dBandwidth", i);
  2415.             if (HXR_OK == pValues->GetPropertyCString((const char*)rgStreamBW, 
  2416.       pBuffer))
  2417.     {
  2418. pulSubscriptionBW[i] = (UINT32)atol((const char*)pBuffer->GetBuffer());
  2419. HX_RELEASE(pBuffer);
  2420.     }
  2421.         }
  2422. HX_RELEASE(pValues);
  2423. HX_RELEASE(pRuleBuf);
  2424.     }
  2425.     HX_RELEASE(pFileHeader);
  2426.     HX_RELEASE(pBandwidth);
  2427.     return TRUE;
  2428. }
  2429. BOOL
  2430. RTSPClientProtocol::GetRightHeaders(REF(IHXValues**)    ppRealHeaders, // out
  2431.           UINT32         ulNumStreams,
  2432.           IHXValues**         ppHeaders,
  2433.           UINT32         cHeaders,
  2434.           UINT32*             pulSubscriptionBW)
  2435. {
  2436.     HX_ASSERT(ulNumStreams >= 1);
  2437.     HX_ASSERT(ppHeaders);
  2438.     HX_ASSERT(pulSubscriptionBW);
  2439.     
  2440.     ppRealHeaders = new IHXValues*[ulNumStreams];
  2441.     memset(ppRealHeaders, NULL, sizeof(IHXValues*) * ulNumStreams);    
  2442.     
  2443.     for (int i = 0; i < (int)ulNumStreams; i++)
  2444.     {
  2445. ULONG32 ulID = 0;
  2446. ULONG32 ulBW = 0;;
  2447. BOOL    bFound = FALSE;
  2448. for (int j = 0; j < (int)cHeaders; j++)
  2449.      {
  2450.          HX_ASSERT(NULL != ppHeaders[j]);
  2451.          IHXValues* pSrcH = ppHeaders[j];
  2452.     pSrcH->AddRef();
  2453.     if ((HXR_OK == pSrcH->GetPropertyULONG32("AvgBitRate", ulBW)) &&
  2454. (ulBW == pulSubscriptionBW[i]))
  2455.     {
  2456. // this one has the right BW, how about stream number?
  2457. if ((HXR_OK == pSrcH->GetPropertyULONG32("StreamId", ulID)) &&
  2458.     ((int)ulID == i))
  2459. {
  2460.     bFound = TRUE;
  2461.     
  2462.     // This is the right heaader, 
  2463.     ppRealHeaders[i] = pSrcH;
  2464.     ppRealHeaders[i]->AddRef();
  2465.     HX_RELEASE(pSrcH);     
  2466.     break; // we found for this stream, go to next one
  2467. }
  2468.     }
  2469.     HX_RELEASE(pSrcH);
  2470. }
  2471. if (!bFound)
  2472. {
  2473.     // this should never happen
  2474.     ppRealHeaders[i] = NULL;
  2475.     HX_ASSERT(FALSE);     
  2476.     return FALSE;
  2477. }
  2478.     }
  2479.     return TRUE;
  2480. }
  2481. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  2482. BOOL
  2483. RTSPClientProtocol::GetStreamCountNoTrust(IHXValues**   ppHeaders, 
  2484.   UINT16        unNumHeader,
  2485.   REF(UINT32)   ulNumStreams)   
  2486. {
  2487.     HX_ASSERT(NULL != ppHeaders);
  2488.     UINT32 ulID = 0;
  2489.     BOOL rgFound[256];    
  2490.     
  2491.     memset(rgFound, 0, 256);
  2492.     for (UINT16 i = 0; i < unNumHeader; i++)
  2493.     {
  2494. HX_ASSERT(ppHeaders[i] != NULL);
  2495. IHXValues* pSrcHeader = NULL;
  2496. pSrcHeader = ppHeaders[i];
  2497. pSrcHeader->AddRef();
  2498. // "StreamId" is the field that ppfobj.cpp puts for a group of
  2499. // streams 
  2500. if (HXR_OK == pSrcHeader->GetPropertyULONG32("StreamId", ulID))
  2501. {
  2502.     if (!rgFound[ulID])
  2503.     {   
  2504. rgFound[ulID] = TRUE;
  2505. ulNumStreams++;
  2506.     }
  2507. }
  2508. else
  2509. {
  2510.     // OK, trust the "StreamCount".  This is not a SDP file generated
  2511.     // by pplyfobj.cpp
  2512.     ulNumStreams = 0;
  2513.     HX_RELEASE(pSrcHeader);
  2514.     return FALSE;
  2515. }
  2516. HX_RELEASE(pSrcHeader);
  2517.     }
  2518.     return TRUE;
  2519. }
  2520. HX_RESULT
  2521. RTSPClientProtocol::CreateUDPSockets(UINT32 ulStream, UINT16 ulPort)
  2522. {
  2523.     HX_RESULT           rc = HXR_OK;
  2524.     IHXUDPSocket*       pUDPSocket1 = NULL;
  2525.     IHXUDPSocket*       pUDPSocket2 = NULL;
  2526.     IHXSetSocketOption* pSockOpt = NULL;
  2527.     UDPResponseHelper*  pUDPResponseHelper1 = NULL;
  2528.     UDPResponseHelper*  pUDPResponseHelper2 = NULL;
  2529.     if((HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket1)) ||
  2530.        (HXR_OK != m_pNetworkServices->CreateUDPSocket(&pUDPSocket2)))
  2531.     {
  2532. rc = HXR_FAIL;
  2533. goto cleanup;
  2534.     }
  2535.     pUDPResponseHelper1 = new UDPResponseHelper(this, ulPort);
  2536.     pUDPResponseHelper2 = new UDPResponseHelper(this, ulPort+1);
  2537.     if (!pUDPResponseHelper1 || !pUDPResponseHelper2)
  2538.     {
  2539. rc = HXR_OUTOFMEMORY;
  2540. goto cleanup;
  2541.     }
  2542.     pUDPResponseHelper1->AddRef();
  2543.     pUDPResponseHelper2->AddRef();
  2544.     m_UDPResponseHelperList.AddTail(pUDPResponseHelper1);
  2545.     m_UDPResponseHelperList.AddTail(pUDPResponseHelper2);
  2546.     if((HXR_OK != pUDPSocket1->Init(0, 0, pUDPResponseHelper1)) ||
  2547.        (HXR_OK != pUDPSocket2->Init(0, 0, pUDPResponseHelper2)))
  2548.     {
  2549.         rc = HXR_FAILED;
  2550.         goto cleanup;
  2551.     }
  2552. #if defined(HELIX_FEATURE_TRANSPORT_MULTICAST)
  2553.     if (m_bMulticast)
  2554.     {
  2555.         if (HXR_OK != pUDPSocket1->QueryInterface(IID_IHXSetSocketOption, (void**)&pSockOpt))
  2556.         {
  2557.             rc = HXR_FAILED;
  2558.             goto cleanup;
  2559.         }
  2560. pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
  2561. pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
  2562.         HX_RELEASE(pSockOpt);
  2563.         if (HXR_OK != pUDPSocket2->QueryInterface(IID_IHXSetSocketOption, (void**)&pSockOpt))
  2564.         {
  2565.             rc = HXR_FAILED;
  2566.             goto cleanup;
  2567.         }
  2568.         pSockOpt->SetOption(HX_SOCKOPT_REUSE_ADDR, TRUE);
  2569. pSockOpt->SetOption(HX_SOCKOPT_REUSE_PORT, TRUE);
  2570.         HX_RELEASE(pSockOpt);
  2571.     }
  2572. #endif /* HELIX_FEATURE_TRANSPORT_MULTICAST */
  2573.     if (HXR_OK != pUDPSocket1->Bind(HXR_INADDR_ANY, ulPort) ||
  2574. HXR_OK != pUDPSocket2->Bind(HXR_INADDR_ANY, ulPort+1))
  2575.     {
  2576.         rc = HXR_FAILED;
  2577.         goto cleanup;
  2578.     }
  2579. cleanup:
  2580.     if (HXR_OK == rc)
  2581.     {
  2582.         (*m_pUDPSocketStreamMap)[ulStream] = pUDPSocket1;
  2583.         (*m_pRTCPSocketStreamMap)[ulStream] = pUDPSocket2;
  2584.         if (!m_bMulticast)
  2585.         {
  2586.     // hang a read on these guys...
  2587.     rc = pUDPSocket1->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  2588.             if( rc != HXR_OUTOFMEMORY )
  2589.             {
  2590.         rc = pUDPSocket2->Read(HX_SAFEUINT(MAX_UDP_PACKET));
  2591.             }
  2592.         }
  2593.     }
  2594.     else
  2595.     {
  2596.         HX_RELEASE(pUDPSocket1);
  2597.         HX_RELEASE(pUDPSocket2);
  2598.     }
  2599.     return rc;
  2600. }
  2601. void
  2602. RTSPClientProtocol::ReportError(
  2603.     HX_RESULT theErr
  2604. )
  2605. {
  2606.     if( m_pSession )
  2607.     {
  2608.         m_pSession->ReportError(theErr);
  2609.     }
  2610. }
  2611. void
  2612. RTSPClientSession::ReportError(
  2613.     HX_RESULT theErr
  2614. )
  2615. {
  2616.     IHXErrorMessages * pErrorNotifier = NULL;
  2617.     IUnknown * pPlayer = NULL;
  2618.     IHXClientEngine* pEngine = NULL;
  2619.     UINT32 nNumPlayers = 0;
  2620.     m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine);
  2621.     if( pEngine )
  2622.     {
  2623. nNumPlayers = pEngine->GetPlayerCount();
  2624. for( int ii=0; ii<nNumPlayers; ii++ )
  2625. {
  2626.     pEngine->GetPlayer(ii,pPlayer);
  2627.     if( pPlayer )
  2628.     {
  2629. pPlayer->QueryInterface( IID_IHXErrorMessages, (void**)&pErrorNotifier );
  2630.     }
  2631.     if( pErrorNotifier )
  2632.     {
  2633. pErrorNotifier->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
  2634. pErrorNotifier->Release();
  2635.             }
  2636.             HX_RELEASE( pPlayer );
  2637. }
  2638.     }
  2639.     HX_RELEASE( pEngine );
  2640. }
  2641. HX_RESULT
  2642. RTSPClientProtocol::RetrieveReconnectInfo(MIMEHeader* pHeader,
  2643.   ReconnectType reconnectType,
  2644.   IHXValues*& pReconnectValues)
  2645. {
  2646.     HX_RESULT rc = HXR_OK;
  2647.     UINT32 ulRand = 0;
  2648.     IHXBuffer* pServer = NULL;
  2649.     MIMEHeaderValue* pHeaderValue = NULL;
  2650.     MIMEParameter* pParam0 = NULL;
  2651.     MIMEParameter* pParam1 = NULL;
  2652.     ReconnectInfo* pReconnectInfo = NULL;
  2653.     CHXSimpleList reconnectInfoList;
  2654.     CHXSimpleList::Iterator i;
  2655.     if (!pReconnectValues)
  2656.     {
  2657. pReconnectValues = new CHXHeader();
  2658. pReconnectValues->AddRef();
  2659.     }
  2660.     pReconnectValues->SetPropertyULONG32("Reconnect", 1);
  2661.     pHeaderValue = pHeader->getFirstHeaderValue();
  2662.     while (pHeaderValue)
  2663.     {
  2664. pParam0 = pHeaderValue->getFirstParameter();
  2665. pParam1 = pHeaderValue->getNextParameter();
  2666. if (pParam0)
  2667. {
  2668.     pReconnectInfo = new ReconnectInfo;
  2669.     pReconnectInfo->m_server = (const char*)pParam0->m_value;
  2670.     if (pParam1)
  2671.     {
  2672. pReconnectInfo->m_ulPort = atoi((const char*)pParam1->m_value);
  2673.     }
  2674. }
  2675. reconnectInfoList.AddTail(pReconnectInfo);
  2676. pHeaderValue = pHeader->getNextHeaderValue();
  2677.     }
  2678.     if (!reconnectInfoList.IsEmpty())
  2679.     {
  2680. ulRand = (HX_GET_TICKCOUNT() % reconnectInfoList.GetCount()) + 1;
  2681. // random select the alternate serverport AND cleanup the list
  2682. for(i = reconnectInfoList.Begin(); i != reconnectInfoList.End(); ++i)
  2683. {
  2684.     pReconnectInfo = (ReconnectInfo*)*i;
  2685.     switch (ulRand)
  2686.     {
  2687.     case 0:
  2688. break;
  2689.     case 1:
  2690. pServer = new CHXBuffer();
  2691. pServer->AddRef();
  2692. pServer->Set((const unsigned char*)(const char*)pReconnectInfo->m_server,
  2693.      pReconnectInfo->m_server.GetLength()+1);
  2694. if (reconnectType == ALTERNATE_SERVER)
  2695. {
  2696.     pReconnectValues->SetPropertyCString("Alternate-Server", pServer);
  2697.     pReconnectValues->SetPropertyULONG32("Alternate-ServerPort", pReconnectInfo->m_ulPort);
  2698. }
  2699. else if (reconnectType == ALTERNATE_PROXY)
  2700. {
  2701.     pReconnectValues->SetPropertyCString("Alternate-Proxy", pServer);
  2702.     pReconnectValues->SetPropertyULONG32("Alternate-ProxyPort", pReconnectInfo->m_ulPort);
  2703. }
  2704. HX_RELEASE(pServer);
  2705. ulRand--;
  2706. break;
  2707.     default:
  2708. ulRand--;
  2709. break;
  2710.     }
  2711.     HX_DELETE(pReconnectInfo);
  2712. }
  2713. reconnectInfoList.RemoveAll();
  2714.     }
  2715.     return rc;
  2716. }
  2717. RTSPClientProtocol::UDPResponseHelper::UDPResponseHelper(RTSPClientProtocol* pParent, UINT16 nPort)
  2718. {
  2719.     m_lRefCount = 0;
  2720.     m_nPort = nPort;
  2721.     m_pOwner = pParent;
  2722. }
  2723. RTSPClientProtocol::UDPResponseHelper::~UDPResponseHelper()
  2724. {
  2725. }
  2726. STDMETHODIMP
  2727. RTSPClientProtocol::UDPResponseHelper::QueryInterface(REFIID riid, void** ppvObj)
  2728. {
  2729. QInterfaceList qiList[] =
  2730. {
  2731. { GET_IIDHANDLE(IID_IUnknown), this },
  2732. { GET_IIDHANDLE(IID_IHXUDPResponse), (IHXUDPResponse*) this },
  2733. { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
  2734. };
  2735.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2736. }
  2737. /////////////////////////////////////////////////////////////////////////
  2738. //  Method:
  2739. // IUnknown::AddRef
  2740. //  Purpose:
  2741. // Everyone usually implements this the same... feel free to use
  2742. // this implementation.
  2743. //
  2744. STDMETHODIMP_(ULONG32)
  2745. RTSPClientProtocol::UDPResponseHelper::AddRef()
  2746. {
  2747.     return InterlockedIncrement(&m_lRefCount);
  2748. }
  2749. /////////////////////////////////////////////////////////////////////////
  2750. //  Method:
  2751. // IUnknown::Release
  2752. //  Purpose:
  2753. // Everyone usually implements this the same... feel free to use
  2754. // this implementation.
  2755. //
  2756. STDMETHODIMP_(ULONG32)
  2757. RTSPClientProtocol::UDPResponseHelper::Release()
  2758. {
  2759.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2760.     {
  2761.         return m_lRefCount;
  2762.     }
  2763.     delete this;
  2764.     return 0;
  2765. }
  2766. STDMETHODIMP
  2767. RTSPClientProtocol::UDPResponseHelper::ReadDone(HX_RESULT status, IHXBuffer* pBuffer,
  2768. UINT32 ulAddr, UINT16 nPort)
  2769. {
  2770.     HX_RESULT retVal = HXR_FAILED;
  2771.     if (m_pOwner)
  2772.     {
  2773.         retVal = m_pOwner->ReadDoneWithToPort(status,
  2774.     pBuffer,
  2775.     ulAddr,
  2776.     nPort,
  2777.     m_nPort);
  2778.         if( retVal == HXR_OUTOFMEMORY )
  2779.         {
  2780.     m_pOwner->ReportError( retVal );
  2781.         }
  2782.     }
  2783.     return retVal;
  2784. }
  2785. RTSPClientProtocol::ConnectionCheckCallback::ConnectionCheckCallback
  2786. (
  2787.     RTSPClientProtocol* pOwner
  2788. ) : m_lRefCount(0)
  2789.   , m_pOwner(pOwner)
  2790. {
  2791.     if (m_pOwner)
  2792.     {
  2793. m_pOwner->AddRef();
  2794.     }
  2795. }
  2796. RTSPClientProtocol::ConnectionCheckCallback::~ConnectionCheckCallback()
  2797. {
  2798.     HX_RELEASE(m_pOwner);
  2799. }
  2800. STDMETHODIMP
  2801. RTSPClientProtocol::ConnectionCheckCallback::QueryInterface(REFIID riid, void** ppvObj)
  2802. {
  2803. QInterfaceList qiList[] =
  2804. {
  2805. { GET_IIDHANDLE(IID_IUnknown), this },
  2806. { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
  2807. };
  2808.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2809. }
  2810. /////////////////////////////////////////////////////////////////////////
  2811. //  Method:
  2812. // IUnknown::AddRef
  2813. //  Purpose:
  2814. // Everyone usually implements this the same... feel free to use
  2815. // this implementation.
  2816. //
  2817. STDMETHODIMP_(ULONG32)
  2818. RTSPClientProtocol::ConnectionCheckCallback::AddRef()
  2819. {
  2820.     return InterlockedIncrement(&m_lRefCount);
  2821. }
  2822. /////////////////////////////////////////////////////////////////////////
  2823. //  Method:
  2824. // IUnknown::Release
  2825. //  Purpose:
  2826. // Everyone usually implements this the same... feel free to use
  2827. // this implementation.
  2828. //
  2829. STDMETHODIMP_(ULONG32)
  2830. RTSPClientProtocol::ConnectionCheckCallback::Release()
  2831. {
  2832.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2833.     {
  2834.         return m_lRefCount;
  2835.     }
  2836.     delete this;
  2837.     return 0;
  2838. }
  2839. STDMETHODIMP
  2840. RTSPClientProtocol::ConnectionCheckCallback::Func()
  2841. {
  2842.     m_pOwner->AddRef();
  2843.     m_pOwner->DoConnectionCheck();
  2844.     m_pOwner->Release();
  2845.     return HXR_OK;
  2846. }
  2847. RTSPClientProtocol::TimeoutCallback::TimeoutCallback
  2848. (
  2849.     RTSPClientProtocol* pOwner
  2850. ) : m_lRefCount(0)
  2851.   , m_pOwner(pOwner)
  2852. {
  2853.     if (m_pOwner)
  2854.     {
  2855. m_pOwner->AddRef();
  2856.     }
  2857. }
  2858. RTSPClientProtocol::TimeoutCallback::~TimeoutCallback()
  2859. {
  2860.     // DON'T use HX_RELEASE
  2861.     // m_pOwner isn't derived from a COM interface
  2862.     if (m_pOwner)
  2863.     {
  2864. m_pOwner->Release();
  2865. m_pOwner = NULL;
  2866.     }
  2867. }
  2868. STDMETHODIMP
  2869. RTSPClientProtocol::TimeoutCallback::QueryInterface(REFIID riid, void** ppvObj)
  2870. {
  2871.     QInterfaceList qiList[] =
  2872.     {
  2873.         { GET_IIDHANDLE(IID_IUnknown), this },
  2874.         { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
  2875.     };
  2876.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2877. }
  2878. STDMETHODIMP_(ULONG32)
  2879. RTSPClientProtocol::TimeoutCallback::AddRef()
  2880. {
  2881.     return InterlockedIncrement(&m_lRefCount);
  2882. }
  2883. STDMETHODIMP_(ULONG32)
  2884. RTSPClientProtocol::TimeoutCallback::Release()
  2885. {
  2886.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2887.     {
  2888.         return m_lRefCount;
  2889.     }
  2890.     delete this;
  2891.     return 0;
  2892. }
  2893. STDMETHODIMP
  2894. RTSPClientProtocol::TimeoutCallback::Func()
  2895. {
  2896.     m_pOwner->AddRef();
  2897.     IHXRTSPClientProtocol* pCP = (IHXRTSPClientProtocol*)m_pOwner;
  2898.     pCP->SendKeepAlive();
  2899.     m_pOwner->Release();
  2900.     return HXR_OK;
  2901. }
  2902. #if defined(_MACINTOSH)
  2903. RTSPClientProtocol::RTSPClientProtocolCallback::RTSPClientProtocolCallback
  2904. (
  2905.     RTSPClientProtocol* pOwner
  2906. ) : m_lRefCount(0)
  2907.   , m_pOwner(pOwner)
  2908.   , m_bIsCallbackPending(FALSE)
  2909.   , m_Handle(0)
  2910.   , m_pPendingRequestHeaders(NULL)
  2911. {
  2912.     if (m_pOwner)
  2913.     {
  2914. m_pOwner->AddRef();
  2915.     }
  2916. }
  2917. RTSPClientProtocol::RTSPClientProtocolCallback::~RTSPClientProtocolCallback()
  2918. {
  2919.     HX_RELEASE(m_pOwner);
  2920.     HX_RELEASE(m_pPendingRequestHeaders);
  2921. }
  2922. STDMETHODIMP
  2923. RTSPClientProtocol::RTSPClientProtocolCallback::QueryInterface(REFIID riid, void** ppvObj)
  2924. {
  2925. QInterfaceList qiList[] =
  2926. {
  2927. { GET_IIDHANDLE(IID_IUnknown), this },
  2928. { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
  2929. };
  2930.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  2931. }
  2932. /////////////////////////////////////////////////////////////////////////
  2933. //  Method:
  2934. // IUnknown::AddRef
  2935. //  Purpose:
  2936. // Everyone usually implements this the same... feel free to use
  2937. // this implementation.
  2938. //
  2939. STDMETHODIMP_(ULONG32)
  2940. RTSPClientProtocol::RTSPClientProtocolCallback::AddRef()
  2941. {
  2942.     return InterlockedIncrement(&m_lRefCount);
  2943. }
  2944. /////////////////////////////////////////////////////////////////////////
  2945. //  Method:
  2946. // IUnknown::Release
  2947. //  Purpose:
  2948. // Everyone usually implements this the same... feel free to use
  2949. // this implementation.
  2950. //
  2951. STDMETHODIMP_(ULONG32)
  2952. RTSPClientProtocol::RTSPClientProtocolCallback::Release()
  2953. {
  2954.     if (InterlockedDecrement(&m_lRefCount) > 0)
  2955.     {
  2956.         return m_lRefCount;
  2957.     }
  2958.     delete this;
  2959.     return 0;
  2960. }
  2961. STDMETHODIMP
  2962. RTSPClientProtocol::RTSPClientProtocolCallback::Func()
  2963. {
  2964.     m_bIsCallbackPending = FALSE;
  2965.     m_Handle = 0;
  2966.     m_pOwner->AddRef();
  2967.     m_pOwner->sendPendingStreamDescription(m_PendingDescURL, m_pPendingRequestHeaders);
  2968.     HX_RELEASE(m_pPendingRequestHeaders);
  2969.     m_pOwner->Release();
  2970.     return HXR_OK;
  2971. }
  2972. #endif /* _MACINTOSH */
  2973. RTSPClientSessionManager::RTSPClientSessionManager():
  2974.     m_lRefCount(0),
  2975.     m_pMutex(NULL)
  2976. {
  2977. #ifdef THREADS_SUPPORTED
  2978. HXMutex::MakeMutex(m_pMutex);
  2979. #else
  2980. HXMutex::MakeStubMutex(m_pMutex);
  2981. #endif
  2982. }
  2983. RTSPClientSessionManager::~RTSPClientSessionManager()
  2984. {
  2985.     CHXSimpleList::Iterator i;
  2986.     for(i=m_sessionList.Begin();i!=m_sessionList.End();++i)
  2987.     {
  2988. RTSPClientSession* pSession = (RTSPClientSession*)(*i);
  2989. pSession->Release();
  2990.     }
  2991.     m_sessionList.RemoveAll();
  2992.     HX_DELETE(m_pMutex);
  2993. }
  2994. /*
  2995.  * IUnknown methods
  2996.  */
  2997. STDMETHODIMP
  2998. RTSPClientSessionManager::QueryInterface(REFIID riid, void** ppvObj)
  2999. {
  3000.     if (IsEqualIID(riid, IID_IUnknown))
  3001.     {
  3002. AddRef();
  3003. *ppvObj = (IUnknown*)this;
  3004. return HXR_OK;
  3005.     }
  3006.     *ppvObj = NULL;
  3007.     return HXR_NOINTERFACE;
  3008. }
  3009. STDMETHODIMP_(UINT32)
  3010. RTSPClientSessionManager::AddRef()
  3011. {
  3012.     return InterlockedIncrement(&m_lRefCount);
  3013. }
  3014. STDMETHODIMP_(UINT32)
  3015. RTSPClientSessionManager::Release()
  3016. {
  3017.     if (InterlockedDecrement(&m_lRefCount) > 0)
  3018.     {
  3019. return m_lRefCount;
  3020.     }
  3021.     delete this;
  3022.     SessionManGlobal() = 0;
  3023.     return 0;
  3024. }
  3025. /*
  3026.  *  RTSPClientSessionManager methods
  3027.  */
  3028. RTSPClientSessionManager*& RTSPClientSessionManager::SessionManGlobal()
  3029. {
  3030. #if defined(HELIX_CONFIG_NOSTATICS)
  3031.     GlobalID globalID = (GlobalID)RTSPClientSessionManager::zm_pSessionManager;
  3032.     return (RTSPClientSessionManager*&)HXGlobalPtr::Get(globalID);
  3033. #else
  3034.     return RTSPClientSessionManager::zm_pSessionManager;
  3035. #endif
  3036. }
  3037. RTSPClientSessionManager*
  3038. RTSPClientSessionManager::instance()
  3039. {
  3040.     RTSPClientSessionManager*& pSessionManager = SessionManGlobal();
  3041.     if(!pSessionManager)
  3042.     {
  3043. pSessionManager = new RTSPClientSessionManager;
  3044.     }
  3045.     pSessionManager->AddRef();
  3046.     return pSessionManager;
  3047. }
  3048. HX_RESULT
  3049. RTSPClientSessionManager::newSession(IUnknown* pContext,
  3050.     RTSPClientProtocol* pProt,
  3051.     const char* pHostName,
  3052.     UINT16 uPort,
  3053.     UINT32 ulActualAddr,
  3054.     BOOL bUseProxy,
  3055.     BOOL bHTTPOnly,
  3056.     UINT16 uCloakPort)
  3057. {
  3058.     m_pMutex->Lock();
  3059.     RTSPClientSession* pSession = new RTSPClientSession;
  3060.     pSession->AddRef();
  3061.     m_sessionList.AddTail(pSession);
  3062.     if (pProt)
  3063.     {
  3064. pProt->SessionCreated(pSession);
  3065.     }
  3066.     HX_RESULT hr = pSession->Init(pContext,
  3067.   pProt,
  3068.   pHostName,
  3069.   uPort,
  3070.   ulActualAddr,
  3071.   bUseProxy,
  3072.   bHTTPOnly,
  3073.   uCloakPort);
  3074.     m_pMutex->Unlock();
  3075.     return hr;
  3076. }
  3077. int
  3078. RTSPClientSessionManager::getSessionCount()
  3079. {
  3080.     return m_sessionList.GetCount();
  3081. }
  3082. BOOL
  3083. RTSPClientSessionManager::MatchPlayerContext(IUnknown* pNewContext,
  3084.      IUnknown* pKnownContext)
  3085. {
  3086.     BOOL bResult = FALSE;
  3087.     IHXPlayer* pNewHXPlayer = NULL;
  3088.     IHXPlayer* pKnownHXPlayer = NULL;
  3089.     if (!pNewContext || !pKnownContext)
  3090.     {
  3091. goto cleanup;
  3092.     }
  3093.     if (HXR_OK == pNewContext->QueryInterface(IID_IHXPlayer, (void**)&pNewHXPlayer) &&
  3094. HXR_OK == pKnownContext->QueryInterface(IID_IHXPlayer, (void**)&pKnownHXPlayer))
  3095.     {
  3096. if (pNewHXPlayer == pKnownHXPlayer)
  3097. {
  3098.     bResult = TRUE;
  3099. }
  3100.     }
  3101. cleanup:
  3102.     HX_RELEASE(pNewHXPlayer);
  3103.     HX_RELEASE(pKnownHXPlayer);
  3104.     return bResult;
  3105. }
  3106. HX_RESULT
  3107. RTSPClientSessionManager::removeFromSession(RTSPClientProtocol* pProt,
  3108.     RTSPClientSession* pSessionRemoved)
  3109. {
  3110.     HX_RESULT hr = HXR_OK;
  3111.     LISTPOSITION pos = m_sessionList.GetHeadPosition();
  3112.     while(pos)
  3113.     {
  3114. RTSPClientSession* pSession =
  3115.     (RTSPClientSession*)m_sessionList.GetAt(pos);
  3116. if(pSession == pSessionRemoved &&
  3117.    HXR_OK == pSession->removeProtocol(pProt))
  3118. {
  3119.     if(pSession->isEmpty())
  3120.     {
  3121. pSession->Done();
  3122. pSession->Release();
  3123. pos = m_sessionList.RemoveAt(pos);
  3124.     }
  3125.     break;
  3126. }
  3127. m_sessionList.GetNext(pos);
  3128.     }
  3129.     return hr;
  3130. }
  3131. RTSPClientSession*
  3132. RTSPClientSessionManager::findSession(UINT32     ulActualAddr,
  3133.       UINT16     uActualPort,
  3134.       BOOL     bUseProxy,
  3135.       const char*   pForeignHost,
  3136.       UINT16     uForeignPort,
  3137.       IUnknown*     pContext /*= NULL*/)
  3138. {
  3139.     m_pMutex->Lock();
  3140.     RTSPClientSession* pSession = NULL;
  3141.     CHXSimpleList::Iterator i;
  3142.     for(i=m_sessionList.Begin();i!=m_sessionList.End();++i)
  3143.     {
  3144. pSession = (RTSPClientSession*)(*i);
  3145. if((pSession->m_ulActualAddr == ulActualAddr) &&
  3146.    (pSession->m_uActualPort == uActualPort) &&
  3147.    /* Either the context passed in is NULL OR it matches
  3148.     * the current session context
  3149.     */
  3150.    (!pContext || MatchPlayerContext(pContext, pSession->m_pContext)))
  3151. {
  3152.     if (bUseProxy && pForeignHost)
  3153.     {
  3154. if (strcasecmp(pForeignHost, pSession->m_pForeignHost) != 0 ||
  3155.     uForeignPort != pSession->m_uForeignPort)
  3156. {
  3157.     pSession = NULL;
  3158.     continue;
  3159. }
  3160.     }
  3161.     goto exit;
  3162. }
  3163. pSession = NULL;
  3164.     }
  3165. exit:
  3166.     m_pMutex->Unlock();
  3167.     return pSession;
  3168. }
  3169. #define QUEUE_START_SIZE    512
  3170. /*
  3171.  * RTSPClientSession methods
  3172.  */
  3173. RTSPClientSession::RTSPClientSession():
  3174.     m_lRefCount(0),
  3175.     m_pNetworkServices(0),
  3176.     m_pSessionSocket(0),
  3177.     m_bIgnoreSession(FALSE),
  3178.     m_bUseProxy(FALSE),
  3179.     m_pForeignHost(0),
  3180.     m_uForeignPort(0),
  3181.     m_ulActualAddr(0),
  3182.     m_pActualHost(NULL),
  3183.     m_uActualPort(0),
  3184.     m_uCloakPort(0),
  3185.     m_ulLastSeqNo(0),
  3186.     m_bSessionDone(FALSE),
  3187.     m_bHTTPOnly(FALSE),
  3188.     m_bReopenSocket(FALSE),
  3189.     m_pMutex(NULL),
  3190.     m_pContext(NULL),
  3191.     m_bChallengeDone(FALSE),
  3192.     m_bChallengeMet(FALSE),
  3193.     m_bIsValidChallengeT(FALSE),
  3194.     m_bSetSessionCalled(FALSE)
  3195. {
  3196.     m_pInQueue = new CByteGrowingQueue(QUEUE_START_SIZE);
  3197.     m_pInQueue->SetMaxSize(MAX_QUEUE_SIZE);
  3198.     m_pParser = new RTSPParser;
  3199. #ifdef THREADS_SUPPORTED
  3200.     HXMutex::MakeMutex(m_pMutex);
  3201. #else
  3202.     HXMutex::MakeStubMutex(m_pMutex);
  3203. #endif
  3204. }
  3205. RTSPClientSession::~RTSPClientSession()
  3206. {
  3207.     CHXSimpleList::Iterator i;
  3208.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3209.     {
  3210. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3211. delete pInfo;
  3212.     }
  3213.     delete m_pInQueue;
  3214.     delete m_pParser;
  3215.     HX_VECTOR_DELETE(m_pActualHost);
  3216.     HX_VECTOR_DELETE(m_pForeignHost);
  3217.     HX_RELEASE(m_pNetworkServices);
  3218.     HX_RELEASE(m_pSessionSocket);
  3219.     HX_RELEASE(m_pContext);
  3220.     HX_DELETE(m_pMutex);
  3221. }
  3222. HX_RESULT
  3223. RTSPClientSession::Init(IUnknown* pContext,
  3224.      RTSPClientProtocol* pProt,
  3225.      const char* pHostName,
  3226. UINT16 uPort,
  3227. UINT32 ulActualAddr,
  3228. BOOL bUseProxy,
  3229. BOOL bHTTPOnly,
  3230. UINT16 uCloakPort)
  3231. {
  3232.     HX_RESULT hr = HXR_OK;
  3233.     m_ulActualAddr = ulActualAddr;
  3234.     m_pActualHost = new_string(pHostName);
  3235.     m_bUseProxy = bUseProxy;
  3236.     m_bHTTPOnly = bHTTPOnly;
  3237.     // this port assignment logic should matches to the logic in
  3238.     // finding session at ::GetHostByNameDone()
  3239.     if (m_bUseProxy)
  3240.     {
  3241. // if there is proxy, we need to also get the foreign host/port
  3242. // in order to find the RTSP session which shares not only the
  3243. // proxy host/port but also the foreign host/port
  3244. if (pProt)
  3245. {
  3246.     pProt->GetForeignHostPort(m_pForeignHost, &(m_uForeignPort));
  3247. }
  3248. m_uActualPort = uPort;     // proxy port
  3249.     }
  3250.     // if it is HTTP cloaking, we need to set the actual port
  3251.     // to the cloaking port
  3252.     else if (m_bHTTPOnly)
  3253.     {
  3254. m_uActualPort = uCloakPort; // cloaking port
  3255.     }
  3256.     else
  3257.     {
  3258. m_uActualPort = uPort;     // server host port
  3259.     }
  3260.     m_bHTTPOnly = bHTTPOnly;
  3261.     addProtocol(pProt);
  3262.     m_pContext = pContext;
  3263.     if (m_pContext)
  3264.     {
  3265. m_pContext->AddRef();
  3266.     }
  3267.     IHXTCPSocket* pSocket = 0;
  3268.     IHXCloakedNetworkServices* pCloakedNetServices = 0;
  3269.     IHXPreferences* pPreferences = 0;
  3270.     IHXBuffer* pBuffer = 0;
  3271.     if (HXR_OK != pContext->QueryInterface(IID_IHXPreferences,
  3272. (void**)&pPreferences))
  3273.     {
  3274. hr = HXR_INVALID_PARAMETER;
  3275. goto cleanup;
  3276.     }
  3277.     if (HXR_OK != pContext->QueryInterface(IID_IHXNetworkServices,
  3278. (void**)&m_pNetworkServices))
  3279.     {
  3280. hr = HXR_OUTOFMEMORY;
  3281. goto cleanup;
  3282.     }
  3283.     if (m_bHTTPOnly)
  3284.     {
  3285. m_uCloakPort = uCloakPort;
  3286. if (HXR_OK != pContext->QueryInterface(IID_IHXCloakedNetworkServices,
  3287. (void**)&pCloakedNetServices))
  3288. {
  3289.     hr = HXR_OUTOFMEMORY;
  3290.     goto cleanup;
  3291. }
  3292. pCloakedNetServices->CreateClientCloakedSocket(&pSocket);
  3293. if (!pSocket)
  3294. {
  3295.     hr = HXR_OUTOFMEMORY;
  3296.     goto cleanup;
  3297. }
  3298. IHXCloakedTCPSocket* pCloakedTCPSocket = NULL;
  3299. if (HXR_OK == pSocket->QueryInterface(IID_IHXCloakedTCPSocket, (void**)&pCloakedTCPSocket))
  3300. {
  3301.     pCloakedTCPSocket->InitCloak(pProt->m_pCloakValues, pContext);
  3302. }
  3303. HX_RELEASE(pCloakedTCPSocket);
  3304. if (pProt->m_bUseHTTPProxy)
  3305. {
  3306.     IHXHTTPProxy* pHTTPProxyInterface = NULL;
  3307.     if (HXR_OK == pSocket->QueryInterface(IID_IHXHTTPProxy, (void**) &pHTTPProxyInterface) &&
  3308. pHTTPProxyInterface)
  3309.     {
  3310. pHTTPProxyInterface->SetProxy(pProt->m_proxyHost, pProt->m_proxyPort);
  3311.     }
  3312.     HX_RELEASE(pHTTPProxyInterface);
  3313. }
  3314. // Connect() in HXClientCloakedTCPSocket requires the foreign host NOT
  3315. // the proxy host
  3316. pHostName = pProt->m_hostName;
  3317. if (m_uCloakPort)
  3318.     uPort = m_uCloakPort;
  3319.     }
  3320.     else
  3321.     {
  3322. m_pNetworkServices->CreateTCPSocket(&pSocket);
  3323.     }
  3324.     hr = pSocket->Init((IHXTCPResponse*)this);
  3325.     if (hr != HXR_OK)
  3326.     {
  3327. goto cleanup;
  3328.     }
  3329.     // already AddRef()'d in CreateTCPSocket
  3330.     m_pSessionSocket = pSocket;
  3331.     m_pConnectingProt = pProt;
  3332.     hr = m_pSessionSocket->Connect(pHostName, uPort);
  3333.     if(FAILED(hr))
  3334.     {
  3335.         ConnectDone(hr);
  3336.     }
  3337. cleanup:
  3338.     HX_RELEASE(pCloakedNetServices);
  3339.     HX_RELEASE(pPreferences);
  3340.     return hr;
  3341. }
  3342. HX_RESULT
  3343. RTSPClientSession::Done()
  3344. {
  3345.     m_pMutex->Lock();
  3346.     m_bSessionDone = TRUE;
  3347.     if(m_pSessionSocket)
  3348.     {
  3349. m_pSessionSocket->Release();
  3350. m_pSessionSocket = 0;
  3351.     }
  3352.     m_pMutex->Unlock();
  3353.     return HXR_OK;
  3354. }
  3355. HX_RESULT
  3356. RTSPClientSession::handleInput(BYTE* pData, UINT32 dataLen)
  3357. {
  3358.     INT32 ret = HXR_OK;
  3359.     if (dataLen)
  3360.     {
  3361. ret = m_pInQueue->EnQueue(pData, (UINT16)dataLen);
  3362.         if( ret == 0 )
  3363. {
  3364.     // Why ABORT? Why not OUTOFMEMORY?
  3365.     return HXR_ABORT;
  3366. }
  3367.     }
  3368.     UINT16 bytesAvail = m_pInQueue->GetQueuedItemCount();
  3369.     UINT32 bytesUsed = 0;
  3370.     if(bytesAvail == 0)
  3371.     {
  3372. return HXR_OK;
  3373.     }
  3374.     BYTE* pBuf = new BYTE[bytesAvail];
  3375.     if(!pBuf)
  3376.     {
  3377.         return HXR_OUTOFMEMORY;
  3378.     }
  3379.     for(;;)
  3380.     {
  3381. RTSPClientProtocol* pProt = NULL;
  3382. if (!bytesAvail || m_bSessionDone)
  3383. {
  3384.     break;
  3385. }
  3386. m_pInQueue->DeQueue(pBuf, bytesAvail);
  3387. if(pBuf[0] == '$')
  3388. {
  3389.     bytesUsed = 0;
  3390.     BOOL bGotData = FALSE;
  3391.     if(bytesAvail >= 4)
  3392.     {
  3393. // handle TCP data
  3394. INT8 interleave = pBuf[1];
  3395. UINT16 tcpDataLen = (UINT16)getshort(&pBuf[2]);
  3396. UINT32 currentDataLen = bytesAvail - 4;
  3397. if(currentDataLen >= tcpDataLen)
  3398. {
  3399.     pProt = findProtocolFromInterleave(interleave);
  3400.     if(pProt)
  3401.     {
  3402. ret = pProt->handleTCPData(&pBuf[4], tcpDataLen, interleave);
  3403.     }
  3404.     bytesUsed = tcpDataLen+4;
  3405.     bytesAvail -= (UINT16)bytesUsed;
  3406.     bGotData = TRUE;
  3407. }
  3408.     }
  3409.     m_pInQueue->EnQueue(&pBuf[bytesUsed], (UINT16)bytesAvail);
  3410.     if(!bGotData)
  3411.     {
  3412. break;
  3413.     }
  3414. }
  3415. else
  3416. {
  3417.     bytesUsed = bytesAvail;
  3418.     RTSPMessage* pMsg = m_pParser->parse((const char*)pBuf,
  3419. bytesUsed);
  3420.     bytesAvail -= (UINT16)bytesUsed;
  3421.     m_pInQueue->EnQueue(&pBuf[bytesUsed], (UINT16)bytesAvail);
  3422.     if (!pMsg)
  3423.     {
  3424. break;
  3425.     }
  3426.     // first always find protocol based on its sessionID
  3427.     CHXString pszSessionID = "";
  3428.     getSessionID(pMsg, &pszSessionID);
  3429.     if (!pszSessionID.IsEmpty())
  3430.     {
  3431. pProt = findProtocolFromSessionID(&pszSessionID);
  3432.     }
  3433.     // then, based on the seq No.
  3434.     if (!pProt)
  3435.     {
  3436. pProt = findProtocolFromSeqNo(pMsg->seqNo());
  3437.     }
  3438.     // then, we just grab the head from our protocol list
  3439.     if (!pProt)
  3440.     {
  3441. RTSPClientProtocolInfo* pInfo =
  3442.     (RTSPClientProtocolInfo*)m_protList.GetHead();
  3443. pProt = pInfo?pInfo->m_pProt:NULL;
  3444.     }
  3445.     if(pProt)
  3446.     {
  3447. AddRef();
  3448. pProt->AddRef();
  3449. ret = pProt->handleMessage(pMsg);
  3450. if(ret == HXR_OK)
  3451. {
  3452.     removeProtocolSeqNo(pProt, pMsg->seqNo());
  3453. }
  3454. pProt->Release();
  3455. Release();
  3456.     }
  3457.     delete pMsg;
  3458. }
  3459.     }
  3460.     delete[] pBuf;
  3461.     return ret;
  3462. }
  3463. UINT32
  3464. RTSPClientSession::getNextSeqNo(RTSPClientProtocol* pProt)
  3465. {
  3466.     m_pMutex->Lock();
  3467.     UINT32 seqNo = ++m_ulLastSeqNo;
  3468.     setProtocolSeqNo(pProt, seqNo);
  3469.     m_pMutex->Unlock();
  3470.     return seqNo;
  3471. }
  3472. RTSPClientProtocol*
  3473. RTSPClientSession::findProtocolFromInterleave(INT8 interleave)
  3474. {
  3475.     CHXSimpleList::Iterator i;
  3476.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3477.     {
  3478. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3479. void* pDummy;
  3480. if(pInfo->m_interleaveMap.Lookup(interleave, pDummy))
  3481. {
  3482.     return pInfo->m_pProt;
  3483. }
  3484.     }
  3485.     return 0;
  3486. }
  3487. RTSPClientProtocol*
  3488. RTSPClientSession::findProtocolFromSeqNo(UINT32 seqNo)
  3489. {
  3490.     CHXSimpleList::Iterator i;
  3491.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3492.     {
  3493. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3494. LISTPOSITION pos = pInfo->m_seqNoList.Find((void*)seqNo);
  3495. if(pos)
  3496. {
  3497.     return pInfo->m_pProt;
  3498. }
  3499.     }
  3500.     return 0;
  3501. }
  3502. RTSPClientProtocol*
  3503. RTSPClientSession::findProtocolFromSessionID(CHXString* pszSessionID)
  3504. {
  3505.     CHXSimpleList::Iterator i;
  3506.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3507.     {
  3508. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3509. if (pInfo->m_pProt &&
  3510.     !pInfo->m_pProt->m_sessionID.IsEmpty())
  3511. {
  3512.     if(pszSessionID->CompareNoCase(pInfo->m_pProt->m_sessionID) == 0)
  3513.     {
  3514. return pInfo->m_pProt;
  3515.     }
  3516. }
  3517.     }
  3518.     return NULL;
  3519. }
  3520. void
  3521. RTSPClientSession::getSessionID(RTSPMessage* pMsg, CHXString* pszSessionID)
  3522. {
  3523.     MIMEHeader* pSessionID = pMsg->getHeader("Session");
  3524.     if(pSessionID)
  3525.     {
  3526. MIMEHeaderValue* pHeaderValue = pSessionID->getFirstHeaderValue();
  3527. if(pHeaderValue)
  3528. {
  3529.     MIMEParameter* pParam = pHeaderValue->getFirstParameter();
  3530.     *pszSessionID = (const char*)pParam->m_attribute;
  3531. }
  3532.     }
  3533.     return;
  3534. }
  3535. HX_RESULT
  3536. RTSPClientSession::addProtocol(RTSPClientProtocol* pProt)
  3537. {
  3538.     HX_RESULT rc = HXR_OK;
  3539.     m_pMutex->Lock();
  3540.     RTSPClientProtocolInfo* pInfo = new RTSPClientProtocolInfo;
  3541.     if(pInfo)
  3542.     {
  3543.         pInfo->m_pProt = pProt;
  3544.         m_protList.AddTail(pInfo);
  3545.     }
  3546.     else
  3547.     {
  3548.         rc = HXR_OUTOFMEMORY;
  3549.     }
  3550.     m_pMutex->Unlock();
  3551.     return rc;
  3552. }
  3553. HX_RESULT
  3554. RTSPClientSession::removeProtocol(RTSPClientProtocol* pProt)
  3555. {
  3556.     m_pMutex->Lock();
  3557.     HX_RESULT hr = HXR_FAIL;
  3558.     LISTPOSITION pos = m_protList.GetHeadPosition();
  3559.     while(pos)
  3560.     {
  3561. RTSPClientProtocolInfo* pInfo =
  3562.     (RTSPClientProtocolInfo*)m_protList.GetAt(pos);
  3563. if(pInfo->m_pProt == pProt)
  3564. {
  3565.     delete pInfo;
  3566.     m_protList.RemoveAt(pos);
  3567.     hr = HXR_OK;
  3568.     goto exit;
  3569. }
  3570. m_protList.GetNext(pos);
  3571.     }
  3572. exit:
  3573.     m_pMutex->Unlock();
  3574.     return hr;
  3575. }
  3576. BOOL
  3577. RTSPClientSession::isEmpty()
  3578. {
  3579.     return (m_protList.GetCount() == 0);
  3580. }
  3581. BOOL
  3582. RTSPClientSession::HttpOnly()
  3583. {
  3584.     return m_bHTTPOnly;
  3585. }
  3586. HX_RESULT
  3587. RTSPClientSession::setProtocolInterleave(
  3588.     RTSPClientProtocol* pProt, INT8 interleave)
  3589. {
  3590.     CHXSimpleList::Iterator i;
  3591.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3592.     {
  3593. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3594. if(pInfo->m_pProt == pProt)
  3595. {
  3596.     pInfo->m_interleaveMap[(UINT32)interleave] = pProt;
  3597.     return HXR_OK;
  3598. }
  3599.     }
  3600.     return HXR_FAIL;
  3601. }
  3602. HX_RESULT
  3603. RTSPClientSession::setProtocolSeqNo(RTSPClientProtocol* pProt,
  3604.     UINT32 seqNo)
  3605. {
  3606.     CHXSimpleList::Iterator i;
  3607.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3608.     {
  3609. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3610. if(pInfo->m_pProt == pProt)
  3611. {
  3612.     pInfo->m_seqNoList.AddTail((void*)seqNo);
  3613.     return HXR_OK;
  3614. }
  3615.     }
  3616.     return HXR_FAIL;
  3617. }
  3618. HX_RESULT
  3619. RTSPClientSession::removeProtocolSeqNo(RTSPClientProtocol* pProt,
  3620.     UINT32 seqNo)
  3621. {
  3622.     CHXSimpleList::Iterator i;
  3623.     for(i=m_protList.Begin();i!=m_protList.End();++i)
  3624.     {
  3625. RTSPClientProtocolInfo* pInfo = (RTSPClientProtocolInfo*)(*i);
  3626. if(pInfo->m_pProt == pProt)
  3627. {
  3628.     LISTPOSITION pos = pInfo->m_seqNoList.Find((void*)seqNo);
  3629.     if(pos)
  3630.     {
  3631. pInfo->m_seqNoList.RemoveAt(pos);
  3632. return HXR_OK;
  3633.     }
  3634. }
  3635.     }
  3636.     return HXR_FAIL;
  3637. }
  3638. IHXTCPSocket*
  3639. RTSPClientSession::getSocket()
  3640. {
  3641.     return m_pSessionSocket;
  3642. }
  3643. HX_RESULT
  3644. RTSPClientSession::closeSocket()
  3645. {
  3646.     m_pMutex->Lock();
  3647.     if(m_pSessionSocket)
  3648.     {
  3649. m_pSessionSocket->Release();
  3650. m_pSessionSocket = 0;
  3651.     }
  3652.     m_pMutex->Unlock();
  3653.     return HXR_OK;
  3654. }
  3655. HX_RESULT
  3656. RTSPClientSession::reopenSocket(RTSPClientProtocol* pProt)
  3657. {
  3658.     m_pMutex->Lock();
  3659.     IHXTCPSocket* pSocket = 0;
  3660.     HX_RESULT rc = HXR_OK;
  3661.     /*
  3662.      * Not checking for HTTP because connectionless control channel is not
  3663.      * currently slated to work with HTTP cloaking
  3664.      */
  3665.     m_pNetworkServices->CreateTCPSocket(&pSocket);
  3666.     if (!pSocket)
  3667.     {
  3668. rc = HXR_OUTOFMEMORY;
  3669. goto exit;
  3670.     }
  3671.     rc = pSocket->Init((IHXTCPResponse*)this);
  3672.     if (rc != HXR_OK)
  3673.     {
  3674. goto exit;
  3675.     }
  3676.     HX_ASSERT(!m_pSessionSocket && !m_pConnectingProt);
  3677.     // already AddRef()'d in CreateTCPSocket
  3678.     m_pSessionSocket = pSocket;
  3679.     m_pConnectingProt = pProt;
  3680.     rc = m_pSessionSocket->Connect(m_pActualHost, m_uActualPort);
  3681. exit:
  3682.     m_pMutex->Unlock();
  3683.     return rc;
  3684. }
  3685. /*
  3686.  * IUnknown methods
  3687.  */
  3688. STDMETHODIMP
  3689. RTSPClientSession::QueryInterface(REFIID riid, void** ppvObj)
  3690. {
  3691. QInterfaceList qiList[] =
  3692. {
  3693. { GET_IIDHANDLE(IID_IUnknown), this },
  3694. { GET_IIDHANDLE(IID_IHXTCPResponse), (IHXTCPResponse*) this },
  3695. { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
  3696. };
  3697.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  3698. }
  3699. STDMETHODIMP_(UINT32)
  3700. RTSPClientSession::AddRef()
  3701. {
  3702.     return InterlockedIncrement(&m_lRefCount);
  3703. }
  3704. STDMETHODIMP_(UINT32)
  3705. RTSPClientSession::Release()
  3706. {
  3707.     if (InterlockedDecrement(&m_lRefCount) > 0)
  3708.     {
  3709.         return m_lRefCount;
  3710.     }
  3711.     delete this;
  3712.     return 0;
  3713. }
  3714. /*
  3715.  * IHXTCPResponse methods
  3716.  */
  3717. STDMETHODIMP
  3718. RTSPClientSession::ConnectDone(HX_RESULT status)
  3719. {
  3720.     HX_ASSERT(m_pConnectingProt);
  3721. #ifdef _MACINTOSH
  3722.     if (!m_pConnectingProt)
  3723.     {
  3724. return HXR_FAIL;
  3725.     }
  3726. #endif
  3727.     if(HXR_OK == status)
  3728.     {
  3729. if (!m_bHTTPOnly && !m_bUseProxy)
  3730. {
  3731.     m_bSetSessionCalled = TRUE;
  3732.     m_pConnectingProt->SessionSucceeded(this, m_pSessionSocket);
  3733. }
  3734. if (m_bReopenSocket)
  3735. {
  3736.     m_pConnectingProt->ReopenSocketDone(HXR_OK);
  3737. }
  3738. else
  3739. {
  3740.     m_pConnectingProt->sendInitialMessage(this, m_pSessionSocket);
  3741.     m_pConnectingProt->InitDone(HXR_OK);
  3742. }
  3743. m_pConnectingProt = 0;
  3744. // start handleInput process
  3745. return m_pSessionSocket->Read(MAX_RTSP_MSG);
  3746.     }
  3747.     m_bSetSessionCalled = TRUE;
  3748.     m_pConnectingProt->SessionFailed(this, m_pSessionSocket);
  3749.     m_pConnectingProt->AddRef();
  3750.     if (m_bReopenSocket)
  3751.     {
  3752. m_pConnectingProt->ReopenSocketDone(HXR_NET_CONNECT);
  3753.     }
  3754.     else
  3755.     {
  3756. m_pConnectingProt->InitDone(HXR_NET_CONNECT);
  3757.     }
  3758.     m_pConnectingProt->Release();
  3759.     m_pConnectingProt = 0;
  3760.     return HXR_FAIL;
  3761. }
  3762. STDMETHODIMP
  3763. RTSPClientSession::ReadDone(HX_RESULT status,
  3764.     IHXBuffer* pBuffer)
  3765. {
  3766.     HX_RESULT hresult = HXR_OK;
  3767.     if (m_bIgnoreSession)
  3768.     {
  3769.         return HXR_OK;
  3770.     }
  3771.     if(status == HXR_OK)
  3772.     {
  3773. AddRef();
  3774. m_pMutex->Lock();
  3775. if (!m_bSetSessionCalled)
  3776. {
  3777.     m_bSetSessionCalled = TRUE;
  3778.     LISTPOSITION pos = m_protList.GetHeadPosition();
  3779.     while (pos)
  3780.     {
  3781. RTSPClientProtocolInfo* pInfo =
  3782.     (RTSPClientProtocolInfo*)m_protList.GetNext(pos);
  3783.                 if (pInfo->m_pProt->IsSessionSucceeded())
  3784.                 {
  3785.                     m_bIgnoreSession = TRUE;
  3786.                     goto ignoreexit;
  3787.                 }
  3788.                 pInfo->m_pProt->SessionSucceeded(this, m_pSessionSocket);
  3789.     }
  3790. }
  3791. hresult = handleInput(pBuffer->GetBuffer(), pBuffer->GetSize());
  3792.         if( hresult == HXR_OUTOFMEMORY )
  3793.         {
  3794.     m_pMutex->Unlock();
  3795.     Release();
  3796.             return hresult;
  3797.         }
  3798. if (m_pSessionSocket && !m_bSessionDone)
  3799. {
  3800.     hresult = m_pSessionSocket->Read(MAX_RTSP_MSG);
  3801. }
  3802. ignoreexit:
  3803. m_pMutex->Unlock();
  3804. Release();
  3805.     }
  3806.     else
  3807.     {
  3808. AddRef();
  3809. m_pMutex->Lock();
  3810. LISTPOSITION pos = m_protList.GetHeadPosition();
  3811. while (pos)
  3812. {
  3813.     RTSPClientProtocolInfo* pInfo =
  3814. (RTSPClientProtocolInfo*)m_protList.GetNext(pos);
  3815.     if (!m_bSetSessionCalled)
  3816.     {
  3817. pInfo->m_pProt->SessionFailed(this, m_pSessionSocket);
  3818.     }
  3819.     hresult = pInfo->m_pProt->OnProtocolError(status);
  3820. }
  3821. m_bSetSessionCalled = TRUE;
  3822. m_pMutex->Unlock();
  3823. Release();
  3824.     }
  3825.     if( hresult == HXR_OUTOFMEMORY )
  3826.     {
  3827.         ReportError( hresult );
  3828.     }
  3829.     // We have handled OOM errors, and it is not the responsibility of the
  3830.     // caller to handle our other errors, so we return HXR_OK.
  3831.     return HXR_OK;
  3832. }
  3833. STDMETHODIMP
  3834. RTSPClientSession::WriteReady(HX_RESULT status)
  3835. {
  3836.     return HXR_NOTIMPL;
  3837. }
  3838. STDMETHODIMP
  3839. RTSPClientSession::Closed(HX_RESULT status)
  3840. {
  3841.     return HXR_NOTIMPL;
  3842. }