⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 session.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }
        
        IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: Request data remaining to be read in session %d.  Now there are %d bytes left.\n"), m_dwSessionId, m_cbRequestRemain));

        *pcchSent = *pcchBuffer;
    }
    else {
        //
        // Now that we have all the headers, parse them.
        //

        BOOL fContinue = TRUE;
        BOOL fAdditionalContent = FALSE;
        
        PBYTE pContent = NULL;
        CBuffer buffContent;
        int cbNewHeaders = 0;     // size of the headers after modification
        int cbContent = 0;          // size of the content in this packet
        int cbTotalContent = 0; // total amount of content that has to be recved
        
        dwRetVal = g_pParser->ParseRequest(pBuffer, *pcchBuffer, headers);
        if (ERROR_SUCCESS != dwRetVal) {
            // If hit this assert then we have encountered an HTTP request that we could not parse
            ASSERT(0);
            goto exit;
        }

        ASSERT(headers.strReason == ""); 
        ASSERT(headers.strStatusCode == "");

        // The following must be in request headers
        if ((headers.strMethod == "") || (headers.strURL == "") || (headers.strVersion == "")) {
            dwRetVal = ERROR_INVALID_DATA;
            goto exit;
        }    

        IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: Request Headers:\n")));
        IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: -- Method: %hs\n"), (LPCSTR)headers.strMethod));
        IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: -- Host: %hs\n"), (LPCSTR)headers.strHost));
        IFDBG(DebugOut(ZONE_REQUEST, _T("WebProxy: -- Version: %hs\n"), (LPCSTR)headers.strVersion));

        if ((headers.strHost == "") && (headers.strVersion == gc_HTTP11)) {
            IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: No host header was present, returning Bad Request.\n")));
            dwRetVal = SendMessage(m_sockClient, "400", gc_Reason400, NULL, 0);
            *pfCloseConnection = TRUE;
            goto exit;
        }

        g_pSettings->Lock();
        if (0 == strncmp(headers.strURL, g_pSettings->strProxyPacURL, g_pSettings->strProxyPacURL.length())) {
            g_pSettings->Unlock();
            dwRetVal = HandleProxyPacRequest();
            *pfCloseConnection = TRUE;
            goto exit;
        }
        g_pSettings->Unlock();

        m_strCurrMethod = headers.strMethod;

        if (headers.strTransferEncoding == gc_TEChunked) {
            m_fChunked = TRUE;
        }

        //
        // Determine how much data is left to be read in this request
        //

        cbTotalContent = atoi(headers.strContentLength);
        cbContent = *pcchBuffer - cchHeaders;
        m_cbRequestRemain = cbTotalContent - cbContent;

        //
        // IE and Netscape both append a CRLF to POST data but do not count it as part of the 
        // content length.  If we have read 2 bytes too many then check if these last two bytes
        // are CRLF on a POST request and reset the remaining bytes to zero if so.
        //
        
        if ((m_strCurrMethod == gc_MethodPost) && (m_cbRequestRemain == -2)) {
            if ((*pcchBuffer >= 2) && (pBuffer[*pcchBuffer - 2] == '\r') && (pBuffer[*pcchBuffer - 1] == '\n')) {
                cbTotalContent += 2;
                m_cbRequestRemain = 0;
            }
        }

        // Only send headers if chunked or if we detected a pipelined request
        if (m_fChunked || (m_cbRequestRemain < 0)) {
            m_cbRequestRemain = 0;
            fAdditionalContent = TRUE;
        }    

        // If this is not a CONNECT request then make sure the protocol is http
        if (m_strCurrMethod != gc_MethodConnect) {
            if (0 != strncmp(headers.strURL, "http://", 7)) {
                ClearRecvBuf(buffer);
                dwRetVal = SendMessage(m_sockClient, "502", gc_Reason502, g_pErrors->szProtocolNotSupported, g_pErrors->cchProtocolNotSupported);
                goto exit;
            }
        }

        //
        // If authentication is in progress, then finish before calling into filter
        //

        if ((m_strUser == "") && (headers.strProxyAuthorization != "")) {
            IFDBG(DebugOut(ZONE_AUTH, _T("WebProxy: Authenticating session %d.\n"), m_dwSessionId));
            
            dwRetVal = HandleAuthentication(headers, buffer, pfCloseConnection);
            if (ERROR_SUCCESS != dwRetVal) {
                goto exit;
            }

            // If HandleAuthentication does not return a user then the client
            // could not be authenticated in this pass.
            if (m_strUser == "") {
                goto exit;
            }

            IFDBG(DebugOut(ZONE_AUTH, _T("WebProxy: Successfully authenticated user %hs.\n"), (LPCSTR)m_strUser));
        }

        //
        // Call into proxy filter
        //
        
        dwRetVal = HandleFilterRequest(headers, buffer, &fContinue, pfCloseConnection);
        if ((ERROR_NOT_AUTHENTICATED == dwRetVal) && (m_strUser == "")) {
            // Need to authenticate before calling filter
            IFDBG(DebugOut(ZONE_AUTH, _T("WebProxy: Filter requires authentication in session %d.\n"), m_dwSessionId));
            dwRetVal = HandleAuthentication(headers, buffer, pfCloseConnection);
            goto exit;
        }
        else if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }
        
        if (! fContinue) {
            goto exit;
        }

        //
        // Do not forward the following headers
        //
        
        headers.strProxyAuthorization = "";

        //
        // Handle a CONNECT request
        //
        
        if (m_strCurrMethod == gc_MethodConnect) {
            //
            // Handle the CONNECT request.  A connect request can be used to tunnel SSL
            // traffic through the HTTP proxy.
            //
            if (g_pSettings->strSecondProxyHost == "") {
                dwRetVal = HandleConnectRequest(headers.strHost, headers.strPort);
                if (ERROR_SUCCESS != dwRetVal) {
                    goto exit;
                }
                
                goto exit;
            }
            else {
                m_fSSLTunnelThruSecondProxy = TRUE;
            }            
        }

        //
        // Handle an OPTIONS request
        //

        if (m_strCurrMethod == gc_MethodOptions) {
            DWORD dwMaxForwards = atoi(headers.strMaxForwards);
            if ((headers.strMaxForwards == "") || (0 == dwMaxForwards)) {
                dwRetVal = SendMessage(m_sockClient, "200", gc_Reason200, NULL, 0);
                goto exit;
            }
            else if (headers.strMaxForwards != "") {
                _itoa(dwMaxForwards-1, headers.strMaxForwards.get_buffer(), 10);
            }            
        }

        //
        // Check if server socket has been opened yet.  If not, open it.  If it has been
        // opened then verify that we are connected to the correct server for this request.
        // If a secondary proxy has been specified, connect to this proxy rather than the
        // origin server.
        //

        if (g_pSettings->strSecondProxyHost != "") {
            if ((! m_sockServer.valid()) || (m_strServerName != g_pSettings->strSecondProxyHost)) {
                dwRetVal = ConnectServer(g_pSettings->strSecondProxyHost, g_pSettings->iSecondProxyPort);
                if (ERROR_SUCCESS != dwRetVal) {
                    ClearRecvBuf(buffer);
                    dwRetVal = SendMessage(m_sockClient, "502", "Proxy Error (Invalid data)", g_pErrors->szURLNotFound, g_pErrors->cchURLNotFound);
                    goto exit;
                }
            }
        }
        else if ((! m_sockServer.valid()) || (m_strServerName != headers.strHost)) {
            dwRetVal = ConnectServer(headers.strHost);
            if (ERROR_SUCCESS != dwRetVal) {
                ClearRecvBuf(buffer);
                dwRetVal = SendMessage(m_sockClient, "502", "Proxy Error (Invalid data)", g_pErrors->szURLNotFound, g_pErrors->cchURLNotFound);
                goto exit;
            }
        }

        //
        // Copy the content to a temporary buffer while the new headers are copied back
        // to the request buffer.  If no content is present in this packet, we do not
        // have to worry about copying content around.
        //

        if (cbContent) {
            pContent = buffContent.GetBuffer(cbContent);
            if (! pContent) {
                dwRetVal = ERROR_OUTOFMEMORY;
                IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Out of memory.\n")));
                goto exit;
            }
            memcpy(pContent, &pBuffer[cchHeaders], cbContent);
        }

        //
        // Update the request headers and copy them along with the content into the final
        // buffer to be sent to the server
        //
        
        headers.UpdateRequest((g_pSettings->strSecondProxyHost != ""));
        cbNewHeaders = headers.GetBufferSize();
        *pcchBuffer += (cbNewHeaders - cchHeaders);
        *pcchSent = fAdditionalContent ? (cbNewHeaders + cbTotalContent) : *pcchBuffer;

        pBuffer = buffer.GetBuffer(*pcchBuffer);  // add one for a null terminating char
        if(! pBuffer) {
            dwRetVal = ERROR_OUTOFMEMORY;
            IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Insufficient memory to allocate send buffer.\n")));
            goto exit;
        }

        // Fill pBuffer with new headers.
        headers.GetRequestBuffer(pBuffer);

        // Copy the content back after new headers
        if (cbContent) {
            memcpy(&pBuffer[cbNewHeaders], pContent, cbContent);
        }
    }
        
    //
    // Send the buffer along to the server
    //

    dwRetVal = SendData(m_sockServer, (char *)pBuffer, *pcchSent);
    
exit:
    return dwRetVal;
}

DWORD CHttpSession::HandleServerMessage(CBuffer& buffer, int* pcchBuffer, int cchHeaders, int* pcchSent, BOOL* pfCloseConnection)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    CHttpHeaders headers;

    ASSERT(pcchBuffer);
    ASSERT(pfCloseConnection);
    ASSERT(pcchSent);

    *pcchSent = 0;
    
    PBYTE pBuffer = buffer.GetBuffer(0, FALSE);
    ASSERT(pBuffer);

    if (m_fSSLTunnel) {
        //
        // If the current connection is just tunnelling SSL data then we do not parse the
        // data, simply send it on to the server.
        //
        *pcchSent = *pcchBuffer;
    }
    else if (0 != m_cbResponseRemain) {
        //
        // If we have already parsed the headers and just need to read remaining content
        // continuing over on a new packet, then just keep reading.
        //

        if (m_cbResponseRemain >= 0) {
            m_cbResponseRemain -= *pcchBuffer;
        }
        else {
            *pfCloseConnection = TRUE;
        }
        
        IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: Response data remaining to be read.  Now there are %d bytes left.\n"), m_cbResponseRemain));

        *pcchSent = *pcchBuffer;
    }
    else if (*pfCloseConnection) {
        //
        // If pfCloseConnection is true then the proxy should assume the data does not have any
        // headers and is just content that has to be read and forwarded to the server.  When
        // the data is completely read, the server will close the connection.
        //
        
        IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: Reading response data until the connection is closed.\n")));
        *pcchSent = *pcchBuffer;
    }
    else {
        //
        // Time to parse headers...
        //

        BOOL fAdditionalContent = FALSE;
        
        PBYTE pContent = NULL;
        CBuffer buffContent;
        int cbNewHeaders = 0;   // size of the headers after modification
        int cbContent = 0;      // size of the content in this packet
        int cbTotalContent = 0;    // total amount of content that has to be recved
        
        dwRetVal = g_pParser->ParseResponse(pBuffer, *pcchBuffer, headers);
        if (ERROR_SUCCESS != dwRetVal) {
            // If hit this assert then we have encountered an HTTP request that we could not parse
            ASSERT(0);
            goto exit;
        }

        ASSERT(headers.strMethod == "");
        ASSERT(headers.strURL == "");

        // The following must be in response headers
        if ((headers.strVersion == "") || (headers.strStatusCode == "")) {
            dwRetVal = ERROR_INVALID_DATA;
            goto exit;
        }

        IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: Response Headers:\n")));
        IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: -- Version: %hs\n"), (LPCSTR)headers.strVersion));
        IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: -- Status: %hs\n"), (LPCSTR)headers.strStatusCode));

        if (headers.strTransferEncoding == gc_TEChunked) {
            m_fChunked = TRUE;
        }

        m_fAuthInProgress = (headers.strStatusCode == "401");
        cbContent = *pcchBuffer - cchHeaders;

        if (m_fSSLTunnelThruSecondProxy) {
            // We need to set up tunnel after response from secondary proxy
            if (headers.strStatusCode == "200") {
                m_fSSLTunnel = TRUE;
            }
            else {
                *pfCloseConnection = TRUE;
            }
        }

        //
        // Determine how much response data needs to still be read in this session.
        //
        
        if (m_fChunked) {
            m_cbResponseRemain = 0;
            cbTotalContent = 0;
            fAdditionalContent = TRUE;            
        }
        else if (m_fSSLTunnel) {
            m_cbResponseRemain = 0;
        }
        else if (headers.strContentLength == "" &&
            (headers.strStatusCode != "204") && 
            (headers.strStatusCode != "304") && 
            (strncmp(headers.strStatusCode, "1", 1))) {
            
            IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: Content-Length was not specified.  Reading response data until server closes connection in session %d.\n"), m_dwSessionId));
            cbTotalContent = cbContent;
            m_cbResponseRemain = -1;    // Signals object that there is an unknown amount of data left to read
            *pfCloseConnection = TRUE;
        }        
        else {
            cbTotalContent = atoi(headers.strContentLength);
            m_cbResponseRemain = cbTotalContent - cbContent;
            if (m_cbResponseRemain < 0) {
                m_cbResponseRemain = 0;
                fAdditionalContent = TRUE;
            }
        }

        //
        // Server signalled proxy to close connection
        //
        
        if (headers.strConnection == gc_ConnClose) {
            headers.strConnection = "";
            *pfCloseConnection = TRUE;
        }

        //
        // Copy the content to a temporary buffer while the new headers are copied back
        // to the response buffer.  If no content is present in this packet, we do not
        // have to worry about copying content around.
        //
        
        if (cbContent) {
            pContent = buffContent.GetBuffer(cbContent);
            if (! pContent) {
                dwRetVal = ERROR_OUTOFMEMORY;
                IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Out of memory.\n")));
                goto exit;
            }
            memcpy(pContent, &pBuffer[cchHeaders], cbContent);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -