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

📄 httpfileobj.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

        if( (!m_pHeader) || (!dataBuff) )
        {
            delete hdr;
            delete data;

            if(!m_bInitialized && m_pFileResponse)
            {
                m_pFileResponse->InitDone(HXR_OUTOFMEMORY);
            }

            return HXR_OK;
        }

        // Destroy the header-chunks list
        HdrChunk *temp3 = m_pHdrListRoot;
        HdrChunk *temp4 = NULL;
        while(temp3 != NULL)
        {
            temp4 = temp3;
            temp3 = temp3->next;
            temp4->pPartOfHdr->Release();
            delete temp4;
        }
        m_pHdrListRoot = NULL;

        // Parse the header for file statistics
        marker = bufnstr((char*)(m_pHeader->GetBuffer()), "\r\nContent-Length: ",
                            m_pHeader->GetSize());
        if(marker == NULL)
        {
            m_ulFileLength = 0;
            HX_RELEASE(m_pHeader);
            m_pHeader = NULL;
            HX_RELEASE(dataBuff);

            if(!m_bInitialized && m_pFileResponse)
            {
                m_pFileResponse->InitDone(HXR_INVALID_FILE);
            }

            return HXR_OK;
        }

        marker += 18;
        int remLen = m_pHeader->GetSize() - (marker - (char*)(m_pHeader->GetBuffer()));
        char *marker2 = bufnstr(marker, "\r\n", remLen);
        if(marker2 == NULL)
        {
            m_ulFileLength = 0;
            HX_RELEASE(m_pHeader);
            m_pHeader = NULL;
            HX_RELEASE(dataBuff);

            if(!m_bInitialized && m_pFileResponse)
            {
                m_pFileResponse->InitDone(HXR_INVALID_FILE);
            }
            return HXR_OK;

        }

        int l = marker2 - marker;
        char *flen = new char[l + 1];
        memcpy((void*)flen, (void*)marker, l);
        flen[l] = '\0';

        m_ulFileLength = atol(flen);
        delete flen;


        if(m_pCache == NULL)
        {
            CHXCache2 *pObj = new CHXCache2();
            pObj->AddRef();

            #ifdef HELIX_FEATURE_HTTP_FILECACHE

                BOOL bCacheEnabled = FALSE;
                char *pCacheFile = NULL;
                _GetCachePreferences(bCacheEnabled, pCacheFile);

                if(bCacheEnabled)
                {
                    pObj->CreateFileCacheObject(&m_pCache, m_pClassFactory,
                                        m_ulFileLength, pCacheFile);
                }

            #endif

            if(m_pCache == NULL)
            {
                pObj->CreateMemCacheObject(&m_pCache, m_pClassFactory);
            }


            pObj->Release();

            m_pCache->Init((IHXCacheObjectResponse*)this, CACHE_CAPACITY,
                                        THRESHOLD);
        }


        // You are on the network thread, so you can't call InitDone(). Let the
        // scheduler do it.
        if(!m_bInitialized)
        {
            m_bInitResponsePending = TRUE;
            m_ulCallbackHandle = m_pScheduler->RelativeEnter(this, 0);
        }

        // Store the non-header portion of the latest chunk in cache.
        m_pPendingAddBlock = (IHXBuffer*)dataBuff;
        m_pCache->AddBlock((IHXBuffer*)dataBuff);

        if(m_bIncompleteReadPending)
        {
            // Now that we have got the data for which we had to "startAllOverAgain",
            // let Func() take over and satisfy the "failed" Read().
            m_ulCallbackHandle = m_pScheduler->RelativeEnter(this, 0);
        }

    }
    else // The TCP data we recvd is applications data (i.e., not part of HTTP header)
    {
        if( (status == HXR_OK) && (pBuffer != NULL) )
        {
            m_ulFileDataRead += pBuffer->GetSize();

            m_pPendingAddBlock = pBuffer;
            m_pCache->AddBlock(pBuffer);

        }
    }

    return HXR_OK;

} //  ReadDone()

/************************************************************************
 *	Method:
 *	    IHXTCPResponse::WriteReady
 *	Purpose:
 *	    This is the response method for WantWrite.
 *	    If HX_RESULT is ok, then the TCP channel is ok to Write to.
 */
STDMETHODIMP
CHXHTTPFileObject::WriteReady(HX_RESULT		status)
{
    MLOG_HTTP("CHXHTTPFileObject::WriteReady(%s)\n", StrRep(status));

    return HXR_NOTIMPL;

} //  WriteReady()

/************************************************************************
 *	Method:
 *	    IHXTCPResponse::Closed
 *	Purpose:
 *	    This method is called to inform you that the TCP channel has
 *	    been closed by the peer or closed due to error.
 */
STDMETHODIMP
CHXHTTPFileObject::Closed(HX_RESULT		status)
{
    MLOG_HTTP("CHXHTTPFileObject::Closed(%s)\n", StrRep(status));

    m_bDisconnected = TRUE;

    return HXR_OK;

} //  Closed()

/************************************************************************
 *	IHXCallback::Func()
 */
STDMETHODIMP
CHXHTTPFileObject::Func()
{
    MLOG_HTTP("CHXHTTPFileObject::Func()\n");

    if(m_bInitResponsePending  && m_pFileResponse)
    {
        m_bInitResponsePending = FALSE;
        m_bInitialized = TRUE;
        m_pFileResponse->InitDone(HXR_OK);
    }

    // Is there any incomplete read pending?
    if(m_bIncompleteReadPending && m_pCache && m_pFileResponse)
    {
        // Ask the cache if it can supply the next installment for the
        // incomplete read.
        HX_RESULT res = m_pCache->ReadBlock(m_pPendingReadInfo.ulReadOffset,
                                            m_pPendingReadInfo.ulSize);

        if(res != HXR_OK)
        {
            m_bIncompleteReadPending = FALSE;
            IHXBuffer* pBuff = m_pPendingReadInfo.pPendingReadBuff;
            m_pPendingReadInfo.pPendingReadBuff = NULL;

            if (m_pFileResponse)
            {
                m_pFileResponse->ReadDone(HXR_INCOMPLETE, pBuff);
            }
            HX_RELEASE(pBuff);
            pBuff = NULL;
        }
    }

    // Is there any block which was rejected by the cache earlier because it
    // was full? If so, let's try inserting into the cache again. Maybe, the
    // cache has since freed some space.
    if(m_bAddBlockPending && m_pCache)
    {
        m_bAddBlockPending = FALSE;
        m_pCache->AddBlock(m_pPendingAddBlock);
    }

    return HXR_OK;

} // Func()


// A utility function which does searches for a *string* in a
// *character buffer* of size haystacksize. strnstr() wouldn't work since
// it requires both the parameters to be strings.
char* bufnstr(char *haystackBuffer, char* needleString, int haystackSize)
{
    char lastchar = haystackBuffer[haystackSize];

    haystackBuffer[haystackSize] = '\0'; // Now, it's a string

    char* marker = strstr(haystackBuffer, needleString);
    if(marker != NULL)
    {
        haystackBuffer[haystackSize] = lastchar;
        return marker;
    }

    // Perhaps the pattern occurs at the very end?
    haystackBuffer[haystackSize] = lastchar;
    int needleSize = strlen(needleString);
    marker = haystackBuffer + haystackSize - needleSize;

    char *tailPiece = new char[needleSize + 1];
    if(tailPiece == NULL)
        return NULL;

    memcpy((void*)tailPiece, (void*)marker, needleSize);
    tailPiece[needleSize] = '\0';

    if( strcmp(tailPiece, needleString) != 0 )
        marker = NULL;

    delete tailPiece;

    return marker;

} // bufnstr()

// From the preferences, get the directory and file where the
// contents should be cached.
STDMETHODIMP
CHXHTTPFileObject::_GetCachePreferences(BOOL& bCacheEnabled, char* &pCacheFile )
{
    IHXPreferences* pPreferences;

    m_pContext->QueryInterface(IID_IHXPreferences, (void **)&pPreferences);
    HX_ASSERT(pPreferences);

    // Get cache directory, if not set and available
    IHXBuffer* pBuffer  = NULL;

    // Check to see if the cache is enabled
    bCacheEnabled = TRUE;
    if (pPreferences->ReadPref("CacheEnabled", pBuffer) == HXR_OK)
    {
        // Cache enabled entry exists
        if (atoi((const char*)pBuffer->GetBuffer()))
        {
            // Cache enabled
            bCacheEnabled = TRUE;
        }
        else
        {
            // Cache disabled
            bCacheEnabled = FALSE;
        }

    }
    else
    {
        bCacheEnabled = FALSE;
    }

    if(bCacheEnabled == FALSE)
    {
        HX_RELEASE(pBuffer);
        return HXR_OK;
    }

    char separator[2] = {OS_SEPARATOR_CHAR, '\0'};

    BOOL bCacheDirSpecified = FALSE;
    if (pPreferences->ReadPref("CacheFolder", pBuffer) == HXR_OK)
    {
        // Make sure that the given filename belongs to a directory
        struct stat statbuf = { 0 };

        // If cache database filename does not refer to a file, drop the filename part
        if (!stat ((const char*)pBuffer->GetBuffer(), &statbuf))
        {
          if (statbuf.st_mode & S_IFDIR)
          {
              // Valid cache directory specified
              bCacheDirSpecified = TRUE;
          }
        }

    }

    if( bCacheDirSpecified == FALSE )
    {
        return HXR_FAIL;
    }

    char *cacheDir = (char*)(pBuffer->GetBuffer());

    // Now append the file name
    HX_ASSERT(m_pCHXURL);
    IHXValues* pHeader = m_pCHXURL->GetProperties();
    HX_ASSERT(pHeader);

    IHXBuffer* pPath = NULL;
    char *path = NULL;

    IHXBuffer* pFullPath = NULL;
    char* fullPath = NULL;

    pHeader->GetPropertyBuffer(PROPERTY_PATH, pPath);
    if(pPath != NULL)
    {
        path = (char*)(pPath->GetBuffer());
    }

    pHeader->GetPropertyBuffer(PROPERTY_FULLPATH, pFullPath);
    if(pFullPath!= NULL)
    {
        fullPath = (char*)(pFullPath->GetBuffer());
    }

    char *justFileName = &fullPath[strlen(path)];

    UINT32 l1 = strlen(cacheDir);
    UINT32 l2 = strlen(separator);
    UINT32 l3 = strlen(justFileName);

    pCacheFile = new char[l1 + l2 + l3 + 1];

    HX_ASSERT(pCacheFile);

    memcpy( (void*)pCacheFile, (void*)cacheDir, l1);
    memcpy( (void*)(pCacheFile + l1), (void*)separator, l2);
    memcpy( (void*)(pCacheFile + l1 + l2), (void*)justFileName, l3);
    pCacheFile[l1 + l2 + l3] = '\0';

    HX_RELEASE(pBuffer);
    HX_RELEASE(pPath);
    HX_RELEASE(pFullPath);

    return HXR_OK;

} // _GetCachePreferences()

// Prepare a HTTP/1.0 GET Request Message with the appropriate headers.
STDMETHODIMP
CHXHTTPFileObject::_PrepareHTTP10GetMessage(char* &pGetMsg,
                                            UINT32 &ulMsgLen)
{
    char* SP = " ";     // space
    char* CRLF = "\r\n";
    char* CRLFCRLF = "\r\n\r\n";

    char* resource = NULL;
    IHXBuffer* pBuffer = NULL;
    IHXValues* pHeader = m_pCHXURL->GetProperties();

    pHeader->GetPropertyBuffer(PROPERTY_RESOURCE, pBuffer);
    if(pBuffer != NULL)
    {
        resource = (char*)(pBuffer->GetBuffer());
    }
    if(resource == NULL)
    {
        return HXR_UNEXPECTED;
    }

    CHXString ReqStr;

    ReqStr += (const char*)"GET /";

    ReqStr += (const char*)resource;

    ReqStr += (const char*)SP;

    ReqStr += (const char*)"HTTP/1.0";


    IHXValues* pHeaders = NULL;
    m_pRequest->GetRequestHeaders(pHeaders);

    const char* pKey = NULL;
    IHXBuffer* pStr = NULL;

    IHXKeyValueList* pKeyVals = NULL;
    m_pClassFactory->CreateInstance(CLSID_IHXKeyValueList,
				    (void**)&pKeyVals);

    pKeyVals->ImportValues(pHeaders);
    IHXKeyValueListIter* pIter;
    pKeyVals->GetIter(pIter);

    // Attach the appropriate HTTP Request headers
    HX_RESULT retVal = pIter->GetNextPair(pKey, pStr);
    while(retVal == HXR_OK)
    {
        ReqStr += (const char*)CRLF;
        ReqStr += (const char*)pKey;
        ReqStr += (const char*)": ";
        ReqStr += (const char*)pStr->GetBuffer();

        retVal = pIter->GetNextPair(pKey, pStr);
    }

    ReqStr += (const char*)CRLFCRLF;

    // Set the function's out parameters
    ulMsgLen = ReqStr.GetLength();

    pGetMsg = NULL;
    pGetMsg = new char[ulMsgLen];
    if(pGetMsg == NULL)
    {
        return HXR_OUTOFMEMORY;
    }
    memcpy(pGetMsg, ReqStr.GetBuffer(ulMsgLen), ulMsgLen);

    return HXR_OK;

} // _PrepareHTTP10GetMessage()

⌨️ 快捷键说明

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