Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #ifndef PVMF_PROTOCOL_ENGINE_INTERNAL_H_INCLUDED
     19 #define PVMF_PROTOCOL_ENGINE_INTERNAL_H_INCLUDED
     20 
     21 #ifndef PVMF_MEDIA_DATA_H_INCLUDED
     22 #include "pvmf_media_data.h"
     23 #endif
     24 
     25 #ifndef OSCL_STR_PTR_LEN_H_INCLUDED
     26 #include "oscl_str_ptr_len.h"
     27 #endif
     28 
     29 #ifndef OSCL_TIME_H_INCLUDED
     30 #include "oscl_time.h"
     31 #endif
     32 
     33 #ifndef OSCL_STRING_CONSTAINERS_H_INCLUDED
     34 #include "oscl_string_utils.h"
     35 #endif
     36 
     37 #ifndef OSCL_SNPRINTF_H_INCLUDED
     38 #include "oscl_snprintf.h"
     39 #endif
     40 
     41 #ifndef OSCL_STRING_CONSTAINERS_H_INCLUDED
     42 #include "oscl_string_containers.h"
     43 #endif
     44 
     45 #ifndef HTTP_COMPOSER_H_INCLUDED
     46 #include "http_composer.h"
     47 #endif
     48 
     49 #ifndef HTTP_PARSER_H_INCLUDED
     50 #include "http_parser.h"
     51 #endif
     52 
     53 #ifndef PVMF_PROTOCOL_ENGINE_NODE_EXTENSION_H_INCLUDED
     54 #include "pvmf_protocol_engine_node_extension.h" // for class PVMFProtocolEngineNodeMSHTTPStreamingParams
     55 #endif
     56 
     57 #ifndef PVLOGGER_H_INCLUDED
     58 #include "pvlogger.h"
     59 #endif
     60 
     61 // log macros
     62 #define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
     63 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
     64 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
     65 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
     66 #define LOGINFO(m) LOGINFOMED(m)
     67 #define LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m);
     68 #define LOGERRORDATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m);
     69 #define LOGINFOCLOCK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iClockLogger,PVLOGMSG_INFO,m);
     70 #define PVMF_PROTOCOL_ENGINE_LOGBIN(iPortLogger, m) PVLOGGER_LOGBIN(PVLOGMSG_INST_LLDBG, iPortLogger, PVLOGMSG_ERR, m);
     71 #define PVMF_PROTOCOL_ENGINE_LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m);
     72 #define PVMF_PROTOCOL_ENGINE_LOGERRINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathErrLogger,PVLOGMSG_INFO,m);
     73 #define NODEDATAPATHLOGGER_TAG "datapath.sourcenode.protocolenginenode"
     74 #define DATAPATHLOGGER_TAG "protocolenginenode.protocolengine"
     75 #define DATAPATHERRLOGGER_TAG "datapath.sourcenode.protocolenginenode"
     76 
     77 
     78 enum pvHttpProcessingMicroState
     79 {
     80     EHttpProcessingMicroState_SendRequest,
     81     EHttpProcessingMicroState_GetResponse,
     82 };
     83 
     84 enum ProcessingStateReturnCodes
     85 {
     86     PROCESS_SUCCESS                          = 0,
     87     PROCESS_SUCCESS_END_OF_MESSAGE           = 1,
     88     PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA = 2,
     89     PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED = 3,
     90     PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT = 4,
     91     PROCESS_SUCCESS_GOT_EOS                  = 5,
     92     PROCESS_OUTPUT_PORT_IS_BUSY              = 6,
     93     PROCESS_WAIT_FOR_INCOMING_DATA           = 7,
     94 
     95     // info from server
     96     PROCESS_SERVER_RESPONSE_ERROR            = 10,  // status code of the first http response line >= 300
     97 
     98     // errors
     99     PROCESS_ERROR_FIRST                      = -100,
    100     PROCESS_GENERAL_ERROR                    = PROCESS_ERROR_FIRST - 1,
    101     PROCESS_INPUT_OUTPUT_NOT_READY           = PROCESS_ERROR_FIRST - 2,     // input(uri) or output(port or data stream) for the http parcom object is not ready
    102     PROCESS_BAD_URL                          = PROCESS_ERROR_FIRST - 3,
    103     PROCESS_MEDIA_DATA_CREATE_FAILURE        = PROCESS_ERROR_FIRST - 4,     // createMediaData() fails
    104     PROCESS_COMPOSE_HTTP_REQUEST_BUFFER_SIZE_NOT_MATCH_REQUEST_SIZE = PROCESS_ERROR_FIRST - 5,
    105     PROCESS_COMPOSE_HTTP_REQUEST_FAILURE     = PROCESS_ERROR_FIRST - 6,     // fail in composing http request, iComposer->compose() fails
    106     PROCESS_PARSE_HTTP_RESPONSE_FAILURE      = PROCESS_ERROR_FIRST - 7,     // fail in parsing response
    107     PROCESS_DATA_STREAM_OPEN_FAILURE         = PROCESS_ERROR_FIRST - 8,     // fail in data stream OpenSession()
    108     PROCESS_OUTPUT_TO_DATA_STREAM_FAILURE    = PROCESS_ERROR_FIRST - 9,     // fail in write data to data stream object
    109     PROCESS_MEMORY_ALLOCATION_FAILURE        = PROCESS_ERROR_FIRST - 10,
    110     PROCESS_HTTP_VERSION_NOT_SUPPORTED       = PROCESS_ERROR_FIRST - 11,
    111     PROCESS_ASF_HEADER_SIZE_EXCEED_LIMIT     = PROCESS_ERROR_FIRST - 12,
    112     PROCESS_CHUNKED_TRANSFER_ENCODING_NOT_SUPPORT = PROCESS_ERROR_FIRST - 13,
    113     PROCESS_TIMEOUT_SERVER_NO_RESPONCE       = PROCESS_ERROR_FIRST - 14,
    114     PROCESS_TIMEOUT_SERVER_INACTIVITY        = PROCESS_ERROR_FIRST - 15,
    115     PROCESS_CONTENT_LENGTH_NOT_MATCH         = PROCESS_ERROR_FIRST - 16,
    116     PROCESS_CONTENT_RANGE_INFO_NOT_MATCH     = PROCESS_ERROR_FIRST - 17,
    117     PROCESS_OUTPUT_TO_OUTPUT_PORT_FAILURE    = PROCESS_ERROR_FIRST - 18,
    118     PROCESS_REACHED_MAXIMUM_SIZE_LIMITATION  = PROCESS_ERROR_FIRST - 19
    119 
    120 };
    121 
    122 enum ProtocolType
    123 {
    124     PROGRESSIVE_DOWNLOAD = 0,
    125     FASTTRACK_DOWNLOAD,
    126     MS_HTTP_STREAMING
    127 };
    128 
    129 #define DEFAULT_HTTP_PORT_NUMBER        80
    130 #define NUM_PROGRESSIVE_DOWNLOAD_STATE  2
    131 #define NUM_FASTTRACK_DOWNLOAD_STATE    2
    132 #define NUM_MS_STREAMING_STATE          5
    133 #define MAX_NUM_RUNTIME_MS_STREAMING_STATE 16
    134 #define DEFAULT_VECTOR_RESERVE_NUMBER   4
    135 #define DEFAULT_CLIENT_GUID             _STRLIT_CHAR("{70CD3310-1598-CE7E-919A-456A4E6E26A0}")
    136 #define MAX_NUM_EOS_MESSAGES_FOR_SAME_REQUEST 2
    137 #define MIN_URL_LENGTH 1
    138 #define DEFAULT_MS_HTTP_STREAMING_SERVER_VERSION 9
    139 #define DEFAULT_MS_STREAMING_ACCEL_BITRATE 3670016
    140 #define DEFAULT_MS_STREAMING_ACCEL_DURATION 10000
    141 
    142 // mask for checking HTTP methods for each extension header
    143 #define MASK_HTTPGET_EXTENSIONHEADER    0x1 // bit 0 for HTTP GET
    144 #define MASK_HTTPPOST_EXTENSIONHEADER   0x2 // bit 1 for HTTP POST
    145 #define MASK_HTTPHEAD_EXTENSIONHEADER   0x4 // bit 2 for HTTP HEAD
    146 
    147 // sequence number for different type packet, used in ProtocolEngineOutputDataSideInfo
    148 #define ASF_HEADER_SEQNUM  0xffffffff
    149 #define EOS_COMMAND_SEQNUM 0xfffffffe
    150 
    151 typedef Oscl_Vector<PVMFSharedMediaMsgPtr, OsclMemAllocator> INPUT_DATA_QUEUE;
    152 typedef Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator> OUTPUT_DATA_QUEUE;
    153 
    154 #define PE_isDigit(c) ((c) >= 48 && (c) <= 57)
    155 #define PROTOCOLENGINE_REDIRECT_STATUS_CODE_START   300
    156 #define PROTOCOLENGINE_REDIRECT_STATUS_CODE_END     399
    157 
    158 
    159 ////////////////////////////////////////////////////////////////////////////////////
    160 class BasicAlloc : public Oscl_DefAlloc
    161 {
    162     public:
    163         void* allocate_fl(const uint32 size, const char *file_name, const int line_number)
    164         {
    165             void* tmp = (void*)iDefAlloc.allocate_fl(size, file_name, line_number);
    166             OSCL_ASSERT(tmp != 0);
    167             return tmp;
    168         }
    169         void* allocate(const uint32 size)
    170         {
    171             void* tmp = (void*)iDefAlloc.ALLOCATE(size);
    172             OSCL_ASSERT(tmp != 0);
    173             return tmp;
    174         }
    175         void deallocate(void* p)
    176         {
    177             iDefAlloc.deallocate(p);
    178         }
    179     private:
    180         OsclMemAllocator iDefAlloc;
    181 };
    182 
    183 template <class T> class PVDlSharedPtrAlloc: public OsclDestructDealloc
    184 {
    185     public:
    186         T* allocate()
    187         {
    188             BasicAlloc alloc;
    189             T* ptr = OSCL_PLACEMENT_NEW(alloc.allocate(sizeof(T)), T());
    190             return ptr;
    191         }
    192 
    193         virtual void destruct_and_dealloc(OsclAny* ptr)
    194         {
    195             T* tptr ;
    196             tptr = reinterpret_cast<T*>(ptr);
    197             tptr->~T();
    198             BasicAlloc alloc;
    199             alloc.deallocate(ptr);
    200         }
    201 };
    202 
    203 // To create OsclRefCounterMemFrag with the actual memory allocation
    204 #define OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE 256
    205 // for clean up object in reference counter object
    206 class OsclRefCounterMemFragCleanupDA : public OsclDestructDealloc
    207 {
    208     public:
    209         OsclRefCounterMemFragCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
    210                 iGenAlloc(in_gen_alloc) {};
    211         virtual ~OsclRefCounterMemFragCleanupDA() {};
    212 
    213         void destruct_and_dealloc(OsclAny* ptr)
    214         {
    215             iGenAlloc->deallocate(ptr);
    216         }
    217 
    218     private:
    219         Oscl_DefAlloc* iGenAlloc;
    220 };
    221 
    222 class OsclRefCounterMemFragCleanupSA : public OsclDestructDealloc
    223 {
    224     public:
    225         virtual ~OsclRefCounterMemFragCleanupSA() {};
    226         virtual void destruct_and_dealloc(OsclAny* ptr)
    227         {
    228             // no need to call destructors in this case just dealloc
    229             OsclMemAllocator alloc;
    230             alloc.deallocate(ptr);
    231         }
    232 };
    233 
    234 class OsclRefCounterMemFragAlloc
    235 {
    236     public:
    237 
    238         //! constructor
    239         OsclRefCounterMemFragAlloc(Oscl_DefAlloc* aGenAlloc = NULL) : iGenAlloc(aGenAlloc)
    240         {
    241             ;
    242         }
    243 
    244         /**
    245          * Create a OsclRefCounterMemFrag object that has the actual memory
    246          * @return the shared pointer of the OsclRefCounterMemFrag object
    247          */
    248         OsclRefCounterMemFrag allocate(uint32 requested_size = OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE)
    249         {
    250 
    251             if (!iGenAlloc) return allocateSA(requested_size);
    252 
    253             uint32 aligned_cleanup_size = oscl_mem_aligned_size(sizeof(OsclRefCounterMemFragCleanupDA));
    254             uint32 aligned_refcnt_size  = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
    255             uint32 aligned_class_size   = oscl_mem_aligned_size(sizeof(OsclMemoryFragment));
    256 
    257             uint32 total_size = aligned_refcnt_size + aligned_cleanup_size + aligned_class_size + requested_size;
    258             uint8* my_ptr = (uint8*) iGenAlloc->ALLOCATE(total_size);
    259 
    260             // 1. create clean up object (for the reference count object). Note that the first pointer should be for reference count object
    261             OsclRefCounterMemFragCleanupDA* cleanup_ptr = OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, OsclRefCounterMemFragCleanupDA(iGenAlloc));
    262 
    263             // 2. create the refcounter after the cleanup object, at the very beginning
    264             OsclRefCounter* my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, cleanup_ptr));
    265             my_ptr += (aligned_refcnt_size + aligned_cleanup_size);
    266 
    267             // 3. create OsclMemoryFragment object after refcounter object and cleanup object
    268             OsclMemoryFragment* memfrag_ptr = OSCL_PLACEMENT_NEW(my_ptr, OsclMemoryFragment);
    269             memfrag_ptr->ptr = (void*)(my_ptr + aligned_class_size);
    270             memfrag_ptr->len = requested_size;
    271 
    272             OsclRefCounterMemFrag refMemFrag(*memfrag_ptr, my_refcnt, requested_size);
    273             return refMemFrag;
    274         }
    275 
    276     private:
    277         OsclRefCounterMemFrag allocateSA(uint32 requested_size = OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE)
    278         {
    279             uint32 aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA<OsclRefCounterMemFragCleanupSA>));
    280             uint32 aligned_class_size  = oscl_mem_aligned_size(sizeof(OsclMemoryFragment));
    281             uint32 total_size = aligned_refcnt_size + aligned_class_size + requested_size;
    282 
    283             OsclMemAllocator my_alloc;
    284             uint8* my_ptr = (uint8*) my_alloc.ALLOCATE(total_size);
    285 
    286             // 1. create the reference counter object
    287             OsclRefCounter* my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA<OsclRefCounterMemFragCleanupSA>(my_ptr));
    288             my_ptr += aligned_refcnt_size;
    289 
    290             // 2. create OsclMemoryFragment object after refcounter object object
    291             OsclMemoryFragment* memfrag_ptr = OSCL_PLACEMENT_NEW(my_ptr, OsclMemoryFragment);
    292             memfrag_ptr->ptr = (void*)(my_ptr + aligned_class_size);
    293             memfrag_ptr->len = requested_size;
    294 
    295             OsclRefCounterMemFrag refMemFrag(*memfrag_ptr, my_refcnt, requested_size);
    296             return refMemFrag;
    297         }
    298 
    299     private:
    300         Oscl_DefAlloc* iGenAlloc;
    301 };
    302 
    303 class PVProtocolEngineMSHttpStreamingParams
    304 {
    305     public:
    306         PVProtocolEngineMSHttpStreamingParams()
    307         {
    308             reset();
    309             iStreamIDList.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    310             iStreamPlayBackModeList.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    311             iStreamExtensionHeaderKeys.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    312             iStreamExtensionHeaderValues.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    313             iMethodMaskForExtensionHeaders.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    314             iExtensionHeadersPurgeOnRedirect.reserve(DEFAULT_VECTOR_RESERVE_NUMBER);
    315 
    316         };
    317 
    318         ~PVProtocolEngineMSHttpStreamingParams()
    319         {
    320             reset();
    321         };
    322 
    323         // reset to default values
    324         void reset()
    325         {
    326             iStreamRate = 1;
    327             iStreamByteOffset = 0xFFFFFFFF;
    328             iStreamStartPacketNumber = 0xFFFFFFFF;
    329             iStreamStartTimeInMS = 0;
    330             iMaxStreamDurationInMS = 0x800188A3;
    331             iPacketGrouping = 0;
    332             iNumStreams = 1;
    333             iHttpVersion = 0;
    334             iPlayBackMode = 1;
    335             iMaxASFHeaderSize = PVPROTOCOLENGINE_DEFAULT_MAXIMUM_ASF_HEADER_SIZE;
    336             iAccelBitrate = DEFAULT_MS_STREAMING_ACCEL_BITRATE;
    337             iAccelDuration = DEFAULT_MS_STREAMING_ACCEL_DURATION;
    338             iMaxHttpStreamingSize = 0;
    339             iStreamIDList.clear();
    340             iStreamPlayBackModeList.clear();
    341             iUserAgent = OSCL_HeapString<OsclMemAllocator> (_STRLIT_CHAR("NSPlayer/10.0.0.3646"));
    342             iStreamExtensionHeaderKeys.clear();
    343             iStreamExtensionHeaderValues.clear();
    344             iMethodMaskForExtensionHeaders.clear();
    345             iExtensionHeadersPurgeOnRedirect.clear();
    346         }
    347 
    348         // copy constructor
    349         PVProtocolEngineMSHttpStreamingParams(const PVMFProtocolEngineNodeMSHTTPStreamingParams &x)
    350         {
    351             iStreamRate                 = x.iStreamRate;
    352             iStreamByteOffset           = x.iStreamByteOffset;
    353             iStreamStartTimeInMS        = x.iStreamStartTimeInMS;
    354             iMaxStreamDurationInMS      = x.iMaxStreamDurationInMS;
    355             iStreamStartPacketNumber    = x.iStreamStartPacketNumber;
    356             iPacketGrouping             = x.iPacketGrouping;
    357             iNumStreams                 = x.iNumStreams;
    358             iPlayBackMode               = x.iPlayBackMode;
    359             iStreamIDList               = x.iStreamIDList;
    360             iStreamPlayBackModeList     = x.iStreamPlayBackModeList;
    361         }
    362 
    363         // assignment operator
    364         PVProtocolEngineMSHttpStreamingParams& operator=(const PVMFProtocolEngineNodeMSHTTPStreamingParams& x)
    365         {
    366             iStreamRate                 = x.iStreamRate;
    367             iStreamByteOffset           = x.iStreamByteOffset;
    368             iStreamStartTimeInMS        = x.iStreamStartTimeInMS;
    369             iMaxStreamDurationInMS      = x.iMaxStreamDurationInMS;
    370             iStreamStartPacketNumber    = x.iStreamStartPacketNumber;
    371             iPacketGrouping             = x.iPacketGrouping;
    372             iNumStreams                 = x.iNumStreams;
    373             iPlayBackMode               = x.iPlayBackMode;
    374             iStreamIDList               = x.iStreamIDList;
    375             iStreamPlayBackModeList     = x.iStreamPlayBackModeList;
    376             return *this;
    377         }
    378 
    379         PVProtocolEngineMSHttpStreamingParams& operator=(const PVProtocolEngineMSHttpStreamingParams& x)
    380         {
    381             iStreamRate                 = x.iStreamRate;
    382             iStreamByteOffset           = x.iStreamByteOffset;
    383             iStreamStartTimeInMS        = x.iStreamStartTimeInMS;
    384             iMaxStreamDurationInMS      = x.iMaxStreamDurationInMS;
    385             iStreamStartPacketNumber    = x.iStreamStartPacketNumber;
    386             iPacketGrouping             = x.iPacketGrouping;
    387             iHttpVersion                = x.iHttpVersion;
    388             iPlayBackMode               = x.iPlayBackMode;
    389             iNumStreams                 = x.iNumStreams;
    390             iMaxASFHeaderSize           = x.iMaxASFHeaderSize;
    391             iUserAgent                  = x.iUserAgent;
    392             iUserID                     = x.iUserID;
    393             iUserPasswd                 = x.iUserPasswd;
    394             iStreamIDList               = x.iStreamIDList;
    395             iStreamPlayBackModeList     = x.iStreamPlayBackModeList;
    396             iStreamExtensionHeaderKeys      = x.iStreamExtensionHeaderKeys;
    397             iStreamExtensionHeaderValues    = x.iStreamExtensionHeaderValues;
    398             iMethodMaskForExtensionHeaders  = x.iMethodMaskForExtensionHeaders;
    399             iExtensionHeadersPurgeOnRedirect = x.iExtensionHeadersPurgeOnRedirect;
    400             iAccelBitrate                   = x.iAccelBitrate;
    401             iAccelDuration                  = x.iAccelDuration;
    402             iMaxHttpStreamingSize           = x.iMaxHttpStreamingSize;
    403             return *this;
    404         }
    405 
    406         uint32 iStreamRate;
    407         uint32 iStreamByteOffset;
    408         uint32 iStreamStartTimeInMS;
    409         uint32 iMaxStreamDurationInMS;
    410         uint32 iStreamStartPacketNumber;
    411         uint32 iPacketGrouping;
    412         uint32 iHttpVersion;
    413         uint32 iPlayBackMode;
    414         uint32 iNumStreams;
    415         uint32 iMaxASFHeaderSize;
    416         uint32 iAccelBitrate;
    417         uint32 iAccelDuration;
    418         uint32 iMaxHttpStreamingSize;
    419         OSCL_HeapString<OsclMemAllocator> iUserAgent;
    420         OSCL_HeapString<OsclMemAllocator> iUserID;
    421         OSCL_HeapString<OsclMemAllocator> iUserPasswd;
    422         Oscl_Vector<uint32, OsclMemAllocator> iStreamIDList;
    423         Oscl_Vector<uint32, OsclMemAllocator> iStreamPlayBackModeList;
    424         Oscl_Vector<OSCL_HeapString<OsclMemAllocator>, OsclMemAllocator> iStreamExtensionHeaderKeys;
    425         Oscl_Vector<OSCL_HeapString<OsclMemAllocator>, OsclMemAllocator> iStreamExtensionHeaderValues;
    426         Oscl_Vector<uint32, OsclMemAllocator> iMethodMaskForExtensionHeaders; // bit 0 = 1 => HTTP GET method
    427         // bit 1 = 1 => HTTP POST method
    428         Oscl_Vector<bool, OsclMemAllocator> iExtensionHeadersPurgeOnRedirect;
    429 
    430 };
    431 
    432 
    433 ////////////////////////////////////////////////////////////////////////////////////
    434 // This class encapsulates input part, the major function is getValidMediaData
    435 class pvHttpDownloadInput
    436 {
    437     public:
    438         // constructor
    439         pvHttpDownloadInput()
    440         {
    441             unbind();
    442         }
    443 
    444         // destructor
    445         virtual ~pvHttpDownloadInput()
    446         {
    447             unbind();
    448         }
    449 
    450         // reset
    451         void unbind()
    452         {
    453             iCurrentInputMediaData.Unbind();
    454         }
    455 
    456         // get valid media data from input data queue, valid => timestamp != 0xFFFFFFFF
    457         bool getValidMediaData(INPUT_DATA_QUEUE &aDataInQueue, PVMFSharedMediaDataPtr &aMediaData, bool &isEOS);
    458 
    459     private:
    460         bool isValidInput();
    461 
    462     private:
    463         PVMFSharedMediaDataPtr iCurrentInputMediaData;
    464 };
    465 
    466 ////////////////////////////////////////////////////////////////////////////////////
    467 // Wrapper class for url provides url parsing
    468 class INetURI
    469 {
    470     public:
    471         bool setURI(OSCL_String &aUri, const bool aRedirectURI = false)
    472         {
    473             iURI = OSCL_HeapString<OsclMemAllocator> (aUri.get_cstr(), aUri.get_size());
    474             iHostName.set(NULL, 0); // clear iHost
    475             iRedirectURI = aRedirectURI;
    476             return true;
    477         }
    478         OSCL_IMPORT_REF bool setURI(OSCL_wString &aUri, const bool aRedirectURI = false);
    479 
    480         // get APIs
    481         OSCL_String &getURI()
    482         {
    483             return iURI;
    484         }
    485         OSCL_String &getHost()
    486         {
    487             return iHostName;
    488         }
    489         OSCL_IMPORT_REF bool getHostAndPort(OSCL_String &aSerAdd, int32 &aSerPort);
    490         bool empty()
    491         {
    492             return (iURI.get_size() == 0);
    493         }
    494         bool isGoodUri()
    495         {
    496             OSCL_HeapString<OsclMemAllocator> tmpUrl8;
    497             int32 port;
    498             return getHostAndPort(tmpUrl8, port);
    499         }
    500         bool isUseAbsoluteURI() const
    501         {
    502             return !iUseRelativeURI;
    503         }
    504         void setUsAbsoluteURI()
    505         {
    506             iUseRelativeURI = false;
    507         }
    508         bool isRedirectURI() const
    509         {
    510             return iRedirectURI;
    511         }
    512 
    513         // constructor
    514         INetURI() : iHostPort(DEFAULT_HTTP_PORT_NUMBER), iUseRelativeURI(true), iRedirectURI(false)
    515         {
    516             ;
    517         }
    518 
    519         // assignment operator
    520         INetURI& operator=(const INetURI& x)
    521         {
    522             iURI            = x.iURI;
    523             iHostName       = x.iHostName;
    524             iHostPort       = x.iHostPort;
    525             iUseRelativeURI = x.iUseRelativeURI;
    526             iRedirectURI    = x.iRedirectURI;
    527             return *this;
    528         }
    529 
    530     private:
    531         bool parseURL(OSCL_String &aUrl8, OSCL_String &aSerAdd, int32 &aSerPort);
    532 
    533     private:
    534         OSCL_HeapString<OsclMemAllocator> iURI;
    535         OSCL_HeapString<OsclMemAllocator> iHostName;
    536         int32 iHostPort;
    537         bool iUseRelativeURI;
    538         bool iRedirectURI;
    539 };
    540 
    541 ////////////////////////////////////////////////////////////////////////////////////
    542 // This class wraps http parser and do basic parsing for every input media data at a time, and also provides
    543 // necessary information for other objects. The objects of this class are running in callback mode, i.e.
    544 // when output data in terms of each entity unit (e.g. http header or data chunk) is available, it will
    545 // notify user to retrieve the output data, since the major consideration here is input is assumed arbitrary.
    546 // Also, the output data is input data fragment queue, which needs to be provided by user. That means
    547 // HttpParsingBasicObject object doesn't want to do any memory copy. In other words, user provides this output
    548 // data queue, and this object will write data to this queue.
    549 
    550 //typedef Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator> OUTPUT_DATA_QUEUE;
    551 
    552 class HttpParsingBasicObjectObserver
    553 {
    554     public:
    555         virtual ~HttpParsingBasicObjectObserver() {}
    556 
    557         // when HttpParsingBasicObject object generates output data, it will notify the observer the data is available
    558         // aOutputQueue, data inside the queue needs to be processed/copied as soon as possible
    559         // Return value would be HttpParsingBasicObject enum return codes, especially for end of message declaration
    560         virtual int32 OutputDataAvailable(OUTPUT_DATA_QUEUE *aOutputQueue, const bool isHttpHeader) = 0;
    561 };
    562 
    563 struct BandwidthEstimationInfo
    564 {
    565     uint32 iFirstMediaDataTsPerRequest;
    566     uint32 iFirstMediaDataSizePerRequest;
    567     uint32 iTotalSizePerRequest;
    568     uint32 iLatestMediaDataTimestamp;
    569 
    570     // constructor
    571     BandwidthEstimationInfo()
    572     {
    573         clear();
    574     }
    575 
    576     // clear()
    577     void clear()
    578     {
    579         iFirstMediaDataTsPerRequest     = 0;
    580         iFirstMediaDataSizePerRequest   = 0;
    581         iTotalSizePerRequest            = 0;
    582         iLatestMediaDataTimestamp       = 0;
    583         iPrevHttpHeaderParsed           = false;
    584         iMediaDataFragPtr               = NULL;
    585     }
    586 
    587     // update
    588     void update(PVMFSharedMediaDataPtr &aMediaData, const bool aHttpHeaderParsed = true)
    589     {
    590         if (!aHttpHeaderParsed) return;
    591 
    592         // aHttpHeaderParsed=true, HTTP header should be already parsed
    593         OsclRefCounterMemFrag fragIn;
    594         aMediaData->getMediaFragment(0, fragIn);
    595         if (!iPrevHttpHeaderParsed)
    596         {
    597             iFirstMediaDataTsPerRequest = aMediaData->getTimestamp();
    598             iFirstMediaDataSizePerRequest = fragIn.getMemFragSize();
    599             iTotalSizePerRequest = 0;
    600             iLatestMediaDataTimestamp = 0;
    601             iPrevHttpHeaderParsed = true;
    602         }
    603 
    604         // update iLatestMediaDataTimestamp
    605         if (iLatestMediaDataTimestamp < aMediaData->getTimestamp())
    606         {
    607             iLatestMediaDataTimestamp = aMediaData->getTimestamp();
    608         }
    609         // update iTotalSizePerRequest
    610         if (iMediaDataFragPtr != (uint8*)fragIn.getMemFragPtr())
    611         {
    612             iTotalSizePerRequest += fragIn.getMemFragSize();
    613             iMediaDataFragPtr = (uint8*)fragIn.getMemFragPtr();
    614         }
    615     }
    616 
    617 private:
    618     bool iPrevHttpHeaderParsed;
    619     uint8 *iMediaDataFragPtr;
    620 
    621 };
    622 
    623 class HttpParsingBasicObject
    624 {
    625     public:
    626         // get/query functions
    627         uint32 getContentLength(const bool aRefresh = false)
    628         {
    629             if (aRefresh) iParser->getContentInfo(iContentInfo);
    630             return iContentInfo.iContentLength;
    631         }
    632         uint32 getDownloadSize()
    633         {
    634             return iTotalDLHttpBodySize;
    635         }
    636         OSCL_IMPORT_REF void setDownloadSize(const uint32 aInitialSize = 0);
    637 
    638         uint32 getTotalHttpStreamingSize()
    639         {
    640             return iTotalHttpStreamingSize;
    641         }
    642         void resetTotalHttpStreamingSize()
    643         {
    644             iTotalHttpStreamingSize = 0;
    645         }
    646 
    647         uint32 getStatusCode()
    648         {
    649             return (iParser == NULL ? 0 : iParser->getHTTPStatusCode());
    650         }
    651         HTTPParser *getHttpParser()
    652         {
    653             return iParser;
    654         }
    655         bool isHttpHeaderParsed()
    656         {
    657             return iHttpHeaderParsed;
    658         }
    659         OSCL_IMPORT_REF bool getRedirectURI(OSCL_String &aRedirectUri);
    660         OSCL_IMPORT_REF bool getContentType(OSCL_String &aContentType);
    661         OSCL_IMPORT_REF bool getAuthenInfo(OSCL_String &aRealm);
    662         OSCL_IMPORT_REF bool isServerSupportBasicAuthentication();
    663         OSCL_IMPORT_REF bool isServerSendAuthenticationHeader();
    664         OSCL_IMPORT_REF void getBasicPtr(const StrPtrLen aAuthenValue, uint32 &length);
    665         OSCL_IMPORT_REF void getRealmPtr(const char *&ptrRealm, uint32 &len, uint32 &length);
    666 
    667         uint32 getServerVersionNumber()
    668         {
    669             return iServerVersionNumber;
    670         }
    671         OSCL_IMPORT_REF int32 isNewContentRangeInfoMatchingCurrentOne(const uint32 aPrevContentLength);
    672         bool isDownloadReallyHappen() const
    673         {
    674             return (iTotalDLHttpBodySize - iTotalDLSizeForPrevEOS > 0);
    675         }
    676         uint32 getLatestMediaDataTimestamp() const
    677         {
    678             return iLatestMediaDataTimestamp;
    679         }
    680         BandwidthEstimationInfo *getBandwidthEstimationInfo()
    681         {
    682             return &iBWEstInfo;
    683         }
    684         void setNumRetry(const uint32 aNumRetry = MAX_NUM_EOS_MESSAGES_FOR_SAME_REQUEST)
    685         {
    686             iNumRetry = aNumRetry;
    687         }
    688 
    689         // return false if (aObserver==NULL || outputQueue==NULL)
    690         bool registerObserverAndOutputQueue(HttpParsingBasicObjectObserver *aObserver, OUTPUT_DATA_QUEUE *aOutputQueue)
    691         {
    692             iObserver = aObserver;
    693             iOutputQueue = aOutputQueue;
    694             return (iObserver != NULL && iOutputQueue != NULL);
    695         }
    696 
    697         // see the following enum definition to get to know the return values
    698         OSCL_IMPORT_REF int32 parseResponse(INPUT_DATA_QUEUE &aDataQueue);
    699 
    700         // return codes for parseResponse function
    701         enum PARSE_RETURN_CODES
    702         {
    703             PARSE_SUCCESS                        = 0,
    704             PARSE_HEADER_AVAILABLE               = 1,   // HTTP header is parsed
    705             PARSE_SUCCESS_END_OF_MESSAGE         = 2,   // success with end of the message (get data with the size of content-length)
    706             PARSE_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA = 3, // success with end of the message (get data with the size of content-length), but with extran data appended
    707             PARSE_SUCCESS_END_OF_INPUT           = 4,   // success with end of the input
    708             PARSE_NEED_MORE_DATA                 = 5,   // no ouput or could have output, need more data
    709             PARSE_STATUS_LINE_SHOW_NOT_SUCCESSFUL = 6,  // parse the first http status line,
    710             // got status code >= 300, 3xx=>redirection, 4xx=>client error, 5xx=>server error
    711             // note that this is return code when parser just finishes parsing the first line,
    712             // user can continue calling parse function to get the complete http header
    713 
    714             PARSE_NO_INPUT_DATA                  = 10,  // input data queue has no data or eos
    715             PARSE_EOS_INPUT_DATA                 = 11,
    716 
    717             // errors
    718             PARSE_GENERAL_ERROR                  = -1,
    719             PARSE_SYNTAX_ERROR                   = -2,  // syntax is not understandable
    720             PARSE_HTTP_VERSION_NOT_SUPPORTED     = -3,
    721             PARSE_TRANSFER_ENCODING_NOT_SUPPORTED = -4,
    722             PARSE_CONTENT_RANGE_INFO_NOT_MATCH   = -5,  // range info in the request doesn't match content-range info from the response
    723             PARSE_CONTENT_LENGTH_NOT_MATCH       = -6,  // content-length info from the response doesn't match from the content-length in config file
    724             PARSE_BAD_URL                        = -7   // bad url causes server to shut down the connection, so view first (server)
    725             // response (from socket node) being EOS as bad url
    726         };
    727 
    728         // reset for parsing each response
    729         void reset()
    730         {
    731             if (iParser) iParser->reset();
    732             iInput.unbind();
    733             iContentInfo.clear();
    734             iBWEstInfo.clear();
    735             iHttpHeaderParsed = false;
    736             iTotalDLHttpBodySize = 0;
    737             iLatestMediaDataTimestamp = 0;
    738         }
    739 
    740         // reset for parsing multiple responses for each protocol state or node state
    741         void resetForBadConnectionDetection()
    742         {
    743             iNumEOSMessagesAfterRequest = 0;
    744             iTotalDLSizeAtCurrEOS  = 0;
    745             iTotalDLSizeForPrevEOS = 0;
    746         }
    747 
    748         // factory method
    749         OSCL_IMPORT_REF static HttpParsingBasicObject *create();
    750         // destructor
    751         virtual ~HttpParsingBasicObject()
    752         {
    753             iLogger = NULL;
    754             iDataPathLogger = NULL;
    755             iClockLogger = NULL;
    756             OSCL_DELETE(iParser);
    757         }
    758 
    759     private:
    760         // constructor
    761         HttpParsingBasicObject() :  iParser(NULL),
    762                 iObserver(NULL),
    763                 iOutputQueue(NULL),
    764                 iNumRetry(MAX_NUM_EOS_MESSAGES_FOR_SAME_REQUEST)
    765         {
    766             iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode");
    767             iDataPathLogger = PVLogger::GetLoggerObject("protocolenginenode.protocolengine");
    768             iDataPathErrLogger = PVLogger::GetLoggerObject("datapath.sourcenode.protocolenginenode");
    769             iClockLogger = PVLogger::GetLoggerObject("clock");
    770             iTotalHttpStreamingSize = 0;
    771             reset();
    772         }
    773 
    774         // called by create()
    775         bool construct();
    776         // return code: PARSE_SUCCESS for new data, PARSE_EOS_INPUT_DATA for eos, PARSE_NO_INPUT_DATA for no input data
    777         int32 getNextMediaData(INPUT_DATA_QUEUE &aDataInQueue, PVMFSharedMediaDataPtr &aMediaData);
    778         // EOS input can be indicated as the sign of bad request (the request just sent is bad request, especially badk URL)
    779         int32 validateEOSInput(int32 parsingStatus);
    780         // return total size of all data in entityUnit, ~0=0xffffffff means error
    781         bool saveOutputData(RefCountHTTPEntityUnit &entityUnit, OUTPUT_DATA_QUEUE &aOutputData, uint32 &aTotalEntityDataSize);
    782         // return codes conversion, may send out callback for end of message or end of input cases
    783         int32 checkParsingDone(const int32 parsingStatus);
    784         // extract the server version number from server field of a HTTP response
    785         void extractServerVersionNum();
    786         // called by getNextMediaData()
    787         bool isRedirectResponse();
    788 
    789         void clearInputOutput()
    790         {
    791             iInput.unbind();
    792             if (iOutputQueue) iOutputQueue->clear();
    793         }
    794         friend class HttpParsingBasicObjectAutoCleanup;
    795 
    796     private:
    797         HTTPParser   *iParser;
    798         pvHttpDownloadInput iInput;
    799         HTTPContentInfo iContentInfo;
    800         bool iHttpHeaderParsed;
    801         HttpParsingBasicObjectObserver *iObserver;
    802         OUTPUT_DATA_QUEUE *iOutputQueue;
    803         uint32 iServerVersionNumber;
    804         uint32 iTotalDLHttpBodySize;
    805         uint32 iNumEOSMessagesAfterRequest;// number of continuous EOS messages received after sending request
    806         uint32 iTotalDLSizeForPrevEOS; // for detecting download size change between two adjacent EOSs or start and first EOS
    807         uint32 iTotalDLSizeAtCurrEOS;
    808         uint32  iLatestMediaDataTimestamp;
    809         BandwidthEstimationInfo iBWEstInfo;
    810         uint32 iNumRetry;
    811 
    812         PVLogger* iLogger;
    813         PVLogger* iDataPathLogger;
    814         PVLogger* iDataPathErrLogger;
    815         PVLogger* iClockLogger;
    816 
    817         uint32 iTotalHttpStreamingSize;
    818 };
    819 
    820 
    821 // A simple container class to do HttpParsingBasicObject::clearInputOutput automatically
    822 class HttpParsingBasicObjectAutoCleanup
    823 {
    824     public:
    825         HttpParsingBasicObjectAutoCleanup(HttpParsingBasicObject *aParser) : iParser(aParser)
    826         {
    827             ;
    828         }
    829         ~HttpParsingBasicObjectAutoCleanup()
    830         {
    831             if (iParser) iParser->clearInputOutput();
    832         }
    833 
    834     private:
    835         HttpParsingBasicObject *iParser;
    836 };
    837 
    838 #endif
    839 
    840