rtspclnt.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 218k
Category:

Symbian

Development Platform:

Visual C++

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