void CHTTPDemux::DetectHandler(HTTPMessage* pMsg) { INT32 nProxyEnabled = 0; if (SUCCEEDED(m_proc->pc->registry->GetInt(REGISTRY_RTSPPROXY_ENABLED, &nProxyEnabled, m_proc))) { m_pResponse = new HTTPProtocol(); m_pResponse->AddRef(); return; } HTTPMessage::Tag tag = pMsg->tag(); if (tag == HTTPMessage::T_GET || tag == HTTPMessage::T_POST) { HTTPRequestMessage* pReq = (HTTPRequestMessage*)pMsg; const char* pUrl = pReq->url(); if (strncmp(pUrl, "/SmpDsBhgRl", 11) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CRN1CloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CRN1CloakPOSTHandler(); m_pResponse->AddRef(); } return; } #ifdef HELIX_FEATURE_SERVER_CLOAKV2 CloakV2SignatureEnforcer pEnforcer; if (SUCCEEDED(pEnforcer.EnforceCloakSignature(pReq))) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CRN1CloakFallbackGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CRN1CloakFallbackPOSTHandler(); m_pResponse->AddRef(); } return; } #endif //defined HELIX_FEATURE_SERVER_CLOAKV2 /* * If the Accept or Content-type header has * application/x-rtsp-tunnelled its a quicktime cloaked connection */ MIMEHeader* pUserAgentHdr = pMsg->getHeader("User-Agent"); MIMEHeader* pSessionHdr = pMsg->getHeader("x-sessioncookie"); if (pSessionHdr) { MIMEHeader* pAcceptHdr = pMsg->getHeader("Accept"); MIMEHeader* pContentTypeHdr = pMsg->getHeader("Content-type"); CHXString strValue; if (pAcceptHdr != NULL) { strValue.Empty(); pAcceptHdr->asString(strValue); if (strncmp(strValue, "application/x-rtsp-tunnelled", 28) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } return; } } if (pContentTypeHdr != NULL) { strValue.Empty(); pContentTypeHdr->asString(strValue); if (strncmp(strValue, "application/x-rtsp-tunnelled", 28) == 0) { if (tag == HTTPMessage::T_POST) { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } return; } } /* * If the User-Agent begins with "QTS " and there is an * x-sessioncookie header, it's a QT cloaking request. */ if (pUserAgentHdr != NULL) { pUserAgentHdr->asString(strValue); if (strncasecmp(strValue, "QTS ", 4) == 0) { if (tag == HTTPMessage::T_GET) { m_pResponse = new CQTCloakGETHandler(); m_pResponse->AddRef(); } else { m_pResponse = new CQTCloakPOSTHandler(); m_pResponse->AddRef(); } return; } } } #if defined(HELIX_FEATURE_SERVER_WMT_MMS) if (IsWMTHTTP(pUrl, pUserAgentHdr)) { m_pResponse = new WMTHttpProtocol(); m_pResponse->AddRef(); return; } #endif } m_pResponse = new HTTPProtocol(); m_pResponse->AddRef(); }
void CHTTPDemux::handleInput(IHXBuffer* pBuf) { UINT32 ulBufLen = 0; if (pBuf) { ulBufLen = pBuf->GetSize(); if (m_ulMsgLen+ulBufLen > MAX_HTTP_MSG_SIZE) { if (m_pSock) { IHXSockAddr* pAddr = 0; m_pSock->GetPeerAddr(&pAddr); if (pAddr) { IHXBuffer* pAddrBuf = 0; pAddr->GetAddr(&pAddrBuf); if (pAddrBuf) { fprintf(stderr, "W: Large HTTP message (greater than 64K) being received from addr <%s>.\n" " Possible DOS attack!\n", (const char *)pAddrBuf->GetBuffer()); pAddrBuf->Release(); } pAddr->Release(); } } Close(HXR_FAIL); return; } } if (m_pFragBuf == NULL) { pBuf->AddRef(); } else { IHXBuffer* pNewBuf = new CHXBuffer(); pNewBuf->AddRef(); pNewBuf->SetSize(m_pFragBuf->GetSize() + ulBufLen); memcpy(pNewBuf->GetBuffer(), m_pFragBuf->GetBuffer(), m_pFragBuf->GetSize()); memcpy(pNewBuf->GetBuffer()+m_pFragBuf->GetSize(), pBuf->GetBuffer(), ulBufLen); HX_RELEASE(m_pFragBuf); pBuf = pNewBuf; } while (pBuf != NULL && !m_bClosed) { BYTE* pData = pBuf->GetBuffer(); UINT32 uDataLen = pBuf->GetSize(); UINT32 uDataUsed = 0; IHXBuffer* pNewBuf = NULL; IHXBuffer* pContentBuf = NULL; BOOL bFirstRun = FALSE; BOOL bMsgTooLarge = FALSE; if (m_ReadState == DEMUX_READ_MSG) { HTTPMessage* pMsg = NULL; uDataUsed = uDataLen; pMsg = m_pParser->parse((const char*)pData, uDataUsed, bMsgTooLarge); if (pMsg == NULL) { if (bMsgTooLarge) { if (pBuf) pBuf->Release(); if (m_pSock) { IHXSockAddr* pAddr = 0; m_pSock->GetPeerAddr(&pAddr); if (pAddr) { IHXBuffer* pAddrBuf = 0; pAddr->GetAddr(&pAddrBuf); if (pAddrBuf) { fprintf(stderr, "W: Large amount of HTTP data being received from addr <%s>.\n" " Possible DOS attack!\n", (const char *)pAddrBuf->GetBuffer()); pAddrBuf->Release(); } pAddr->Release(); } } Close(HXR_FAIL); return; } break; } // Remove used data from the buffer if (uDataUsed == uDataLen) { HX_RELEASE(pBuf); } else { pNewBuf = new CHXStaticBuffer(pBuf, uDataUsed, uDataLen-uDataUsed); pNewBuf->AddRef(); HX_RELEASE(pBuf); pBuf = pNewBuf; } if (m_pResponse == NULL) { DetectHandler(pMsg); HX_ASSERT(m_pResponse != NULL); m_pResponse->Init(this); bFirstRun = TRUE; } if (m_pResponse->GetFeatureFlags() & HTTP_FEATURE_IGNORE_CONTENT_LENGTH) { // Cloaking V2. if (m_pResponse->GetFeatureFlags() & ( HTTP_FEATURE_V11_SUPPORT | HTTP_FEATURE_CHUNKED_ENCODING_SUPPORT)) { m_uContentRemain = 0; CHXString strEncoding = pMsg->getHeaderValue("Transfer-Encoding"); if (strEncoding == "chunked") { m_ReadState = DEMUX_READ_DATA; } } else // Far less strict for non-persistent HTTP/1.0 connections. { m_uContentRemain = 0; m_ReadState = DEMUX_READ_DATA; } } else { MIMEHeader* pHdr = pMsg->getHeader("Content-Length"); if (!pHdr) { m_uContentRemain = 0; } else { CHXString strLen; pHdr->asString(strLen); int iLen = atoi(strLen); if (iLen < 0 || iLen > 0xffff) { DPRINTF(D_ERROR, ("HTTP: Bad content length %d\n", iLen)); if (pBuf) pBuf->Release(); Close(HXR_FAIL); return; } m_uContentRemain = (UINT32)iLen; m_ReadState = DEMUX_READ_DATA; } } if (bFirstRun && m_pResponse->AutoDispatch()) { m_pSavedMessage = pMsg; static_cast<CHXServSocket*>(m_pSock)->Dispatch(); break; } DispatchMessage(pMsg); delete pMsg; } else if (m_ReadState == DEMUX_READ_DATA) { BOOL bEnforceContentLength = FALSE; if (m_pResponse->GetFeatureFlags() & HTTP_FEATURE_IGNORE_CONTENT_LENGTH) { HX_ASSERT(m_uContentRemain == 0); // This value not used. pContentBuf = pBuf; pBuf = NULL; } else { if (m_uContentRemain >= pBuf->GetSize()) { pContentBuf = pBuf; m_uContentRemain -= pBuf->GetSize(); pBuf = NULL; } else { pContentBuf = new CHXStaticBuffer(pBuf, 0, m_uContentRemain); pContentBuf->AddRef(); pNewBuf = new CHXStaticBuffer(pBuf, m_uContentRemain, pBuf->GetSize()-m_uContentRemain); pNewBuf->AddRef(); HX_RELEASE(pBuf); pBuf = pNewBuf; m_uContentRemain = 0; m_ReadState = DEMUX_READ_MSG; } } m_pResponse->OnData(pContentBuf); HX_RELEASE(pContentBuf); } } if (pBuf != NULL) { m_pFragBuf = pBuf; m_pFragBuf->AddRef(); } HX_RELEASE(pBuf); }