Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #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