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

📄 httpfileobj.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    // for all these conditions because if the server disconnected after
    // serving all data and if it is stored in the cache, then we shouldn't
    // be worried.
    if(
            (status == HXR_INCOMPLETE) && (pBuffer == NULL) &&
            (m_bDisconnected == TRUE)  && (m_pCache->IsEmpty())
        )
    {
        if (m_pFileResponse)
        {
            m_pFileResponse->ReadDone(HXR_SERVER_DISCONNECTED, NULL);
        }

        return HXR_OK;
    }

    if(pBuffer != NULL)
        pBuffer->AddRef();

    HX_RESULT res = HXR_OK;

    // This is a response to a ReadBlock() called from Func(). Func() does this
    // only when there is an incomplete Read.
    if(m_bIncompleteReadPending)
    {
        if( ((status == HXR_OK) || (status == HXR_INCOMPLETE)) && (pBuffer != NULL) )
        {
            // Copy data into the buffer set aside for the incomplete read.
            memcpy((void*)(m_pPendingReadInfo.pPendingReadBuff->GetBuffer() + m_pPendingReadInfo.ulWriteOffset),
                           (void*)(pBuffer->GetBuffer()), pBuffer->GetSize());

            // Update offsets and sizes for the next read installment
            m_pPendingReadInfo.ulWriteOffset += pBuffer->GetSize(); // Next installment buffer-write offset
            m_pPendingReadInfo.ulReadOffset += pBuffer->GetSize();  // Next installment cache-read offset
            m_pPendingReadInfo.ulSize -= pBuffer->GetSize();        // Next installment max-size
        }
        if(HXR_OK == status)
        {
            // This installment finally fills up the incomplete read buffer.
            m_ulCurrentReadOffset = m_pPendingReadInfo.ulReadOffset;
            m_bIncompleteReadPending = FALSE;
            m_bReadPending = FALSE;

            // Get a handle since there is a possibilily of m_pPendingReadInfo
            // being modified in some method called from ReadDone().
            IHXBuffer* pBuff = m_pPendingReadInfo.pPendingReadBuff;
            m_pPendingReadInfo.pPendingReadBuff = NULL;

            if (m_pFileResponse)
            {
                m_pFileResponse->ReadDone(HXR_OK, pBuff);
            }

            HX_RELEASE(pBuff);
            pBuff = NULL;

        }
        else if(status == HXR_INCOMPLETE) // Need to get more installments to fill up ReadBuffer
        {
            m_ulCallbackHandle = m_pScheduler->RelativeEnter(this, m_ulCallBackInterval);
        }
        else
        {
            // Can't happen
        }

    }
    else // !m_bIncompleteReadPending
    {

        if(status == HXR_OK) // Cool, hand data over to the FF object
        {
            m_ulCurrentReadOffset = m_pPendingReadInfo.ulReadOffset + m_pPendingReadInfo.ulSize;
            m_bReadPending = FALSE;

            if (m_pFileResponse)
            {
                m_pFileResponse->ReadDone(HXR_OK, pBuffer);
            }
        }

        // This means that the Cache has only partial data. Create a buffer to store this partial data.
        // Mark this read as incomplete and try to read from the cache in installments.
        // Request scheduler to signal you after some time. When the scheduler signals
        // you (via Func()), check to see if Cache has recieved anymore data.
        else if(status == HXR_INCOMPLETE)
        {
            if(m_pClassFactory != NULL)
            {
                // Create a buffer to fill it in installments.
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
				                (void**)&m_pPendingReadInfo.pPendingReadBuff);

                if (m_pPendingReadInfo.pPendingReadBuff != NULL)
                {
                    res =  m_pPendingReadInfo.pPendingReadBuff->SetSize(m_pPendingReadInfo.ulSize);
                    if(HXR_OK == res)
                    {
                        if(pBuffer != NULL)
                        {
                            // Copy the partial data into the pending read buffer.
                            memcpy((void*)(m_pPendingReadInfo.pPendingReadBuff->GetBuffer()),
                                   (void*)(pBuffer->GetBuffer()), pBuffer->GetSize());

                            m_pPendingReadInfo.ulWriteOffset = pBuffer->GetSize();  // Next installment buffer-write offset
                            m_pPendingReadInfo.ulReadOffset += pBuffer->GetSize();  // Next installment cache-read offset
                            m_pPendingReadInfo.ulSize -= pBuffer->GetSize();        // Next installment max-size

                        }
                    }
                    else
                    {
                        HX_RELEASE(m_pPendingReadInfo.pPendingReadBuff);
                        res = HXR_OUTOFMEMORY;
                    }
                }
                else
                {
                    res = HXR_OUTOFMEMORY;
                }
            }
            else
            {
                res = HXR_UNEXPECTED;
            }

            // Not enough memory to create buffers.
            // Let's do the best we can do! Return the incomplete data.
            if(HXR_OK != res)
            {
                m_bReadPending = FALSE;
                m_ulCurrentReadOffset = m_pPendingReadInfo.ulReadOffset;

                if (m_pFileResponse)
                {
                    m_pFileResponse->ReadDone(HXR_INCOMPLETE, pBuffer);
                }
            }
            else
            {
                // We will try to fill the remaining data in the buffer after waiting for some
                // time. We ask the scheduler to call us back after some time and then we check if the
                // Cache has recieved any new data.
                m_bIncompleteReadPending = TRUE;
                m_ulCallbackHandle = m_pScheduler->RelativeEnter(this, m_ulCallBackInterval);
            }

        }

        // status = HXR_FAIL, i.e, the Cache had discarded some part of the data
        // we requeted. The cache has already discarded the data and so there is no hope
        // of getting that data. The only way to satisfy the Read request
        // is to tear down the connection and start-all-over-again.
        else //status = HXR_FAIL and the reason is request for past data
        {
            // Set this flag so that other activities are all paralysed
            m_bStartAllOverAgain = TRUE;

            m_bAddBlockPending = FALSE;
            HX_RELEASE(m_pPendingAddBlock);
            m_pPendingAddBlock = NULL;

            // Close the socket
            HX_RELEASE(m_pSocket);

            m_bIncompleteReadPending = TRUE;
            if(m_pClassFactory != NULL)
            {
                // Create a buffer and fill it in installments.
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
				                (void**)&m_pPendingReadInfo.pPendingReadBuff);

                m_pPendingReadInfo.pPendingReadBuff->SetSize(m_pPendingReadInfo.ulSize);
            }

            // Flush the cache so that we can freshly start
            // storing the new info into it.
            m_pCache->Flush();
            // Rest of the the "start-all-over-again" continues in FlushDone()
        }

    } // !m_bIncompleteReadPending

    if(m_bAddBlockPending)
    {
        // Now that we have read some data out of cache, maybe the cache would accept
        // the previously rejected data.
        if( (pBuffer != NULL) && (pBuffer->GetSize() > 0) )
        {
            if(m_pCache->GetUnusedCapacity() >= m_pPendingAddBlock->GetSize())
            {
                m_ulCallbackHandle = m_pScheduler->RelativeEnter(this, 0);
            }
        }
    }

    HX_RELEASE(pBuffer);
    pBuffer = NULL;

    return HXR_OK;

} // ReadBlockDone()

/************************************************************************
 *	Method:
 *
 *	    IHXCacheObjectResponse::FlushDone
 *
 *	Purpose:
 *
 *	    Notification that IHXCacheObject::Flush operation has completed.
 */

STDMETHODIMP
CHXHTTPFileObject::FlushDone(HX_RESULT  /*IN*/	status)
{
    MLOG_HTTP("CHXHTTPFileObject::FlushDone(%s)\n", StrRep(status));

    // Discard the old header so that the incoming new
    // hdr is not confused for data.
    HX_RELEASE(m_pHeader);
    m_pHeader = NULL;

    m_bHeaderCompletelyRead = FALSE;
    m_ulFileDataRead = 0;
    m_bFirstChunk = TRUE;   // The TCP chunk that will be recived later
                            // will be the first one from the new connection.

    m_bStartAllOverAgain = FALSE;

    // Start the whole process (viz., connecting, GET request, etc) all over again.
    _Start();

    return HXR_OK;

} // FlushDone()


/*
 *	IHXTCPResponse methods
 */

/************************************************************************
 *	Method:
 *	    IHXTCPResponse::ConnectDone
 *	Purpose:
 *	    A Connect operation has been completed or an error has occurred.
 */
STDMETHODIMP
CHXHTTPFileObject::ConnectDone(HX_RESULT	status)
{
    MLOG_HTTP("CHXHTTPFileObject::ConnectDone(%s)\n", StrRep(status));

    if(status != HXR_OK)
    {
        if(!m_bInitialized && m_pFileResponse)
        {
           m_pFileResponse->InitDone(status);
        }

        return HXR_OK;
    }

    // OK, the connection has been established. Now send a GET request to
    // start getting the file.
    char* HttpGetReq = NULL;
    UINT32 ulReqLen = 0;
    HX_RESULT res = HXR_OK;

    res = _PrepareHTTP10GetMessage(HttpGetReq, ulReqLen);
    if(res != HXR_OK)
    {
        if(!m_bInitialized && m_pFileResponse)
        {
            m_pFileResponse->InitDone(HXR_OUTOFMEMORY);
        }

        return HXR_OK;
    }

    CHXBuffer* pSendBuffer = new CHXBuffer((UCHAR*)HttpGetReq, ulReqLen);
    if(pSendBuffer == NULL)
    {
        if(!m_bInitialized && m_pFileResponse)
        {
            m_pFileResponse->InitDone(HXR_OUTOFMEMORY);
        }

        return HXR_OK;
    }

    pSendBuffer->AddRef();

    // Now write the HTTP/1.0 GET request into the socket
    res = m_pSocket->Write( (IHXBuffer *)pSendBuffer );

    // Ask for the response
    res = m_pSocket->Read((UINT16)CHUNK_SIZE);

    HX_RELEASE(pSendBuffer);

    return res;

} //  ConnectDone()

/************************************************************************
 *	Method:
 *	    IHXTCPResponse::ReadDone
 *	Purpose:
 *	    A Read operation has been completed or an error has occurred.
 *	    The data is returned in the IHXBuffer.
 */
STDMETHODIMP
CHXHTTPFileObject::ReadDone(HX_RESULT		status,
			    IHXBuffer*		pBuffer)
{
    MLOG_HTTP("CHXHTTPFileObject::ReadDone(%s)\n", StrRep(status));

    if(pBuffer != NULL)
        pBuffer->AddRef();

    // A backward seek had failed. Which means the Cache is going
    // to be flushed, connection tore down and everythings going to
    // start all over again. So, no point storing this in the cache.
    if(m_bStartAllOverAgain)
    {
        HX_RELEASE(pBuffer);
        return HXR_OK;
    }

    if(!m_bHeaderCompletelyRead) // The TCP data we recvd is a chunk of HTTP header
    {
        if( (status != HXR_OK) || (pBuffer == NULL) )
        {
            if(!m_bInitialized && m_pFileResponse)
            {
                m_pFileResponse->InitDone(HXR_FAIL);
            }

            return HXR_OK;
        }

        // Check if response indicates success
        if(m_bFirstChunk)  // If it is the first chunk from the server
        {
            m_bFirstChunk = FALSE;

            const char pSuccess[] = "200 OK\r\n"; // HTTP success code

            // Is the starting line "HTTP/1.x 200 OK\r\n" ?
            if( memcmp((void*)(pBuffer->GetBuffer() + 9), (void*)pSuccess, strlen(pSuccess)) != 0 )
            {
                if(!m_bInitialized)
                {
                    m_bFirstChunk = TRUE;

                    // The requested file is not present on the web server
                    if (m_pFileResponse)
                    {
                        m_pFileResponse->InitDone(HXR_DOC_MISSING);
                    }
                }

                return HXR_OK;
            }
        }


        // Append this header chunk to the list of such chunks being maintained.
        HdrChunk *hi = new HdrChunk;
        hi->pPartOfHdr = pBuffer;
        hi->next = NULL;

        if(m_pHdrListRoot == NULL)
        {
            m_pHdrListRoot = hi;
        }
        else
        {
            HdrChunk *temp = NULL;
            for(temp = m_pHdrListRoot; temp->next != NULL; temp = temp->next);

            temp->next = hi;
        }

        // Is this the last header chunk? If so, does this chunk
        // also contain some non-header data? If true, store this
        // non-hdr data in the Cache and consolidate all the previous
        // header chunks into a single buffer. Then destroy the
        // header-chunks list.

        // Note!!!! GetBuffer() doesn't return a NULL terminated string. So,
        // shouldn't use strstr(). That's why I used my utility function bufnstr()!
        char *marker = bufnstr((char*)(hi->pPartOfHdr->GetBuffer()), "\r\n\r\n",
                                hi->pPartOfHdr->GetSize());

        if(marker == NULL) // End of hdr not found in this chunk
        {
            return m_pSocket->Read((UINT16)CHUNK_SIZE); // Read more data
        }
        else
        {
            m_bHeaderCompletelyRead = TRUE;
        }

        // This chunk has the end-of-header marker.
        // Consolidate all the header chunks

        marker += 4; // Move the pointer just after the header end-marker.
        int hdrLen = 0;
        int dataLen = 0;
        char *hdr = NULL;
        char *data = NULL;
        CHXBuffer* dataBuff = NULL;

        int len = 0;
        for(HdrChunk *temp = m_pHdrListRoot; temp != hi; temp = temp->next)
            len += temp->pPartOfHdr->GetSize();

        int lastPktHdrLen = marker - (char *)(hi->pPartOfHdr->GetBuffer());
        hdrLen = len + lastPktHdrLen;
        dataLen = hi->pPartOfHdr->GetSize() - lastPktHdrLen;

        hdr = new char[hdrLen];
        data = new char[dataLen];

        if( (hdr == NULL) || (data == NULL) )
        {
            if(!m_bInitialized && m_pFileResponse)
            {
                m_pFileResponse->InitDone(HXR_OUTOFMEMORY);
            }

            return HXR_OK;
        }

        int i = 0;
        for(HdrChunk *temp2 = m_pHdrListRoot; temp2 != hi; temp2 = temp2->next)
        {
            int buffLen = temp2->pPartOfHdr->GetSize();
            memcpy((void*)(hdr + i), (void*)(temp2->pPartOfHdr->GetBuffer()),buffLen);
            i += buffLen;
        }

        // m_ulFileDataRead is the amount of file data that has been read
        // so far.
        m_ulFileDataRead = dataLen;

        memcpy((void*)hdr, (void*)(hi->pPartOfHdr->GetBuffer()), lastPktHdrLen);
        memcpy((void*)data, (void*)(hi->pPartOfHdr->GetBuffer() + lastPktHdrLen), dataLen);

        m_pHeader = new CHXBuffer((UCHAR*)hdr, hdrLen);
        m_pHeader->AddRef();

        dataBuff = new CHXBuffer((UCHAR*)data, dataLen);
        dataBuff->AddRef();

⌨️ 快捷键说明

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