• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
allocate_fl(const uint32 size,const char * file_name,const int line_number)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         }
allocate(const uint32 size)169         void* allocate(const uint32 size)
170         {
171             void* tmp = (void*)iDefAlloc.ALLOCATE(size);
172             OSCL_ASSERT(tmp != 0);
173             return tmp;
174         }
deallocate(void * p)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:
allocate()186         T* allocate()
187         {
188             BasicAlloc alloc;
189             T* ptr = OSCL_PLACEMENT_NEW(alloc.allocate(sizeof(T)), T());
190             return ptr;
191         }
192 
destruct_and_dealloc(OsclAny * ptr)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:
OsclRefCounterMemFragCleanupDA(Oscl_DefAlloc * in_gen_alloc)209         OsclRefCounterMemFragCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
210                 iGenAlloc(in_gen_alloc) {};
~OsclRefCounterMemFragCleanupDA()211         virtual ~OsclRefCounterMemFragCleanupDA() {};
212 
destruct_and_dealloc(OsclAny * ptr)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:
~OsclRefCounterMemFragCleanupSA()225         virtual ~OsclRefCounterMemFragCleanupSA() {};
destruct_and_dealloc(OsclAny * ptr)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
iGenAlloc(aGenAlloc)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:
PVProtocolEngineMSHttpStreamingParams()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 
~PVProtocolEngineMSHttpStreamingParams()318         ~PVProtocolEngineMSHttpStreamingParams()
319         {
320             reset();
321         };
322 
323         // reset to default values
reset()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
PVProtocolEngineMSHttpStreamingParams(const PVMFProtocolEngineNodeMSHTTPStreamingParams & x)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
pvHttpDownloadInput()439         pvHttpDownloadInput()
440         {
441             unbind();
442         }
443 
444         // destructor
~pvHttpDownloadInput()445         virtual ~pvHttpDownloadInput()
446         {
447             unbind();
448         }
449 
450         // reset
unbind()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
getURI()481         OSCL_String &getURI()
482         {
483             return iURI;
484         }
getHost()485         OSCL_String &getHost()
486         {
487             return iHostName;
488         }
489         OSCL_IMPORT_REF bool getHostAndPort(OSCL_String &aSerAdd, int32 &aSerPort);
empty()490         bool empty()
491         {
492             return (iURI.get_size() == 0);
493         }
isGoodUri()494         bool isGoodUri()
495         {
496             OSCL_HeapString<OsclMemAllocator> tmpUrl8;
497             int32 port;
498             return getHostAndPort(tmpUrl8, port);
499         }
isUseAbsoluteURI()500         bool isUseAbsoluteURI() const
501         {
502             return !iUseRelativeURI;
503         }
setUsAbsoluteURI()504         void setUsAbsoluteURI()
505         {
506             iUseRelativeURI = false;
507         }
isRedirectURI()508         bool isRedirectURI() const
509         {
510             return iRedirectURI;
511         }
512 
513         // constructor
INetURI()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:
~HttpParsingBasicObjectObserver()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
BandwidthEstimationInfoBandwidthEstimationInfo571     BandwidthEstimationInfo()
572     {
573         clear();
574     }
575 
576     // clear()
clearBandwidthEstimationInfo577     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         }
getDownloadSize()632         uint32 getDownloadSize()
633         {
634             return iTotalDLHttpBodySize;
635         }
636         OSCL_IMPORT_REF void setDownloadSize(const uint32 aInitialSize = 0);
637 
getTotalHttpStreamingSize()638         uint32 getTotalHttpStreamingSize()
639         {
640             return iTotalHttpStreamingSize;
641         }
resetTotalHttpStreamingSize()642         void resetTotalHttpStreamingSize()
643         {
644             iTotalHttpStreamingSize = 0;
645         }
646 
getStatusCode()647         uint32 getStatusCode()
648         {
649             return (iParser == NULL ? 0 : iParser->getHTTPStatusCode());
650         }
getHttpParser()651         HTTPParser *getHttpParser()
652         {
653             return iParser;
654         }
isHttpHeaderParsed()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 
getServerVersionNumber()667         uint32 getServerVersionNumber()
668         {
669             return iServerVersionNumber;
670         }
671         OSCL_IMPORT_REF int32 isNewContentRangeInfoMatchingCurrentOne(const uint32 aPrevContentLength);
isDownloadReallyHappen()672         bool isDownloadReallyHappen() const
673         {
674             return (iTotalDLHttpBodySize - iTotalDLSizeForPrevEOS > 0);
675         }
getLatestMediaDataTimestamp()676         uint32 getLatestMediaDataTimestamp() const
677         {
678             return iLatestMediaDataTimestamp;
679         }
getBandwidthEstimationInfo()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)
registerObserverAndOutputQueue(HttpParsingBasicObjectObserver * aObserver,OUTPUT_DATA_QUEUE * aOutputQueue)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
reset()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
resetForBadConnectionDetection()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
~HttpParsingBasicObject()751         virtual ~HttpParsingBasicObject()
752         {
753             iLogger = NULL;
754             iDataPathLogger = NULL;
755             iClockLogger = NULL;
756             OSCL_DELETE(iParser);
757         }
758 
759     private:
760         // constructor
HttpParsingBasicObject()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 
clearInputOutput()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:
HttpParsingBasicObjectAutoCleanup(HttpParsingBasicObject * aParser)825         HttpParsingBasicObjectAutoCleanup(HttpParsingBasicObject *aParser) : iParser(aParser)
826         {
827             ;
828         }
~HttpParsingBasicObjectAutoCleanup()829         ~HttpParsingBasicObjectAutoCleanup()
830         {
831             if (iParser) iParser->clearInputOutput();
832         }
833 
834     private:
835         HttpParsingBasicObject *iParser;
836 };
837 
838 #endif
839 
840