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

📄 httpfileobj.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* ***** BEGIN LICENSE BLOCK *****
 * Version: RCSL 1.0/RPSL 1.0
 *
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
 *
 * The contents of this file, and the files included with this file, are
 * subject to the current version of the RealNetworks Public Source License
 * Version 1.0 (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the RealNetworks Community Source License Version 1.0
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
 * in which case the RCSL will apply. You may also obtain the license terms
 * directly from RealNetworks.  You may not use this file except in
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
 * applicable to this file, the RCSL.  Please see the applicable RPSL or
 * RCSL for the rights, obligations and limitations governing use of the
 * contents of the file.
 *
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the portions
 * it created.
 *
 * This file, and the files included with this file, is distributed and made
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 *
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

/****************************************************************************
 * Includes
 */
#include "hlxclib/stdio.h"              /* FILE                     */
#include "hlxclib/string.h"             /* strcpy, etc.             */
#include "hlxclib/sys/stat.h"           /* stat, etc.               */
#include "hxtypes.h"                    /* UINT32, BOOL, etc        */
#include "hxcom.h"                      /* IUnknown                 */
#include "hxcomm.h"                     /* IHXCommonClassFactory    */
#include "ihxpckts.h"                   /* IHXValues, IHXBuffers    */
#include "hxbuffer.h"                   /* CHXBuffer                */
#include "hxurl.h"                      /* CHXURL                   */
#include "chxpckts.h"                   /* CHXHeader                */
#include "hxcache2.h"                   /* IHXCache2, IHXCacheObject,
                                           IHXCacheObjectResponse   */
#include "httpfilesys.h"                /* FILE_SYS_PROTOCOL        */
#include "httpfileobj.h"                /* CHXHTTPFileObject        */
#include "debug.h"                      /* DPRINTF                  */
#include "chxcache2.h"                  /* CHXCache2                */
#include "hxprefs.h"                    /* IHXPreferences           */
#include "multilog.h"                   /* INIT_MULTILOG_GROUP_NO_COREDEBUG(...) */
#include "mlog_http.h"                  /* MLOG_HTTP(...)           */

#ifdef _SYMBIAN
    #include "symbhxdir.h"              /*  OS_SEPARATOE_CHAR       */
#else
    #include "hxdir.h"
#endif

#define D_HTTP_FO 0x1000000

// The capacity of the Cache in bytes. IMPORTANT >> See the comment for CHUNK_SIZE.
#define CACHE_CAPACITY (12 * 1024)

// The amount of data requested through the TCP socket read operation.
// IMPORTANT !!! The chunk_size should be <= (1 - THRESHOLD/100)*CACHE_CAPACITY
// Otherwise we may get into a position wherein the cache has less than
// THRESHOLD read-data but it won't ever be able to accept any new data as the
// new data buffer size (CHUNK_SIZE) will overflow the cache. Also, since
// read-data is below threshold, the cache will never discard any more data.
#define CHUNK_SIZE (2 * 1024)

// 70%  -> The percentage of read data we would like the cache
// to hold. It is made high because when a request for old data can't
// be satisfied, then the whole connection has to be teared down
// everything has to be restrated.  So, it's better to have this value high.
// Note that some fileformat objects start seeking from start whatever be
// the direction of the User Interface seek. In such cases, threshold doesn't
// matter.
#define THRESHOLD 70

#define DEFAULT_HTTP_PORT 80
#define DEFAULT_CALLBACK_INTERVAL 10 // ms

// 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);


// CHXHTTPFileObject Class Methods

/****************************************************************************
 *  CHXHTTPFileObject::CHXHTTPFileObject
 *
 *  Constructor
 */
CHXHTTPFileObject::CHXHTTPFileObject(IUnknown* pContext, IHXValues* pOptions)
    : m_RefCount                (0),        // See header file for the
      m_pContext                (NULL),     // purpose of these variables.
      m_pOptions                (NULL),
      m_pClassFactory           (NULL),
      m_pFileResponse           (NULL),
      m_pRequest                (NULL),
      m_pCache                  (NULL),
      m_pSocket                 (NULL),
      m_pCHXURL                 (NULL),
      m_ulCurrentReadOffset     (0),
      m_lNewReadOffset          (-1),
      m_bInSeekDone             (FALSE),
      m_bInReadDone             (FALSE),
      m_bReadPending            (FALSE),
      m_bIncompleteReadPending  (FALSE),
      m_ulFileLength            (0),
      m_pHdrListRoot            (NULL),
      m_bHeaderCompletelyRead   (FALSE),
      m_pHeader                 (NULL),
      m_bStartAllOverAgain      (FALSE),
      m_pScheduler              (NULL),
      m_ulCallbackHandle        (0),
      m_ulCallBackInterval      (DEFAULT_CALLBACK_INTERVAL),  // 10 ms
      m_bFirstChunk             (TRUE),
      m_bInitResponsePending    (FALSE),
      m_bInitialized            (FALSE),
      m_ulFileDataRead          (0),
      m_bAddBlockPending        (FALSE),
      m_pPendingAddBlock        (NULL),
      m_bDisconnected           (FALSE)

{
    MLOG_HTTP("CHXHTTPFileObject::CHXHTTPFileObject()\n");

    m_pContext = pContext;
    m_pOptions = pOptions;

    // Signify that we need to keep a reference to this object
    if (m_pOptions != NULL)
    {
	m_pOptions->AddRef();
    }

    if (m_pContext != NULL)
    {
	m_pContext->AddRef();
        m_pContext->QueryInterface(IID_IHXScheduler,
                                 (void**) &m_pScheduler);
        m_pContext->QueryInterface(IID_IHXCommonClassFactory,
				 (void**)&m_pClassFactory);
    }

} // CHXHTTPFileObject()


/****************************************************************************
 *  CHXHTTPFileObject::~CHXHTTPFileObject
 *
 *  Destructor.
 */
CHXHTTPFileObject::~CHXHTTPFileObject(void)
{
    MLOG_HTTP("CHXHTTPFileObject::~CHXHTTPFileObject()\n");


    _CleanUp();

} // ~CHXHTTPFileObject()

/****************************************************************************
* IHXFileObject::_CleanUp()
*
* Cleans up the object by relesing all member objects. This is a helper
* function used by the Close() and the destructor.
*
*/

STDMETHODIMP
CHXHTTPFileObject::_CleanUp(void)
{
    MLOG_HTTP("CHXHTTPFileObject::_CleanUp()\n");

    m_bAddBlockPending = FALSE;
    HX_RELEASE(m_pPendingAddBlock);
    
    if (m_ulCallbackHandle)
    {
	m_pScheduler->Remove(m_ulCallbackHandle);
	m_ulCallbackHandle = 0;
    }

    m_bInitialized = FALSE;
    
    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pOptions);
    HX_RELEASE(m_pClassFactory);
    HX_RELEASE(m_pFileResponse);
    HX_RELEASE(m_pRequest);
    HX_RELEASE(m_pCache);
    HX_RELEASE(m_pSocket);
    HX_DELETE(m_pCHXURL);
    HX_RELEASE(m_pPendingReadInfo.pPendingReadBuff);
    HX_RELEASE(m_pHeader);
    HX_RELEASE(m_pScheduler);
    HX_RELEASE(m_pPendingAddBlock);

    return HXR_OK;

} // _CleanUp()


// IHXFileObject Interface Methods

/****************************************************************************
 *  IHXFileObject::Init
 *
 *  This routine associates this File Object with a File Response object
 *  which is notified when file operations (read, write, seek, etc.) are
 *  complete. This method also checks the validity of the file by actually
 *  opening it.
 */
STDMETHODIMP
CHXHTTPFileObject::Init(UINT32            fileAccessMode, // We ignore access mode here
			IHXFileResponse*  pFileResponse)
{
    MLOG_HTTP("CHXHTTPFileObject::Init()\n");

    HX_RESULT res = HXR_OK;

    if (pFileResponse != NULL)
    {
	// Release any previous File Response objects
	if (m_pFileResponse != NULL)
	{
	    m_pFileResponse->Release();
	}

	m_pFileResponse = pFileResponse;
	m_pFileResponse->AddRef();
    }
    else
    {
	return HXR_INVALID_PARAMETER;
    }


    if(m_bInitialized) // Init() was previously called atleast once
    {
        // There is no point continuing with a pending read as
        // the caller has changed.
        m_bReadPending = FALSE;
        m_bIncompleteReadPending = FALSE;
        HX_RELEASE(m_pPendingReadInfo.pPendingReadBuff);

        /* If we have already opened a file, then seek back
         * to zero during re-initialization
         */
        m_ulCurrentReadOffset = 0;
        m_pFileResponse->InitDone(HXR_OK);
        return HXR_OK;
     }

    m_pPendingReadInfo.pPendingReadBuff = NULL;

    // Else, this is the first time Init() is being called

    if(m_pCHXURL == NULL) // Init() being called before calling SetRequest()
    {
        return HXR_INVALID_OPERATION;
    }

    /*
     * We have to check the validity of the file. What we do is we
     * contact the HTTP server and request for the HTTP file header.
     * This lets us do two things:
     *      (1) It lets us know if the file really exists on the server.
     *      (2) If file exists, the response contains the stats of the file.
     */

    res = _Start(); // Commence the action - connect to server, send GET req, etc

    return res;

} // Init()

// Assumes the state of the network related state variables is
// as it would be if this method is called for the first time
// (for eg., from the constructor). So, m_pSocket, etc should all
// be NULL
STDMETHODIMP
CHXHTTPFileObject::_Start()
{
    MLOG_HTTP("CHXHTTPFileObject::_Start()\n");

    IHXNetworkServices* pNetworkServices = NULL;

    if (HXR_OK != m_pContext->QueryInterface( IID_IHXNetworkServices,
                                            (void **)&pNetworkServices))
    {
        return HXR_FAIL;
    }

    HX_RESULT res = HXR_OK;

    res = pNetworkServices->CreateTCPSocket(&m_pSocket);
    pNetworkServices->Release();

    if( (res != HXR_OK) || (m_pSocket == NULL) )
    {
        return HXR_FAIL;
    }

    // Identify yourself as the object to whom the results of all
    // socket related operations should be reported.
    res = m_pSocket->Init( (IHXTCPResponse *)this );
    if( ( res != HXR_OK) || (m_pCHXURL == NULL) )
    {
        HX_RELEASE(m_pSocket);
        return HXR_FAIL;
    }

    // Parse the URL to get server address and port
    IHXValues* pHeader = m_pCHXURL->GetProperties();
    IHXBuffer* pBuffer = NULL;

    char *serverAddress = NULL;
    pHeader->GetPropertyBuffer(PROPERTY_HOST, pBuffer);
    if(pBuffer != NULL)
    {
        serverAddress = (char*)(pBuffer->GetBuffer());
    }

    ULONG32 serverPort = 0;
    pHeader->GetPropertyULONG32(PROPERTY_PORT, serverPort);

    // Connect to the HTTP server
    res = m_pSocket->Connect(serverAddress, (UINT16)serverPort);

    if(res != HXR_OK)
    {
        HX_RELEASE(m_pSocket);
        return HXR_FAIL;
    }

    return HXR_OK;

} // _Start()


/****************************************************************************
 *  IHXFileObject::GetFilename
 *
 *  This routine returns the name of the requested file (without any path
 *  information). This method may be called by the File Format plug-in if the
 *  short name of the file is required.
 */
STDMETHODIMP
CHXHTTPFileObject::GetFilename(REF(const char*) pFileName)
{
    MLOG_HTTP("CHXHTTPFileObject::GetFilename()\n");

    pFileName = NULL;
    HX_RESULT res = HXR_OK;

    //  From the File path, extract the file name and return it.
    if(m_pCHXURL != NULL)
    {
        IHXBuffer* pBuffer = NULL;
        IHXValues* pHeader = m_pCHXURL->GetProperties();
        pHeader->GetPropertyBuffer(PROPERTY_RESOURCE, pBuffer);
        if(pBuffer != NULL)
        {
            pFileName = (char*)(pBuffer->GetBuffer());
        }
    }
    else
    {
        res = HXR_FAIL;
    }

    return res;
}


/****************************************************************************
 *  IHXFileObject::Read
 *
 *  This routine reads a block of data of the specified length from the file.
 *  When reading has completed, the caller is asynchronously notified via the
 *  File Response object associated with this File Object. This method is
 *  called by the File Format plug-in when it needs to read from the file.
 */
STDMETHODIMP
CHXHTTPFileObject::Read(UINT32 byteCount)
{
    MLOG_HTTP("CHXHTTPFileObject::Read(%u)\n", byteCount);

    // The whole file has already been read
    if(m_ulCurrentReadOffset == m_ulFileLength)
    {
        HX_RESULT res = HXR_FAIL;

        if (m_pFileResponse)
        {
            m_pFileResponse->ReadDone(HXR_FAIL, 0);
            res = HXR_OK;
        }

        return res;
    }

    // Can't have a read when a previous read is outstanding
    if(m_bReadPending)
    {
        return HXR_INVALID_OPERATION;
    }

    m_bIncompleteReadPending = FALSE;

    // Can't read more than the (remaining) file length
    int actualLen = m_ulFileLength - m_ulCurrentReadOffset;
    if(actualLen > byteCount)
        actualLen = byteCount;

    m_bReadPending = TRUE;

    m_pPendingReadInfo.pPendingReadBuff = NULL;
    m_pPendingReadInfo.ulWriteOffset = 0;
    m_pPendingReadInfo.ulReadOffset = m_ulCurrentReadOffset;
    m_pPendingReadInfo.ulSize = (UINT32)actualLen;

    HX_RESULT r = m_pCache->ReadBlock(m_ulCurrentReadOffset, (UINT32)actualLen);

    return r;

} // Read()


/****************************************************************************
 *  IHXFileObject::Write
 *
 *  This routine writes a block of data to the file. When writing has
 *  completed, the caller is asynchronously notified via the File Response
 *  object associated with this File Object. This method called by the File
 *  Format plug-in when it needs to write to the file.
 */
STDMETHODIMP
CHXHTTPFileObject::Write(IHXBuffer* pDataToWrite)
{
    MLOG_HTTP("CHXHTTPFileObject::Write()\n");

    return HXR_NOTIMPL;
}

⌨️ 快捷键说明

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