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 22 #include "pvlogger.h" 23 #include "oscl_utf8conv.h" 24 25 /** 26 //Macros for calling PVLogger 27 */ 28 #define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); 29 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m); 30 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m); 31 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m); 32 #define LOGINFO(m) LOGINFOMED(m) 33 #define LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m); 34 #define LOGERRORDATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m); 35 #define LOGINFOCLOCK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iClockLogger,PVLOGMSG_INFO,m); 36 #define PVMF_PROTOCOL_ENGINE_LOGBIN(iPortLogger, m) PVLOGGER_LOGBIN(PVLOGMSG_INST_LLDBG, iPortLogger, PVLOGMSG_ERR, m); 37 #define NODEDATAPATHLOGGER_TAG "datapath.sourcenode.protocolenginenode" 38 39 //////////////////////////////////////////////////////////////////////////////////// 40 ////// ProtocolContainer implementation 41 //////////////////////////////////////////////////////////////////////////////////// 42 43 // constructor 44 OSCL_EXPORT_REF ProtocolContainer::ProtocolContainer(PVMFProtocolEngineNode *aNode) : iNode(aNode) 45 { 46 clear(); 47 iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG); 48 } 49 50 OSCL_EXPORT_REF void ProtocolContainer::clear() 51 { 52 iProtocol = NULL; 53 iNodeOutput = NULL; 54 iDownloadControl = NULL; 55 iDownloadProgess = NULL; 56 iEventReport = NULL; 57 iCfgFileContainer = NULL; 58 iDownloadSource = NULL; 59 iNodeTimer = NULL; 60 iInterfacingObjectContainer = NULL; 61 iUserAgentField = NULL; 62 iPortInForData = iPortInForLogging = iPortOut = NULL; 63 iInternalEventQueue = NULL; 64 } 65 66 OSCL_EXPORT_REF OsclAny* ProtocolContainer::getObject(const NodeObjectType aObjectType) 67 { 68 switch (aObjectType) 69 { 70 case NodeObjectType_Protocol: 71 return (OsclAny*)iProtocol; 72 break; 73 74 case NodeObjectType_Output: 75 return (OsclAny*)iNodeOutput; 76 break; 77 78 case NodeObjectType_DownloadControl: 79 return (OsclAny*)iDownloadControl; 80 break; 81 82 case NodeObjectType_DownloadProgress: 83 return (OsclAny*)iDownloadProgess; 84 break; 85 86 case NodeObjectType_EventReport: 87 return (OsclAny*)iEventReport; 88 break; 89 90 case NodeObjectType_DlCfgFileContainer: 91 return (OsclAny*)iCfgFileContainer; 92 break; 93 94 case NodeObjectType_DataSourceContainer: 95 return (OsclAny*)iDownloadSource; 96 break; 97 98 case NodeObjectType_Timer: 99 return (OsclAny*)iNodeTimer; 100 break; 101 102 case NodeObjectType_InterfacingObjectContainer: 103 return (OsclAny*)iInterfacingObjectContainer; 104 break; 105 106 case NodeObjectType_UseAgentField: 107 return (OsclAny*)iUserAgentField; 108 break; 109 110 default: 111 break; 112 } 113 return NULL; 114 } 115 116 OSCL_EXPORT_REF bool ProtocolContainer::isObjectsReady() 117 { 118 if (!iProtocol || 119 !iNodeOutput || 120 !iInterfacingObjectContainer || 121 iInterfacingObjectContainer->getURIObject().empty() || 122 !iInterfacingObjectContainer->getDataStreamFactory() || 123 !iPortInForData) return false; 124 return true; 125 } 126 127 OSCL_EXPORT_REF void ProtocolContainer::setSupportObject(OsclAny* aSupportObject, const uint32 aType) 128 { 129 switch ((NodeObjectType)aType) 130 { 131 case NodeObjectType_InputPortForData: 132 iPortInForData = (PVMFProtocolEnginePort*)aSupportObject; 133 break; 134 135 case NodeObjectType_InputPortForLogging: 136 iPortInForLogging = (PVMFProtocolEnginePort*)aSupportObject; 137 break; 138 139 case NodeObjectType_OutPort: 140 iPortOut = (PVMFProtocolEnginePort*)aSupportObject; 141 break; 142 143 case NodeObjectType_InternalEventQueue: 144 iInternalEventQueue = (Oscl_Vector<PVProtocolEngineNodeInternalEvent, PVMFProtocolEngineNodeAllocator>*)aSupportObject; 145 break; 146 default: 147 break; 148 } 149 } 150 151 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::doPrepare() 152 { 153 return initImpl(); 154 } 155 156 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::initImpl() 157 { 158 if (!isObjectsReady()) 159 { 160 return PVMFErrNotReady; 161 } 162 163 // initialize output object 164 int32 status = initNodeOutput(); 165 if (status != PVMFSuccess) return status; 166 167 // initialize protocol object 168 if (!initProtocol()) return PVMFFailure; 169 170 // initialize download control object 171 initDownloadControl(); 172 173 // start data flow 174 // if the current socket connection is down, then do socket reconnect 175 bool needSocketReconnect = !iInterfacingObjectContainer->isSocketConnectionUp(); 176 startDataFlowByCommand(needSocketReconnect); 177 178 return PVMFPending; 179 } 180 181 182 OSCL_EXPORT_REF bool ProtocolContainer::initProtocol() 183 { 184 // then pass objects to protocol object (note that the order matters) 185 iProtocol->setURI(iInterfacingObjectContainer->getURIObject()); 186 187 // update user-agent field 188 if (!initProtocol_SetConfigInfo()) return false; 189 iProtocol->setObserver(iNode); 190 191 // protocol initialization and objects dispatch 192 iProtocol->initialize(); 193 return true; 194 } 195 196 OSCL_EXPORT_REF PVMFStatus ProtocolContainer::doStop() 197 { 198 // send socket disconnect command if necessary 199 sendSocketDisconnectCmd(); 200 201 // disable sending logging message, but try to disconnect socket 202 // use end of processing event to streamline all end of processing cases for stop 203 EndOfDataProcessingInfo *aEOPInfo = iInterfacingObjectContainer->getEOPInfo(); 204 aEOPInfo->clear(); 205 aEOPInfo->iForceStop = true; 206 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo); 207 iObserver->DispatchEvent(&aEvent); 208 209 return PVMFSuccess; 210 } 211 212 OSCL_EXPORT_REF void ProtocolContainer::sendSocketDisconnectCmd() 213 { 214 if (iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)) 215 { 216 if (iPortInForData->Send()) 217 { 218 LOGINFODATAPATH((0, "ProtocolContainer::doStop()->sendSocketDisconnectCmd(), Send() SUCCESS: MsgID=%d(SOCKET DISCONNECT)", (uint32)PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)); 219 } 220 } 221 } 222 223 void ProtocolContainer::startDataFlowByCommand(const bool needDoSocketReconnect) 224 { 225 // flush out existing data at this point 226 checkEOSMsgFromInputPort(); 227 iObserver->ClearRest(); 228 229 // cancel all the existing timers 230 iNodeTimer->clear(); 231 232 // disable info update at this point, will be enabled when new response comes in 233 enableInfoUpdate(false); 234 235 // socket reconnect 236 if (needDoSocketReconnect) reconnectSocket(); 237 238 iObserver->RecheduleDataFlow(); 239 } 240 241 void ProtocolContainer::checkEOSMsgFromInputPort() 242 { 243 if (iPortInForData->IncomingMsgQueueSize() == 0) return; 244 245 // input port has media message 246 while (iPortInForData->IncomingMsgQueueSize() > 0) 247 { 248 PVMFSharedMediaMsgPtr msg; 249 PVMFStatus status = iPortInForData->DequeueIncomingMsg(msg); 250 if (status != PVMFSuccess) continue; 251 if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 252 { 253 iInterfacingObjectContainer->updateSocketConnectFlags(true); 254 return; 255 } 256 } 257 } 258 259 OSCL_EXPORT_REF void ProtocolContainer::doClear(const bool aNeedDelete) 260 { 261 iObserver->ClearRest(aNeedDelete); 262 if (iInternalEventQueue) iInternalEventQueue->clear(); 263 if (iInterfacingObjectContainer) iInterfacingObjectContainer->clear(); 264 if (iNodeTimer) iNodeTimer->clear(); 265 } 266 267 OSCL_EXPORT_REF void ProtocolContainer::doStopClear() 268 { 269 doClear(); 270 if (iDownloadControl) iDownloadControl->clear(); 271 iEventReport->clear(); 272 } 273 274 OSCL_EXPORT_REF void ProtocolContainer::doCancelClear() 275 { 276 iObserver->ClearRest(); 277 if (iInternalEventQueue) iInternalEventQueue->clear(); 278 if (iNodeTimer) iNodeTimer->clear(); 279 if (iDownloadControl) iDownloadControl->clear(); 280 if (iEventReport) iEventReport->clear(); 281 //if (iInterfacingObjectContainer) iInterfacingObjectContainer->setInputDataUnwanted(); 282 283 // if re-do cancelled command, start from sending http request 284 if (iProtocol) iProtocol->sendRequest(); 285 } 286 287 OSCL_EXPORT_REF bool ProtocolContainer::reconnectSocket(const bool aForceSocketReconnect) 288 { 289 if (!aForceSocketReconnect) 290 { 291 // Do not force to do socket reconnect, and then need to check the possibility 292 if (iInterfacingObjectContainer->isSocketReconnectCmdSent()) return true; 293 } 294 if (!iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false; 295 iProtocol->sendRequest(); 296 iInterfacingObjectContainer->setSocketReconnectCmdSent(); 297 return true; 298 } 299 300 OSCL_EXPORT_REF bool ProtocolContainer::doEOS(const bool isTrueEOS) 301 { 302 // download done 303 if (isTrueEOS) 304 { 305 iObserver->SendMediaCommand(iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID); 306 } 307 else // EOS packet hasn't been received, so re-connect socket 308 { 309 bool aForceSocketReconnect = false; 310 if (!iInterfacingObjectContainer->isPrevSocketConnectionUp()) 311 { 312 // the situation is, previous connection is down and the current connection is down. 313 // then force reconnect 314 aForceSocketReconnect = true; 315 } 316 reconnectSocket(aForceSocketReconnect); 317 } 318 319 return true; 320 } 321 322 OSCL_EXPORT_REF uint32 ProtocolContainer::getBitMaskForHTTPMethod(const HttpMethod aMethod) 323 { 324 uint32 bitMaskForHttpMethod = 0; 325 if (aMethod == HTTP_GET) bitMaskForHttpMethod = BITMASK_HTTPGET; 326 if (aMethod == HTTP_POST) bitMaskForHttpMethod = BITMASK_HTTPPOST; 327 if (aMethod == HTTP_HEAD) bitMaskForHttpMethod = BITMASK_HTTPHEAD; 328 if (aMethod == HTTP_ALLMETHOD) bitMaskForHttpMethod = ~0; 329 return bitMaskForHttpMethod; 330 } 331 332 OSCL_EXPORT_REF bool ProtocolContainer::createProtocolObjects() 333 { 334 // create iInterfacingObjectContainer 335 iInterfacingObjectContainer = OSCL_NEW(InterfacingObjectContainer, ()); 336 if (!iInterfacingObjectContainer) return false; 337 338 // create iNodeTimer 339 return createNetworkTimer(); 340 } 341 342 bool ProtocolContainer::createNetworkTimer() 343 { 344 iNodeTimer = PVMFProtocolEngineNodeTimer::create(iNode); 345 if (!iNodeTimer) return false; 346 iNodeTimer->set(SERVER_RESPONSE_TIMER_ID); 347 iNodeTimer->set(SERVER_INACTIVITY_TIMER_ID); 348 iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING); 349 iNodeTimer->set(WALL_CLOCK_TIMER_ID); 350 iNodeTimer->set(BUFFER_STATUS_TIMER_ID); 351 return true; 352 } 353 354 OSCL_EXPORT_REF void ProtocolContainer::deleteProtocolObjects() 355 { 356 if (iInterfacingObjectContainer) OSCL_DELETE(iInterfacingObjectContainer); 357 iInterfacingObjectContainer = NULL; 358 359 if (iNodeTimer) OSCL_DELETE(iNodeTimer); 360 iNodeTimer = NULL; 361 362 363 if (iProtocol) OSCL_DELETE(iProtocol); 364 iProtocol = NULL; 365 if (iNodeOutput) OSCL_DELETE(iNodeOutput); 366 iNodeOutput = NULL; 367 if (iDownloadControl) OSCL_DELETE(iDownloadControl); 368 iDownloadControl = NULL; 369 if (iDownloadProgess) OSCL_DELETE(iDownloadProgess); 370 iDownloadProgess = NULL; 371 if (iUserAgentField) OSCL_DELETE(iUserAgentField); 372 iUserAgentField = NULL; 373 if (iEventReport) OSCL_DELETE(iEventReport); 374 iEventReport = NULL; 375 } 376 377 OSCL_EXPORT_REF void ProtocolContainer::handleTimeout(const int32 timerID) 378 { 379 if (ignoreThisTimeout(timerID)) return; 380 handleTimeoutErr(timerID); 381 382 // currently for wm http streaming only 383 handleTimeoutInPause(timerID); 384 // may clean flags to cause handleTimeoutErr() to get excecuted, so move handleTimeoutErr() above 385 handleTimeoutInDownloadStreamingDone(timerID); 386 } 387 388 OSCL_EXPORT_REF bool ProtocolContainer::ignoreThisTimeout(const int32 timerID) 389 { 390 // check the end processing status: EOS recved and whole session is done 391 if (iInterfacingObjectContainer->isEOSAchieved() && 392 iInterfacingObjectContainer->isWholeSessionDone()) return true; 393 394 // Next, all focus on checking server inactivity timeout 395 if (timerID != (int32)SERVER_INACTIVITY_TIMER_ID) return false; 396 397 // inactivity timeout should be ignored in the following cases: 398 // (i) input/output port queue still has data, 399 // (ii) buffer full in progressive streaming 400 if (iPortInForData) 401 { 402 if (iPortInForData->IncomingMsgQueueSize() > 0) return true; 403 } 404 if (iPortOut) 405 { 406 if (iPortOut->OutgoingMsgQueueSize() > 0) return true; 407 } 408 409 if (iNodeOutput) 410 { 411 if (iNodeOutput->getAvailableOutputSize() == 0) return true; 412 } 413 return false; 414 } 415 416 bool ProtocolContainer::handleTimeoutErr(const int32 timerID) 417 { 418 if (iInterfacingObjectContainer->isDownloadStreamingDone() || 419 iObserver->GetObserverState() == EPVMFNodePaused) return false; 420 421 int32 timeoutErr = PVMFErrTimeout; 422 if (timerID == SERVER_RESPONSE_TIMER_ID) timeoutErr = PROCESS_TIMEOUT_SERVER_NO_RESPONCE; 423 if (timerID == SERVER_INACTIVITY_TIMER_ID) timeoutErr = PROCESS_TIMEOUT_SERVER_INACTIVITY; 424 425 ProtocolStateErrorInfo aInfo(timeoutErr); 426 PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo)); 427 iObserver->DispatchEvent(&aEvent); 428 return true; 429 } 430 431 OSCL_EXPORT_REF bool ProtocolContainer::handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler) 432 { 433 bool aSessionDone = iInterfacingObjectContainer->isWholeSessionDone(); 434 bool aDownloadStreamingDone = iInterfacingObjectContainer->isDownloadStreamingDone(); 435 OSCL_UNUSED_ARG(aDownloadStreamingDone); 436 bool aEOSArrived = iInterfacingObjectContainer->isEOSAchieved(); 437 438 iInterfacingObjectContainer->setInputDataUnwanted(); 439 if (aSessionDone) 440 { 441 // flush all the remaining output 442 iNodeOutput->flushData(); 443 iNodeTimer->clear(); 444 if (aEOSArrived && iInterfacingObjectContainer->getOutputPortConnect()) 445 { 446 doEOS(); // true EOS 447 return aEventHandler->completePendingCommand(aEvent); 448 } 449 } 450 return aEventHandler->completePendingCommand(aEvent); 451 } 452 453 454 //////////////////////////////////////////////////////////////////////////////////// 455 ////// PVMFProtocolEngineNodeOutput implementation 456 //////////////////////////////////////////////////////////////////////////////////// 457 458 // constructor 459 OSCL_EXPORT_REF PVMFProtocolEngineNodeOutput::PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNodeOutputObserver *aObserver) : 460 iPortIn(NULL), 461 iContentDataMemPool(NULL), 462 iMediaDataAlloc(NULL), 463 iMediaDataMemPool("PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNode)", 464 PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM, 465 PVHTTPDOWNLOADOUTPUT_MEDIADATA_CHUNKSIZE), 466 iObserver(aObserver), 467 iCurrTotalOutputSize(0) 468 469 { 470 iOutputFramesQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES); 471 iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode"); 472 iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG); 473 iClockLogger = PVLogger::GetLoggerObject("clock"); 474 iMediaDataMemPool.enablenullpointerreturn(); 475 } 476 477 OSCL_EXPORT_REF PVMFProtocolEngineNodeOutput::~PVMFProtocolEngineNodeOutput() 478 { 479 reset(); 480 } 481 482 // reset 483 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::reset() 484 { 485 iPortIn = NULL; 486 iLogger = NULL; 487 iDataPathLogger = NULL; 488 iClockLogger = NULL; 489 iOutputFramesQueue.clear(); 490 iMediaData.Unbind(); 491 deleteMemPool(); 492 } 493 494 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType) 495 { 496 if (aObjectType == NodeOutputType_InputPortForData && aOutputObject) iPortIn = (PVMFProtocolEnginePort *)aOutputObject; 497 } 498 499 500 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::sendToPort(PVMFSharedMediaDataPtr &aMediaData, const uint32 aPortType) 501 { 502 OSCL_UNUSED_ARG(aPortType); 503 return sendToDestPort(aMediaData, iPortIn); 504 } 505 506 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::createMediaData(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize) 507 { 508 // check if need to create memory pool 509 int32 errcode = OsclErrNone; 510 if (!iMediaDataAlloc) 511 { 512 errcode = createMemPool(); 513 if (errcode != PVMFSuccess) return false; 514 } 515 516 OsclSharedPtr<PVMFMediaDataImpl> mediadataImpl; 517 errcode = 0; 518 OSCL_TRY(errcode, mediadataImpl = iMediaDataAlloc->allocate(aRequestSize)); 519 if (errcode != OsclErrNone) return false; 520 521 522 // Then wrap it around with PVMFMediaData 523 iMediaData.Unbind(); 524 525 errcode = OsclErrNoResources; 526 527 iMediaData = PVMFMediaData::createMediaData(mediadataImpl, &iMediaDataMemPool); 528 529 if (iMediaData.GetRep() != NULL) 530 { 531 errcode = OsclErrNone; 532 } 533 534 if (errcode != OsclErrNone) return false; 535 536 aMediaData = iMediaData; 537 return true; 538 } 539 540 OSCL_EXPORT_REF PVMFStatus PVMFProtocolEngineNodeOutput::createMemPool() 541 { 542 // Create the memory pool 543 int32 errcode = 0; 544 OSCL_TRY(errcode, iContentDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM))); 545 if (errcode || iContentDataMemPool == NULL) return PVMFErrNoMemory; 546 547 548 OSCL_TRY(errcode, iMediaDataAlloc = OSCL_NEW(PVMFSimpleMediaBufferCombinedAlloc, (iContentDataMemPool))); 549 if (errcode || iMediaDataAlloc == NULL) return PVMFErrNoMemory; 550 551 return PVMFSuccess; 552 } 553 554 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::deleteMemPool() 555 { 556 // Cleanup output media data memory pool 557 if (iMediaDataAlloc != NULL) 558 { 559 OSCL_DELETE(iMediaDataAlloc); 560 iMediaDataAlloc = NULL; 561 } 562 563 if (iContentDataMemPool != NULL) 564 { 565 OSCL_DELETE(iContentDataMemPool); 566 iContentDataMemPool = NULL; 567 } 568 } 569 570 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::sendToDestPort(PVMFSharedMediaDataPtr &aMediaData, PVMFProtocolEnginePort *aPort) 571 { 572 // compute data frag size for log purposes 573 uint32 dataSize = 0; 574 uint32 numFrags = aMediaData->getNumFragments(); 575 for (uint32 i = 0; i < numFrags; i++) 576 { 577 OsclRefCounterMemFrag memFragIn; 578 aMediaData->getMediaFragment(i, memFragIn); 579 uint32 fragLen = memFragIn.getMemFrag().len; 580 dataSize += fragLen; 581 } 582 583 // Send frame to downstream node 584 PVMFSharedMediaMsgPtr mediaMsgOut; 585 convertToPVMFMediaMsg(mediaMsgOut, aMediaData); 586 587 LOGINFODATAPATH((0, "PVMFProtocolEngineNodeOutput::sendToDestPort() SEQNUM= %d, SIZE= %d, port = 0x%x", 588 mediaMsgOut->getSeqNum(), dataSize, aPort)); 589 590 PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut); 591 return iObserver->QueueOutgoingMsgSentComplete(aPort, mediaMsgOut, status); 592 } 593 594 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::passDownNewOutputData(OUTPUT_DATA_QUEUE &aOutputQueue, OsclAny* aSideInfo) 595 { 596 OSCL_UNUSED_ARG(aSideInfo); 597 int32 err = 0; 598 OSCL_TRY(err, iOutputFramesQueue.push_back(aOutputQueue);); 599 return (err == 0); 600 } 601 602 OSCL_EXPORT_REF int32 PVMFProtocolEngineNodeOutput::flushData(const uint32 aOutputType) 603 { 604 if (iMediaData.GetRep() == NULL) return PROCESS_SUCCESS; 605 606 // send to port 607 if (!sendToPort(iMediaData, aOutputType)) return PROCESS_OUTPUT_PORT_IS_BUSY; 608 iMediaData.Unbind(); 609 return PROCESS_SUCCESS; 610 } 611 612 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::getBuffer(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize) 613 { 614 if (!createMediaData(aMediaData, aRequestSize)) return false; 615 return true; 616 } 617 618 OSCL_EXPORT_REF void PVMFProtocolEngineNodeOutput::discardData(const bool aNeedReopen) 619 { 620 OSCL_UNUSED_ARG(aNeedReopen); 621 iOutputFramesQueue.clear(); 622 iMediaData.Unbind(); 623 } 624 625 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeOutput::isPortBusy() 626 { 627 return iPortIn->IsOutgoingQueueBusy(); 628 } 629 630 631 632 //////////////////////////////////////////////////////////////////////////////////// 633 ////// UserAgentField implementation 634 //////////////////////////////////////////////////////////////////////////////////// 635 // constructor 636 OSCL_EXPORT_REF UserAgentField::UserAgentField(OSCL_wString &aUserAgent, const bool isOverwritable) 637 { 638 setUserAgent(aUserAgent, isOverwritable); 639 } 640 641 OSCL_EXPORT_REF UserAgentField::UserAgentField(OSCL_String &aUserAgent, const bool isOverwritable) 642 { 643 setUserAgent(aUserAgent, isOverwritable); 644 } 645 646 // set user agent 647 OSCL_EXPORT_REF bool UserAgentField::setUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable) 648 { 649 iOverwritable = isOverwritable; 650 651 // check for empty string 652 if (aUserAgent.get_size() == 0) return true; 653 654 OsclMemAllocator alloc; 655 char *buf = (char*)alloc.allocate(aUserAgent.get_size() + 1); 656 if (!buf) return false; 657 uint32 size = 0; 658 if ((size = oscl_UnicodeToUTF8(aUserAgent.get_cstr(), aUserAgent.get_size(), buf, aUserAgent.get_size() + 1)) == 0) 659 { 660 alloc.deallocate(buf); 661 return false; 662 } 663 iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size); 664 alloc.deallocate(buf); 665 return true; 666 } 667 668 OSCL_EXPORT_REF bool UserAgentField::setUserAgent(OSCL_String &aUserAgent, const bool isOverwritable) 669 { 670 iOverwritable = isOverwritable; 671 // check for empty string 672 if (aUserAgent.get_size() == 0) return true; 673 674 iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (aUserAgent.get_str(), aUserAgent.get_size()); 675 return true; 676 } 677 678 // get the actual user agent (not wide string version) based on overwrite mode or replace mode (set the input user agent to the default one) 679 OSCL_EXPORT_REF bool UserAgentField::getUserAgent(OSCL_String &aUserAgent) 680 { 681 if (iActualUserAgent.get_size() > 0) 682 { 683 aUserAgent = iActualUserAgent; 684 return true; 685 } 686 687 // create iActualUserAgent at the first call 688 if (iOverwritable && iInputUserAgent.get_size() > 0) 689 { 690 iActualUserAgent = iInputUserAgent; 691 } 692 else // append 693 { 694 //OSCL_FastString defaultUserAgent(_STRLIT_CHAR("PVPlayer/4.0 (Beta release)")); 695 OSCL_HeapString<OsclMemAllocator> defaultUserAgent; 696 getDefaultUserAgent(defaultUserAgent); 697 uint32 size = defaultUserAgent.get_size() + iInputUserAgent.get_size() + 1; // 1 => space 698 OsclMemAllocator alloc; 699 char *buf = (char*)alloc.allocate(size + 1); 700 if (!buf) return false; 701 oscl_memcpy(buf, defaultUserAgent.get_cstr(), defaultUserAgent.get_size()); 702 buf[defaultUserAgent.get_size()] = PROTOCOLENGINENODE_SPACE_ASCIICODE; 703 if (iInputUserAgent.get_size() > 0) 704 { 705 oscl_memcpy(buf + defaultUserAgent.get_size() + 1, iInputUserAgent.get_cstr(), iInputUserAgent.get_size()); 706 } 707 buf[size] = 0; 708 iActualUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size); 709 alloc.deallocate(buf); 710 } 711 aUserAgent = iActualUserAgent; 712 return true; 713 } 714 715 //////////////////////////////////////////////////////////////////////////////////// 716 ////// EventReporter implementation 717 //////////////////////////////////////////////////////////////////////////////////// 718 OSCL_EXPORT_REF EventReporter::EventReporter(EventReporterObserver *aObserver) : iObserver(aObserver) 719 { 720 clear(); 721 iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG); 722 } 723 724 OSCL_EXPORT_REF void EventReporter::clear() 725 { 726 iStarted = false; 727 } 728 729 OSCL_EXPORT_REF void EventReporter::startRealDataflow() 730 { 731 iStarted = true; 732 } 733 734 735 //////////////////////////////////////////////////////////////////////////////////// 736 ////// InterfacingObjectContainer implementation 737 //////////////////////////////////////////////////////////////////////////////////// 738 739 // constructor 740 InterfacingObjectContainer::InterfacingObjectContainer() : 741 iDownloadFormat(PVMF_MIME_DATA_SOURCE_HTTP_URL), 742 iDataStreamFactory(NULL), 743 iNumBuffersInAllocator(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM), 744 iNumRedirectTrials(PVPROTOCOLENGINE_DEFAULT_NUMBER_OF_REDIRECT_TRIALS), 745 iNumBuffersInMediaDataPoolSMCalc(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM), 746 iCurrSocketConnection(true), 747 iPrevSocketConnection(true), 748 iLatestDataPacketNumSent(0), 749 iOutputPortConnected(false) 750 { 751 clear(); 752 iOutgoingMsgSentSuccessInfoVec.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE / 4); 753 } 754 755 // set and get http header 756 OSCL_EXPORT_REF uint32 InterfacingObjectContainer::setHttpHeader(OUTPUT_DATA_QUEUE &aHttpHeader) 757 { 758 iHttpHeaderLength = 0; 759 uint32 i = 0; 760 char *ptr = (char*)iHttpHeaderBuffer; 761 for (i = 0; i < aHttpHeader.size(); i++) 762 { 763 uint32 fragSize = aHttpHeader[i].getMemFragSize(); 764 oscl_memcpy(ptr, (char*)aHttpHeader[i].getMemFragPtr(), fragSize); 765 iHttpHeaderLength += fragSize; 766 ptr += fragSize; 767 } 768 iHttpHeaderBuffer[iHttpHeaderLength] = 0; 769 return iHttpHeaderLength; 770 } 771 772 OSCL_EXPORT_REF bool InterfacingObjectContainer::setStreamingProxy(OSCL_wString& aProxyName, const uint32 aProxyPort) 773 { 774 if (aProxyName.get_size() == 0) return false; 775 776 OsclMemAllocator alloc; 777 char *buf = (char*)alloc.allocate(aProxyName.get_size() + 1); 778 if (!buf) return false; 779 uint32 size = oscl_UnicodeToUTF8(aProxyName.get_cstr(), aProxyName.get_size(), buf, aProxyName.get_size() + 1); 780 if (size == 0) 781 { 782 alloc.deallocate(buf); 783 return false; 784 } 785 iProxyName = OSCL_HeapString<OsclMemAllocator> (buf, size); 786 iProxyPort = aProxyPort; 787 alloc.deallocate(buf); 788 return true; 789 } 790 791 OSCL_EXPORT_REF void InterfacingObjectContainer::setNumBuffersInMediaDataPoolSMCalc(uint32 aVal) 792 { 793 iNumBuffersInMediaDataPoolSMCalc = aVal; 794 } 795 796 797 //////////////////////////////////////////////////////////////////////////////////// 798 ////// PVMFProtocolEngineNodeTimer implementation 799 //////////////////////////////////////////////////////////////////////////////////// 800 801 OSCL_EXPORT_REF PVMFProtocolEngineNodeTimer* PVMFProtocolEngineNodeTimer::create(OsclTimerObserver *aObserver) 802 { 803 PVMFProtocolEngineNodeTimer *timer = OSCL_NEW(PVMFProtocolEngineNodeTimer, ()); 804 if (!timer) return NULL; 805 if (!timer->construct(aObserver)) 806 { 807 OSCL_DELETE(timer); 808 return NULL; 809 } 810 return timer; 811 } 812 813 bool PVMFProtocolEngineNodeTimer::construct(OsclTimerObserver *aObserver) 814 { 815 // create iWatchdogTimer 816 iWatchdogTimer = OSCL_NEW(OsclTimer<PVMFProtocolEngineNodeAllocator>, ("ProtEngineNodeWatchdogTimer")); 817 if (!iWatchdogTimer) return false; 818 iWatchdogTimer->SetObserver(aObserver); 819 iWatchdogTimer->SetFrequency(PVPROTOCOLENGINENODE_TIMER_FREQUENCY); 820 821 int32 err = 0; 822 OSCL_TRY(err, iTimerVec.reserve(DEFAULT_TIMER_VECTOR_RESERVE_NUMBER);) 823 return (err ? false : true); 824 } 825 826 OSCL_EXPORT_REF PVMFProtocolEngineNodeTimer::~PVMFProtocolEngineNodeTimer() 827 { 828 if (iWatchdogTimer) 829 { 830 OSCL_DELETE(iWatchdogTimer); 831 iWatchdogTimer = NULL; 832 } 833 834 iTimerVec.clear(); 835 } 836 837 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::set(const uint32 aTimerID, const int32 aTimeout) 838 { 839 uint32 index = getTimerVectorIndex(aTimerID); 840 if (index == 0xffffffff) 841 { 842 // attach the new timer 843 uint32 timeout = aTimeout; 844 if (timeout == 0) timeout = getDefaultTimeout(aTimerID); 845 TimerUnit timerUnit(aTimerID, timeout); 846 iTimerVec.push_back(timerUnit); 847 } 848 else 849 { 850 // existing timer 851 uint32 timeout = iTimerVec[index].iTimeout; 852 if (aTimeout > 0 || (aTimeout == 0 && aTimerID == SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING)) 853 { 854 // for stop/eos logging timeout, allow zero timeout 855 iTimerVec[index].iTimeout = aTimeout; 856 } 857 timeout = iTimerVec[index].iTimeout; 858 } 859 } 860 861 OSCL_EXPORT_REF uint32 PVMFProtocolEngineNodeTimer::getTimeout(const uint32 aTimerID) 862 { 863 uint32 aTimeout = 0xffffffff; 864 uint32 index = getTimerVectorIndex(aTimerID); 865 if (index != 0xffffffff) 866 { 867 // existing timer 868 aTimeout = iTimerVec[index].iTimeout; 869 } 870 return aTimeout; 871 } 872 873 874 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::cancel(const uint32 aTimerID) 875 { 876 uint32 index = getTimerVectorIndex(aTimerID); 877 if (index != 0xffffffff) 878 { 879 // find this timer and cancel it 880 iWatchdogTimer->Cancel(aTimerID); 881 } 882 } 883 884 void PVMFProtocolEngineNodeTimer::clear() 885 { 886 for (uint32 i = 0; i < iTimerVec.size(); i++) 887 { 888 iWatchdogTimer->Cancel(iTimerVec[i].iTimerID); 889 } 890 } 891 892 OSCL_EXPORT_REF void PVMFProtocolEngineNodeTimer::clearExcept(const uint32 aTimerID) 893 { 894 for (uint32 i = 0; i < iTimerVec.size(); i++) 895 { 896 if (iTimerVec[i].iTimerID != aTimerID) 897 { 898 iWatchdogTimer->Cancel(iTimerVec[i].iTimerID); 899 } 900 } 901 } 902 903 OSCL_EXPORT_REF bool PVMFProtocolEngineNodeTimer::start(const uint32 aTimerID, const int32 aTimeout) 904 { 905 uint32 index = getTimerVectorIndex(aTimerID); 906 if (index == 0xffffffff) return false; 907 if (aTimeout) iTimerVec[index].iTimeout = aTimeout; 908 if (iTimerVec[index].iTimeout == 0) 909 { 910 iTimerVec[index].iTimeout = getDefaultTimeout(aTimerID); 911 } 912 913 iWatchdogTimer->Cancel(iTimerVec[index].iTimerID); 914 iWatchdogTimer->Request(iTimerVec[index].iTimerID, 0, iTimerVec[index].iTimeout); 915 return true; 916 } 917 918 uint32 PVMFProtocolEngineNodeTimer::getDefaultTimeout(const uint32 aTimerID) 919 { 920 switch (aTimerID) 921 { 922 case SERVER_RESPONSE_TIMER_ID: 923 return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC; 924 case SERVER_INACTIVITY_TIMER_ID: 925 return DEFAULT_MAX_SERVER_INACTIVITY_DURATION_IN_SEC; 926 case SERVER_KEEPALIVE_TIMER_ID: 927 return DEFAULT_KEEPALIVE_TIMEOUT_IN_SEC; 928 case SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING: 929 return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC_FOR_STOPEOS_LOGGING; 930 case WALL_CLOCK_TIMER_ID: 931 return DEFAULT_WALLCLOCK_TIMEOUT_IN_SEC; 932 case BUFFER_STATUS_TIMER_ID: 933 return DEFAULT_BUFFER_STATUS_CLOCK_TIMEOUT_IN_SEC; 934 default: 935 break; 936 } 937 return 0; 938 } 939 940 uint32 PVMFProtocolEngineNodeTimer::getTimerVectorIndex(const uint32 aTimerID) 941 { 942 for (uint32 i = 0; i < iTimerVec.size(); i++) 943 { 944 if (iTimerVec[i].iTimerID == aTimerID) return i; 945 } 946 return ~0; 947 } 948 949