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

📄 session.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    //
    // Get the next chunk size.  The format of this string is as follows:
    // "chunk-size [chunk-extension]\r\n"
    // We want to return chunk_size and the total length of this string.
    //

    while (dwReadAttempts < MAX_CHUNKED_READ_ATTEMPTS) {
        CHAR* pszStopString = NULL;
        CHAR* pszEndChunk = NULL;
        PBYTE pBuffer = buffer.GetBuffer(0, FALSE);
        ASSERT(pBuffer);

        // Read to end of chunk-extension
        pszEndChunk = strstr((char*)pBuffer, "\r\n");
        if (NULL == pszEndChunk) {
            // Need to read more data to read past chunk-extension
            dwRetVal = ProxyRecv(recvSock, buffer, pcbRecved, -1, NULL);
            if (ERROR_SUCCESS != dwRetVal) {
                IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Could not recv data for rest of chunk size.\n")));
                goto exit;
            }

            dwReadAttempts++;
            continue;
        }

        // Read chunk-size
        *pdwChunkSize = strtol((char*)pBuffer, &pszStopString, 16);
        if ((0 == *pdwChunkSize) && (pszStopString == (char*)pBuffer)) {
            dwRetVal = ERROR_INVALID_DATA;
            goto exit;
        }

        // Calculate total chunk header size (Add two for \r\n)
        *pdwChunkHeaderSize = (pszEndChunk - (char*)pBuffer) + 2;
        break;        
    }
    
    if (0 == *pdwChunkHeaderSize) {
        dwRetVal = ERROR_INVALID_DATA;
    }

exit:
    return dwRetVal;
}

DWORD CHttpSession::HandleChunked(CBuffer& buffer, int* pcchBuffer, int* pcchSent, BOOL fRequest)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    DWORD dwChunkSize = 0;          // Size of chunk
    DWORD dwChunkHeaderSize = 0;    // Size of chunk header
    DWORD dwReadAttempts = 0;       // Number of attempts to read chunk header before giving up
    int cbChunkRemain = 0;          // Amount of data left to read in chunk
    int cbSend = 0;                 // Size of buffer to send to Client
    int cchBuffer;                  // Total Amount of data in buffer
    SOCKET recvSock, sendSock;

    recvSock = fRequest ? m_sockClient : m_sockServer;
    sendSock = fRequest ? m_sockServer : m_sockClient;

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

    cchBuffer = *pcchBuffer;

    while (m_fChunked) {
        if (0 == cchBuffer) {
            // Read some more data if the buffer is empty
            dwRetVal = ProxyRecv(recvSock, buffer, &cchBuffer, -1, NULL);
            if (ERROR_SUCCESS != dwRetVal) {
                goto exit;
            } 
        }
        
        if (cbChunkRemain != 0) {
            // We still have data left in the chunk to forward to client
            cbSend = (cbChunkRemain < cchBuffer) ? cbChunkRemain : cchBuffer;
            cbChunkRemain -= cbSend;
        }
        else {
            // We are at the start of the next chunk
            
            DWORD dwTotalChunkSize;
            int cbDeltaRecv = cchBuffer;

            dwRetVal = ReadChunkSize(recvSock, buffer, &cchBuffer, &dwChunkSize, &dwChunkHeaderSize);
            if (ERROR_SUCCESS != dwRetVal) {
                IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Invalid chunk syntax.\n")));
                goto exit;
            }

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

            *pcchBuffer += (cchBuffer - cbDeltaRecv);
            dwTotalChunkSize = dwChunkSize + dwChunkHeaderSize + 2;

            IFDBG(DebugOut(ZONE_SESSION, _T("WebProxy: Received chunk of size %d.  Forwarding to %s.\n"), dwChunkSize, (fRequest?L"server":L"client")));

            if (0 == dwChunkSize) {
                m_fChunked = FALSE; // We are done
                
                do {
                    cbSend = GetHeadersLength(pBuffer);
                    if (0 == cbSend) {
                        // Need to recv more data
                        dwRetVal = ProxyRecv(recvSock, buffer, &cchBuffer, -1, NULL);
                        if (ERROR_SUCCESS != dwRetVal) {
                            goto exit;
                        }
                        pBuffer = buffer.GetBuffer(0, FALSE);
                        ASSERT(pBuffer);                        
                    }
                } while (0 == cbSend);
            }
            else if (cchBuffer < dwTotalChunkSize) {
                cbChunkRemain = dwTotalChunkSize - cchBuffer;
                cbSend = cchBuffer;
            }
            else {
                cbSend = dwTotalChunkSize;
            }
        }
        
        dwRetVal = SendData(sendSock, (char *)pBuffer, cbSend);
        if (ERROR_SUCCESS != dwRetVal) {
            goto exit;
        }

        *pcchSent += cbSend;

        // If we did not send all data in the buffer, move the rest of the
        // data to the front of the buffer.
        if (cchBuffer > cbSend) {
            memmove(pBuffer, pBuffer + cbSend, cchBuffer - cbSend);
            pBuffer[cchBuffer-cbSend] = '\0';
        }

        cchBuffer -= cbSend;
    }

exit:    
    return dwRetVal;
}

DWORD CHttpSession::HandleFilterRequest(const CHttpHeaders& headers, CBuffer& buffer, BOOL* pfContinue, BOOL* pfCloseConnection)
{    
    DWORD dwRetVal = ERROR_SUCCESS;
    char szNewURLBuf[128];
    int cbNewURL = sizeof(szNewURLBuf);
    char* pszNewURL = szNewURLBuf;
    int cResizeBuf = 0;

    ASSERT(pfContinue);
    ASSERT(pfCloseConnection);

    // If no filter is provided then just return success and leave
    // the request unchanged.
    if (g_pProxyFilter->GetFilterCount() == 0) {
        *pfContinue = TRUE;
        return ERROR_SUCCESS;
    }
    
    *pfContinue = FALSE;
    *pfCloseConnection = FALSE;

    stringi strCanonicalizedURL;
    strCanonicalizedURL.reserve(headers.strURL.capacity()); // Canonicalized string is no bigger than original
    svsutil_HttpCanonicalizeUrlA(headers.strURL, strCanonicalizedURL.get_buffer());    

    while(1) {
        SOCKADDR_IN saPrivate;
        saPrivate.sin_family = AF_INET;
        g_pSettings->Lock();
        saPrivate.sin_addr.S_un.S_addr = inet_addr(g_pSettings->strPrivateAddrV4);
        g_pSettings->Unlock();
        
        PROXY_HTTP_REQUEST request;
        request.dwSize = sizeof(request);
        request.psaClient = (SOCKADDR_STORAGE*)&m_saClient;
        request.cbsaClient = sizeof(m_saClient);
        request.szUser = m_strUser;
        request.cchUser = m_strUser.length();
        request.szURL = strCanonicalizedURL;
        request.cchURL = strCanonicalizedURL.length();
        request.szURLOut = pszNewURL;
        request.cbURLOut = cbNewURL;
        request.psaProxy = (SOCKADDR_STORAGE*)&saPrivate;
        request.cbsaProxy = sizeof(saPrivate);

        pszNewURL[0] = '\0';
        
        dwRetVal = g_pProxyFilter->FilterRequest(&request);
        if (ERROR_INSUFFICIENT_BUFFER == dwRetVal) {
            //
            // Only give filter two chances to resize buffer then close session.
            //
            cResizeBuf++;
            if (cResizeBuf > 1) {
                dwRetVal = ERROR_INTERNAL_ERROR;
                goto exit;
            }
            
            //
            // Alloc larger buffer if necessary
            //
            cbNewURL = request.cbURLOut;
            pszNewURL = new char[cbNewURL];
            if (! pszNewURL) {
                dwRetVal = ERROR_OUTOFMEMORY;
                goto exit;
            }
        }
        else if (ERROR_NOT_AUTHENTICATED == dwRetVal) {
            //
            // Filter requires user to be authenticated
            //
            goto exit;
        }
        else if (ERROR_SUCCESS != dwRetVal) {
            //
            // Internal error in ProxyFilterHttpRequest
            //
            goto exit;
        }
        else {
            //
            // Function succeeded.  If URLs are the same afterwards then just continue with
            // the request.  Otherwise, handle the denied request.
            //
            if (strCanonicalizedURL == request.szURLOut) {
                *pfContinue = TRUE;
                break;
            }
            else if ((0 == request.cbURLOut) || (0 == strcmp(request.szURLOut, ""))) {
                *pfCloseConnection = TRUE;
                dwRetVal = SendMessage(m_sockClient, "403", gc_Reason403, NULL, 0);
                goto exit;
            }
            else {
                ClearRecvBuf(buffer);
                dwRetVal = SendDeniedRequest(m_sockClient, request.szURLOut);
                goto exit;
            }
        }
    }

exit:
    if (szNewURLBuf != pszNewURL) {
        delete[] pszNewURL;
    }
    return dwRetVal;
}



//
// Miscellaneous functions used by session objects
//

DWORD GetHeadersLength(const PBYTE pBuffer)
{
    DWORD dwLenEnd = 4;
    ASSERT(pBuffer);

    // Read until CRLF x2
    char* chEnd = strstr((char*)pBuffer, "\r\n\r\n");
    if (chEnd == NULL) {
        // Or LFx2
        dwLenEnd = 2;
        chEnd = strstr((char*)pBuffer, "\n\n");
        if (chEnd == NULL) {
            return 0;
        }
    }

    return (chEnd - (char*)pBuffer) + dwLenEnd;
}

DWORD NonBlockingRecv(SOCKET sock, PBYTE pBuffer, int cbBuffer, int* piBytesRecved)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    FD_SET sockSet;

    ASSERT(piBytesRecved);
    ASSERT(INVALID_SOCKET != sock);

    timeval timeout = {0};
    timeout.tv_sec = 10;

    FD_ZERO(&sockSet);
    FD_SET(sock, &sockSet);

    int iSockets = select(0,&sockSet,NULL,NULL,&timeout);

    if ((SOCKET_ERROR == iSockets) || (0 == iSockets)) {
        dwRetVal = ERROR_TIMEOUT;
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: NonBlockingRecv timed out trying to recv data\n")));
        goto exit;
    }

    *piBytesRecved = recv(sock, (char *)pBuffer, cbBuffer, 0);
    if ((SOCKET_ERROR == *piBytesRecved)) {
        dwRetVal = WSAGetLastError();
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Recv on sock %d, buf 0x%08X, len %d, failed with error %d.\n"), sock, pBuffer, cbBuffer, dwRetVal));
        goto exit;
    }

    if (0 == *piBytesRecved) {
        dwRetVal = ERROR_NO_DATA;
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Recv on sock %d, buf 0x%08X, len %d, cannot receive anymore data.\n"), sock, pBuffer, cbBuffer));
        goto exit;
    }

exit:
    return dwRetVal;
}

DWORD SendDeniedRequest(SOCKET sock, const char* pszURL)
{
    CHttpHeaders response;

    IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: HTTP request has been denied.  A new URL is being substituted.\n")));

    response.strStatusCode = "302";
    response.strReason = gc_Reason302;
    response.strContentLength = "0";
    response.strContentType = "text/html";
    response.strLocation = pszURL;

    response.UpdateResponse();

    // Send "Found" message with new URL
    return SendCustomPacket(sock, response);
}

DWORD SendMessage(SOCKET sock, const char* szCode, const char* szReason, const char* szContent, int cchContent)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    CHttpHeaders response;

    IFDBG(DebugOut(ZONE_RESPONSE, _T("WebProxy: Sending response with code %hs.\n"), szCode));

    response.strStatusCode = szCode;
    response.strReason = szReason;

    char szBuf[5];
    response.strContentLength = _itoa(cchContent, szBuf, 10);

    response.UpdateResponse();

    dwRetVal = SendCustomPacket(sock, response);
    if (cchContent && (ERROR_SUCCESS == dwRetVal)) {
        dwRetVal = SendData(sock, szContent, cchContent);
    }

    return dwRetVal;
}

DWORD SendCustomPacket(SOCKET sock, CHttpHeaders& headers)
{
    DWORD dwRetVal = ERROR_SUCCESS;
    CBuffer buffer;
    PBYTE pBuffer;
    
    int cbSize = headers.GetBufferSize();
    
    pBuffer = buffer.GetBuffer(cbSize + 1); // Add one for terminating null char
    if (! pBuffer) {
        dwRetVal = ERROR_OUTOFMEMORY;
        goto exit;
    }

    headers.GetResponseBuffer(pBuffer);

    dwRetVal = SendData(sock, (char *)pBuffer, cbSize);
#ifdef DEBUG
    if (ERROR_SUCCESS != dwRetVal) {
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Send returned error on sock %d (error:%d) with %d bytes.\n"), sock, dwRetVal, cbSize));
    }
#endif //DEBUG

exit:
    return dwRetVal;
}

DWORD SendData(SOCKET sock, const char* szData, int cbData)
{
    int cbSent = send(sock, szData, cbData, 0);
    if (SOCKET_ERROR == cbSent) {
        IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Send returned error %d with %d bytes.\n"), WSAGetLastError(), cbSent));
        return WSAGetLastError();
    }
    else {
#ifdef DEBUG
        if (cbSent != cbData) {
            IFDBG(DebugOut(ZONE_ERROR, _T("WebProxy: Tried to send %d bytes but actually sent %d bytes.\n"), cbData, cbSent));
            ASSERT(0);
        }
#endif // DEBUG

        return ERROR_SUCCESS;
    }
}

⌨️ 快捷键说明

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