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 #include "pvmf_protocol_engine_node.h" 19 #include "pvmf_protocol_engine_command_format_ids.h" 20 #include "pvmf_protocolengine_node_tunables.h" 21 #include "pvlogger.h" 22 #include "oscl_utf8conv.h" 23 24 25 /** 26 ////////////////////////////////////////////////// 27 // Node Constructor & Destructor 28 ////////////////////////////////////////////////// 29 */ 30 31 PVMFProtocolEngineNode::PVMFProtocolEngineNode(int32 aPriority) : 32 OsclTimerObject(aPriority, "PVMFProtocolEngineNode"), 33 iStatusCode(0), 34 iProcessingState(ProcessingState_Idle), 35 iInterfacingObjectContainer(NULL), 36 iProtocol(NULL), 37 iProtocolContainer(NULL), 38 iProtocolContainerFactory(NULL), 39 iNodeOutput(NULL), 40 iCurrEventHandler(NULL), 41 iCfgFileContainer(NULL), 42 iDownloadSource(NULL), 43 iDownloadControl(NULL), 44 iDownloadProgess(NULL), 45 iSDPInfo(NULL), 46 iUserAgentField(NULL), 47 iEventReport(NULL), 48 iPortConfigFSInfoAlloc(NULL), 49 iPortConfigMemPool(PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM, OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE), 50 iNodeTimer(NULL), 51 iPortInForData(NULL), 52 iPortInForLogging(NULL), 53 iPortOut(NULL), 54 iCurrentCmdId(0), 55 iCmdRespPort(NULL), 56 iLogger(NULL), 57 iDataPathLogger(NULL), 58 iClockLogger(NULL), 59 iExtensionRefCount(0), 60 iCurrentDataStreamCmdId(0) 61 { 62 int32 err = 0; 63 OSCL_TRY(err, 64 //Create the input command queue. Use a reserve to avoid lots of 65 //dynamic memory allocation. 66 iInputCommands.Construct(PVMF_PROTOCOLENGINE_NODE_COMMAND_ID_START, PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE); 67 68 //Create the "current command" queue. It will only contain one 69 //command at a time, so use a reserve of 1. 70 iCurrentCommand.Construct(0, 1); 71 72 //Create the port vector. 73 iPortVector.Construct(PVMF_PROTOCOLENGINE_NODE_PORT_VECTOR_RESERVE); 74 75 //Set the node capability data. 76 //This node can support an unlimited number of ports. 77 iCapability.iCanSupportMultipleInputPorts = false; 78 iCapability.iCanSupportMultipleOutputPorts = false; 79 iCapability.iHasMaxNumberOfPorts = false; 80 iCapability.iMaxNumberOfPorts = 0;//no maximum 81 iCapability.iInputFormatCapability.push_back(PVMF_MIME_INET_TCP); 82 83 // create the internal data queue 84 iDataInQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES); 85 iInternalEventQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES); 86 ); 87 88 if (err) 89 { 90 //if a leave happened, cleanup and re-throw the error 91 iInputCommands.clear(); 92 iCurrentCommand.clear(); 93 iPortVector.clear(); 94 iCapability.iInputFormatCapability.clear(); 95 iCapability.iOutputFormatCapability.clear(); 96 iDataInQueue.clear(); 97 iInternalEventQueue.clear(); 98 OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface); 99 OSCL_CLEANUP_BASE_CLASS(OsclTimerObject); 100 OSCL_LEAVE(err); 101 } 102 103 for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++) iEventHandlers[i] = NULL; 104 } 105 106 PVMFProtocolEngineNode::~PVMFProtocolEngineNode() 107 { 108 //thread logoff 109 if (IsAdded()) RemoveFromScheduler(); 110 111 112 //Cleanup commands 113 //The command queues are self-deleting, but we want to 114 //notify the observer of unprocessed commands. 115 while (!iCurrentCommand.empty()) 116 { 117 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure); 118 } 119 120 while (!iInputCommands.empty()) 121 { 122 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure); 123 } 124 125 Clear(true); 126 } 127 128 /** 129 ////////////////////////////////////////////////// 130 // Public Node API implementation 131 ////////////////////////////////////////////////// 132 */ 133 134 135 PVMFStatus PVMFProtocolEngineNode::ThreadLogon() 136 { 137 LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogon()")); 138 switch (iInterfaceState) 139 { 140 case EPVMFNodeCreated: 141 if (!IsAdded()) AddToScheduler(); 142 iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode"); 143 iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG); 144 iClockLogger = PVLogger::GetLoggerObject("clock"); 145 SetState(EPVMFNodeIdle); 146 return PVMFSuccess; 147 148 default: 149 return PVMFErrInvalidState; 150 } 151 } 152 153 154 PVMFStatus PVMFProtocolEngineNode::ThreadLogoff() 155 { 156 LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogoff()")); 157 switch (iInterfaceState) 158 { 159 case EPVMFNodeIdle: 160 if (IsAdded()) RemoveFromScheduler(); 161 162 iLogger = NULL; 163 iDataPathLogger = NULL; 164 iClockLogger = NULL; 165 SetState(EPVMFNodeCreated); 166 return PVMFSuccess; 167 168 default: 169 return PVMFErrInvalidState; 170 } 171 } 172 173 174 PVMFStatus PVMFProtocolEngineNode::GetCapability(PVMFNodeCapability& aNodeCapability) 175 { 176 OSCL_UNUSED_ARG(aNodeCapability); 177 LOGINFO((0, "PVMFProtocolEngineNode::GetCapability()")); 178 //aNodeCapability=iCapability; 179 return PVMFSuccess; 180 } 181 182 183 PVMFPortIter* PVMFProtocolEngineNode::GetPorts(const PVMFPortFilter* aFilter) 184 { 185 LOGINFO((0, "PVMFProtocolEngineNode::GetPorts()")); 186 OSCL_UNUSED_ARG(aFilter);//port filter is not implemented. 187 iPortVector.Reset(); 188 return &iPortVector; 189 } 190 191 192 PVMFCommandId PVMFProtocolEngineNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType, 193 Oscl_Vector<PVUuid, PVMFProtocolEngineNodeAllocator>& aUuids, 194 bool aExactUuidsOnly, const OsclAny* aContext) 195 { 196 LOGINFO((0, "PVMFProtocolEngineNode::QueryUUID()")); 197 PVMFProtocolEngineNodeCommand cmd; 198 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext); 199 return QueueCommandL(cmd); 200 } 201 202 203 PVMFCommandId PVMFProtocolEngineNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext) 204 { 205 LOGINFO((0, "PVMFProtocolEngineNode::QueryInterface()")); 206 PVMFProtocolEngineNodeCommand cmd; 207 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext); 208 return QueueCommandL(cmd); 209 } 210 211 212 PVMFCommandId PVMFProtocolEngineNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext) 213 { 214 OSCL_UNUSED_ARG(aPortConfig); 215 LOGINFO((0, "PVMFProtocolEngineNode::RequestPort()")); 216 PVMFProtocolEngineNodeCommand cmd; 217 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aContext); 218 return QueueCommandL(cmd); 219 } 220 221 222 PVMFCommandId PVMFProtocolEngineNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext) 223 { 224 LOGINFO((0, "PVMFProtocolEngineNode::ReleasePort()")); 225 PVMFProtocolEngineNodeCommand cmd; 226 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext); 227 return QueueCommandL(cmd); 228 } 229 230 231 PVMFCommandId PVMFProtocolEngineNode::Init(PVMFSessionId s, const OsclAny* aContext) 232 { 233 LOGINFO((0, "PVMFProtocolEngineNode::Init()")); 234 PVMFProtocolEngineNodeCommand cmd; 235 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext); 236 return QueueCommandL(cmd); 237 } 238 239 240 PVMFCommandId PVMFProtocolEngineNode::Prepare(PVMFSessionId s, const OsclAny* aContext) 241 { 242 LOGINFO((0, "PVMFProtocolEngineNode::Prepare()")); 243 PVMFProtocolEngineNodeCommand cmd; 244 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext); 245 return QueueCommandL(cmd); 246 } 247 248 249 PVMFCommandId PVMFProtocolEngineNode::Start(PVMFSessionId s, const OsclAny* aContext) 250 { 251 LOGINFO((0, "PVMFProtocolEngineNode::Start()")); 252 253 PVMFProtocolEngineNodeCommand cmd; 254 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext); 255 return QueueCommandL(cmd); 256 } 257 258 259 PVMFCommandId PVMFProtocolEngineNode::Stop(PVMFSessionId s, const OsclAny* aContext) 260 { 261 LOGINFO((0, "PVMFProtocolEngineNode::Stop()")); 262 263 PVMFProtocolEngineNodeCommand cmd; 264 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext); 265 return QueueCommandL(cmd); 266 } 267 268 269 PVMFCommandId PVMFProtocolEngineNode::Flush(PVMFSessionId s, const OsclAny* aContext) 270 { 271 LOGINFO((0, "PVMFProtocolEngineNode::Flush()")); 272 PVMFProtocolEngineNodeCommand cmd; 273 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext); 274 return QueueCommandL(cmd); 275 } 276 277 278 PVMFCommandId PVMFProtocolEngineNode::Pause(PVMFSessionId s, const OsclAny* aContext) 279 { 280 LOGINFO((0, "PVMFProtocolEngineNode::Pause()")); 281 282 PVMFProtocolEngineNodeCommand cmd; 283 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext); 284 return QueueCommandL(cmd); 285 } 286 287 288 PVMFCommandId PVMFProtocolEngineNode::Reset(PVMFSessionId s, const OsclAny* aContext) 289 { 290 LOGINFO((0, "PVMFProtocolEngineNode::Reset()")); 291 PVMFProtocolEngineNodeCommand cmd; 292 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext); 293 return QueueCommandL(cmd); 294 } 295 296 297 PVMFCommandId PVMFProtocolEngineNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext) 298 { 299 LOGINFO((0, "PVMFProtocolEngineNode::CancelAllCommands()")); 300 PVMFProtocolEngineNodeCommand cmd; 301 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext); 302 return QueueCommandL(cmd); 303 } 304 305 306 PVMFCommandId PVMFProtocolEngineNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext) 307 { 308 LOGINFO((0, "PVMFProtocolEngineNode::CancelCommand()")); 309 PVMFProtocolEngineNodeCommand cmd; 310 cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext); 311 return QueueCommandL(cmd); 312 } 313 314 315 PVMFCommandId PVMFProtocolEngineNode::Seek(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSeek, OsclAny* aContext) 316 { 317 LOGINFO((0, "PVMFProtocolEngineNode::Seek()")); 318 PVMFProtocolEngineNodeCommand cmd; 319 cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_SEEK, aNPTInMS, aFirstSeqNumAfterSeek, aContext); 320 return QueueCommandL(cmd); 321 } 322 323 PVMFCommandId PVMFProtocolEngineNode::BitstreamSwitch(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSwitch, OsclAny* aContext) 324 { 325 LOGINFO((0, "PVMFProtocolEngineNode::BitstreamSwitch()")); 326 PVMFProtocolEngineNodeCommand cmd; 327 cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH, aNPTInMS, aFirstSeqNumAfterSwitch, aContext); 328 return QueueCommandL(cmd); 329 } 330 331 PvmiDataStreamCommandId PVMFProtocolEngineNode::DataStreamRequest(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID, 332 OsclAny* aRequestData, OsclAny* aContextData) 333 { 334 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequest()")); 335 336 // This is for asynchronous requests, such as repositioning 337 // Caller's SourceRequestCompleted will be called 338 if (aRequestID != PVDS_REQUEST_REPOSITION) 339 { 340 // currently we only define reposition request 341 OSCL_LEAVE(OsclErrArgument); 342 return 0; 343 } 344 345 PVMFProtocolEngineNodeCommand cmd; // internal command, use 0 as session id. 346 cmd.PVMFProtocolEngineNodeCommand::Construct((PVMFSessionId)0, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION, 347 aSessionID, aRequestID, aRequestData, iCurrentDataStreamCmdId, aContextData); 348 QueueCommandL(cmd); 349 return iCurrentDataStreamCmdId++; 350 } 351 352 PvmiDataStreamStatus PVMFProtocolEngineNode::DataStreamRequestSync(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID, OsclAny* aRequestData) 353 { 354 OSCL_UNUSED_ARG(aSessionID); 355 // This is for synchronous requests, such as returning memory fragments 356 PvmiDataStreamStatus status = PVDS_FAILURE; 357 switch (aRequestID) 358 { 359 case PVDS_REQUEST_MEM_FRAG_RELEASED: 360 if (aRequestData != NULL) 361 { 362 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequestSync, got PVDS_REQUEST_MEM_FRAG_RELEASED request")); 363 OsclRefCounterMemFrag* frag = ((OsclRefCounterMemFrag*)aRequestData); 364 if (iNodeOutput->releaseMemFrag(frag)) status = PVDS_SUCCESS; 365 } 366 break; 367 368 default: 369 break; 370 } 371 372 return status; 373 } 374 375 bool PVMFProtocolEngineNode::IsRepositioningRequestPending() 376 { 377 PVMFProtocolEngineNodeCommand *pInputCmd = FindCmd(iInputCommands, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION); 378 PVMFProtocolEngineNodeCommand *pPendingCmd = FindCmd(iCurrentCommand, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION); 379 380 return (pInputCmd || pPendingCmd); 381 } 382 383 void PVMFProtocolEngineNode::addRef() 384 { 385 ++iExtensionRefCount; 386 } 387 388 void PVMFProtocolEngineNode::removeRef() 389 { 390 --iExtensionRefCount; 391 } 392 393 bool PVMFProtocolEngineNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 394 { 395 if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID) 396 { 397 PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this); 398 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 399 addRef(); 400 return true; 401 } 402 else if (uuid == PVMIDatastreamuserInterfaceUuid) 403 { 404 PVMIDatastreamuserInterface* myInterface = OSCL_STATIC_CAST(PVMIDatastreamuserInterface*, this); 405 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 406 addRef(); 407 return true; 408 } 409 else if (uuid == KPVMFProtocolEngineNodeExtensionUuid) 410 { 411 PVMFProtocolEngineNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeExtensionInterface*, this); 412 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 413 addRef(); 414 return true; 415 } 416 else if (uuid == PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID) 417 { 418 PVMFDownloadProgressInterface* myInterface = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this); 419 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 420 addRef(); 421 return true; 422 } 423 else if (uuid == KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid) 424 { 425 PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface*, this); 426 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 427 addRef(); 428 return true; 429 } 430 else if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID) 431 { 432 if (!iInterfacingObjectContainer || iInterfacingObjectContainer->getDownloadFormat() != PVMF_MIME_DATA_SOURCE_PVX_FILE) return false; 433 PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this); 434 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 435 addRef(); 436 return true; 437 } 438 439 return false; 440 } 441 442 /** 443 //This routine is called by various command APIs to queue an 444 //asynchronous command for processing by the command handler AO. 445 //This function may leave if the command can't be queued due to 446 //memory allocation failure. 447 */ 448 PVMFCommandId PVMFProtocolEngineNode::QueueCommandL(PVMFProtocolEngineNodeCommand& aCmd) 449 { 450 PVMFCommandId id = iInputCommands.AddL(aCmd); 451 452 //wakeup the AO 453 RunIfNotReady(); 454 return id; 455 } 456 457 PVMFProtocolEngineNodeCommand* PVMFProtocolEngineNode::FindCmd(PVMFProtocolEngineNodeCmdQ &aCmdQueue, int32 aCmdId) 458 { 459 for (uint32 i = 0; i < aCmdQueue.size(); i++) 460 { 461 if (aCmdQueue[i].iCmd == aCmdId) return &aCmdQueue[i]; 462 } 463 return NULL; 464 } 465 466 /** 467 ///////////////////////////////////////////////////// 468 // Asynchronous Command processing routines. 469 // These routines are all called under the AO. 470 ///////////////////////////////////////////////////// 471 */ 472 473 /** 474 //Called by the command handler AO to process a command from 475 //the input queue. 476 //Return true if a command was processed, false if the command 477 //processor is busy and can't process another command now. 478 */ 479 bool PVMFProtocolEngineNode::ProcessCommand(PVMFProtocolEngineNodeCommand& aCmd) 480 { 481 //normally this node will not start processing one command 482 //until the prior one is finished. However, a hi priority 483 //command such as Cancel must be able to interrupt a command 484 //in progress. 485 if (!iCurrentCommand.empty() && !aCmd.hipri()) 486 { 487 return false; // keep waiting 488 } 489 490 PVMFStatus cmdStatus; 491 switch (aCmd.iCmd) 492 { 493 case PVMF_GENERIC_NODE_REQUESTPORT: 494 cmdStatus = DoRequestPort(aCmd); 495 break; 496 497 case PVMF_GENERIC_NODE_RELEASEPORT: 498 cmdStatus = DoReleasePort(aCmd); 499 break; 500 501 case PVMF_GENERIC_NODE_QUERYUUID: 502 cmdStatus = DoQueryUuid(aCmd); 503 break; 504 505 case PVMF_GENERIC_NODE_QUERYINTERFACE: 506 cmdStatus = DoQueryInterface(aCmd); 507 break; 508 509 case PVMF_GENERIC_NODE_INIT: 510 cmdStatus = DoInit(aCmd); 511 break; 512 513 case PVMF_GENERIC_NODE_PREPARE: 514 cmdStatus = DoPrepare(aCmd); 515 break; 516 517 case PVMF_GENERIC_NODE_START: 518 cmdStatus = DoStart(aCmd); 519 break; 520 521 case PVMF_GENERIC_NODE_STOP: 522 cmdStatus = DoStop(aCmd); 523 break; 524 525 case PVMF_GENERIC_NODE_FLUSH: 526 cmdStatus = DoFlush(aCmd); 527 break; 528 529 case PVMF_GENERIC_NODE_PAUSE: 530 cmdStatus = DoPause(aCmd); 531 break; 532 533 case PVMF_GENERIC_NODE_RESET: 534 cmdStatus = DoReset(aCmd); 535 break; 536 537 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS: 538 cmdStatus = DoCancelAllCommands(aCmd); 539 break; 540 541 case PVMF_GENERIC_NODE_CANCELCOMMAND: 542 cmdStatus = DoCancelCommand(aCmd); 543 break; 544 545 case PVPROTOCOLENGINE_NODE_CMD_SEEK: 546 cmdStatus = DoSeek(aCmd); 547 break; 548 549 case PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH: 550 cmdStatus = DoBitsteamSwitch(aCmd); 551 break; 552 553 case PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION: 554 cmdStatus = DoReposition(aCmd); 555 break; 556 557 default://unknown command type. Assert and treat as not supported error 558 OSCL_ASSERT(false); 559 CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported); 560 cmdStatus = PVMFErrNotSupported; 561 break; 562 } 563 564 //If completion is pending, move the command from the input queue to the current command. 565 //This is necessary since the input queue could get rearranged by new commands coming in. 566 if (cmdStatus == PVMFPending) 567 { 568 iCurrentCommand.StoreL(aCmd); 569 iInputCommands.Erase(&aCmd); 570 } 571 572 return true; 573 } 574 575 /** 576 //The various command handlers call this when a command is complete. 577 */ 578 int32 PVMFProtocolEngineNode::HandleCommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ, 579 PVMFProtocolEngineNodeCommand& aCmd, 580 int32 aStatus) 581 { 582 if (aStatus == PVMFPending) return PVMFPending; 583 if (aStatus > 0 || IsPVMFErrCode(aStatus)) 584 { 585 CommandComplete(aCmdQ, aCmd, aStatus); // no extension error code in case of error 586 return aStatus; 587 } 588 589 // should be PE node extension error code 590 PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID; 591 // Check for error code for not enough disk space 592 int32 pvmfReturnCode = PVMFFailure; 593 if (aStatus == PROCESS_DATA_STREAM_OPEN_FAILURE) pvmfReturnCode = PVMFErrResource; 594 int32 errorCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - aStatus); 595 CommandComplete(aCmdQ, aCmd, pvmfReturnCode, NULL, &uuid, &errorCode); 596 return pvmfReturnCode; 597 } 598 599 600 void PVMFProtocolEngineNode::CommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ, 601 PVMFProtocolEngineNodeCommand& aCmd, 602 PVMFStatus aStatus, 603 OsclAny* aEventData, 604 PVUuid* aEventUUID, 605 int32* aEventCode, 606 int32 aEventDataLen) 607 608 { 609 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d" 610 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 611 612 PVInterface* extif = NULL; 613 PVMFBasicErrorInfoMessage* errormsg = NULL; 614 if (aEventUUID && aEventCode) 615 { 616 errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL)); 617 extif = OSCL_STATIC_CAST(PVInterface*, errormsg); 618 } 619 620 //create response 621 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData); 622 if (aEventDataLen != 0) 623 { 624 resp.SetEventDataLen(aEventDataLen); 625 } 626 627 PVMFSessionId session = aCmd.iSession; 628 629 //Erase the command from the queue. 630 aCmdQ.Erase(&aCmd); 631 632 //Report completion to the session observer. 633 ReportCmdCompleteEvent(session, resp); 634 635 if (errormsg) errormsg->removeRef(); 636 } 637 638 639 /** 640 //Called by the command handler AO to do the node Reset. 641 */ 642 PVMFStatus PVMFProtocolEngineNode::DoReset(PVMFProtocolEngineNodeCommand& aCmd) 643 { 644 LOGINFO((0, "PVMFProtocolEngineNode::DoReset()")); 645 646 // Allow a reset on ANY state. 647 ResetClear(true); // true means deleting the relevant objects 648 649 // Logoff and go back to Created state. 650 SetState(EPVMFNodeIdle); 651 PVMFStatus status = ThreadLogoff(); 652 CommandComplete(iInputCommands, aCmd, status); 653 return status; 654 } 655 656 657 /** 658 //Called by the command handler AO to do the port request 659 */ 660 PVMFStatus PVMFProtocolEngineNode::DoRequestPort(PVMFProtocolEngineNodeCommand& aCmd) 661 { 662 LOGINFO((0, "PVMFProtocolEngineNode::DoRequestPort()")); 663 664 //This node supports port request from any state 665 666 //retrieve port tag. 667 int32 tag; 668 OSCL_String* mimetype; 669 aCmd.PVMFProtocolEngineNodeCommandBase::Parse(tag, mimetype); 670 671 //(mimetype is not used on this node) 672 673 //validate the tag... 674 switch (tag) 675 { 676 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT: 677 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT: 678 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK: 679 break; 680 681 default: 682 { 683 //bad port tag 684 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 685 (0, "PVMFProtocolEngineNode::DoRequestPort: Error - Invalid port tag")); 686 CommandComplete(iInputCommands, aCmd, PVMFFailure); 687 return PVMFFailure; 688 } 689 // break; This statement was removed to avoid compiler warning for Unreachable Code 690 } 691 692 //Allocate a new port 693 OsclAny *ptr = NULL; 694 int32 err; 695 OSCL_TRY(err, ptr = iPortVector.Allocate();); 696 if (err != OsclErrNone || !ptr) 697 { 698 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 699 (0, "PVMFProtocolEngineNode::DoRequestPort: Error - iPortVector Out of memory")); 700 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 701 return PVMFErrNoMemory; 702 } 703 704 //create base port with default settings... 705 PVMFProtocolEnginePort*port = NULL; 706 switch (tag) 707 { 708 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT: 709 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK: 710 //create base port with default settings... 711 port = new(ptr) PVMFProtocolEnginePort(tag, this, 712 DEFAULT_DATA_QUEUE_CAPACITY, 713 DEFAULT_DATA_QUEUE_CAPACITY, 714 DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT, 715 DEFAULT_DATA_QUEUE_CAPACITY, 716 DEFAULT_DATA_QUEUE_CAPACITY, 717 DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT, 718 "ProtocolEngineIn(Protocol)"); 719 720 if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) iPortInForData = port; 721 if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK) iPortInForLogging = port; 722 break; 723 724 case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT: 725 port = new(ptr) PVMFProtocolEnginePort(tag, this, 726 0, 0, 0, // input queue isn't needed. 727 DEFAULT_DATA_QUEUE_CAPACITY, 728 DEFAULT_DATA_QUEUE_CAPACITY, 729 DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT, 730 "ProtocolEngineOut(Protocol)"); 731 732 iPortOut = port; 733 break; 734 } 735 736 iPortActivityQueue.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE); 737 738 //Add the port to the port vector. 739 OSCL_TRY(err, iPortVector.AddL(port);); 740 if (err != OsclErrNone) 741 { 742 iPortInForData = iPortInForLogging = iPortOut = NULL; 743 OSCL_DELETE(port); 744 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 745 return PVMFErrNoMemory; 746 } 747 748 //Return the port pointer to the caller. 749 CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port, 0, 0, sizeof(PVMFProtocolEnginePort)); 750 return PVMFSuccess; 751 } 752 753 /** 754 //Called by the command handler AO to do the port release 755 */ 756 PVMFStatus PVMFProtocolEngineNode::DoReleasePort(PVMFProtocolEngineNodeCommand& aCmd) 757 { 758 LOGINFO((0, "PVMFProtocolEngineNode::DoReleasePort()")); 759 760 //This node supports release port from any state 761 PVMFStatus status = PVMFSuccess; 762 763 //Find the port in the port vector 764 PVMFPortInterface* p = NULL; 765 aCmd.PVMFProtocolEngineNodeCommandBase::Parse(p); 766 767 PVMFProtocolEnginePort* port = (PVMFProtocolEnginePort*)p; 768 769 770 if (port == NULL) status = PVMFErrArgument; 771 772 PVMFProtocolEnginePort** portPtr = iPortVector.FindByValue(port); 773 if (portPtr) 774 { 775 if (*portPtr == iPortInForData) iPortInForData = NULL; 776 if (*portPtr == iPortInForLogging) iPortInForLogging = NULL; 777 if (*portPtr == iPortOut) iPortOut = NULL; 778 779 Clear(true); 780 781 //delete the port. 782 iPortVector.Erase(portPtr); 783 status = PVMFSuccess; 784 } 785 else 786 { 787 //port not found. 788 status = PVMFErrArgument; 789 } 790 791 CommandComplete(iInputCommands, aCmd, status); 792 return status; 793 } 794 795 796 PVMFStatus PVMFProtocolEngineNode::DoQueryUuid(PVMFProtocolEngineNodeCommand& aCmd) 797 { 798 LOGINFO((0, "PVMFProtocolEngineNode::DoQueryUuid()")); 799 800 //This node supports Query UUID from any state 801 OSCL_String* mimetype; 802 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 803 bool exactmatch; 804 aCmd.PVMFProtocolEngineNodeCommandBase::Parse(mimetype, uuidvec, exactmatch); 805 806 //TODO: Try to match the input mimetype against any of 807 //the custom interfaces for this node 808 PVUuid uuid1(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID); 809 uuidvec->push_back(uuid1); 810 PVUuid uuid2(PVMIDatastreamuserInterfaceUuid); 811 uuidvec->push_back(uuid2); 812 PVUuid uuid3(KPVMFProtocolEngineNodeExtensionUuid); 813 uuidvec->push_back(uuid3); 814 PVUuid uuid4(PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID); 815 uuidvec->push_back(uuid4); 816 PVUuid uuid5(KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid); 817 uuidvec->push_back(uuid5); 818 PVUuid uuid6(PVMF_TRACK_SELECTION_INTERFACE_UUID); 819 uuidvec->push_back(uuid6); 820 821 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 822 return PVMFSuccess; 823 } 824 825 826 PVMFStatus PVMFProtocolEngineNode::DoQueryInterface(PVMFProtocolEngineNodeCommand& aCmd) 827 { 828 LOGINFO((0, "PVMFProtocolEngineNode::DoQueryInterface()")); 829 830 PVUuid* uuid; 831 PVInterface** ptr; 832 aCmd.PVMFProtocolEngineNodeCommandBase::Parse(uuid, ptr); 833 PVMFStatus status = PVMFSuccess; 834 if (!queryInterface(*uuid, *ptr)) 835 { 836 //Not supported 837 *ptr = NULL; 838 status = PVMFFailure; 839 } 840 841 CommandComplete(iInputCommands, aCmd, status); 842 return status; 843 } 844 845 846 /** 847 //Called by the command handler AO to do the node Init 848 */ 849 PVMFStatus PVMFProtocolEngineNode::DoInit(PVMFProtocolEngineNodeCommand& aCmd) 850 { 851 LOGINFO((0, "PVMFProtocolEngineNode::DoInit()")); 852 853 PVMFStatus status = PVMFSuccess; 854 // exceptional cases 855 if (!iProtocolContainer) status = PVMFFailure; 856 if (iInterfaceState != EPVMFNodeIdle) status = PVMFErrInvalidState; 857 PassInObjects(); 858 859 // normal case 860 if (iInterfaceState == EPVMFNodeIdle && iProtocolContainer) 861 { 862 // do init, if init is async call, then return PVMFPending 863 if ((status = iProtocolContainer->doInit()) == PVMFSuccess) 864 { 865 SetState(EPVMFNodeInitialized); 866 } 867 } 868 return HandleCommandComplete(iInputCommands, aCmd, status); 869 } 870 871 void PVMFProtocolEngineNode::PassInObjects() 872 { 873 iProtocolContainer->setSupportObject((OsclAny*)iPortInForData, NodeObjectType_InputPortForData); 874 iProtocolContainer->setSupportObject((OsclAny*)iPortInForLogging, NodeObjectType_InputPortForLogging); 875 iProtocolContainer->setSupportObject((OsclAny*)iPortOut, NodeObjectType_OutPort); 876 iProtocolContainer->setSupportObject((OsclAny*)(&iInternalEventQueue), NodeObjectType_InternalEventQueue); 877 } 878 879 880 /** 881 //Called by the command handler AO to do the node Prepare 882 */ 883 PVMFStatus PVMFProtocolEngineNode::DoPrepare(PVMFProtocolEngineNodeCommand& aCmd) 884 { 885 LOGINFO((0, "PVMFProtocolEngineNode::DoPrepare()")); 886 if (!iProtocolContainer) return PVMFFailure; 887 888 PVMFStatus status = PVMFSuccess; //PVMFPending; 889 PassInObjects(); 890 switch (iInterfaceState) 891 { 892 case EPVMFNodeInitialized: 893 { 894 status = iProtocolContainer->doPrepare(); 895 if (status == PVMFSuccess) SetState(EPVMFNodePrepared); 896 break; 897 } 898 default: 899 status = PVMFErrInvalidState; 900 break; 901 } 902 903 return HandleCommandComplete(iInputCommands, aCmd, status); 904 } 905 906 907 /** 908 //Called by the command handler AO to do the node Start 909 */ 910 PVMFStatus PVMFProtocolEngineNode::DoStart(PVMFProtocolEngineNodeCommand& aCmd) 911 { 912 LOGINFO((0, "PVMFProtocolEngineNode::DoStart()")); 913 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoStart() : Start command gets called and executed, iInterfaceState=%d, currSocketConnection=%d", 914 (int32)iInterfaceState, (uint32)iInterfacingObjectContainer->isSocketConnectionUp())); 915 916 // check if download/streaming is done, if it is done, no need to start/resume download/streaming 917 if (CheckAvailabilityOfDoStart(aCmd)) return PVMFSuccess; 918 919 PVMFStatus status = PVMFSuccess; 920 iProcessingState = ProcessingState_NormalDataflow; 921 iInterfacingObjectContainer->setInputDataUnwanted(false); 922 switch (iInterfaceState) 923 { 924 case EPVMFNodePrepared: 925 { 926 if (iProtocolContainer->doPreStart() == PROCESS_SUCCESS) 927 { 928 // do socket reconnect for init->start, prepare->start and stop->start 929 // for pause->start, no need. For seek, no start command is issued. doseek() will 930 // do socket reconnect 931 iProtocolContainer->startDataFlowByCommand(iProtocolContainer->needSocketReconnect()); // make start command (prepare->start) asynchonous 932 933 // Transition to BeingStarted 934 // intentionally set node state as this node internal state to ignore any left-over messages from POST port from previous stop or EOS handling 935 SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted); 936 937 return PVMFPending; 938 } 939 status = PVMFSuccess; 940 break; 941 } 942 943 case EPVMFNodePaused: 944 { 945 // Transition to BeingStarted 946 // intentionally set node state as this node internal state to ignore any left-over messages from POST port because currently node is paused state. 947 // need to differentiate this case from the paused case. 948 SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted); 949 950 iProtocol->resume(); 951 iProtocolContainer->startDataFlowByCommand(); 952 return PVMFPending; 953 954 // break; This statement was removed to avoid compiler warning for Unreachable Code 955 } 956 957 /* 958 * If the node is already started just return success - multiple starts can happen with 959 * flow control (auto-pause / auto-resume) scenarios 960 */ 961 case EPVMFNodeStarted: 962 status = PVMFSuccess; 963 break; 964 965 default: 966 status = PVMFErrInvalidState; 967 break; 968 } 969 970 CommandComplete(iInputCommands, aCmd, status); 971 return status; 972 } 973 974 bool PVMFProtocolEngineNode::CheckAvailabilityOfDoStart(PVMFProtocolEngineNodeCommand& aCmd) 975 { 976 // check if download/streaming is done, if it is done, no need to start/resume download/streaming 977 if (iInterfacingObjectContainer->isDownloadStreamingDone()) 978 { 979 SetState(EPVMFNodeStarted); 980 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 981 return true; 982 } 983 return false; 984 } 985 986 /** 987 //Called by the command handler AO to do the node Pause 988 */ 989 PVMFStatus PVMFProtocolEngineNode::DoPause(PVMFProtocolEngineNodeCommand& aCmd) 990 { 991 LOGINFO((0, "PVMFProtocolEngineNode::DoPause()")); 992 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoPause() : Pause command gets called and executed, iInterfaceState=%d", (int32)iInterfaceState)); 993 994 PVMFStatus status = PVMFSuccess; 995 switch (iInterfaceState) 996 { 997 case EPVMFNodeStarted: 998 { 999 TPVMFNodeInterfaceState prevState = iInterfaceState; 1000 SetState(EPVMFNodePaused); 1001 if (!iProtocolContainer->doPause()) 1002 { 1003 SetState(prevState); 1004 status = PVMFFailure; 1005 } 1006 } 1007 break; 1008 1009 case EPVMFNodePaused: 1010 status = PVMFSuccess; 1011 1012 default: 1013 status = PVMFErrInvalidState; 1014 break; 1015 } 1016 1017 CommandComplete(iInputCommands, aCmd, status); 1018 return status; 1019 } 1020 1021 /** 1022 //Called by the command handler AO to do the node Seek 1023 */ 1024 PVMFStatus PVMFProtocolEngineNode::DoSeek(PVMFProtocolEngineNodeCommand& aCmd) 1025 { 1026 return iProtocolContainer->doSeek(aCmd); 1027 } 1028 1029 1030 /** 1031 //Called by the command handler AO to do the node BitstreamSwitch 1032 */ 1033 PVMFStatus PVMFProtocolEngineNode::DoBitsteamSwitch(PVMFProtocolEngineNodeCommand& aCmd) 1034 { 1035 return iProtocolContainer->doBitstreamSwitch(aCmd); 1036 } 1037 1038 PVMFStatus PVMFProtocolEngineNode::DoReposition(PVMFProtocolEngineNodeCommand& aCmd) 1039 { 1040 return iProtocolContainer->doSeek(aCmd); 1041 } 1042 1043 /** 1044 //Called by the command handler AO to do the node Stop 1045 */ 1046 PVMFStatus PVMFProtocolEngineNode::DoStop(PVMFProtocolEngineNodeCommand& aCmd) 1047 { 1048 LOGINFO((0, "PVMFProtocolEngineNode::DoStop()")); 1049 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::Stop() : Stop command gets called, iInterfaceState=%d", (int32)iInterfaceState)); 1050 1051 PVMFStatus status = PVMFSuccess; 1052 switch (iInterfaceState) 1053 { 1054 case EPVMFNodeStarted: 1055 case EPVMFNodePaused: 1056 1057 status = iProtocolContainer->doStop(); 1058 if (status == PVMFPending) return PVMFPending; 1059 if (status == PVMFSuccess) 1060 { 1061 1062 StopClear(); 1063 // Transition to Prepared state 1064 SetState(EPVMFNodePrepared); 1065 } 1066 break; 1067 1068 case EPVMFNodeError: 1069 SetState(EPVMFNodePrepared); 1070 break; 1071 1072 default: 1073 status = PVMFErrInvalidState; 1074 break; 1075 } 1076 1077 CommandComplete(iInputCommands, aCmd, status); 1078 return status; 1079 } 1080 1081 /** 1082 //Called by the command handler AO to do the node Flush 1083 */ 1084 PVMFStatus PVMFProtocolEngineNode::DoFlush(PVMFProtocolEngineNodeCommand& aCmd) 1085 { 1086 LOGINFO((0, "PVMFProtocolEngineNode::DoFlush()")); 1087 1088 switch (iInterfaceState) 1089 { 1090 case EPVMFNodeStarted: 1091 case EPVMFNodePaused: 1092 { 1093 //the flush is asynchronous. Move the command from 1094 //the input command queue to the current command, where 1095 //it will remain until the flush completes. 1096 int32 err; 1097 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 1098 if (err != OsclErrNone) 1099 { 1100 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 1101 return PVMFErrNoMemory; 1102 } 1103 iInputCommands.Erase(&aCmd); 1104 1105 //Notify all ports to suspend their input 1106 for (uint32 i = 0; i < iPortVector.size(); i++) 1107 { 1108 iPortVector[i]->SuspendInput(); 1109 } 1110 } 1111 1112 break; 1113 1114 default: 1115 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 1116 return PVMFErrInvalidState; 1117 // break; This statement was removed to avoid compiler warning for Unreachable Code 1118 } 1119 return PVMFSuccess; 1120 } 1121 1122 /** 1123 //A routine to tell if a flush operation is in progress. 1124 */ 1125 bool PVMFProtocolEngineNode::FlushPending() 1126 { 1127 return (iCurrentCommand.size() > 0 && 1128 iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH); 1129 } 1130 1131 1132 /** 1133 //Called by the command handler AO to do the Cancel All 1134 */ 1135 PVMFStatus PVMFProtocolEngineNode::DoCancelAllCommands(PVMFProtocolEngineNodeCommand& aCmd) 1136 { 1137 LOGINFO((0, "PVMFProtocolEngineNode::DoCancelAllCommands()")); 1138 1139 //first cancel the current command if any 1140 while (!iCurrentCommand.empty()) 1141 { 1142 CancelClear(); 1143 CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled); 1144 } 1145 1146 //next cancel all queued commands 1147 //start at element 1 since this cancel command is element 0. 1148 while (iInputCommands.size() > 1) 1149 { 1150 CancelClear(); 1151 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled); 1152 } 1153 1154 //finally, report cancel complete. 1155 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 1156 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened(); 1157 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted(); 1158 return PVMFSuccess; 1159 } 1160 1161 /** 1162 //Called by the command handler AO to do the Cancel single command 1163 */ 1164 PVMFStatus PVMFProtocolEngineNode::DoCancelCommand(PVMFProtocolEngineNodeCommand& aCmd) 1165 { 1166 LOGINFO((0, "PVMFProtocolEngineNode::DoCancelCommand()")); 1167 1168 //extract the command ID from the parameters. 1169 PVMFCommandId id; 1170 aCmd.PVMFProtocolEngineNodeCommandBase::Parse(id); 1171 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted(); 1172 1173 // first check "current" command if any, and check the input queue starting 1174 // at element 1 since this cancel command is element 0. 1175 PVMFProtocolEngineNodeCommand* cmd = iCurrentCommand.FindById(id); 1176 if (cmd) 1177 { 1178 CancelClear(); 1179 //cancel the queued command 1180 CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled); 1181 //report cancel success 1182 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 1183 return PVMFSuccess; 1184 } 1185 1186 //next check input queue. 1187 //start at element 1 since this cancel command is element 0. 1188 cmd = iInputCommands.FindById(id, 1); 1189 if (cmd) 1190 { 1191 CancelClear(); 1192 //cancel the queued command 1193 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled); 1194 //report cancel success 1195 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 1196 return PVMFSuccess; 1197 } 1198 1199 //at this point, nothing needs to be cancelled and thus report cancel complete 1200 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 1201 // set cancel cmd happened flag for stop command processing 1202 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened(); 1203 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted(); 1204 return PVMFSuccess; 1205 } 1206 1207 1208 ///////////////////////////////////////////////////// 1209 // Event reporting routines. 1210 ///////////////////////////////////////////////////// 1211 void PVMFProtocolEngineNode::SetState(TPVMFNodeInterfaceState s) 1212 { 1213 LOGINFO((0, "PVMFProtocolEngineNode::SetState() %d", s)); 1214 PVMFNodeInterface::SetState(s); 1215 } 1216 1217 void PVMFProtocolEngineNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, const int32 aEventCode, OsclAny* aEventLocalBuffer, const uint32 aEventLocalBufferSize) 1218 { 1219 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:NodeInfoEvent Type %d Data %d", 1220 aEventType, aEventData)); 1221 1222 if (aEventCode == 0) 1223 { 1224 //report basic event, no extended event 1225 PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData); 1226 } 1227 else 1228 { 1229 //report extended event. 1230 PVUuid uuid = PVMFPROTOCOLENGINENODEInfoEventTypesUUID; 1231 PVMFBasicErrorInfoMessage *msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL)); 1232 1233 PVMFAsyncEvent event(PVMFInfoEvent, 1234 aEventType, 1235 NULL, //context 1236 msg, 1237 aEventData, 1238 (uint8*)aEventLocalBuffer, 1239 aEventLocalBufferSize); 1240 1241 //report to the session observers. 1242 PVMFNodeInterface::ReportInfoEvent(event); 1243 1244 //remove the ref to the extended response 1245 if (msg) msg->removeRef(); 1246 } 1247 } 1248 1249 void PVMFProtocolEngineNode::ReportErrorEvent(PVMFEventType aEventType, 1250 OsclAny* aEventData, 1251 const int32 aEventCode, 1252 int32 aEventDataLen) 1253 { 1254 LOGINFO((0, "PVMFProtocolEngineNode::ReportErrorEvent() Type %d Data %d" 1255 , aEventType, aEventData)); 1256 1257 PVMFBasicErrorInfoMessage*msg = NULL; 1258 1259 if (aEventCode != 0) 1260 { 1261 // extended error event with aEventCode 1262 PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID; 1263 msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL)); 1264 } 1265 1266 PVMFAsyncEvent event(PVMFErrorEvent, 1267 aEventType, 1268 NULL, // context 1269 msg, 1270 aEventData, 1271 NULL, 1272 0); 1273 1274 if (aEventDataLen != 0) 1275 event.SetEventDataLen(aEventDataLen); 1276 1277 PVMFNodeInterface::ReportErrorEvent(event); 1278 if (msg) msg->removeRef(); 1279 1280 } 1281 1282 ///////////////////////////////////////////////////// 1283 // Port Processing routines 1284 ///////////////////////////////////////////////////// 1285 1286 void PVMFProtocolEngineNode::QueuePortActivity(const PVMFPortActivity &aActivity) 1287 { 1288 //queue a new port activity event 1289 int32 err; 1290 OSCL_TRY(err, iPortActivityQueue.push_back(aActivity);); 1291 if (err != OsclErrNone) 1292 { 1293 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1294 (0, "PVMFProtocolEngineNode::QueuePortActivity() Error - iPortActivityQueue.push_back() failed")); 1295 ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort), sizeof(PVMFProtocolEnginePort)); 1296 } 1297 else 1298 { 1299 //wake up the AO to process the port activity event. 1300 RunIfNotReady(); 1301 } 1302 } 1303 1304 1305 void PVMFProtocolEngineNode::HandlePortActivity(const PVMFPortActivity &aActivity) 1306 { 1307 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, PAQSize=%d", 1308 aActivity.iPort, aActivity.iType, aActivity.iPort->IncomingMsgQueueSize(), aActivity.iPort->OutgoingMsgQueueSize(), iPortActivityQueue.size())); 1309 1310 //A port is reporting some activity or state change. This code 1311 //figures out whether we need to queue a processing event 1312 //for the AO, and/or report a node event to the observer. 1313 1314 switch (aActivity.iType) 1315 { 1316 case PVMF_PORT_ACTIVITY_CREATED: 1317 //Report port created info event 1318 ReportInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort); 1319 break; 1320 1321 case PVMF_PORT_ACTIVITY_DELETED: 1322 //Report port deleted info event 1323 ReportInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort); 1324 //Purge any port activity events already queued 1325 //for this port. 1326 { 1327 for (uint32 i = 0; i < iPortActivityQueue.size();) 1328 { 1329 if (iPortActivityQueue[i].iPort == aActivity.iPort) 1330 { 1331 iPortActivityQueue.erase(&iPortActivityQueue[i]); 1332 } 1333 else 1334 { 1335 i++; 1336 } 1337 } 1338 } 1339 break; 1340 1341 case PVMF_PORT_ACTIVITY_CONNECT: 1342 //nothing needed. 1343 if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut) 1344 { 1345 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_CONNECT), PE node output port connected to downstream node port!", 1346 aActivity.iPort, aActivity.iType)); 1347 iInterfacingObjectContainer->setOutputPortConnect(); 1348 } 1349 1350 break; 1351 1352 case PVMF_PORT_ACTIVITY_DISCONNECT: 1353 //clear the node input queue when either port is disconnected. 1354 while (!iDataInQueue.empty()) 1355 { 1356 PVMFSharedMediaMsgPtr msg = iDataInQueue.front(); 1357 iDataInQueue.erase(iDataInQueue.begin()); 1358 ((PVMFProtocolEnginePort*)aActivity.iPort)->LogMediaMsgInfo(msg, "In Msg Cleared", iDataInQueue.size()); 1359 } 1360 1361 if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut) 1362 { 1363 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_DISCONNECT), PE node output port disconnected from downstream node port!", 1364 aActivity.iPort, aActivity.iType)); 1365 iInterfacingObjectContainer->setOutputPortConnect(false); 1366 } 1367 break; 1368 1369 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 1370 //An outgoing message was queued on this port. 1371 //We only need to queue a port activity event on the 1372 //first message. Additional events will be queued during 1373 //the port processing as needed. 1374 if ((aActivity.iPort->OutgoingMsgQueueSize() == 1) || 1375 (iPortActivityQueue.size() == 0)) 1376 { 1377 QueuePortActivity(aActivity); 1378 } 1379 break; 1380 1381 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 1382 //An incoming message was queued on this port. 1383 //We only need to queue a port activity event on the 1384 //first message. Additional events will be queued during 1385 //the port processing as needed. 1386 if ((aActivity.iPort->IncomingMsgQueueSize() == 1) || 1387 (iPortActivityQueue.size() == 0)) 1388 { 1389 QueuePortActivity(aActivity); 1390 } 1391 break; 1392 1393 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY: 1394 //Outgoing queue is now busy. 1395 //No action is needed here-- the node checks for 1396 //outgoing queue busy as needed during data processing. 1397 iProcessingState = ProcessingState_Idle; // disable data flow 1398 break; 1399 1400 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 1401 //Outgoing queue was previously busy, but is now ready. 1402 //it's time to start processing incoming data again. 1403 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d", 1404 aActivity.iPort->OutgoingMsgQueueSize())); 1405 ProcessOutgoingQueueReady(); 1406 break; 1407 1408 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY: 1409 // The connected port has become busy (its incoming queue is 1410 // busy). 1411 // No action is needed here-- the port processing code 1412 // checks for connected port busy during data processing. 1413 break; 1414 1415 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY: 1416 // The connected port has transitioned from Busy to Ready. 1417 // It's time to start processing outgoing messages again. 1418 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY, OutgoingQueueSize=%d", 1419 aActivity.iPort->OutgoingMsgQueueSize())); 1420 1421 if (aActivity.iPort->OutgoingMsgQueueSize() > 0) 1422 { 1423 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1424 (0, "0x%x PVMFProtocolEngineNode::PortActivity: Connected port is now ready", this)); 1425 PVMFPortActivity activity(aActivity.iPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG); 1426 QueuePortActivity(activity); 1427 } 1428 break; 1429 1430 default: 1431 break; 1432 } 1433 } 1434 1435 1436 ///////////////////////////////////////////////////// 1437 // Called by the AO to process a port activity message 1438 bool PVMFProtocolEngineNode::ProcessPortActivity() 1439 { 1440 //Pop the queue... 1441 PVMFPortActivity activity(iPortActivityQueue.front()); 1442 iPortActivityQueue.erase(&iPortActivityQueue.front()); 1443 1444 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, iInterfaceState=%d, PAQSize=%d", 1445 activity.iPort, activity.iType, activity.iPort->IncomingMsgQueueSize(), activity.iPort->OutgoingMsgQueueSize(), iInterfaceState, iPortActivityQueue.size())); 1446 1447 PVMFStatus status = PVMFSuccess; 1448 switch (activity.iType) 1449 { 1450 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 1451 status = ProcessOutgoingMsg(activity.iPort); 1452 //Re-queue the port activity event as long as there's 1453 //more data to process and it isn't in a Busy state. 1454 QueueActivityOutgoingMessage(status, activity); 1455 break; 1456 1457 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 1458 status = ProcessIncomingMsg(activity.iPort); 1459 //Re-queue the port activity event as long as there's 1460 //more data to process and it isn't in a Busy state. 1461 QueueActivityIncomingMessage(status, activity); 1462 break; 1463 1464 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 1465 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d", 1466 activity.iPort->OutgoingMsgQueueSize())); 1467 ProcessOutgoingQueueReady(); 1468 break; 1469 1470 default: 1471 break; 1472 } 1473 1474 //Report any unexpected failure in port processing... 1475 //(the InvalidState error happens when port input is suspended, 1476 //so don't report it.) 1477 if (status != PVMFErrBusy && 1478 status != PVMFSuccess && 1479 status != PVMFErrInvalidState) 1480 { 1481 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1482 (0, "PVMFProtocolEngineNode::ProcessPortActivity() Error - ProcessPortActivity failed. port=0x%x, type=%d", 1483 activity.iPort, activity.iType)); 1484 ReportErrorEvent(PVMFErrPortProcessing); 1485 } 1486 1487 //return true if we processed an activity... 1488 return (status != PVMFErrBusy); 1489 } 1490 1491 // wrap OSCL_TRY block 1492 void PVMFProtocolEngineNode::QueueActivityOutgoingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity) 1493 { 1494 if (aStatus != PVMFErrBusy && aActivity.iPort->OutgoingMsgQueueSize() > 0) 1495 { 1496 int32 err; 1497 OSCL_TRY(err, iPortActivityQueue.push_back(aActivity);); 1498 if (err) ReportErrorEvent(PVMFErrPortProcessing); 1499 } 1500 } 1501 1502 // wrap OSCL_TRY block 1503 void PVMFProtocolEngineNode::QueueActivityIncomingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity) 1504 { 1505 //Re-queue the port activity event as long as there's more data to process and it isn't in a Busy state. 1506 if (aStatus != PVMFErrBusy && aActivity.iPort->IncomingMsgQueueSize() > 0) 1507 { 1508 //OSCL_TRY(err,iPortActivityQueue.push_back(activity);); 1509 // only insert outgoing queue ready event in case of no such event in the port activity queue 1510 if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_INCOMING_MSG)) 1511 { 1512 int32 err; 1513 OSCL_TRY(err, iPortActivityQueue.push_back(aActivity);); 1514 if (err) ReportErrorEvent(PVMFErrPortProcessing); 1515 } 1516 } 1517 } 1518 1519 ///////////////////////////////////////////////////// 1520 PVMFStatus PVMFProtocolEngineNode::ProcessIncomingMsg(PVMFPortInterface* aPort) 1521 { 1522 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1523 (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() aPort=0x%x, IncomingMsgQueueSize=%d, iProcessingState=%d", 1524 aPort, aPort->IncomingMsgQueueSize(), iProcessingState)); 1525 1526 // Called by the AO to process one buffer off the port's 1527 // incoming data queue. This routine will dequeue and dispatch the data. 1528 // for pause, don't dequeue the message 1529 if (aPort->IncomingMsgQueueSize() == 0) return PVMFSuccess; 1530 1531 if (aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT && 1532 aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK) 1533 { 1534 return PVMFFailure; 1535 } 1536 1537 if (iDataInQueue.size() < DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT / 100) 1538 { 1539 // DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT/100 = 7 1540 // only dequeue the message when data queue buffers less number of media message than the port queue 1541 1542 // Get one incoming message 1543 PVMFSharedMediaMsgPtr msg; 1544 PVMFStatus status = aPort->DequeueIncomingMsg(msg); 1545 if (status != PVMFSuccess) 1546 { 1547 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1548 (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() Error - DequeueIncomingMsg failed")); 1549 return status; 1550 } 1551 1552 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1553 (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() FmtId=%d", msg->getFormatID())); 1554 1555 bool isEOS = (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID); 1556 if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) 1557 { 1558 iInterfacingObjectContainer->updateSocketConnectFlags(isEOS); // will update flags 1559 } 1560 1561 if (IgnoreCurrentInputData(aPort, isEOS, msg)) 1562 { 1563 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() INCOMING MESSAGE IGNORED!! isEOS=%d, port=0x%x, iInterfaceState=%d", 1564 (uint32)isEOS, aPort, iInterfaceState)); 1565 return PVMFSuccess; 1566 } 1567 1568 uint32 frameIndex = ((PVMFProtocolEnginePort*)aPort)->iNumFramesConsumed++; 1569 msg->setSeqNum(frameIndex); 1570 iDataInQueue.push_back(msg); 1571 1572 UpdateTimersInProcessIncomingMsg(isEOS, aPort); 1573 LogIncomingMessage(msg, isEOS, aPort); 1574 1575 } // end of if(iDataInQueue.size() < 7) 1576 else 1577 { 1578 if (iInterfaceState != EPVMFNodePaused && aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) 1579 { 1580 iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout 1581 } 1582 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() iDataInQueue becomes FULL! iProcessingState = %d (1 for normal data flow), iInterfaceState = %d", 1583 (uint32)iProcessingState, (uint32)iInterfaceState)); 1584 if (iProcessingState != ProcessingState_NormalDataflow) return PVMFErrBusy; 1585 } 1586 1587 if (iProcessingState == ProcessingState_NormalDataflow) 1588 { 1589 if (!IsDataFlowEventAlreadyInQueue()) 1590 { 1591 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_IncomingMessageReady); 1592 iInternalEventQueue.push_back(aEvent); 1593 } 1594 } 1595 1596 RunIfNotReady(); 1597 return PVMFSuccess; 1598 } 1599 1600 void PVMFProtocolEngineNode::UpdateTimersInProcessIncomingMsg(const bool aEOSMsg, PVMFPortInterface* aPort) 1601 { 1602 // for response timers 1603 if (!aEOSMsg) 1604 { 1605 // only non-EOS media data can cancel the response timer, EOS message shouldn't(that will cause no timeout happens) 1606 iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID); 1607 iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING); 1608 } 1609 1610 // for inactivity timer 1611 if (!aEOSMsg && iInterfaceState != EPVMFNodePaused) 1612 { 1613 if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // set up inactivity timer 1614 } 1615 else // aEOSMsg=true or iInterfaceState = EPVMFNodePaused 1616 { 1617 iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID); 1618 } 1619 } 1620 1621 bool PVMFProtocolEngineNode::IgnoreCurrentInputData(PVMFPortInterface* aPort, const bool isEOS, PVMFSharedMediaMsgPtr &aMsg) 1622 { 1623 OSCL_UNUSED_ARG(aMsg); 1624 if (iInterfacingObjectContainer->ignoreCurrentInputData()) 1625 { 1626 if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) 1627 { 1628 CheckEndOfProcessingInIgoreData(isEOS); 1629 } 1630 return true; 1631 } 1632 1633 // for input port (HTTP GET) 1634 if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) 1635 { 1636 // processing done => ignore the rest data 1637 if (CheckEndOfProcessingInIgoreData(isEOS)) return true; 1638 1639 // paused state, ignore EOS for socket disconnect 1640 if (/*isEOS &&*/ iInterfaceState == EPVMFNodePaused) return true; 1641 } 1642 1643 // for feedback port (HTTP POST) 1644 if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK) 1645 { 1646 if (isEOS) return true; 1647 if (!isEOS && 1648 (iInterfaceState == EPVMFNodeStarted || 1649 iInterfaceState == (TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted) && 1650 !iInterfacingObjectContainer->isDownloadStreamingDone()) 1651 { 1652 return true; 1653 } 1654 } 1655 1656 return false; 1657 } 1658 1659 bool PVMFProtocolEngineNode::CheckEndOfProcessingInIgoreData(const bool isEOS, const bool isDataPort) 1660 { 1661 if (!iInterfacingObjectContainer->isDownloadStreamingDone()) return false; 1662 1663 EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo(); 1664 if (isEOS) 1665 { 1666 if (iProtocolContainer->needCheckEOSAfterDisconnectSocket()) 1667 { 1668 aInfo->clear(); 1669 aInfo->iSendServerDisconnectEvent = true; 1670 } 1671 } 1672 else 1673 { 1674 if (iProtocolContainer->needCheckExtraDataComeIn()) 1675 { 1676 aInfo->clear(); 1677 aInfo->iExtraDataComeIn = true; 1678 } 1679 } 1680 1681 if (aInfo->isValid()) 1682 { 1683 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo); 1684 iInternalEventQueue.push_back(aEvent); 1685 SetProcessingState(ProcessingState_NormalDataflow); 1686 RunIfNotReady(); 1687 return true; 1688 } 1689 1690 // Current situation: iInterfacingObjectContainer->isDownloadStreamingDone() = true 1691 if (isDataPort) return true; 1692 return false; 1693 } 1694 1695 void PVMFProtocolEngineNode::LogIncomingMessage(PVMFSharedMediaMsgPtr &aMsg, bool isEOS, PVMFPortInterface* aPort) 1696 { 1697 if (isEOS) 1698 { 1699 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage() GOT EOS! port=0x%x, iInterfaceState=%d", 1700 aPort, iInterfaceState)); 1701 OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable, 'aPort' 1702 } 1703 else 1704 { 1705 // Compute data size for logging purposes 1706 PVMFSharedMediaDataPtr mediaData; 1707 convertToPVMFMediaData(mediaData, aMsg); 1708 uint32 dataSize = 0; 1709 uint32 numFrags = mediaData->getNumFragments(); 1710 for (uint32 i = 0; i < numFrags; i++) 1711 { 1712 OsclRefCounterMemFrag memFragIn; 1713 mediaData->getMediaFragment(i, memFragIn); 1714 uint32 fragLen = memFragIn.getMemFrag().len; 1715 dataSize += fragLen; 1716 } 1717 1718 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage() SEQNUM=%d,SIZE=%d,port=0x%x,portIncomingQueueSize(AfterDequeue)=%d,iInterfaceState=%d", 1719 aMsg->getSeqNum(), dataSize, aPort, aPort->IncomingMsgQueueSize(), iInterfaceState)); 1720 } 1721 } 1722 1723 1724 ///////////////////////////////////////////////////// 1725 PVMFStatus PVMFProtocolEngineNode::ProcessOutgoingMsg(PVMFPortInterface* aPort) 1726 { 1727 //Called by the AO to process one message off the outgoing 1728 //message queue for the given port. This routine will 1729 //try to send the data to the connected port. 1730 if (aPort->OutgoingMsgQueueSize() == 0) return PVMFSuccess; 1731 1732 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() aPort=0x%x, OutgoingMsgQueueSize=%d", 1733 aPort, aPort->OutgoingMsgQueueSize())); 1734 1735 // check whether outgoing message is media command or media data 1736 PVMFSharedMediaMsgPtr msg; 1737 if (!((PVMFProtocolEnginePort*)aPort)->PeekOutgoingMsg(msg)) return PVMFFailure; 1738 1739 PVMFStatus status = aPort->Send(); 1740 if (status == PVMFErrBusy) 1741 { 1742 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() Connected port goes into busy state")); 1743 } 1744 if (status != PVMFSuccess) return status; 1745 1746 return PostProcessForMsgSentSuccess(aPort, msg); 1747 } 1748 1749 PVMFStatus PVMFProtocolEngineNode::PostProcessForMsgSentSuccess(PVMFPortInterface* aPort, PVMFSharedMediaMsgPtr &aMsg) 1750 { 1751 PVMFStatus status = PVMFSuccess; 1752 1753 // keep track the sequence no of the media msg just sent out successfully 1754 uint32 aCurrPacketNumSet = iInterfacingObjectContainer->getLatestPacketNumSent(); 1755 if (aMsg->getSeqNum() > aCurrPacketNumSet) iInterfacingObjectContainer->setLatestPacketNumSent(aMsg->getSeqNum()); 1756 1757 // set up server response timer and cancel inactivity timer 1758 bool isMediaData = (aMsg->getFormatID() < PVMF_MEDIA_CMD_FORMAT_IDS_START) || 1759 (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID); 1760 UpdateTimersInProcessOutgoingMsg(isMediaData, aPort); 1761 1762 // send() success means outgoing queue should always be ready, then send out outgoing queue ready event 1763 if ((PVMFProtocolEnginePort*)aPort == iPortOut) SendOutgoingQueueReadyEvent(aPort); 1764 1765 // handle the remaining post processing for the different media cmds. 1766 if (aMsg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 1767 { 1768 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: EOS SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort)); 1769 1770 // complete the pending command if there is, especially for the case of sending EOS due to error 1771 ProtocolStateErrorInfo aInfo(0, false); 1772 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo)); 1773 DispatchInternalEvent(&aEvent); 1774 } 1775 else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID) 1776 { 1777 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: RE_CONFIG SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort)); 1778 1779 uint32 aFirstPacketNum = 0xFFFFFFFF; 1780 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_FirstPacketAvailable, (OsclAny*)aFirstPacketNum); 1781 DispatchInternalEvent(&aEvent); 1782 } 1783 else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID) 1784 { 1785 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SOCKET CONNECT SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort)); 1786 bool status = iProtocolContainer->completeRepositionRequest(); 1787 if (status) LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SOCKET CONNECT cmd SUCCESS: complete data stream reposition request")); 1788 } 1789 else 1790 { 1791 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort)); 1792 } 1793 1794 return status; 1795 } 1796 1797 1798 void PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg(const bool isMediaData, PVMFPortInterface* aPort) 1799 { 1800 // set up server response timer 1801 if (((PVMFProtocolEnginePort*)aPort == iPortInForData || 1802 (PVMFProtocolEnginePort*)aPort == iPortInForLogging) && 1803 isMediaData) 1804 { 1805 iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID); 1806 1807 uint32 timerID = SERVER_RESPONSE_TIMER_ID; 1808 if (iInterfacingObjectContainer->isDownloadStreamingDone() && (PVMFProtocolEnginePort*)aPort == iPortInForLogging) 1809 { 1810 // logging POST for EOS and stop 1811 timerID = SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING; 1812 } 1813 iNodeTimer->start(timerID); 1814 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg() server response timer starts! timerID=%d, timeoutValue=%d", timerID, iNodeTimer->getTimeout(timerID))); 1815 } 1816 } 1817 1818 void PVMFProtocolEngineNode::SendOutgoingQueueReadyEvent(PVMFPortInterface* aPort) 1819 { 1820 if (aPort->OutgoingMsgQueueSize() == 0) return; 1821 1822 // only insert outgoing queue ready event in case of no such event in the port activity queue 1823 if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY)) 1824 { 1825 PVMFPortActivity activity(aPort, PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY); 1826 QueuePortActivity(activity); 1827 } 1828 } 1829 1830 bool PVMFProtocolEngineNode::SearchPortActivityInQueue(const PVMFPortActivityType aType) 1831 { 1832 bool bFound = false; 1833 for (uint32 i = 0; i < iPortActivityQueue.size(); i++) 1834 { 1835 if (iPortActivityQueue[i].iType == aType) 1836 { 1837 bFound = true; 1838 break; 1839 } 1840 } 1841 return bFound; 1842 } 1843 1844 void PVMFProtocolEngineNode::ProcessOutgoingQueueReady() 1845 { 1846 if (iPortInForData) 1847 { 1848 if (iPortInForData->IncomingMsgQueueSize() > 0) 1849 { 1850 ProcessIncomingMsg(iPortInForData); 1851 } 1852 } 1853 1854 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByPortOutgoingQueueReady); 1855 iInternalEventQueue.push_back(aEvent); 1856 iProcessingState = ProcessingState_NormalDataflow; // enable data flow 1857 if (IsAdded()) 1858 RunIfNotReady(); 1859 } 1860 1861 /** 1862 ///////////////////////////////////////////////////// 1863 // Active object implementation 1864 ///////////////////////////////////////////////////// 1865 */ 1866 1867 /** 1868 // The AO will either process one command or service one connected 1869 // port per call. It will re-schedule itself and run continuously 1870 // until it runs out of things to do. 1871 */ 1872 void PVMFProtocolEngineNode::Run() 1873 { 1874 //Process commands. 1875 if (!iInputCommands.empty() && ProcessCommand(iInputCommands.front())) 1876 { 1877 //note: need to check the state before re-scheduling 1878 //since the node could have been reset in the ProcessCommand call. 1879 if (iInterfaceState != EPVMFNodeCreated) RunIfNotReady(); 1880 return; 1881 } 1882 1883 // Process data, higher priority than port processing 1884 // Do this last after handling all node command and port activity but before checking if flush is complete 1885 if (HandleProcessingState()) 1886 { 1887 RunIfNotReady(); 1888 return; 1889 } 1890 1891 // Process port activity 1892 if (HandleRunPortActivityProcessing()) 1893 { 1894 //Re-schedule 1895 //if(iProcessingState == ProcessingState_NormalDataflow) RunIfNotReady(); 1896 RunIfNotReady(); 1897 return; 1898 } 1899 1900 1901 // If we get here we did not process any node commands, port activity, or decode. 1902 // Check for completion of a flush command... 1903 HandleRunFlush(); 1904 1905 // final check if there is the input command, but no pending command 1906 if (!iInputCommands.empty() && iCurrentCommand.empty()) RunIfNotReady(); 1907 } 1908 1909 bool PVMFProtocolEngineNode::HandleRunPortActivityProcessing() 1910 { 1911 if (!iPortActivityQueue.empty() && !FlushPending()) ///*&& (iInterfaceState==EPVMFNodeStarted || FlushPending())*/) 1912 { 1913 // If the port activity cannot be processed because a port is 1914 // busy, discard the activity and continue to process the next 1915 // activity in queue until getting to one that can be processed. 1916 while (!iPortActivityQueue.empty()) 1917 { 1918 if (ProcessPortActivity()) break; //processed a port 1919 } 1920 return true; 1921 } 1922 return false; 1923 } 1924 1925 void PVMFProtocolEngineNode::HandleRunFlush() 1926 { 1927 if (FlushPending() && iPortActivityQueue.empty()) 1928 { 1929 uint32 i; 1930 //Debug check-- all the port queues should be empty at 1931 //this point. 1932 for (i = 0; i < iPortVector.size(); i++) 1933 { 1934 if (iPortVector[i]->IncomingMsgQueueSize() > 0 1935 || iPortVector[i]->OutgoingMsgQueueSize() > 0) 1936 { 1937 OSCL_ASSERT(false); 1938 } 1939 } 1940 1941 //Flush is complete. Go to prepared state. 1942 SetState(EPVMFNodePrepared); 1943 //resume port input so the ports can be re-started. 1944 for (i = 0; i < iPortVector.size(); i++) 1945 { 1946 iPortVector[i]->ResumeInput(); 1947 } 1948 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 1949 RunIfNotReady(); 1950 } 1951 } 1952 1953 void PVMFProtocolEngineNode::SetProcessingState(PVProtocolEngineNodePrcoessingState aState) 1954 { 1955 iProcessingState = aState; 1956 RunIfNotReady(); 1957 } 1958 1959 1960 // Using state to handle different scenarios 1961 bool PVMFProtocolEngineNode::HandleProcessingState() 1962 { 1963 if (iProcessingState == ProcessingState_NormalDataflow) 1964 { 1965 return DispatchInternalEvent(); 1966 } 1967 return false; 1968 } 1969 1970 // The following method is (internal) event dispatcher, which is an important component for event-driven model 1971 // to handle the interactions inside the node, between protocol engine and the node. All events are defined as 1972 // PVProtocolEngineNodeInternalEventType in pvmf_protocol_engine_node_internal.h. 1973 // Typical events are, 1974 1975 // ** init/prepar/start/seek/bitstreamSwitch command trigger the data flow (class NormalDataFlowHandler), 1976 // ** multple events based on the callbacks from protocol engine 1977 // -- http header available (class HttpHeaderAvailableHandler) to complete start command 1978 // -- first data packet available (class FirstPacketAvailableHandler) to complete seek/bitstreamSwitch command 1979 // -- normal data packet available (class NormalDataAvailableHandler) to pass down to node output object, and then output data packets 1980 // -- protocol state complete (class ProtocolStateCompleteHandler) to complete init/prepare command 1981 // -- protocol state error (class ProtocolStateErrorHandler) to handle all the errors from protocol engine 1982 1983 // ** timer out event (will go to ProtocolStateErrorHandler) to complete any pending commands or report error event 1984 // ** end of data processing, especially for after download complete, parser node still send resume request, (class EndOfDataProcessingHandler) 1985 // ** by-pass server response for HEAD request in progressive download (class ServerResponseErrorBypassingHandler) 1986 1987 // The design is OO-based, i.e. each event handler is encapsulated into an object following the simple generic interface (virtual bool handle()=0), a 1988 // typical polymophimic treatment.The dispatching logic is table-based, i.e the mapping between most events and their corresponding handlers is 1989 // achieved by table look-up. 1990 1991 // aLatestEvent!=NULL means the event source sends the event without pushing it into the event queue 1992 // so no need to dequeue the event from the event queue, and just process it. This way aims to save 1993 // queueing and dequeuing operations on the queue. 1994 bool PVMFProtocolEngineNode::DispatchInternalEvent(PVProtocolEngineNodeInternalEvent *aLatestEvent) 1995 { 1996 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DispatchInternalEvent() IN, iInternalEventQueue.size=%d, aLatestEvent=%x", 1997 iInternalEventQueue.size(), (uint32)aLatestEvent)); 1998 1999 if (iInternalEventQueue.empty() && !aLatestEvent) return false; 2000 2001 PVProtocolEngineNodeInternalEvent aEvent = ((aLatestEvent != NULL) ? (*aLatestEvent) : (PVProtocolEngineNodeInternalEvent) iInternalEventQueue[0]); 2002 if (!aLatestEvent) iInternalEventQueue.erase(&(iInternalEventQueue.front())); 2003 2004 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DispatchInternalEvent() get the event from iInternalEventQueue, iInternalEventQueue.size=%d, aEvent.iEventId=%d, totalEventNum=%d", 2005 iInternalEventQueue.size(), (uint32)aEvent.iEventId, (uint32)EVENT_HANDLER_TOTAL)); 2006 2007 if ((uint32)aEvent.iEventId >= (uint32)PVProtocolEngineNodeInternalEventType_IncomingMessageReady) 2008 iCurrEventHandler = iEventHandlers[EVENT_HANDLER_TOTAL-1]; 2009 else 2010 iCurrEventHandler = iEventHandlers[(uint32)aEvent.iEventId]; 2011 2012 iCurrEventHandler->handle(aEvent); 2013 if (!iInternalEventQueue.empty()) return true; // true means this function will re-run again 2014 return false; // let specific event handler determine this function needs to be re-run again 2015 } 2016 2017 inline bool PVMFProtocolEngineNode::IsDataFlowEventAlreadyInQueue() 2018 { 2019 if (iInternalEventQueue.empty()) return false; 2020 2021 for (uint32 i = 0; i < iInternalEventQueue.size(); i++) 2022 { 2023 if ((uint32)iInternalEventQueue[i].iEventId >= (uint32)PVProtocolEngineNodeInternalEventType_IncomingMessageReady) return true; 2024 } 2025 return false; 2026 } 2027 2028 void PVMFProtocolEngineNode::ProtocolStateComplete(const ProtocolStateCompleteInfo &aInfo) 2029 { 2030 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateComplete); 2031 iInterfacingObjectContainer->setProtocolStateCompleteInfo(aInfo); 2032 //aEvent.iEventInfo = (OsclAny*)iInterfacingObjectContainer->getProtocolStateCompleteInfo(); 2033 DispatchInternalEvent(&aEvent); 2034 } 2035 2036 void PVMFProtocolEngineNode::OutputDataAvailable(OUTPUT_DATA_QUEUE &aOutputQueue, ProtocolEngineOutputDataSideInfo& aSideInfo) 2037 { 2038 OUTPUT_DATA_QUEUE *pOutput = &aOutputQueue; 2039 PVProtocolEngineNodeInternalEvent aEvent(aSideInfo, (OsclAny*)pOutput); 2040 DispatchInternalEvent(&aEvent); 2041 } 2042 2043 void PVMFProtocolEngineNode::ProtocolStateError(int32 aErrorCode) 2044 { 2045 if (iProtocol->isCurrentStateOptional()) 2046 { 2047 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing); 2048 DispatchInternalEvent(&aEvent); 2049 } 2050 else 2051 { 2052 ProtocolStateErrorInfo aInfo(aErrorCode); 2053 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo)); 2054 DispatchInternalEvent(&aEvent); 2055 } 2056 } 2057 2058 bool PVMFProtocolEngineNode::GetBufferForRequest(PVMFSharedMediaDataPtr &aMediaData) 2059 { 2060 return iNodeOutput->getBuffer(aMediaData); 2061 } 2062 2063 void PVMFProtocolEngineNode::ProtocolRequestAvailable(uint32 aRequestType) 2064 { 2065 uint32 aOutputType; 2066 if (aRequestType == ProtocolRequestType_Logging) 2067 { 2068 aOutputType = NodeOutputType_InputPortForLogging; 2069 } 2070 else 2071 { 2072 aOutputType = NodeOutputType_InputPortForData; 2073 } 2074 2075 iNodeOutput->flushData(aOutputType); 2076 } 2077 2078 2079 void PVMFProtocolEngineNode::OutputBufferPoolFull() 2080 { 2081 iProcessingState = ProcessingState_Idle; // hold off any data flow until the output buffer callback 2082 } 2083 2084 void PVMFProtocolEngineNode::OutputBufferAvailable() 2085 { 2086 if (iPortOut && !iPortOut->IsOutgoingQueueBusy()) 2087 { 2088 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByBufferAvailability); 2089 iInternalEventQueue.push_back(aEvent); 2090 SetProcessingState(ProcessingState_NormalDataflow); 2091 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::OutputBufferAvailable() - MemCallBackReturn")); 2092 } 2093 2094 if (iPortInForData) 2095 { 2096 if (iPortInForData->IncomingMsgQueueSize() > 0) 2097 { 2098 PVMFPortActivity activity(iPortInForData, PVMF_PORT_ACTIVITY_INCOMING_MSG); 2099 QueuePortActivity(activity); 2100 } 2101 } 2102 } 2103 2104 void PVMFProtocolEngineNode::ReadyToUpdateDownloadControl() 2105 { 2106 iProtocolContainer->doInfoUpdate(PROCESS_SUCCESS); 2107 } 2108 2109 bool PVMFProtocolEngineNode::QueueOutgoingMsgSentComplete(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg, const PVMFStatus aStatus) 2110 { 2111 if (aStatus == PVMFErrBusy) return false; 2112 if (aStatus == PVMFSuccess) return true; 2113 2114 // for other status, PVMFSuccessOutgoingMsgSent, and other failures, and just complete the command process. 2115 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::QueueOutgoingMsgSentComplete() - Msg queued and sent successfully!, Port=0x%x, status=%d", aPort, aStatus)); 2116 if (aStatus == PVMFSuccessOutgoingMsgSent) iInterfacingObjectContainer->setLatestPacketNumSent(aMsg->getSeqNum()); 2117 RerunForPostProcessAfterOutgoingMsgSent(aPort, aMsg); 2118 return (aStatus == PVMFSuccessOutgoingMsgSent); 2119 } 2120 2121 void PVMFProtocolEngineNode::TimeoutOccurred(int32 timerID, int32 timeoutInfo) 2122 { 2123 OSCL_UNUSED_ARG(timeoutInfo); 2124 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::TimeoutOccurred() timerID = %d, (0-server response, 1-inactivity, 2-KeepAlive, 3-Logging response, 4-Wall clock, 5-Buffer status timer), iInterfaceState=%d", 2125 timerID, (int32)iInterfaceState)); 2126 2127 iProtocolContainer->handleTimeout(timerID); 2128 } 2129 2130 2131 // create iProtocolContainer, iProtocol and iNodeOutput and all other protocol related projects 2132 bool PVMFProtocolEngineNode::CreateProtocolObjects(OsclAny* &aProtocolInfo) 2133 { 2134 AutoCleanup cleanup(this); // cleanup's destructor will automatically call DeleteProtocolObjects() if failure happens 2135 2136 // use PE node registry to create protocol container 2137 DeleteProtocolObjects(); 2138 iProtocolContainer = iRegistry.CreateProtocolEngineContainer(aProtocolInfo, this); 2139 if (!iProtocolContainer) return false; 2140 iProtocolContainer->setObserver(this); 2141 2142 // use protocol container to create all other protocol objects 2143 if (!iProtocolContainer->createProtocolObjects()) return false; 2144 2145 // create the rest projects for node use itself 2146 if (!CreateRestObjects()) return false; 2147 2148 cleanup.cancel(); 2149 return true; 2150 } 2151 2152 2153 bool PVMFProtocolEngineNode::RecheckProtocolObjects(OsclAny* aSourceData, OsclAny* aPluginInfo) 2154 { 2155 uint32 isProgressiveStreaming = (uint32)iProtocolContainer->isStreamingPlayback(); 2156 if (isProgressiveStreaming == (uint32)aPluginInfo) return true; 2157 2158 // in case of progressive streaming 2159 DeleteProtocolObjects(); 2160 OsclAny* aNewPluginInfo = (OsclAny*)isProgressiveStreaming; 2161 if (!CreateProtocolObjects(aNewPluginInfo)) return false; 2162 2163 // add source data again 2164 return iProtocolContainer->addSourceData(aSourceData); 2165 } 2166 2167 bool PVMFProtocolEngineNode::CreateRestObjects() 2168 { 2169 // create iPortConfigFSInfoAlloc for redirect port config 2170 iPortConfigFSInfoAlloc = OSCL_NEW(OsclRefCounterMemFragAlloc, (&iPortConfigMemPool)); 2171 if (!iPortConfigFSInfoAlloc) return false; 2172 2173 // create event handlers 2174 return CreateEventHandlers(); 2175 } 2176 2177 2178 bool PVMFProtocolEngineNode::CreateEventHandlers() 2179 { 2180 iEventHandlers[0] = OSCL_NEW(HttpHeaderAvailableHandler, (this)); 2181 if (!iEventHandlers[0]) return false; 2182 iEventHandlers[1] = OSCL_NEW(FirstPacketAvailableHandler, (this)); 2183 if (!iEventHandlers[1]) return false; 2184 iEventHandlers[2] = OSCL_NEW(NormalDataAvailableHandler, (this)); 2185 if (!iEventHandlers[2]) return false; 2186 iEventHandlers[3] = OSCL_NEW(ProtocolStateCompleteHandler, (this)); 2187 if (!iEventHandlers[3]) return false; 2188 iEventHandlers[4] = OSCL_NEW(EndOfDataProcessingHandler, (this)); 2189 if (!iEventHandlers[4]) return false; 2190 iEventHandlers[5] = OSCL_NEW(ServerResponseErrorBypassingHandler, (this)); 2191 if (!iEventHandlers[5]) return false; 2192 iEventHandlers[6] = OSCL_NEW(ProtocolStateErrorHandler, (this)); 2193 if (!iEventHandlers[6]) return false; 2194 iEventHandlers[7] = OSCL_NEW(CheckResumeNotificationHandler, (this)); 2195 if (!iEventHandlers[7]) return false; 2196 iEventHandlers[8] = OSCL_NEW(OutgoingMsgSentSuccessHandler, (this)); 2197 if (!iEventHandlers[8]) return false; 2198 2199 iEventHandlers[EVENT_HANDLER_TOTAL-1] = OSCL_NEW(NormalDataFlowHandler, (this)); 2200 if (!iEventHandlers[EVENT_HANDLER_TOTAL-1]) return false; 2201 return true; 2202 } 2203 2204 void PVMFProtocolEngineNode::DeleteProtocolObjects() 2205 { 2206 if (iProtocolContainer) 2207 { 2208 iProtocolContainer->deleteProtocolObjects(); 2209 //delete iProtocolContainer 2210 iRegistry.ReleaseProtocolEngineContainer(iProtocolContainer); 2211 } 2212 iProtocolContainer = NULL; 2213 DeleteRestObjects(); 2214 } 2215 2216 2217 void PVMFProtocolEngineNode::DeleteRestObjects() 2218 { 2219 if (iPortConfigFSInfoAlloc) OSCL_DELETE(iPortConfigFSInfoAlloc); 2220 iPortConfigFSInfoAlloc = NULL; 2221 2222 for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++) 2223 { 2224 if (iEventHandlers[i]) OSCL_DELETE(iEventHandlers[i]); 2225 iEventHandlers[i] = NULL; 2226 } 2227 2228 iInterfacingObjectContainer = NULL; 2229 iNodeTimer = NULL; 2230 iProtocol = NULL; 2231 iNodeOutput = NULL; 2232 iDownloadControl = NULL; 2233 iDownloadProgess = NULL; 2234 iUserAgentField = NULL; 2235 iEventReport = NULL; 2236 } 2237 2238 void PVMFProtocolEngineNode::ClearPorts(const bool aNeedDelete) 2239 { 2240 // clear queued messages in ports 2241 uint32 i; 2242 for (i = 0; i < iPortVector.size(); i++) iPortVector[i]->ClearMsgQueues(); 2243 2244 // Discard any port activity events 2245 iPortActivityQueue.clear(); 2246 2247 if (aNeedDelete) 2248 { 2249 while (!iPortVector.empty()) 2250 { 2251 PVMFProtocolEnginePort* port = iPortVector.front(); 2252 iPortVector.Erase(&iPortVector.front()); 2253 2254 if (port == iPortInForData) iPortInForData = NULL; 2255 if (port == iPortInForLogging) iPortInForLogging = NULL; 2256 if (port == iPortOut) iPortOut = NULL; 2257 } 2258 // Restore original port vector reserve. 2259 iPortVector.Reconstruct(); 2260 } 2261 } 2262 2263 void PVMFProtocolEngineNode::Clear(const bool aNeedDelete) 2264 { 2265 if (iProtocolContainer) iProtocolContainer->doClear(aNeedDelete); 2266 if (aNeedDelete) DeleteProtocolObjects(); 2267 2268 } 2269 2270 void PVMFProtocolEngineNode::ResetClear(const bool aNeedDelete) 2271 { 2272 if (iProtocolContainer) iProtocolContainer->doClear(aNeedDelete); 2273 if (iProtocolContainer) iProtocolContainer->deleteProtocolObjects(); 2274 DeleteRestObjects(); 2275 // leave iProtocolContainer undeleted 2276 2277 } 2278 2279 void PVMFProtocolEngineNode::StopClear() 2280 { 2281 if (iProtocolContainer) iProtocolContainer->doStopClear(); 2282 } 2283 2284 void PVMFProtocolEngineNode::CancelClear() 2285 { 2286 if (iProtocolContainer) iProtocolContainer->doCancelClear(); 2287 } 2288 2289 ////////// PVMFDataSourceInitializationExtensionInterface implementation //////////////////////// 2290 PVMFStatus PVMFProtocolEngineNode::SetSourceInitializationData(OSCL_wString& aSourceURL, 2291 PVMFFormatType& aSourceFormat, 2292 OsclAny* aSourceData) 2293 { 2294 // check supported protocol plugin 2295 if (!iRegistry.CheckPluginAvailability(aSourceFormat, aSourceData)) return PVMFErrNotSupported; 2296 2297 // create protocol objects 2298 OsclAny *aPluginInfo = NULL; 2299 if (!CreateProtocolObjects(aPluginInfo)) return PVMFErrNoMemory; 2300 2301 // check and add source data 2302 if (!iProtocolContainer->addSourceData(aSourceData)) return PVMFFailure; 2303 2304 // need to recreate protocol objects for progressive streaming based on source data 2305 if (!RecheckProtocolObjects(aSourceData, aPluginInfo)) return PVMFErrNoMemory; 2306 2307 // get references of all the necessary objects from iProtocolContainer 2308 GetObjects(); 2309 2310 // set download format 2311 if (iInterfacingObjectContainer) iInterfacingObjectContainer->setDownloadFormat(aSourceFormat); 2312 2313 // set URI 2314 if (!iInterfacingObjectContainer->getURIObject().setURI(aSourceURL)) return PVMFFailure; 2315 2316 2317 // create and set iCfgFile 2318 if (!iProtocolContainer->createCfgFile(iInterfacingObjectContainer->getURIObject().getURI())) return PVMFFailure; 2319 2320 return PVMFSuccess; 2321 } 2322 2323 2324 PVMFStatus PVMFProtocolEngineNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock) 2325 { 2326 if (iDownloadControl) 2327 { 2328 iDownloadControl->setSupportObject((OsclAny *)aClientClock, DownloadControlSupportObjectType_EnginePlaybackClock); 2329 return PVMFSuccess; 2330 } 2331 return PVMFFailure; 2332 } 2333 2334 2335 // From PVMIDatastreamuserInterface 2336 void PVMFProtocolEngineNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory, int32 aFactoryTag, const PvmfMimeString* aFactoryConfig) 2337 { 2338 OSCL_UNUSED_ARG(aFactoryTag); 2339 OSCL_UNUSED_ARG(aFactoryConfig); 2340 iInterfacingObjectContainer->setDataStreamFactory(&aFactory); 2341 } 2342 2343 2344 // From PVMFProtocolEngineNodeExtensionInterface 2345 PVMFStatus PVMFProtocolEngineNode::GetHTTPHeader(uint8*& aHeader, uint32& aHeaderLen) 2346 { 2347 iInterfacingObjectContainer->getHTTPHeader(aHeader, aHeaderLen); 2348 return PVMFSuccess; 2349 } 2350 2351 bool PVMFProtocolEngineNode::GetSocketConfig(OSCL_String &aPortConfig) 2352 { 2353 if (CheckUsingProxy(aPortConfig)) return true; 2354 return GetSocketConfigImp(iInterfacingObjectContainer->getURIObject(), aPortConfig); 2355 } 2356 2357 bool PVMFProtocolEngineNode::GetSocketConfigForLogging(OSCL_String &aPortConfig) 2358 { 2359 if (CheckUsingProxy(aPortConfig)) return true; 2360 return GetSocketConfigImp(iInterfacingObjectContainer->getLoggingURIObject(), aPortConfig); 2361 } 2362 2363 bool PVMFProtocolEngineNode::GetSocketConfigImp(const INetURI &aURI, OSCL_String &aPortConfig) 2364 { 2365 INetURI *pURI = &((INetURI &)aURI); 2366 if (pURI->empty()) return false; 2367 2368 OSCL_HeapString<OsclMemAllocator> serverAddr; 2369 int32 serverPort = 0; 2370 if (!pURI->getHostAndPort(serverAddr, serverPort)) return false; 2371 2372 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, \ 2373 (0, "PVMFProtocolEngineNode::GetSocketConfigImp(), serverAddr=%s , serverPort=%d", \ 2374 serverAddr.get_cstr(), serverPort)); 2375 2376 return ComposeSocketConfig(serverAddr, serverPort, aPortConfig); 2377 } 2378 2379 bool PVMFProtocolEngineNode::ComposeSocketConfig(OSCL_String &aServerAddr, const uint32 aPortNum, OSCL_String &aPortConfig) 2380 { 2381 // compose port config string: "TCP/remote_address=pvs.pv.com;remote_port=554" 2382 uint32 tempBufSize = aServerAddr.get_size() + 64; 2383 OsclMemAllocator alloc; 2384 char *buffer = (char*)alloc.allocate(tempBufSize); 2385 if (!buffer) return false; 2386 oscl_snprintf(buffer, tempBufSize, "TCP/remote_address="); 2387 oscl_strcat(buffer, aServerAddr.get_cstr()); 2388 OSCL_FastString port(_STRLIT_CHAR(";remote_port=")); 2389 oscl_strcat(buffer, port.get_cstr()); 2390 char portString[16]; 2391 oscl_snprintf(portString, 16, "%d", aPortNum); 2392 oscl_strcat(buffer, (char*)portString); 2393 2394 aPortConfig = OSCL_HeapString<OsclMemAllocator> (buffer, oscl_strlen(buffer)); 2395 alloc.deallocate(buffer); 2396 return true; 2397 } 2398 2399 2400 bool PVMFProtocolEngineNode::CheckUsingProxy(OSCL_String &aPortConfig) 2401 { 2402 uint32 aProxyPort = 0; 2403 OSCL_HeapString<OsclMemAllocator> aProxyName; 2404 if (!getProxy(aProxyName, aProxyPort)) return false; 2405 iInterfacingObjectContainer->getURIObject().setUsAbsoluteURI(); 2406 iInterfacingObjectContainer->getLoggingURIObject().setUsAbsoluteURI(); 2407 return ComposeSocketConfig(aProxyName, aProxyPort, aPortConfig); 2408 } 2409 2410 bool PVMFProtocolEngineNode::getProxy(OSCL_String& aProxyName, uint32 &aProxyPort) 2411 { 2412 if (!iProtocolContainer) return false; 2413 return iProtocolContainer->getProxy(aProxyName, aProxyPort); 2414 } 2415 2416 2417 bool PVMFProtocolEngineNode::SetUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable) 2418 { 2419 // assume setsourceinit API already gets called 2420 if (!iUserAgentField) return false; 2421 return iUserAgentField->setUserAgent(aUserAgent, isOverwritable); 2422 } 2423 2424 void PVMFProtocolEngineNode::SetHttpVersion(const uint32 aHttpVersion) 2425 { 2426 if (iProtocolContainer) iProtocolContainer->setHttpVersion(aHttpVersion); 2427 } 2428 2429 void PVMFProtocolEngineNode::SetHttpExtensionHeaderField(OSCL_String &aFieldKey, OSCL_String &aFieldValue, const HttpMethod aMethod, const bool aPurgeOnRedirect) 2430 { 2431 if (iProtocolContainer) iProtocolContainer->setHttpExtensionHeaderField(aFieldKey, aFieldValue, aMethod, aPurgeOnRedirect); 2432 } 2433 2434 void PVMFProtocolEngineNode::SetLoggingURL(OSCL_wString& aSourceURL) 2435 { 2436 iInterfacingObjectContainer->setLoggingURI(aSourceURL); 2437 } 2438 2439 void PVMFProtocolEngineNode::SetNetworkTimeout(const uint32 aTimeout) 2440 { 2441 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkTimeout(), responseTimeout=%d", aTimeout)); 2442 uint32 timeout = aTimeout; 2443 if ((int32)timeout < 0) timeout = 0x7fffffff; 2444 if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID, timeout); 2445 } 2446 2447 void PVMFProtocolEngineNode::SetNetworkLoggingTimeout(const uint32 aTimeout) 2448 { 2449 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkLoggingTimeout(), loggingTimeout=%d", aTimeout)); 2450 uint32 timeout = aTimeout; 2451 if ((int32)timeout < 0) timeout = 0x7fffffff; 2452 if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING, timeout); 2453 } 2454 2455 bool PVMFProtocolEngineNode::IsWMServerVersion4() 2456 { 2457 if (iProtocol) 2458 { 2459 return (iProtocol->getServerVersionNum() < DEFAULT_MS_HTTP_STREAMING_SERVER_VERSION); 2460 } 2461 return false; 2462 } 2463 2464 2465 void PVMFProtocolEngineNode::setFormatDownloadSupportInterface(PVMFFormatProgDownloadSupportInterface* download_support_interface) 2466 { 2467 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setFormatDownloadSupportInterface() IN, download_support_interface=0x%x", download_support_interface)); 2468 2469 if (iDownloadControl && iDownloadProgess) 2470 { 2471 iDownloadControl->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface); 2472 iDownloadProgess->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface); 2473 2474 PVMFDownloadProgressInterface *aProgDownload = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this); 2475 iDownloadControl->setSupportObject((OsclAny *)aProgDownload, DownloadControlSupportObjectType_ProgressInterface); 2476 } 2477 } 2478 2479 void PVMFProtocolEngineNode::setClipDuration(const uint32 aClipDurationMsec) 2480 { 2481 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setClipDuration(), aClipDurationMsec = %dms", aClipDurationMsec)); 2482 2483 if (iDownloadControl) iDownloadControl->setClipDuration(aClipDurationMsec); 2484 if (iDownloadProgess) iDownloadProgess->setClipDuration(aClipDurationMsec); 2485 } 2486 2487 OsclSharedPtr<PVMFMediaClock> PVMFProtocolEngineNode::getDownloadProgressClock() 2488 { 2489 OsclSharedPtr<PVMFMediaClock> clock; 2490 iDownloadControl->getDownloadClock(clock); 2491 return clock; 2492 } 2493 2494 void PVMFProtocolEngineNode::requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete) 2495 { 2496 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification() IN, currentNPTReadPosition=%d", currentNPTReadPosition)); 2497 2498 bool needSendUnderflowEvent = false; 2499 iDownloadControl->requestResumeNotification(currentNPTReadPosition, aDownloadComplete, needSendUnderflowEvent); 2500 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification(), after iDownloadControl->requestResumeNotification(), currentNPTReadPosition=%d, needSendUnderflowEvent=%d, aDownloadComplete=%d", 2501 currentNPTReadPosition, (uint32)needSendUnderflowEvent, (uint32)aDownloadComplete)); 2502 2503 // report underflow event for download incomplete 2504 // but only send it once, for multiple back to back requestResumeNotification 2505 if (!aDownloadComplete && needSendUnderflowEvent) ReportInfoEvent(PVMFInfoUnderflow); 2506 2507 if (aDownloadComplete) // end of processing 2508 { 2509 EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo(); 2510 aInfo->clear(); 2511 aInfo->iSendResumeNotification = true; 2512 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo); 2513 iInternalEventQueue.push_back(aEvent); 2514 SetProcessingState(ProcessingState_NormalDataflow); 2515 RunIfNotReady(); 2516 } 2517 2518 // check the need of sending resume notification manually 2519 iProtocolContainer->checkSendResumeNotification(); 2520 } 2521 2522 void PVMFProtocolEngineNode::cancelResumeNotification() 2523 { 2524 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::cancelResumeNotification")); 2525 2526 if (iDownloadControl != NULL) 2527 { 2528 iDownloadControl->cancelResumeNotification(); 2529 } 2530 } 2531 2532 bool PVMFProtocolEngineNode::SendPortMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging) 2533 { 2534 // Create an output media command 2535 PVMFSharedMediaCmdPtr aCmdPtr = PVMFMediaCmd::createMediaCmd(); 2536 2537 // Set the input format ID 2538 aCmdPtr->setFormatID(aCmdId); 2539 2540 // check format specific info 2541 if (!CheckFormatSpecificInfoForMediaCommand(aCmdPtr, aCmdId, isForLogging)) return false; 2542 2543 // Convert to media message and send it out 2544 PVMFSharedMediaMsgPtr mediaMsgOut; 2545 convertToPVMFMediaCmdMsg(mediaMsgOut, aCmdPtr); 2546 PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut); 2547 if (status < PVMFSuccess) return false; 2548 if (status == PVMFSuccessOutgoingMsgSent) 2549 { 2550 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SendPortMediaCommand() - Msg queued and sent successfully!, Port=0x%x", aPort)); 2551 RerunForPostProcessAfterOutgoingMsgSent(aPort, mediaMsgOut); 2552 } 2553 2554 LogPortMediaCmdQueued(aPort, aCmdId); 2555 return true; 2556 } 2557 2558 void PVMFProtocolEngineNode::RerunForPostProcessAfterOutgoingMsgSent(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg) 2559 { 2560 // form PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully event 2561 OutgoingMsgSentSuccessInfo aInfo(aPort, aMsg); 2562 OutgoingMsgSentSuccessInfoVec *aVec = iInterfacingObjectContainer->getOutgoingMsgSentSuccessInfoVec(); 2563 aVec->push_back(aInfo); 2564 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully, 2565 (OsclAny*)aVec); 2566 iInternalEventQueue.push_back(aEvent); 2567 SetProcessingState(ProcessingState_NormalDataflow); 2568 RunIfNotReady(); 2569 } 2570 2571 void PVMFProtocolEngineNode::LogPortMediaCmdQueued(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId) 2572 { 2573 // log message 2574 if (aCmdId == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID) 2575 { 2576 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RECONNECT SENT, Port=0x%x", aPort)); 2577 } 2578 else if (aCmdId == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 2579 { 2580 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - EOS SENT, Port=0x%x", aPort)); 2581 } 2582 else if (aCmdId == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID) 2583 { 2584 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RE_CONFIG SENT, Port=0x%x", aPort)); 2585 } 2586 else if (aCmdId == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID) 2587 { 2588 LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - DISCONNECT SENT, Port=0x%x", aPort)); 2589 } 2590 2591 OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable 'aPort' 2592 2593 } 2594 2595 2596 bool PVMFProtocolEngineNode::CheckFormatSpecificInfoForMediaCommand(PVMFSharedMediaCmdPtr &aCmdPtr, PVUid32 aCmdId, const bool isForLogging) 2597 { 2598 if (aCmdId != PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID) return true; 2599 2600 // for socket recconnect command, set port config as format specific info 2601 bool needAttachFormatSpecificInfo = false; 2602 OSCL_HeapString<OsclMemAllocator> aPortConfig; 2603 if (iInterfacingObjectContainer->getCurrNumRedirectTrials() > 0 || iInterfaceState == EPVMFNodePaused) 2604 { 2605 bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty(); 2606 if (isForLogging && hasLoggingUrl) 2607 { 2608 if (!GetSocketConfigForLogging(aPortConfig)) return false; 2609 } 2610 else 2611 { 2612 if (!GetSocketConfig(aPortConfig)) return false; 2613 } 2614 needAttachFormatSpecificInfo = true; 2615 } 2616 else if (iInterfacingObjectContainer->isDownloadStreamingDone()) 2617 { 2618 bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty(); 2619 if (hasLoggingUrl) 2620 { 2621 if (!GetSocketConfigForLogging(aPortConfig)) return false; 2622 } 2623 else 2624 { 2625 if (!GetSocketConfig(aPortConfig)) return false; 2626 } 2627 needAttachFormatSpecificInfo = true; 2628 } 2629 2630 if (needAttachFormatSpecificInfo) 2631 { 2632 OsclRefCounterMemFrag socketConfigMemfrag; 2633 int32 err = 0; 2634 OSCL_TRY(err, socketConfigMemfrag = iPortConfigFSInfoAlloc->allocate(aPortConfig.get_size() + 1)); 2635 if (err) return false; 2636 oscl_memcpy((char*)(socketConfigMemfrag.getMemFragPtr()), aPortConfig.get_cstr(), aPortConfig.get_size()); 2637 char *ptr = (char*)socketConfigMemfrag.getMemFragPtr() + aPortConfig.get_size(); 2638 *ptr = 0; // make it string 2639 aCmdPtr->setFormatSpecificInfo(socketConfigMemfrag); 2640 } 2641 return true; 2642 } 2643 2644 OSCL_EXPORT_REF PVMFStatus PVMFProtocolEngineNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo) 2645 { 2646 return iProtocolContainer->getMediaPresentationInfo(aInfo); 2647 } 2648 2649 PVMFStatus PVMFProtocolEngineNode::SelectTracks(PVMFMediaPresentationInfo& aInfo) 2650 { 2651 return iProtocolContainer->selectTracks(aInfo); 2652 } 2653 2654 void PVMFProtocolEngineNode::ReportEvent(PVMFEventType aEventType, OsclAny* aEventData, const int32 aEventCode, OsclAny* aEventLocalBuffer, const uint32 aEventLocalBufferSize) 2655 { 2656 ReportInfoEvent(aEventType, aEventData, aEventCode, aEventLocalBuffer, aEventLocalBufferSize); 2657 } 2658 2659 void PVMFProtocolEngineNode::NotifyContentTooLarge() 2660 { 2661 // before error out, settle down the interaction with parser node 2662 iDownloadControl->checkResumeNotification(false); 2663 2664 ProtocolStateErrorInfo aInfo(PVMFErrContentTooLarge); 2665 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo)); 2666 DispatchInternalEvent(&aEvent); 2667 } 2668 2669 uint32 PVMFProtocolEngineNode::GetObserverState() 2670 { 2671 return (uint32)iInterfaceState; 2672 } 2673 2674 void PVMFProtocolEngineNode::SetObserverState(const uint32 aState) 2675 { 2676 iInterfaceState = (TPVMFNodeInterfaceState)aState; 2677 } 2678 2679 bool PVMFProtocolEngineNode::DispatchEvent(PVProtocolEngineNodeInternalEvent *aEvent) 2680 { 2681 return DispatchInternalEvent(aEvent); 2682 } 2683 2684 bool PVMFProtocolEngineNode::SendMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging) 2685 { 2686 return SendPortMediaCommand(aPort, aCmdId, isForLogging); 2687 } 2688 2689 void PVMFProtocolEngineNode::ClearRest(const bool aNeedDelete) 2690 { 2691 iDataInQueue.clear(); 2692 ClearPorts(aNeedDelete); // clear any queued messages in ports 2693 } 2694 2695 void PVMFProtocolEngineNode::RecheduleDataFlow() 2696 { 2697 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByCommand); 2698 iInternalEventQueue.push_back(aEvent); 2699 iProcessingState = ProcessingState_NormalDataflow; 2700 iInterfacingObjectContainer->setInputDataUnwanted(false); 2701 RunIfNotReady(); 2702 } 2703 2704 void PVMFProtocolEngineNode::SendManualResumeNotificationEvent() 2705 { 2706 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_CheckResumeNotificationMaually); 2707 iInternalEventQueue.clear(); 2708 iInternalEventQueue.push_back(aEvent); 2709 SetProcessingState(ProcessingState_NormalDataflow); 2710 RunIfNotReady(); 2711 } 2712 2713 bool PVMFProtocolEngineNode::IsRepositionCmdPending() 2714 { 2715 PVMFProtocolEngineNodeCommand *pInputCmd = FindCmd(iInputCommands, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION); 2716 PVMFProtocolEngineNodeCommand *pPendingCmd = FindCmd(iCurrentCommand, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION); 2717 2718 return (pInputCmd || pPendingCmd); 2719 } 2720 2721 PVMFProtocolEngineNodeCommand* PVMFProtocolEngineNode::FindPendingCmd(int32 aCmdId) 2722 { 2723 return FindCmd(iCurrentCommand, aCmdId); 2724 } 2725 2726 void PVMFProtocolEngineNode::CompletePendingCmd(int32 status) 2727 { 2728 CommandComplete(iCurrentCommand, iCurrentCommand.front(), status); 2729 } 2730 2731 void PVMFProtocolEngineNode::CompleteInputCmd(PVMFProtocolEngineNodeCommand& aCmd, int32 status) 2732 { 2733 CommandComplete(iInputCommands, aCmd, status); 2734 } 2735 2736 void PVMFProtocolEngineNode::ErasePendingCmd(PVMFProtocolEngineNodeCommand *aCmd) 2737 { 2738 iCurrentCommand.Erase(aCmd); 2739 } 2740 2741 void PVMFProtocolEngineNode::GetObjects() 2742 { 2743 iProtocol = (HttpBasedProtocol*)iProtocolContainer->getObject(NodeObjectType_Protocol); 2744 iNodeOutput = (PVMFProtocolEngineNodeOutput*)iProtocolContainer->getObject(NodeObjectType_Output); 2745 iDownloadControl = (DownloadControlInterface*)iProtocolContainer->getObject(NodeObjectType_DownloadControl); 2746 iDownloadProgess = (DownloadProgressInterface*)iProtocolContainer->getObject(NodeObjectType_DownloadProgress); 2747 iEventReport = (EventReporter*)iProtocolContainer->getObject(NodeObjectType_EventReport); 2748 iCfgFileContainer = (PVDlCfgFileContainer*)iProtocolContainer->getObject(NodeObjectType_DlCfgFileContainer); 2749 iDownloadSource = (PVMFDownloadDataSourceContainer*)iProtocolContainer->getObject(NodeObjectType_DataSourceContainer); 2750 iNodeTimer = (PVMFProtocolEngineNodeTimer*)iProtocolContainer->getObject(NodeObjectType_Timer); 2751 iInterfacingObjectContainer = (InterfacingObjectContainer*)iProtocolContainer->getObject(NodeObjectType_InterfacingObjectContainer); 2752 iUserAgentField = (UserAgentField*)iProtocolContainer->getObject(NodeObjectType_UseAgentField); 2753 } 2754 2755 //////////////////////////////////////////////////////////////////////////////////// 2756 ////// PVProtocolEngineNodeInternalEventHandler implementation 2757 //////////////////////////////////////////////////////////////////////////////////// 2758 2759 PVProtocolEngineNodeInternalEventHandler::PVProtocolEngineNodeInternalEventHandler(PVMFProtocolEngineNode *aNode) : iNode(aNode) 2760 { 2761 iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG); 2762 } 2763 2764 bool PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(PVProtocolEngineNodeInternalEvent &aEvent) 2765 { 2766 int32 errorCode = (int32)aEvent.iEventInfo; 2767 if (iNode->iCurrentCommand.size() > 0) 2768 { 2769 if (IsPVMFErrCode(errorCode)) // basic error event 2770 { 2771 iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), errorCode); 2772 } 2773 else // extension error event 2774 { 2775 PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID; 2776 int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode); 2777 char *errEventData = NULL; 2778 uint32 errEventDataLen = 0; 2779 handleErrResponse(basePVMFErrorCode, errorCode, errEventData, errEventDataLen); 2780 iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), basePVMFErrorCode, errEventData, &uuid, &errorCode, errEventDataLen); 2781 LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d", 2782 basePVMFErrorCode, errorCode)); 2783 } 2784 } 2785 else 2786 { 2787 // report error event 2788 if (IsPVMFErrCode(errorCode)) 2789 iNode->ReportErrorEvent(errorCode); 2790 else 2791 { 2792 int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode, false); // false for error event 2793 char *errEventData = NULL; 2794 uint32 eventDataLen = 0; 2795 handleErrResponse(basePVMFErrorCode, errorCode, errEventData, eventDataLen); 2796 iNode->ReportErrorEvent(basePVMFErrorCode, errEventData, errorCode, eventDataLen); 2797 LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d", 2798 basePVMFErrorCode, errorCode)); 2799 } 2800 } 2801 2802 iNode->SetState(EPVMFNodeError); 2803 iNode->StopClear(); 2804 //iNode->iProcessingState = ProcessingState_Idle; 2805 2806 if (!iNode->iInputCommands.empty()) 2807 { 2808 if (iNode->IsAdded()) iNode->RunIfNotReady(); 2809 } 2810 2811 return true; 2812 } 2813 2814 int32 PVProtocolEngineNodeInternalEventHandler::getBasePVMFErrorReturnCode(const int32 errorCode, const bool isForCommandComplete) 2815 { 2816 int32 pvmfReturnCode = PVMFFailure; 2817 if (!isForCommandComplete) pvmfReturnCode = PVMFErrProcessing; // if not for command complete, should for error event 2818 if (iNode->iProtocolContainer->isHTTP409ForLowDiskSpace(errorCode)) pvmfReturnCode = PVMFLowDiskSpace; 2819 2820 switch (errorCode) 2821 { 2822 case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerNoResponce: 2823 case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerInactivity: 2824 pvmfReturnCode = PVMFErrTimeout; 2825 break; 2826 2827 case PVProtocolEngineNodeErrorHTTPErrorCode401: 2828 case PVProtocolEngineNodeErrorHTTPErrorCode407: 2829 case PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm: 2830 pvmfReturnCode = PVMFErrHTTPAuthenticationRequired; 2831 break; 2832 2833 case PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType: 2834 pvmfReturnCode = PVMFErrNotSupported; 2835 break; 2836 2837 case PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit: 2838 if (iNode->iInterfacingObjectContainer->getNumRedirectTrials() == 0) 2839 { 2840 pvmfReturnCode = PVMFErrRedirect; 2841 } 2842 break; 2843 default: 2844 break; 2845 } 2846 2847 return pvmfReturnCode; 2848 } 2849 2850 void PVProtocolEngineNodeInternalEventHandler::handleErrResponse(int32 &aBaseCode, int32 &errCode, char* &aEventData, uint32 &aEventDataLen) 2851 { 2852 if (aBaseCode == PVMFErrRedirect) 2853 { 2854 handleRedirectErrResponse(aEventData, aEventDataLen); 2855 } 2856 else 2857 { 2858 handleAuthenErrResponse(errCode, aEventData, aEventDataLen); 2859 aBaseCode = getBasePVMFErrorReturnCode(errCode); 2860 } 2861 } 2862 2863 void PVProtocolEngineNodeInternalEventHandler::handleAuthenErrResponse(int32 &aErrCode, char* &aEventData, uint32 &aEventDataLen) 2864 { 2865 aEventData = NULL; 2866 aEventDataLen = 0; 2867 if (aErrCode == PVProtocolEngineNodeErrorHTTPErrorCode401) 2868 { 2869 if (false == iNode->iProtocol->isServerSendAuthenticationHeader()) 2870 { 2871 aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_NoAuthenticationHeader; 2872 return; 2873 } 2874 2875 if (false == iNode->iProtocol->isServerSupportBasicAuthentication()) 2876 { 2877 aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType; 2878 return; 2879 } 2880 2881 if (iNode->iProtocol->getAuthenInfo(iAuthenInfoRealm)) 2882 { 2883 aEventData = (char*)iAuthenInfoRealm.get_cstr(); 2884 aEventDataLen = iAuthenInfoRealm.get_size() + 1; //Incremented by one to save c string terminating char ('\0') 2885 } 2886 else 2887 { 2888 aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm; 2889 } 2890 } 2891 } 2892 2893 void PVProtocolEngineNodeInternalEventHandler::handleRedirectErrResponse(char* &aEventData, uint32 &aEventDataLen) 2894 { 2895 aEventData = NULL; 2896 aEventDataLen = 0; 2897 // set the new url into info event 2898 OSCL_HeapString<OsclMemAllocator> newUrl; 2899 iNode->iProtocol->getRedirectURI(newUrl); 2900 2901 // then set this value 2902 iNode->iInterfacingObjectContainer->setURI(newUrl, true); 2903 iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject()); 2904 2905 aEventData = (char*)iNode->iInterfacingObjectContainer->getURIObject().getURI().get_cstr(); 2906 aEventDataLen = iNode->iInterfacingObjectContainer->getURIObject().getURI().get_size() + 1; 2907 } 2908 2909 inline bool PVProtocolEngineNodeInternalEventHandler::isCurrEventMatchCurrPendingCommand(uint32 aCurrEventId) 2910 { 2911 if (iNode->iCurrentCommand.empty()) return false; 2912 PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front(); 2913 2914 // matching logic for event vs. pending command 2915 // init or prepare command 2916 if ((aCmd.iCmd == PVMF_GENERIC_NODE_INIT || 2917 aCmd.iCmd == PVMF_GENERIC_NODE_PREPARE) && 2918 (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete || 2919 aCurrEventId == PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing)) return true; 2920 2921 // start command 2922 if (aCmd.iCmd == PVMF_GENERIC_NODE_START && 2923 aCurrEventId == PVProtocolEngineNodeInternalEventType_HttpHeaderAvailable) return true; 2924 2925 // stop command 2926 if (aCmd.iCmd == PVMF_GENERIC_NODE_STOP && 2927 (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete || 2928 aCurrEventId == PVProtocolEngineNodeInternalEventType_EndOfProcessing)) return true; 2929 2930 // seek or bitstream switch command 2931 if ((aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_SEEK || 2932 aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH) && 2933 (aCurrEventId == PVProtocolEngineNodeInternalEventType_FirstPacketAvailable)) return true; 2934 2935 return false; // no matching 2936 } 2937 2938 // return value: true means completing pending command; false means no matching 2939 bool PVProtocolEngineNodeInternalEventHandler::completePendingCommand(PVProtocolEngineNodeInternalEvent &aEvent) 2940 { 2941 if (aEvent.iEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateError) 2942 { 2943 return completePendingCommandWithError(aEvent); 2944 } 2945 if (!isCurrEventMatchCurrPendingCommand((uint32)aEvent.iEventId)) return false; 2946 2947 PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front(); 2948 iNode->SetState(SetStateByCommand[aCmd.iCmd-(int32)PVMF_GENERIC_NODE_INIT]); 2949 iNode->CommandComplete(iNode->iCurrentCommand, aCmd, PVMFSuccess); 2950 return true; 2951 } 2952 2953 bool PVProtocolEngineNodeInternalEventHandler::isBeingStopped(const int32 aStatus) 2954 { 2955 // stopped, stop command is completed and node state is changed to prepared state 2956 if (iNode->iInterfacingObjectContainer->isWholeSessionDone() && 2957 iNode->iInterfaceState == EPVMFNodePrepared) return true; 2958 2959 // being stopped, stop command is pending plus protcol state complete 2960 return (iNode->iInterfacingObjectContainer->isWholeSessionDone() && 2961 isStopCmdPending() && 2962 isProtocolStateComplete(aStatus)); 2963 } 2964 2965 inline bool PVProtocolEngineNodeInternalEventHandler::isStopCmdPending() 2966 { 2967 for (uint32 i = 0; i < iNode->iCurrentCommand.size(); i++) 2968 { 2969 if (iNode->iCurrentCommand[i].iCmd == PVMF_GENERIC_NODE_STOP) return true; 2970 } 2971 return false; 2972 } 2973 2974 inline bool PVProtocolEngineNodeInternalEventHandler::isProtocolStateComplete(const int32 aStatus) 2975 { 2976 return (aStatus == PROCESS_SUCCESS_END_OF_MESSAGE || 2977 aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA || 2978 aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED || 2979 aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT); 2980 } 2981 2982 bool ProtocolStateErrorHandler::needCompletePendingCommandAtThisRound(PVProtocolEngineNodeInternalEvent &aEvent) 2983 { 2984 // get error code if necessary 2985 ProtocolStateErrorInfo *aInfo = (ProtocolStateErrorInfo *)aEvent.iEventInfo; 2986 if (aInfo->iUseInputErrorCode) iErrorCode = aInfo->iErrorCode; 2987 2988 // check if complete pending command at this round is needed 2989 if (!aInfo->iUseInputErrorCode) return true; // use previous error code, for sure complete pending command 2990 return !iNode->iProtocolContainer->needSendEOSDuetoError(iErrorCode); 2991 } 2992 2993 bool ProtocolStateErrorHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 2994 { 2995 if (!needCompletePendingCommandAtThisRound(aEvent)) 2996 { 2997 // send EOS message to downstream node, and doesn't complete pending command at all 2998 iNode->StopClear(); 2999 iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_EOS_FORMAT_ID); // enqueuing EOS should be successful 3000 return true; 3001 } 3002 3003 int32 errorCode = iErrorCode; 3004 if (errorCode == 0) return true; 3005 if (NeedHandleContentRangeUnmatch(errorCode)) return true; 3006 3007 if (errorCode < 0) 3008 { 3009 int32 nodeErrorEventTypeCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - errorCode); 3010 if (!IsPVMFErrCode(errorCode)) aEvent.iEventInfo = (OsclAny*)nodeErrorEventTypeCode; // convert to PVProtocolEngineNodeErrorEventType error code 3011 else aEvent.iEventInfo = (OsclAny*)errorCode; 3012 completePendingCommand(aEvent); 3013 } 3014 else 3015 { 3016 int32 errCode = checkRedirectHandling(errorCode); 3017 if (errCode == 0) 3018 { 3019 iErrorCode = 0; 3020 return true; 3021 } 3022 3023 // command complete with error or error event 3024 aEvent.iEventInfo = (OsclAny*)errCode; 3025 completePendingCommand(aEvent); 3026 } 3027 3028 return true; 3029 } 3030 3031 // return value: 0 means caller needs to return immediately, not 0 means error 3032 int32 ProtocolStateErrorHandler::checkRedirectHandling(const int32 aErrorCode) 3033 { 3034 bool isInfoEvent = true; 3035 int32 errCode = parseServerResponseCode(aErrorCode, isInfoEvent); 3036 uint32 numRedirectTrials = iNode->iInterfacingObjectContainer->getNumRedirectTrials(); 3037 uint32 numCurrRedirectTrials = iNode->iInterfacingObjectContainer->getCurrNumRedirectTrials(); 3038 3039 if (isInfoEvent && ++numCurrRedirectTrials <= numRedirectTrials) 3040 { 3041 iNode->iInterfacingObjectContainer->setCurrNumRedirectTrials(numCurrRedirectTrials); 3042 3043 if (handleRedirect()) 3044 { 3045 // set the new url into info event 3046 OSCL_HeapString<OsclMemAllocator> url(iNode->iInterfacingObjectContainer->getURIObject().getURI()); 3047 iNode->ReportInfoEvent(PVMFInfoRemoteSourceNotification, (OsclAny*)(url.get_cstr()), errCode); 3048 return 0; 3049 } 3050 3051 // treat it as error 3052 errCode = aErrorCode + PVProtocolEngineNodeErrorEventStart; 3053 } 3054 3055 if (isInfoEvent && numCurrRedirectTrials > numRedirectTrials) 3056 { 3057 // redirect trials out of limit 3058 errCode = PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit; 3059 } 3060 3061 return errCode; 3062 } 3063 3064 3065 int32 ProtocolStateErrorHandler::parseServerResponseCode(const int32 aErrorCode, bool &isInfoEvent) 3066 { 3067 isInfoEvent = true; 3068 int32 errCode = aErrorCode; 3069 // redirect code 3xx 3070 if (errCode >= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_START && 3071 errCode <= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_END) 3072 { 3073 errCode += PVMFPROTOCOLENGINENODEInfo_Redirect; 3074 } 3075 else 3076 { 3077 errCode += PVProtocolEngineNodeErrorEventStart; 3078 isInfoEvent = false; 3079 } 3080 return errCode; 3081 } 3082 3083 bool ProtocolStateErrorHandler::NeedHandleContentRangeUnmatch(const int32 aErrorCode) 3084 { 3085 if (aErrorCode == PROCESS_CONTENT_RANGE_INFO_NOT_MATCH) 3086 { 3087 if (!handleContentRangeUnmatch()) return false; 3088 return true; 3089 } 3090 return false; 3091 } 3092 3093 bool ProtocolStateErrorHandler::handleContentRangeUnmatch() 3094 { 3095 return iNode->iProtocolContainer->handleContentRangeUnmatch(); 3096 } 3097 3098 bool ProtocolStateErrorHandler::handleRedirect() 3099 { 3100 // Get redirect url 3101 OSCL_HeapString<OsclMemAllocator> newUrl; 3102 if (iNode->iProtocol->getRedirectURI(newUrl) && newUrl.get_size() > 0) 3103 { 3104 // then set info to protocol 3105 iNode->iInterfacingObjectContainer->setURI(newUrl, true); 3106 iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject()); 3107 iNode->iProtocolContainer->reconnectSocket(); 3108 // Activate so processing will continue 3109 iNode->iEventReport->startRealDataflow(); 3110 iNode->SetProcessingState(ProcessingState_NormalDataflow); 3111 return true; 3112 } 3113 return false; 3114 } 3115 3116 bool HttpHeaderAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3117 { 3118 // enable info update for download 3119 iNode->iProtocolContainer->enableInfoUpdate(); 3120 3121 // get Http header 3122 OUTPUT_DATA_QUEUE aHttpHeader = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData); 3123 uint32 headerLength = iNode->iInterfacingObjectContainer->setHttpHeader(aHttpHeader); 3124 bool status = true; 3125 if (iNode->iProtocol && headerLength > 0) 3126 { 3127 uint32 length = iNode->iProtocol->getContentLength(); 3128 iNode->iInterfacingObjectContainer->setFileSize(length); 3129 iNode->iNodeOutput->setContentLength(length); 3130 status = iNode->iProtocolContainer->downloadUpdateForHttpHeaderAvailable(); 3131 } 3132 3133 // check PVMFInfoContentLength, PVMFErrContentTooLarge and PVMFInfoContentTruncated before completing the command 3134 iNode->iEventReport->checkContentInfoEvent(PROCESS_SUCCESS); 3135 3136 // complete start command if it is not completed 3137 if (completePendingCommand(aEvent)) 3138 { 3139 iNode->iEventReport->startRealDataflow(); 3140 } 3141 3142 return status; 3143 } 3144 3145 bool FirstPacketAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3146 { 3147 uint32 aFirstPacketNumber = (uint32)aEvent.iEventInfo; 3148 3149 // first packet number is only needed in seek or bitstream switching 3150 if (iNode->iInterfaceState == EPVMFNodeStarted && iNode->iCurrentCommand.size() > 0) 3151 { 3152 PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front(); 3153 3154 // for bitstream switching command, guarantee completing command AFTER sending RE_CONFIG port command 3155 if (aFirstPacketNumber == 0xFFFFFFFF && aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH) 3156 { 3157 return completePendingCommand(aEvent); 3158 } 3159 3160 //extract the parameters. 3161 uint64 aNPTInMS; 3162 uint32 *aFirstSeqNumAfterSeekOrSwitch; 3163 aCmd.PVMFProtocolEngineNodeCommand::Parse(aNPTInMS, aFirstSeqNumAfterSeekOrSwitch); 3164 *aFirstSeqNumAfterSeekOrSwitch = aFirstPacketNumber; 3165 3166 // send RE_CONFIG port command or complete seek command 3167 if (aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH) 3168 { 3169 // send RE_CONFIG port command 3170 iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID); 3171 } 3172 else // for seek command, complete the command 3173 { 3174 return completePendingCommand(aEvent); 3175 } 3176 } 3177 return true; 3178 } 3179 bool NormalDataAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3180 { 3181 OUTPUT_DATA_QUEUE aOutputData; 3182 if (aEvent.iEventData) aOutputData = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData); 3183 if (iNode->iNodeOutput) iNode->iNodeOutput->passDownNewOutputData(aOutputData, aEvent.iEventInfo); 3184 3185 if (!iNode->IsDataFlowEventAlreadyInQueue()) 3186 { 3187 PVProtocolEngineNodeInternalEvent newEvent(PVProtocolEngineNodeInternalEventType_OutputDataReady); 3188 iNode->iInternalEventQueue.push_back(newEvent); 3189 } 3190 iNode->RunIfNotReady(); 3191 return true; 3192 } 3193 3194 bool ProtocolStateCompleteHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3195 { 3196 bool aSessionDone = iNode->iInterfacingObjectContainer->isWholeSessionDone(); 3197 bool aDownloadStreamingDone = iNode->iInterfacingObjectContainer->isDownloadStreamingDone(); 3198 bool aEOSArrived = iNode->iInterfacingObjectContainer->isEOSAchieved(); 3199 3200 LOGINFODATAPATH((0, "ProtocolStateCompleteHandler::handle() : iNode->iInterfaceState = %d, sessionDone=%d,DownloadStreamingDone=%d,EOSArrived=%d", 3201 iNode->iInterfaceState, (uint32)aSessionDone, (uint32)aDownloadStreamingDone, (uint32)aEOSArrived)); 3202 3203 OSCL_UNUSED_ARG(aSessionDone); 3204 OSCL_UNUSED_ARG(aDownloadStreamingDone); 3205 OSCL_UNUSED_ARG(aEOSArrived); 3206 return iNode->iProtocolContainer->handleProtocolStateComplete(aEvent, this); 3207 } 3208 3209 bool NormalDataFlowHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3210 { 3211 OSCL_UNUSED_ARG(aEvent); 3212 3213 // First check and flush output data 3214 int32 statusFlushData = iNode->iNodeOutput->flushData(); 3215 if (!flushDataPostProcessing(statusFlushData)) return false; 3216 3217 // send reconnect cmd for logging request for stop or EOS packet received 3218 if (!handleEOSLogging()) return false; 3219 3220 // Second, run state machine to continue data processing 3221 iNode->iProcessingState = ProcessingState_NormalDataflow; 3222 if (iNode->iDataInQueue.size() > 0) LOGINFODATAPATH((0, "NormalDataFlowHandler::handle() : iNode->iDataInQueue.size() = %d", iNode->iDataInQueue.size())); 3223 int32 status = iNode->iProtocol->runStateMachine(iNode->iDataInQueue); 3224 if (status < 0 || statusFlushData != PROCESS_SUCCESS || iNode->iInterfaceState == EPVMFNodeError) return false; 3225 3226 // handle EOS 3227 if (handleEOS(status)) return true; 3228 3229 // handle end of processing, e.g., stop 3230 if (handleEndOfProcessing(status)) return true; 3231 3232 // check the next action, go to next protocol state 3233 return dataFlowContinue(status); 3234 } 3235 3236 bool NormalDataFlowHandler::dataFlowContinue(const int32 aStatus) 3237 { 3238 // info update for download and for streaming, 3239 if (!iNode->iProtocolContainer->doInfoUpdate(aStatus)) return false; 3240 3241 // go to next protocol state for end of message in current protocol state 3242 // The reason for making this call explicit is, when end of message happens (protocol state complete), 3243 // the node still needs some information from current state to do some extra work, like the above 3244 // download control update and info events processing. If we make this call implicit or hidden and 3245 // right after ProtcolStateComplete(), then the above info processing would fail. 3246 if (isReadyGotoNextState(aStatus)) iNode->iProtocol->gotoNextState(); 3247 3248 3249 if (iNode->iDataInQueue.empty() && iNode->iPortInForData->IncomingMsgQueueSize() > 0) 3250 { 3251 iNode->ProcessIncomingMsg(iNode->iPortInForData); 3252 } 3253 3254 if (iNode->iDataInQueue.size() > 0) 3255 { 3256 if (!iNode->IsDataFlowEventAlreadyInQueue()) 3257 { 3258 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_HasExtraInputData); 3259 iNode->iInternalEventQueue.push_back(aEvent); 3260 } 3261 iNode->RunIfNotReady(); 3262 return true; 3263 } 3264 3265 if (aStatus == PROCESS_WAIT_FOR_INCOMING_DATA) return false; 3266 return true; 3267 } 3268 3269 inline bool NormalDataFlowHandler::isReadyGotoNextState(const int32 aStatus) 3270 { 3271 return (aStatus == PROCESS_SUCCESS_END_OF_MESSAGE && 3272 !iNode->iInterfacingObjectContainer->isWholeSessionDone() && 3273 iNode->iInterfaceState != EPVMFNodePaused); 3274 } 3275 3276 bool NormalDataFlowHandler::flushDataPostProcessing(const int32 aStatusFlushData) 3277 { 3278 // status is ok or need sending new request, then no post processing 3279 if (aStatusFlushData == PROCESS_SUCCESS || iNode->iProtocol->isSendingNewRequest()) return true; 3280 3281 // post processing only occur for output port failure 3282 if (aStatusFlushData == PROCESS_OUTPUT_TO_OUTPUT_PORT_FAILURE) 3283 { 3284 3285 if (iNode->iNodeOutput->isPortBusy()) iNode->iProcessingState = ProcessingState_Idle; 3286 3287 // since queuing mesage for port outgoing queue fails, check the connected port state and try send 3288 if (!iNode->iPortOut->IsConnectedPortBusy()) iNode->ProcessOutgoingMsg(iNode->iPortOut); 3289 3290 // if port failure is due to no memory for media data, reset inactivity timer to prevent unnessary timeout 3291 if (!iNode->iPortOut->IsOutgoingQueueBusy() && // this means port failure is due to no memory 3292 iNode->iInterfaceState != EPVMFNodePaused && 3293 (iNode->iDataInQueue.size() > 0 || iNode->iPortInForData->IncomingMsgQueueSize() > 0)) 3294 { 3295 LOGINFODATAPATH((0, "NormalDataFlowHandler::flushDataPostProcessing() : iNode->iDataInQueue.size()=%d, iNode->iPortInForData->IncomingMsgQueueSize()=%d", 3296 iNode->iDataInQueue.size(), iNode->iPortInForData->IncomingMsgQueueSize())); 3297 iNode->iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout 3298 } 3299 } 3300 return false; 3301 } 3302 3303 bool NormalDataFlowHandler::handleEOSLogging() 3304 { 3305 if (iNode->iInterfacingObjectContainer->isDownloadStreamingDone() && 3306 !iSendSocketReconnect && 3307 iNode->iPortInForLogging) 3308 { 3309 // reconnect first 3310 if (!iNode->SendPortMediaCommand(iNode->iPortInForLogging, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false; 3311 iNode->iProtocol->sendRequest(); 3312 iSendSocketReconnect = true; 3313 3314 // start stop/eos logging timer at this point to protect itself from the case where logging request 3315 // cannot be sent out due to connected port busy. For this case, logging timer timeout will help keep going 3316 iNode->iNodeTimer->start(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING); 3317 LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOSLogging() server stop/eos logging response timer starts! timerID=3, timeoutValue=%d", 3318 iNode->iNodeTimer->getTimeout(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING))); 3319 } 3320 else if (!iNode->iInterfacingObjectContainer->isDownloadStreamingDone()) 3321 { 3322 // reset the flag 3323 iSendSocketReconnect = false; 3324 } 3325 return true; 3326 } 3327 3328 bool NormalDataFlowHandler::handleEOS(const int32 aStatus) 3329 { 3330 if (aStatus != PROCESS_SUCCESS_GOT_EOS) return false; 3331 3332 if (//(iNode->iInterfaceState==EPVMFNodeStarted || iNode->iInterfaceState==EPVMFNodePrepared || iNode->iInterfaceState==EPVMFNodeInitialized) && 3333 !iNode->iInterfacingObjectContainer->isDownloadStreamingDone()) // only issue socket reconnect during the streaming 3334 { 3335 LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOS() : status == PROCESS_SUCCESS_GOT_EOS")); 3336 iNode->iProtocolContainer->doEOS(false); 3337 3338 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowBySendRequestAction); 3339 iNode->iInternalEventQueue.push_back(aEvent); 3340 iNode->RunIfNotReady(); 3341 return true; 3342 } 3343 3344 return false; 3345 } 3346 3347 bool NormalDataFlowHandler::handleEndOfProcessing(const int32 aStatus) 3348 { 3349 if (!isBeingStopped(aStatus)) return false; 3350 3351 // use end of processing event to streamline all end of processing cases for stop 3352 EndOfDataProcessingInfo *aEOPInfo = iNode->iInterfacingObjectContainer->getEOPInfo(); 3353 aEOPInfo->clear(); 3354 aEOPInfo->iStreamingDone = true; 3355 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo); 3356 iNode->DispatchInternalEvent(&aEvent); 3357 return true; 3358 } 3359 3360 bool EndOfDataProcessingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3361 { 3362 EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo; 3363 if (!aInfo) return true; 3364 3365 if (aInfo->iSendResumeNotification) 3366 { 3367 iNode->iDownloadControl->checkResumeNotification(); 3368 iNode->iNodeTimer->clear(); 3369 LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), send resume notification to parser node, for DOWNLOAD COMPLETE")); 3370 } 3371 if (aInfo->iExtraDataComeIn) 3372 { 3373 iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA); 3374 LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFUnexpectedData info event after DOWNLOAD COMPLETE")); 3375 } 3376 if (aInfo->iSendServerDisconnectEvent) 3377 { 3378 iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT); 3379 LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFInfoSessionDisconnect info event after DOWNLOAD COMPLETE")); 3380 } 3381 if (aInfo->iStreamingDone || aInfo->iForceStop) 3382 { 3383 cleanupForStop(aEvent); 3384 LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), handle the remaining stuff for EOS or stop")); 3385 } 3386 3387 aInfo->clear(); 3388 iNode->iProcessingState = ProcessingState_Idle; 3389 return true; 3390 } 3391 3392 void EndOfDataProcessingHandler::cleanupForStop(PVProtocolEngineNodeInternalEvent &aEvent) 3393 { 3394 EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo; 3395 if (isBeingStopped() || aInfo->iForceStop) 3396 { 3397 completePendingCommand(aEvent); 3398 iNode->iProtocol->stop(true); 3399 iNode->StopClear(); 3400 } 3401 } 3402 3403 bool ServerResponseErrorBypassingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3404 { 3405 completePendingCommand(aEvent); 3406 iNode->iProtocol->gotoNextState(); 3407 //iNode->iProcessingState = ProcessingState_Idle; 3408 return true; 3409 } 3410 3411 bool CheckResumeNotificationHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3412 { 3413 OSCL_UNUSED_ARG(aEvent); 3414 3415 // double check if the reposition request is pending or not 3416 if (iNode->IsRepositioningRequestPending()) return true; 3417 3418 if (iNode->iDownloadControl->checkResumeNotification(false) == 1) // false means download is not complete yet 3419 { 3420 LOGINFODATAPATH((0, "CheckResumeNotificationHandler::handle(), send resume notification to parser node, in case of MBDS getting full in progressive streaming")); 3421 // report data ready event 3422 iNode->iEventReport->sendDataReadyEvent(); 3423 } 3424 return true; 3425 } 3426 3427 bool OutgoingMsgSentSuccessHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent) 3428 { 3429 OutgoingMsgSentSuccessInfoVec *aVec = (OutgoingMsgSentSuccessInfoVec*)aEvent.iEventInfo; 3430 if (!aVec || aVec->empty()) return false; 3431 bool retVal = (iNode->PostProcessForMsgSentSuccess(aVec->front().iPort, aVec->front().iMsg) == PVMFSuccess); 3432 if (!aVec->empty()) aVec->erase(aVec->begin()); 3433 return retVal; 3434 } 3435 3436 3437 3438