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