/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
#include "pvmf_protocol_engine_node.h"
#include "pvmf_protocol_engine_command_format_ids.h"
#include "pvmf_protocolengine_node_tunables.h"


#include "pvlogger.h"
#include "pvmf_media_cmd.h"
#include "pvmf_media_msg_format_ids.h"
#include "pv_mime_string_utils.h"
#include "pvmi_kvp_util.h"

#include "oscl_snprintf.h"
#include "oscl_utf8conv.h"

/**
//Macros for calling PVLogger
*/
#define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
#define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
#define LOGINFO(m) LOGINFOMED(m)
#define LOGINFODATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iDataPathLogger,PVLOGMSG_INFO,m);
#define LOGERRORDATAPATH(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m);
#define LOGINFOCLOCK(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iClockLogger,PVLOGMSG_INFO,m);
#define PVMF_PROTOCOL_ENGINE_LOGBIN(iPortLogger, m) PVLOGGER_LOGBIN(PVLOGMSG_INST_LLDBG, iPortLogger, PVLOGMSG_ERR, m);
#define	NODEDATAPATHLOGGER_TAG "datapath.sourcenode.protocolenginenode"


/**
//////////////////////////////////////////////////
// Node Constructor & Destructor
//////////////////////////////////////////////////
*/

PVMFProtocolEngineNode::PVMFProtocolEngineNode(int32 aPriority) :
        OsclTimerObject(aPriority, "PVMFProtocolEngineNode"),
        iStatusCode(0),
        iProcessingState(ProcessingState_Idle),
        iInterfacingObjectContainer(NULL),
        iProtocol(NULL),
        iProtocolContainer(NULL),
        iProtocolContainerFactory(NULL),
        iNodeOutput(NULL),
        iCurrEventHandler(NULL),
        iCfgFileContainer(NULL),
        iDownloadSource(NULL),
        iDownloadControl(NULL),
        iDownloadProgess(NULL),
        iSDPInfo(NULL),
        iUserAgentField(NULL),
        iEventReport(NULL),
        iPortConfigFSInfoAlloc(NULL),
        iPortConfigMemPool(PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM, OSCL_REFCOUNTER_MEMFRAG_DEFAULT_SIZE),
        iNodeTimer(NULL),
        iPortInForData(NULL),
        iPortInForLogging(NULL),
        iPortOut(NULL),
        iCurrentCmdId(0),
        iCmdRespPort(NULL),
        iLogger(NULL),
        iDataPathLogger(NULL),
        iClockLogger(NULL),
        iExtensionRefCount(0),
        iCurrentDataStreamCmdId(0)
{
    int32 err = 0;
    OSCL_TRY(err,
             //Create the input command queue.  Use a reserve to avoid lots of
             //dynamic memory allocation.
             iInputCommands.Construct(PVMF_PROTOCOLENGINE_NODE_COMMAND_ID_START, PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE);

             //Create the "current command" queue.  It will only contain one
             //command at a time, so use a reserve of 1.
             iCurrentCommand.Construct(0, 1);

             //Create the port vector.
             iPortVector.Construct(PVMF_PROTOCOLENGINE_NODE_PORT_VECTOR_RESERVE);

             //Set the node capability data.
             //This node can support an unlimited number of ports.
             iCapability.iCanSupportMultipleInputPorts = false;
             iCapability.iCanSupportMultipleOutputPorts = false;
             iCapability.iHasMaxNumberOfPorts = false;
             iCapability.iMaxNumberOfPorts = 0;//no maximum
             iCapability.iInputFormatCapability.push_back(PVMF_MIME_INET_TCP);

             // create the internal data queue
             iDataInQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
             iInternalEventQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
            );

    if (err)
    {
        //if a leave happened, cleanup and re-throw the error
        iInputCommands.clear();
        iCurrentCommand.clear();
        iPortVector.clear();
        iCapability.iInputFormatCapability.clear();
        iCapability.iOutputFormatCapability.clear();
        iDataInQueue.clear();
        iInternalEventQueue.clear();
        OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
        OSCL_CLEANUP_BASE_CLASS(OsclTimerObject);
        OSCL_LEAVE(err);
    }

    for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++) iEventHandlers[i] = NULL;
}

PVMFProtocolEngineNode::~PVMFProtocolEngineNode()
{
    //thread logoff
    if (IsAdded()) RemoveFromScheduler();


    //Cleanup commands
    //The command queues are self-deleting, but we want to
    //notify the observer of unprocessed commands.
    while (!iCurrentCommand.empty())
    {
        CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
    }

    while (!iInputCommands.empty())
    {
        CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
    }

    Clear(true);
}

/**
//////////////////////////////////////////////////
// Public Node API implementation
//////////////////////////////////////////////////
*/


PVMFStatus PVMFProtocolEngineNode::ThreadLogon()
{
    LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogon()"));
    switch (iInterfaceState)
    {
        case EPVMFNodeCreated:
            if (!IsAdded()) AddToScheduler();
            iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode");
            iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
            iClockLogger = PVLogger::GetLoggerObject("clock");
            SetState(EPVMFNodeIdle);
            return PVMFSuccess;

        default:
            return PVMFErrInvalidState;
    }
}


PVMFStatus PVMFProtocolEngineNode::ThreadLogoff()
{
    LOGINFO((0, "PVMFProtocolEngineNode::ThreadLogoff()"));
    switch (iInterfaceState)
    {
        case EPVMFNodeIdle:
            if (IsAdded()) RemoveFromScheduler();

            iLogger = NULL;
            iDataPathLogger = NULL;
            iClockLogger = NULL;
            SetState(EPVMFNodeCreated);
            return PVMFSuccess;

        default:
            return PVMFErrInvalidState;
    }
}


PVMFStatus PVMFProtocolEngineNode::GetCapability(PVMFNodeCapability& aNodeCapability)
{
    OSCL_UNUSED_ARG(aNodeCapability);
    LOGINFO((0, "PVMFProtocolEngineNode::GetCapability()"));
    //aNodeCapability=iCapability;
    return PVMFSuccess;
}


PVMFPortIter* PVMFProtocolEngineNode::GetPorts(const PVMFPortFilter* aFilter)
{
    LOGINFO((0, "PVMFProtocolEngineNode::GetPorts()"));
    OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
    iPortVector.Reset();
    return &iPortVector;
}


PVMFCommandId PVMFProtocolEngineNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
        Oscl_Vector<PVUuid, PVMFProtocolEngineNodeAllocator>& aUuids,
        bool aExactUuidsOnly, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::QueryUUID()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::QueryInterface()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
{
    OSCL_UNUSED_ARG(aPortConfig);
    LOGINFO((0, "PVMFProtocolEngineNode::RequestPort()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::ReleasePort()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Init(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Init()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Prepare()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Start(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Start()"));

    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Stop(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Stop()"));

    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Flush(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Flush()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Pause(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Pause()"));

    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Reset(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Reset()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::CancelAllCommands()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::CancelCommand()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFProtocolEngineNode::Seek(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSeek, OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::Seek()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_SEEK, aNPTInMS, aFirstSeqNumAfterSeek, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFProtocolEngineNode::BitstreamSwitch(PVMFSessionId aSessionId, uint64 aNPTInMS, uint32& aFirstSeqNumAfterSwitch, OsclAny* aContext)
{
    LOGINFO((0, "PVMFProtocolEngineNode::BitstreamSwitch()"));
    PVMFProtocolEngineNodeCommand cmd;
    cmd.PVMFProtocolEngineNodeCommand::Construct(aSessionId, PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH, aNPTInMS, aFirstSeqNumAfterSwitch, aContext);
    return QueueCommandL(cmd);
}

PvmiDataStreamCommandId PVMFProtocolEngineNode::DataStreamRequest(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID,
        OsclAny* aRequestData, OsclAny* aContextData)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequest()"));

    // This is for asynchronous requests, such as repositioning
    // Caller's SourceRequestCompleted will be called
    if (aRequestID != PVDS_REQUEST_REPOSITION)
    {
        // currently we only define reposition request
        OSCL_LEAVE(OsclErrArgument);
        return 0;
    }

    PVMFProtocolEngineNodeCommand cmd; // internal command, use 0 as session id.
    cmd.PVMFProtocolEngineNodeCommand::Construct((PVMFSessionId)0, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION,
            aSessionID, aRequestID, aRequestData, iCurrentDataStreamCmdId, aContextData);
    QueueCommandL(cmd);
    return iCurrentDataStreamCmdId++;
}

PvmiDataStreamStatus PVMFProtocolEngineNode::DataStreamRequestSync(PvmiDataStreamSession aSessionID, PvmiDataStreamRequest aRequestID, OsclAny* aRequestData)
{
    OSCL_UNUSED_ARG(aSessionID);
    // This is for synchronous requests, such as returning memory fragments
    PvmiDataStreamStatus status = PVDS_FAILURE;
    switch (aRequestID)
    {
        case PVDS_REQUEST_MEM_FRAG_RELEASED:
            if (aRequestData != NULL)
            {
                LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DataStreamRequestSync, got PVDS_REQUEST_MEM_FRAG_RELEASED request"));
                OsclRefCounterMemFrag* frag = ((OsclRefCounterMemFrag*)aRequestData);
                if (iNodeOutput->releaseMemFrag(frag)) status = PVDS_SUCCESS;
            }
            break;

        default:
            break;
    }

    return status;
}

bool PVMFProtocolEngineNode::IsRepositioningRequestPending()
{
    PVMFProtocolEngineNodeCommand *pInputCmd   = FindCmd(iInputCommands, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);
    PVMFProtocolEngineNodeCommand *pPendingCmd = FindCmd(iCurrentCommand, PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION);

    return (pInputCmd || pPendingCmd);
}

void PVMFProtocolEngineNode::addRef()
{
    ++iExtensionRefCount;
}

void PVMFProtocolEngineNode::removeRef()
{
    --iExtensionRefCount;
}

bool PVMFProtocolEngineNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
{
    if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID)
    {
        PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }
    else if (uuid == PVMIDatastreamuserInterfaceUuid)
    {
        PVMIDatastreamuserInterface* myInterface = OSCL_STATIC_CAST(PVMIDatastreamuserInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }
    else if (uuid == KPVMFProtocolEngineNodeExtensionUuid)
    {
        PVMFProtocolEngineNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }
    else if (uuid == PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID)
    {
        PVMFDownloadProgressInterface* myInterface = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }
    else if (uuid == KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid)
    {
        PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFProtocolEngineNodeMSHTTPStreamingExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }
    else if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID)
    {
        if (!iInterfacingObjectContainer || iInterfacingObjectContainer->getDownloadFormat() != PVMF_MIME_DATA_SOURCE_PVX_FILE) return false;
        PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
        addRef();
        return true;
    }

    return false;
}

/**
//This routine is called by various command APIs to queue an
//asynchronous command for processing by the command handler AO.
//This function may leave if the command can't be queued due to
//memory allocation failure.
*/
PVMFCommandId PVMFProtocolEngineNode::QueueCommandL(PVMFProtocolEngineNodeCommand& aCmd)
{
    PVMFCommandId id = iInputCommands.AddL(aCmd);

    //wakeup the AO
    RunIfNotReady();
    return id;
}

PVMFProtocolEngineNodeCommand* PVMFProtocolEngineNode::FindCmd(PVMFProtocolEngineNodeCmdQ &aCmdQueue, int32 aCmdId)
{
    for (uint32 i = 0; i < aCmdQueue.size(); i++)
    {
        if (aCmdQueue[i].iCmd == aCmdId) return &aCmdQueue[i];
    }
    return NULL;
}

/**
/////////////////////////////////////////////////////
// Asynchronous Command processing routines.
// These routines are all called under the AO.
/////////////////////////////////////////////////////
*/

/**
//Called by the command handler AO to process a command from
//the input queue.
//Return true if a command was processed, false if the command
//processor is busy and can't process another command now.
*/
bool PVMFProtocolEngineNode::ProcessCommand(PVMFProtocolEngineNodeCommand& aCmd)
{
    //normally this node will not start processing one command
    //until the prior one is finished.  However, a hi priority
    //command such as Cancel must be able to interrupt a command
    //in progress.
    if (!iCurrentCommand.empty() && !aCmd.hipri())
    {
        return false; // keep waiting
    }

    PVMFStatus cmdStatus;
    switch (aCmd.iCmd)
    {
        case PVMF_GENERIC_NODE_REQUESTPORT:
            cmdStatus = DoRequestPort(aCmd);
            break;

        case PVMF_GENERIC_NODE_RELEASEPORT:
            cmdStatus = DoReleasePort(aCmd);
            break;

        case PVMF_GENERIC_NODE_QUERYUUID:
            cmdStatus = DoQueryUuid(aCmd);
            break;

        case PVMF_GENERIC_NODE_QUERYINTERFACE:
            cmdStatus = DoQueryInterface(aCmd);
            break;

        case PVMF_GENERIC_NODE_INIT:
            cmdStatus = DoInit(aCmd);
            break;

        case PVMF_GENERIC_NODE_PREPARE:
            cmdStatus = DoPrepare(aCmd);
            break;

        case PVMF_GENERIC_NODE_START:
            cmdStatus = DoStart(aCmd);
            break;

        case PVMF_GENERIC_NODE_STOP:
            cmdStatus = DoStop(aCmd);
            break;

        case PVMF_GENERIC_NODE_FLUSH:
            cmdStatus = DoFlush(aCmd);
            break;

        case PVMF_GENERIC_NODE_PAUSE:
            cmdStatus = DoPause(aCmd);
            break;

        case PVMF_GENERIC_NODE_RESET:
            cmdStatus = DoReset(aCmd);
            break;

        case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
            cmdStatus = DoCancelAllCommands(aCmd);
            break;

        case PVMF_GENERIC_NODE_CANCELCOMMAND:
            cmdStatus = DoCancelCommand(aCmd);
            break;

        case PVPROTOCOLENGINE_NODE_CMD_SEEK:
            cmdStatus = DoSeek(aCmd);
            break;

        case PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH:
            cmdStatus = DoBitsteamSwitch(aCmd);
            break;

        case PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION:
            cmdStatus = DoReposition(aCmd);
            break;

        default://unknown command type. Assert and treat as not supported error
            OSCL_ASSERT(false);
            CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
            cmdStatus = PVMFErrNotSupported;
            break;
    }

    //If completion is pending, move the command from the input queue to the current command.
    //This is necessary since the input queue could get rearranged by new commands coming in.
    if (cmdStatus == PVMFPending)
    {
        iCurrentCommand.StoreL(aCmd);
        iInputCommands.Erase(&aCmd);
    }

    return true;
}

/**
//The various command handlers call this when a command is complete.
*/
int32 PVMFProtocolEngineNode::HandleCommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ,
        PVMFProtocolEngineNodeCommand& aCmd,
        int32 aStatus)
{
    if (aStatus == PVMFPending) return PVMFPending;
    if (aStatus > 0 || IsPVMFErrCode(aStatus))
    {
        CommandComplete(aCmdQ, aCmd, aStatus); // no extension error code in case of error
        return aStatus;
    }

    // should be PE node extension error code
    PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
    // Check for error code for not enough disk space
    int32 pvmfReturnCode = PVMFFailure;
    if (aStatus == PROCESS_DATA_STREAM_OPEN_FAILURE) pvmfReturnCode = PVMFErrResource;
    int32 errorCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - aStatus);
    CommandComplete(aCmdQ, aCmd, pvmfReturnCode, NULL, &uuid, &errorCode);
    return pvmfReturnCode;
}


void PVMFProtocolEngineNode::CommandComplete(PVMFProtocolEngineNodeCmdQ& aCmdQ,
        PVMFProtocolEngineNodeCommand& aCmd,
        PVMFStatus aStatus,
        OsclAny* aEventData,
        PVUuid* aEventUUID,
        int32* aEventCode,
        int32 aEventDataLen)

{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
                    , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));

    PVInterface* extif = NULL;
    PVMFBasicErrorInfoMessage* errormsg = NULL;
    if (aEventUUID && aEventCode)
    {
        errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
        extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
    }

    //create response
    PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData);
    if (aEventDataLen != 0)
    {
        resp.SetEventDataLen(aEventDataLen);
    }

    PVMFSessionId session = aCmd.iSession;

    //Erase the command from the queue.
    aCmdQ.Erase(&aCmd);

    //Report completion to the session observer.
    ReportCmdCompleteEvent(session, resp);

    if (errormsg) errormsg->removeRef();
}


/**
//Called by the command handler AO to do the node Reset.
*/
PVMFStatus PVMFProtocolEngineNode::DoReset(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoReset()"));

    // Allow a reset on ANY state.
    Clear(true); // true means deleting the relevant objects

    // Logoff and go back to Created state.
    SetState(EPVMFNodeIdle);
    PVMFStatus	status = ThreadLogoff();
    CommandComplete(iInputCommands, aCmd, status);
    return status;
}


/**
//Called by the command handler AO to do the port request
*/
PVMFStatus PVMFProtocolEngineNode::DoRequestPort(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoRequestPort()"));

    //This node supports port request from any state

    //retrieve port tag.
    int32 tag;
    OSCL_String* mimetype;
    aCmd.PVMFProtocolEngineNodeCommandBase::Parse(tag, mimetype);

    //(mimetype is not used on this node)

    //validate the tag...
    switch (tag)
    {
        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT:
        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT:
        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK:
            break;

        default:
        {
            //bad port tag
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVMFProtocolEngineNode::DoRequestPort: Error - Invalid port tag"));
            CommandComplete(iInputCommands, aCmd, PVMFFailure);
            return PVMFFailure;
        }
        // break;	This statement was removed to avoid compiler warning for Unreachable Code
    }

    //Allocate a new port
    OsclAny *ptr = NULL;
    int32 err;
    OSCL_TRY(err, ptr = iPortVector.Allocate(););
    if (err != OsclErrNone || !ptr)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVMFProtocolEngineNode::DoRequestPort: Error - iPortVector Out of memory"));
        CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
        return PVMFErrNoMemory;
    }

    //create base port with default settings...
    PVMFProtocolEnginePort*port = NULL;
    switch (tag)
    {
        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT:
        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK:
            //create base port with default settings...
            port = new(ptr) PVMFProtocolEnginePort(tag, this,
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
                                                   "ProtocolEngineIn(Protocol)");

            if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)		iPortInForData = port;
            if (tag == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)	iPortInForLogging = port;
            break;

        case PVMF_PROTOCOLENGINENODE_PORT_TYPE_OUTPUT:
            port = new(ptr) PVMFProtocolEnginePort(tag, this,
                                                   0, 0, 0,	// input queue isn't needed.
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_DATA_QUEUE_CAPACITY,
                                                   DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
                                                   "ProtocolEngineOut(Protocol)");

            iPortOut = port;
            break;
    }

    iPortActivityQueue.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE);

    //Add the port to the port vector.
    OSCL_TRY(err, iPortVector.AddL(port););
    if (err != OsclErrNone)
    {
        iPortInForData = iPortInForLogging = iPortOut = NULL;
        OSCL_DELETE(port);
        CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
        return PVMFErrNoMemory;
    }

    //Return the port pointer to the caller.
    CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port, 0, 0, sizeof(PVMFProtocolEnginePort));
    return PVMFSuccess;
}

/**
//Called by the command handler AO to do the port release
*/
PVMFStatus PVMFProtocolEngineNode::DoReleasePort(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoReleasePort()"));

    //This node supports release port from any state
    PVMFStatus status = PVMFSuccess;

    //Find the port in the port vector
    PVMFPortInterface* p = NULL;
    aCmd.PVMFProtocolEngineNodeCommandBase::Parse(p);

    PVMFProtocolEnginePort* port = (PVMFProtocolEnginePort*)p;


    if (port == NULL) status = PVMFErrArgument;

    PVMFProtocolEnginePort** portPtr = iPortVector.FindByValue(port);
    if (portPtr)
    {
        if (*portPtr == iPortInForData)	iPortInForData = NULL;
        if (*portPtr == iPortInForLogging) iPortInForLogging = NULL;
        if (*portPtr == iPortOut)			iPortOut = NULL;

        Clear(true);

        //delete the port.
        iPortVector.Erase(portPtr);
        status = PVMFSuccess;
    }
    else
    {
        //port not found.
        status = PVMFErrArgument;
    }

    CommandComplete(iInputCommands, aCmd, status);
    return status;
}


PVMFStatus PVMFProtocolEngineNode::DoQueryUuid(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoQueryUuid()"));

    //This node supports Query UUID from any state
    OSCL_String* mimetype;
    Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
    bool exactmatch;
    aCmd.PVMFProtocolEngineNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);

    //TODO: Try to match the input mimetype against any of
    //the custom interfaces for this node
    PVUuid uuid1(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID);
    uuidvec->push_back(uuid1);
    PVUuid uuid2(PVMIDatastreamuserInterfaceUuid);
    uuidvec->push_back(uuid2);
    PVUuid uuid3(KPVMFProtocolEngineNodeExtensionUuid);
    uuidvec->push_back(uuid3);
    PVUuid uuid4(PVMF_DOWNLOAD_PROGRESS_INTERFACE_UUID);
    uuidvec->push_back(uuid4);
    PVUuid uuid5(KPVMFProtocolEngineNodeMSHTTPStreamingExtensionUuid);
    uuidvec->push_back(uuid5);
    PVUuid uuid6(PVMF_TRACK_SELECTION_INTERFACE_UUID);
    uuidvec->push_back(uuid6);

    CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    return PVMFSuccess;
}


PVMFStatus PVMFProtocolEngineNode::DoQueryInterface(PVMFProtocolEngineNodeCommand&  aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoQueryInterface()"));

    PVUuid* uuid;
    PVInterface** ptr;
    aCmd.PVMFProtocolEngineNodeCommandBase::Parse(uuid, ptr);
    PVMFStatus status = PVMFSuccess;
    if (!queryInterface(*uuid, *ptr))
    {
        //Not supported
        *ptr = NULL;
        status = PVMFFailure;
    }

    CommandComplete(iInputCommands, aCmd, status);
    return status;
}


/**
//Called by the command handler AO to do the node Init
*/
PVMFStatus PVMFProtocolEngineNode::DoInit(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoInit()"));

    PVMFStatus status = PVMFSuccess;
    // exceptional cases
    if (!iProtocolContainer) status = PVMFFailure;
    if (iInterfaceState != EPVMFNodeIdle) status = PVMFErrInvalidState;

    // normal case
    if (iInterfaceState == EPVMFNodeIdle && iProtocolContainer)
    {
        // do init, if init is async call, then return PVMFPending
        if ((status = iProtocolContainer->doInit()) == PVMFSuccess)
        {
            SetState(EPVMFNodeInitialized);
        }
    }
    return HandleCommandComplete(iInputCommands, aCmd, status);
}


/**
//Called by the command handler AO to do the node Prepare
*/
PVMFStatus PVMFProtocolEngineNode::DoPrepare(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoPrepare()"));
    if (!iProtocolContainer)	return PVMFFailure;

    PVMFStatus status = PVMFSuccess; //PVMFPending;
    switch (iInterfaceState)
    {
        case EPVMFNodeInitialized:
        {
            status = iProtocolContainer->doPrepare();
            if (status == PVMFSuccess) SetState(EPVMFNodePrepared);
            break;
        }
        default:
            status = PVMFErrInvalidState;
            break;
    }

    return HandleCommandComplete(iInputCommands, aCmd, status);
}


/**
//Called by the command handler AO to do the node Start
*/
PVMFStatus PVMFProtocolEngineNode::DoStart(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoStart()"));
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoStart() : Start command gets called and executed, iInterfaceState=%d, currSocketConnection=%d",
                     (int32)iInterfaceState, (uint32)iInterfacingObjectContainer->isSocketConnectionUp()));

    // check if download/streaming is done, if it is done, no need to start/resume download/streaming
    if (CheckAvailabilityOfDoStart(aCmd)) return PVMFSuccess;

    PVMFStatus status = PVMFSuccess;
    iProcessingState = ProcessingState_NormalDataflow;
    iInterfacingObjectContainer->setInputDataUnwanted(false);
    switch (iInterfaceState)
    {
        case EPVMFNodePrepared:
        {
            if (iProtocolContainer->doPreStart() == PROCESS_SUCCESS)
            {
                // do socket reconnect for init->start, prepare->start and stop->start
                // for pause->start, no need. For seek, no start command is issued. doseek() will
                // do socket reconnect
                iProtocolContainer->startDataFlowByCommand(iProtocolContainer->needSocketReconnect()); // make start command (prepare->start) asynchonous

                // Transition to BeingStarted
                // intentionally set node state as this node internal state to ignore any left-over messages from POST port from previous stop or EOS handling
                SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted);

                return PVMFPending;
            }
            status = PVMFSuccess;
            break;
        }

        case EPVMFNodePaused:
        {
            if (iInterfacingObjectContainer->getTruncatedForLimitSize())
            {
                LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoStart() : size limitation"));
                status = PVMFSuccess;
                break;
            }
            else
            {
                // Transition to BeingStarted
                // intentionally set node state as this node internal state to ignore any left-over messages from POST port because currently node is paused state.
                // need to differentiate this case from the paused case.
                SetState((TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted);

                iProtocol->resume();
                iProtocolContainer->startDataFlowByCommand();
                return PVMFPending;

                // break;	This statement was removed to avoid compiler warning for Unreachable Code
            }
        }

        /*
         * If the node is already started just return success - multiple starts can happen with
         * flow control (auto-pause / auto-resume) scenarios
         */
        case EPVMFNodeStarted:
            status = PVMFSuccess;
            break;

        default:
            status = PVMFErrInvalidState;
            break;
    }

    CommandComplete(iInputCommands, aCmd, status);
    return status;
}

bool PVMFProtocolEngineNode::CheckAvailabilityOfDoStart(PVMFProtocolEngineNodeCommand& aCmd)
{
    // check if download/streaming is done, if it is done, no need to start/resume download/streaming
    if (iInterfacingObjectContainer->isDownloadStreamingDone())
    {
        SetState(EPVMFNodeStarted);
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        return true;
    }
    return false;
}

/**
//Called by the command handler AO to do the node Pause
*/
PVMFStatus PVMFProtocolEngineNode::DoPause(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoPause()"));
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoPause() : Pause command gets called and executed, iInterfaceState=%d", (int32)iInterfaceState));

    if (iInterfacingObjectContainer->getTruncatedForLimitSize())
    {
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoPause() : size limitation = PVMFSuccess"));
        return PVMFSuccess;
    }

    PVMFStatus status = PVMFSuccess;
    switch (iInterfaceState)
    {
        case EPVMFNodeStarted:
        {
            TPVMFNodeInterfaceState prevState = iInterfaceState;
            SetState(EPVMFNodePaused);
            if (!iProtocolContainer->doPause())
            {
                SetState(prevState);
                status = PVMFFailure;
            }
        }
        break;

        case EPVMFNodePaused:
            status = PVMFSuccess;

        default:
            status = PVMFErrInvalidState;
            break;
    }

    CommandComplete(iInputCommands, aCmd, status);
    return status;
}

/**
//Called by the command handler AO to do the node Seek
*/
PVMFStatus PVMFProtocolEngineNode::DoSeek(PVMFProtocolEngineNodeCommand& aCmd)
{
    if (iInterfacingObjectContainer->getTruncatedForLimitSize())
    {
        CommandComplete(iInputCommands, aCmd, PVMFFailure);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoSeek() : size limitation = PVMFFailure"));
        return PVMFFailure;
    }
    return iProtocolContainer->doSeek(aCmd);
}


/**
//Called by the command handler AO to do the node BitstreamSwitch
*/
PVMFStatus PVMFProtocolEngineNode::DoBitsteamSwitch(PVMFProtocolEngineNodeCommand& aCmd)
{
    if (iInterfacingObjectContainer->getTruncatedForLimitSize())
    {
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoBitsteamSwitch() : size limitation = PVMFFailure"));
        return PVMFFailure;
    }
    return iProtocolContainer->doBitstreamSwitch(aCmd);
}

PVMFStatus PVMFProtocolEngineNode::DoReposition(PVMFProtocolEngineNodeCommand& aCmd)
{
    if (iInterfacingObjectContainer->getTruncatedForLimitSize())
    {
        CommandComplete(iInputCommands, aCmd, PVMFFailure);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::DoReposition() : size limitation = PVMFFailure"));
        return PVMFFailure;
    }
    return iProtocolContainer->doSeek(aCmd);
}

/**
//Called by the command handler AO to do the node Stop
*/
PVMFStatus PVMFProtocolEngineNode::DoStop(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoStop()"));
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::Stop() : Stop command gets called, iInterfaceState=%d", (int32)iInterfaceState));

    PVMFStatus status = PVMFSuccess;
    switch (iInterfaceState)
    {
        case EPVMFNodeStarted:
        case EPVMFNodePaused:

            status = iProtocolContainer->doStop();
            if (status == PVMFPending) return PVMFPending;
            if (status == PVMFSuccess)
            {

                StopClear();
                // Transition to Prepared state
                SetState(EPVMFNodePrepared);
            }
            break;

        case EPVMFNodeError:
            SetState(EPVMFNodePrepared);
            break;

        default:
            status = PVMFErrInvalidState;
            break;
    }

    CommandComplete(iInputCommands, aCmd, status);
    return status;
}

/**
//Called by the command handler AO to do the node Flush
*/
PVMFStatus PVMFProtocolEngineNode::DoFlush(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoFlush()"));

    switch (iInterfaceState)
    {
        case EPVMFNodeStarted:
        case EPVMFNodePaused:
        {
            //the flush is asynchronous. Move the command from
            //the input command queue to the current command, where
            //it will remain until the flush completes.
            int32 err;
            OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
            if (err != OsclErrNone)
            {
                CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
                return PVMFErrNoMemory;
            }
            iInputCommands.Erase(&aCmd);

            //Notify all ports to suspend their input
            for (uint32 i = 0;i < iPortVector.size();i++)
            {
                iPortVector[i]->SuspendInput();
            }
        }

        break;

        default:
            CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
            return PVMFErrInvalidState;
            // break;	This statement was removed to avoid compiler warning for Unreachable Code
    }
    return PVMFSuccess;
}

/**
//A routine to tell if a flush operation is in progress.
*/
bool PVMFProtocolEngineNode::FlushPending()
{
    return (iCurrentCommand.size() > 0 &&
            iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
}


/**
//Called by the command handler AO to do the Cancel All
*/
PVMFStatus PVMFProtocolEngineNode::DoCancelAllCommands(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoCancelAllCommands()"));

    //first cancel the current command if any
    while (!iCurrentCommand.empty())
    {
        CancelClear();
        CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
    }

    //next cancel all queued commands
    //start at element 1 since this cancel command is element 0.
    while (iInputCommands.size() > 1)
    {
        CancelClear();
        CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
    }

    //finally, report cancel complete.
    CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
    return PVMFSuccess;
}

/**
//Called by the command handler AO to do the Cancel single command
*/
PVMFStatus PVMFProtocolEngineNode::DoCancelCommand(PVMFProtocolEngineNodeCommand& aCmd)
{
    LOGINFO((0, "PVMFProtocolEngineNode::DoCancelCommand()"));

    //extract the command ID from the parameters.
    PVMFCommandId id;
    aCmd.PVMFProtocolEngineNodeCommandBase::Parse(id);

    // first check "current" command if any, and check the input queue starting
    // at element 1 since this cancel command is element 0.
    PVMFProtocolEngineNodeCommand* cmd = iCurrentCommand.FindById(id);
    if (cmd)
    {
        CancelClear();
        //cancel the queued command
        CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
        //report cancel success
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        // set cancel cmd happened flag for stop command processing
        if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
        return PVMFSuccess;
    }

    //next check input queue.
    //start at element 1 since this cancel command is element 0.
    cmd = iInputCommands.FindById(id, 1);
    if (cmd)
    {
        CancelClear();
        //cancel the queued command
        CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
        //report cancel success
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        // set cancel cmd happened flag for stop command processing
        if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
        return PVMFSuccess;
    }

    //at this point, nothing needs to be cancelled and thus report cancel complete
    CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    // set cancel cmd happened flag for stop command processing
    if (iInterfacingObjectContainer) iInterfacingObjectContainer->setCancelCmdHappened();
    return PVMFSuccess;
}


/////////////////////////////////////////////////////
// Event reporting routines.
/////////////////////////////////////////////////////
void PVMFProtocolEngineNode::SetState(TPVMFNodeInterfaceState s)
{
    LOGINFO((0, "PVMFProtocolEngineNode::SetState() %d", s));
    PVMFNodeInterface::SetState(s);
}

void PVMFProtocolEngineNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, const int32 aEventCode, OsclAny* aEventLocalBuffer, const uint32 aEventLocalBufferSize)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode:NodeInfoEvent Type %d Data %d",
                    aEventType, aEventData));

    if (aEventCode == 0)
    {
        //report basic event, no extended event
        PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
    }
    else
    {
        //report extended event.
        PVUuid uuid = PVMFPROTOCOLENGINENODEInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL));

        PVMFAsyncEvent event(PVMFInfoEvent,
                             aEventType,
                             NULL, //context
                             msg,
                             aEventData,
                             (uint8*)aEventLocalBuffer,
                             aEventLocalBufferSize);

        //report to the session observers.
        PVMFNodeInterface::ReportInfoEvent(event);

        //remove the ref to the extended response
        if (msg) msg->removeRef();
    }
}

void PVMFProtocolEngineNode::ReportErrorEvent(PVMFEventType aEventType,
        OsclAny* aEventData,
        const int32 aEventCode,
        int32 aEventDataLen)
{
    LOGINFO((0, "PVMFProtocolEngineNode::ReportErrorEvent() Type %d Data %d"
             , aEventType, aEventData));

    PVMFBasicErrorInfoMessage*msg  = NULL;

    if (aEventCode != 0)
    {
        // extended error event with aEventCode
        PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
        msg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, uuid, NULL));
    }

    PVMFAsyncEvent event(PVMFErrorEvent,
                         aEventType,
                         NULL, // context
                         msg,
                         aEventData,
                         NULL,
                         0);

    if (aEventDataLen != 0)
        event.SetEventDataLen(aEventDataLen);

    PVMFNodeInterface::ReportErrorEvent(event);
    if (msg) msg->removeRef();

}

/////////////////////////////////////////////////////
// Port Processing routines
/////////////////////////////////////////////////////

void PVMFProtocolEngineNode::QueuePortActivity(const PVMFPortActivity &aActivity)
{
    //queue a new port activity event
    int32 err;
    OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
    if (err != OsclErrNone)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVMFProtocolEngineNode::QueuePortActivity() Error - iPortActivityQueue.push_back() failed"));
        ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort), sizeof(PVMFProtocolEnginePort));
    }
    else
    {
        //wake up the AO to process the port activity event.
        RunIfNotReady();
    }
}


void PVMFProtocolEngineNode::HandlePortActivity(const PVMFPortActivity &aActivity)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, PAQSize=%d",
                     aActivity.iPort, aActivity.iType, aActivity.iPort->IncomingMsgQueueSize(), aActivity.iPort->OutgoingMsgQueueSize(), iPortActivityQueue.size()));

    //A port is reporting some activity or state change.  This code
    //figures out whether we need to  queue a processing event
    //for the AO, and/or report a node event to the observer.

    switch (aActivity.iType)
    {
        case PVMF_PORT_ACTIVITY_CREATED:
            //Report port created info event
            ReportInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort);
            break;

        case PVMF_PORT_ACTIVITY_DELETED:
            //Report port deleted info event
            ReportInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort);
            //Purge any port activity events already queued
            //for this port.
            {
                for (uint32 i = 0;i < iPortActivityQueue.size();)
                {
                    if (iPortActivityQueue[i].iPort == aActivity.iPort)
                    {
                        iPortActivityQueue.erase(&iPortActivityQueue[i]);
                    }
                    else
                    {
                        i++;
                    }
                }
            }
            break;

        case PVMF_PORT_ACTIVITY_CONNECT:
            //nothing needed.
            if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut)
            {
                LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_CONNECT), PE node output port connected to downstream node port!",
                                 aActivity.iPort, aActivity.iType));
                iInterfacingObjectContainer->setOutputPortConnect();
            }

            break;

        case PVMF_PORT_ACTIVITY_DISCONNECT:
            //clear the node input queue when either port is disconnected.
            while (!iDataInQueue.empty())
            {
                PVMFSharedMediaMsgPtr msg = iDataInQueue.front();
                iDataInQueue.erase(iDataInQueue.begin());
                ((PVMFProtocolEnginePort*)aActivity.iPort)->LogMediaMsgInfo(msg, "In Msg Cleared", iDataInQueue.size());
            }

            if ((PVMFProtocolEnginePort*)aActivity.iPort == iPortOut)
            {
                LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity: port=0x%x, type=%d(PVMF_PORT_ACTIVITY_DISCONNECT), PE node output port disconnected from downstream node port!",
                                 aActivity.iPort, aActivity.iType));
                iInterfacingObjectContainer->setOutputPortConnect(false);
            }
            break;

        case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
            //An outgoing message was queued on this port.
            //We only need to queue a port activity event on the
            //first message.  Additional events will be queued during
            //the port processing as needed.
            if ((aActivity.iPort->OutgoingMsgQueueSize() == 1) ||
                    (iPortActivityQueue.size() == 0))
            {
                QueuePortActivity(aActivity);
            }
            break;

        case PVMF_PORT_ACTIVITY_INCOMING_MSG:
            //An incoming message was queued on this port.
            //We only need to queue a port activity event on the
            //first message.  Additional events will be queued during
            //the port processing as needed.
            if ((aActivity.iPort->IncomingMsgQueueSize() == 1) ||
                    (iPortActivityQueue.size() == 0))
            {
                QueuePortActivity(aActivity);
            }
            break;

        case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
            //Outgoing queue is now busy.
            //No action is needed here-- the node checks for
            //outgoing queue busy as needed during data processing.
            iProcessingState = ProcessingState_Idle; // disable data flow
            break;

        case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
            //Outgoing queue was previously busy, but is now ready.
            //it's time to start processing incoming data again.
            LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d",
                             aActivity.iPort->OutgoingMsgQueueSize()));
            ProcessOutgoingQueueReady();
            break;

        case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
            // The connected port has become busy (its incoming queue is
            // busy).
            // No action is needed here-- the port processing code
            // checks for connected port busy during data processing.
            break;

        case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
            // The connected port has transitioned from Busy to Ready.
            // It's time to start processing outgoing messages again.
            LOGINFODATAPATH((0, "PVMFProtocolEngineNode::HandlePortActivity() : PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY, OutgoingQueueSize=%d",
                             aActivity.iPort->OutgoingMsgQueueSize()));

            if (aActivity.iPort->OutgoingMsgQueueSize() > 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "0x%x PVMFProtocolEngineNode::PortActivity: Connected port is now ready", this));
                PVMFPortActivity activity(aActivity.iPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG);
                QueuePortActivity(activity);
            }
            break;

        default:
            break;
    }
}


/////////////////////////////////////////////////////
// Called by the AO to process a port activity message
bool PVMFProtocolEngineNode::ProcessPortActivity()
{
    //Pop the queue...
    PVMFPortActivity activity(iPortActivityQueue.front());
    iPortActivityQueue.erase(&iPortActivityQueue.front());

    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() port=0x%x, type=%d, IncomingQueueSize=%d, OutgoingQueueSize=%d, iInterfaceState=%d, PAQSize=%d",
                     activity.iPort, activity.iType, activity.iPort->IncomingMsgQueueSize(), activity.iPort->OutgoingMsgQueueSize(), iInterfaceState, iPortActivityQueue.size()));

    PVMFStatus status = PVMFSuccess;
    switch (activity.iType)
    {
        case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
            status = ProcessOutgoingMsg(activity.iPort);
            //Re-queue the port activity event as long as there's
            //more data to process and it isn't in a Busy state.
            QueueActivityOutgoingMessage(status, activity);
            break;

        case PVMF_PORT_ACTIVITY_INCOMING_MSG:
            status = ProcessIncomingMsg(activity.iPort);
            //Re-queue the port activity event as long as there's
            //more data to process and it isn't in a Busy state.
            QueueActivityIncomingMessage(status, activity);
            break;

        case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
            LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessPortActivity() : PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY, OutgoingQueueSize=%d",
                             activity.iPort->OutgoingMsgQueueSize()));
            ProcessOutgoingQueueReady();
            break;

        default:
            break;
    }

    //Report any unexpected failure in port processing...
    //(the InvalidState error happens when port input is suspended,
    //so don't report it.)
    if (status != PVMFErrBusy &&
            status != PVMFSuccess &&
            status != PVMFErrInvalidState)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVMFProtocolEngineNode::ProcessPortActivity() Error - ProcessPortActivity failed. port=0x%x, type=%d",
                         activity.iPort, activity.iType));
        ReportErrorEvent(PVMFErrPortProcessing);
    }

    //return true if we processed an activity...
    return (status != PVMFErrBusy);
}

// wrap OSCL_TRY block
void PVMFProtocolEngineNode::QueueActivityOutgoingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity)
{
    if (aStatus != PVMFErrBusy && aActivity.iPort->OutgoingMsgQueueSize() > 0)
    {
        int32 err;
        OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
        if (err) ReportErrorEvent(PVMFErrPortProcessing);
    }
}

// wrap OSCL_TRY block
void PVMFProtocolEngineNode::QueueActivityIncomingMessage(const PVMFStatus aStatus, const PVMFPortActivity &aActivity)
{
    //Re-queue the port activity event as long as there's more data to process and it isn't in a Busy state.
    if (aStatus != PVMFErrBusy && aActivity.iPort->IncomingMsgQueueSize() > 0)
    {
        //OSCL_TRY(err,iPortActivityQueue.push_back(activity););
        // only insert outgoing queue ready event in case of no such event in the port activity queue
        if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_INCOMING_MSG))
        {
            int32 err;
            OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
            if (err) ReportErrorEvent(PVMFErrPortProcessing);
        }
    }
}

/////////////////////////////////////////////////////
PVMFStatus PVMFProtocolEngineNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() aPort=0x%x, IncomingMsgQueueSize=%d, iProcessingState=%d", aPort, aPort->IncomingMsgQueueSize(), iProcessingState));

    // Called by the AO to process one buffer off the port's
    // incoming data queue.  This routine will dequeue and dispatch the data.
    // for pause, don't dequeue the message
    if (aPort->IncomingMsgQueueSize() == 0) return PVMFSuccess;

    if (aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT &&
            aPort->GetPortTag() != PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)
    {
        return PVMFFailure;
    }

    if (iDataInQueue.size() < DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT / 100)
    {
        // DEFAULT_DATA_QUEUE_CAPACITY*DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT/100 = 7
        // only dequeue the message when data queue buffers less number of media message than the port queue

        // Get one incoming message
        PVMFSharedMediaMsgPtr msg;
        PVMFStatus status = aPort->DequeueIncomingMsg(msg);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() Error - DequeueIncomingMsg failed"));
            return status;
        }

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVMFProtocolEngineNode::ProcessIncomingMsg() FmtId=%d", msg->getFormatID()));

        bool isEOS = (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID);
        if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
        {
            iInterfacingObjectContainer->updateSocketConnectFlags(isEOS); // will update flags
        }

        if (IgnoreCurrentInputData(aPort, isEOS, msg))
        {
            LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() INCOMING MESSAGE IGNORED!! isEOS=%d, port=0x%x, iInterfaceState=%d",
                             (uint32)isEOS, aPort, iInterfaceState));
            return PVMFSuccess;
        }

        uint32 frameIndex = ((PVMFProtocolEnginePort*)aPort)->iNumFramesConsumed++;
        msg->setSeqNum(frameIndex);
        iDataInQueue.push_back(msg);

        UpdateTimersInProcessIncomingMsg(isEOS, aPort);
        LogIncomingMessage(msg, isEOS, aPort);

    } // end of if(iDataInQueue.size() < 7)
    else
    {
        if (iInterfaceState != EPVMFNodePaused && aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
        {
            iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout
        }
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::ProcessIncomingMsg() iDataInQueue becomes FULL! iProcessingState = %d (1 for normal data flow), iInterfaceState = %d",
                         (uint32)iProcessingState, (uint32)iInterfaceState));
        if (iProcessingState != ProcessingState_NormalDataflow) return PVMFErrBusy;
    }

    if (iProcessingState == ProcessingState_NormalDataflow)
    {
        if (!IsDataFlowEventAlreadyInQueue(PVProtocolEngineNodeInternalEventType_IncomingMessageReady))
        {
            PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_IncomingMessageReady);
            iInternalEventQueue.push_back(aEvent);
        }
    }

    RunIfNotReady();
    return PVMFSuccess;
}

void PVMFProtocolEngineNode::UpdateTimersInProcessIncomingMsg(const bool aEOSMsg, PVMFPortInterface* aPort)
{
    // for response timers
    if (!aEOSMsg)
    {
        // only non-EOS media data can cancel the response timer, EOS message shouldn't(that will cause no timeout happens)
        iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID);
        iNodeTimer->cancel(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
    }

    // for inactivity timer
    if (!aEOSMsg && iInterfaceState != EPVMFNodePaused)
    {
        if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT) iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // set up inactivity timer
    }
    else   // aEOSMsg=true or iInterfaceState = EPVMFNodePaused
    {
        iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID);
    }
}

bool PVMFProtocolEngineNode::IgnoreCurrentInputData(PVMFPortInterface* aPort, const bool isEOS, PVMFSharedMediaMsgPtr &aMsg)
{
    OSCL_UNUSED_ARG(aMsg);
    if (iInterfacingObjectContainer->ignoreCurrentInputData())
    {
        if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
        {
            CheckEndOfProcessingInIgoreData(isEOS);
        }
        return true;
    }

    // for input port (HTTP GET)
    if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_INPUT)
    {
        // processing done => ignore the rest data
        if (CheckEndOfProcessingInIgoreData(isEOS)) return true;

        // paused state, ignore EOS for socket disconnect
        if (/*isEOS &&*/ iInterfaceState == EPVMFNodePaused) return true;
    }

    // for feedback port (HTTP POST)
    if (aPort->GetPortTag() == PVMF_PROTOCOLENGINENODE_PORT_TYPE_FEEDBACK)
    {
        if (isEOS) return true;
        if (!isEOS &&
                (iInterfaceState == EPVMFNodeStarted ||
                 iInterfaceState == (TPVMFNodeInterfaceState)PVMFProtocolEngineNodeState_BeingStarted) &&
                !iInterfacingObjectContainer->isDownloadStreamingDone())
        {
            return true;
        }
    }

    return false;
}

bool PVMFProtocolEngineNode::CheckEndOfProcessingInIgoreData(const bool isEOS, const bool isDataPort)
{
    if (!iInterfacingObjectContainer->isDownloadStreamingDone()) return false;

    EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo();
    if (isEOS)
    {
        if (iProtocolContainer->needCheckEOSAfterDisconnectSocket())
        {
            aInfo->clear();
            aInfo->iSendServerDisconnectEvent = true;
        }
    }
    else
    {
        if (iProtocolContainer->needCheckExtraDataComeIn())
        {
            aInfo->clear();
            aInfo->iExtraDataComeIn = true;
        }
    }

    if (aInfo->isValid())
    {
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo);
        iInternalEventQueue.push_back(aEvent);
        SetProcessingState(ProcessingState_NormalDataflow);
        RunIfNotReady();
        return true;
    }

    // Current situation: iInterfacingObjectContainer->isDownloadStreamingDone() = true
    if (isDataPort) return true;
    return false;
}

void PVMFProtocolEngineNode::LogIncomingMessage(PVMFSharedMediaMsgPtr &aMsg, bool isEOS, PVMFPortInterface* aPort)
{
    if (isEOS)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage() GOT EOS! port=0x%x, iInterfaceState=%d",
                         aPort, iInterfaceState));
        OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable, 'aPort'
    }
    else
    {
        // Compute data size for logging purposes
        PVMFSharedMediaDataPtr mediaData;
        convertToPVMFMediaData(mediaData, aMsg);
        uint32 dataSize = 0;
        uint32 numFrags = mediaData->getNumFragments();
        for (uint32 i = 0; i < numFrags; i++)
        {
            OsclRefCounterMemFrag memFragIn;
            mediaData->getMediaFragment(i, memFragIn);
            uint32 fragLen = memFragIn.getMemFrag().len;
            dataSize += fragLen;
        }

        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogIncomingMessage()  SEQNUM=%d,SIZE=%d,port=0x%x,portIncomingQueueSize(AfterDequeue)=%d,iInterfaceState=%d",
                         aMsg->getSeqNum(), dataSize, aPort, aPort->IncomingMsgQueueSize(), iInterfaceState));
    }
}


/////////////////////////////////////////////////////
PVMFStatus PVMFProtocolEngineNode::ProcessOutgoingMsg(PVMFPortInterface* aPort)
{
    //Called by the AO to process one message off the outgoing
    //message queue for the given port.  This routine will
    //try to send the data to the connected port.
    if (aPort->OutgoingMsgQueueSize() == 0) return PVMFSuccess;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() aPort=0x%x, OutgoingMsgQueueSize=%d",
                    aPort, aPort->OutgoingMsgQueueSize()));

    // check whether outgoing message is media command or media data
    PVMFSharedMediaMsgPtr msg;
    if (!((PVMFProtocolEnginePort*)aPort)->PeekOutgoingMsg(msg)) return PVMFFailure;

    PVMFStatus status = aPort->Send();
    if (status == PVMFErrBusy)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFProtocolEngineNode::ProcessOutgoingMsg() Connected port goes into busy state"));
    }
    if (status != PVMFSuccess) return status;

    return PostProcessForMsgSentSuccess(aPort, msg);
}

PVMFStatus PVMFProtocolEngineNode::PostProcessForMsgSentSuccess(PVMFPortInterface* aPort, PVMFSharedMediaMsgPtr &aMsg)
{
    PVMFStatus status = PVMFSuccess;

    // keep track the sequence no of the media msg just sent out successfully
    iInterfacingObjectContainer->setLatestPacketNumSent(aMsg->getSeqNum());

    // set up server response timer and cancel inactivity timer
    bool isMediaData = (aMsg->getFormatID() <  PVMF_MEDIA_CMD_FORMAT_IDS_START) ||
                       (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID);
    UpdateTimersInProcessOutgoingMsg(isMediaData, aPort);

    // send() success means outgoing queue should always be ready, then send out outgoing queue ready event
    if ((PVMFProtocolEnginePort*)aPort == iPortOut) SendOutgoingQueueReadyEvent(aPort);

    // handle the remaining post processing for the different media cmds.
    if (aMsg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: EOS SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));

        // complete the pending command if there is, especially for the case of sending EOS due to error
        ProtocolStateErrorInfo aInfo(0, false);
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
        DispatchInternalEvent(&aEvent);
    }
    else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: RE_CONFIG SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));

        uint32 aFirstPacketNum = 0xFFFFFFFF;
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_FirstPacketAvailable, (OsclAny*)aFirstPacketNum);
        DispatchInternalEvent(&aEvent);
    }
    else if (aMsg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SOCKET CONNECT SENT! SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
        bool status = iProtocolContainer->completeRepositionRequest();
        if (status) LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SOCKET CONNECT cmd SUCCESS: complete data stream reposition request"));
    }
    else
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::PostProcessForMsgSentSuccess() Send() SUCCESS: SEQNUM= %d, MsgID=%d, port=0x%x", aMsg->getSeqNum(), aMsg->getFormatID(), aPort));
    }

    return status;
}

void PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg(const bool isMediaData, PVMFPortInterface* aPort)
{
    // set up server response timer
    if (((PVMFProtocolEnginePort*)aPort == iPortInForData ||
            (PVMFProtocolEnginePort*)aPort == iPortInForLogging) &&
            isMediaData)
    {
        iNodeTimer->cancel(SERVER_INACTIVITY_TIMER_ID);

        uint32 timerID = SERVER_RESPONSE_TIMER_ID;
        if (iInterfacingObjectContainer->isDownloadStreamingDone() && (PVMFProtocolEnginePort*)aPort == iPortInForLogging)
        {
            // logging POST for EOS and stop
            timerID = SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING;
        }
        iNodeTimer->start(timerID);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::UpdateTimersInProcessOutgoingMsg() server response timer starts! timerID=%d, timeoutValue=%d", timerID, iNodeTimer->getTimeout(timerID)));
    }
}

void PVMFProtocolEngineNode::SendOutgoingQueueReadyEvent(PVMFPortInterface* aPort)
{
    if (aPort->OutgoingMsgQueueSize() == 0) return;

    // only insert outgoing queue ready event in case of no such event in the port activity queue
    if (!SearchPortActivityInQueue(PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY))
    {
        PVMFPortActivity activity(aPort, PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY);
        QueuePortActivity(activity);
    }
}

bool PVMFProtocolEngineNode::SearchPortActivityInQueue(const PVMFPortActivityType aType)
{
    bool bFound = false;
    for (uint32 i = 0; i < iPortActivityQueue.size(); i++)
    {
        if (iPortActivityQueue[i].iType == aType)
        {
            bFound = true;
            break;
        }
    }
    return bFound;
}

void PVMFProtocolEngineNode::ProcessOutgoingQueueReady()
{
    if (iPortInForData)
    {
        if (iPortInForData->IncomingMsgQueueSize() > 0)
        {
            ProcessIncomingMsg(iPortInForData);
        }
    }

    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByPortOutgoingQueueReady);
    iInternalEventQueue.push_back(aEvent);
    iProcessingState = ProcessingState_NormalDataflow; // enable data flow
    if (IsAdded())
        RunIfNotReady();
}

/**
/////////////////////////////////////////////////////
// Active object implementation
/////////////////////////////////////////////////////
*/

/**
// The AO will either process one command or service one connected
// port per call.  It will re-schedule itself and run continuously
// until it runs out of things to do.
*/
void PVMFProtocolEngineNode::Run()
{
    //Process commands.
    if (!iInputCommands.empty() && ProcessCommand(iInputCommands.front()))
    {
        //note: need to check the state before re-scheduling
        //since the node could have been reset in the ProcessCommand call.
        if (iInterfaceState != EPVMFNodeCreated) RunIfNotReady();
        return;
    }

    // Process data, higher priority than port processing
    // Do this last after handling all node command and port activity but before checking if flush is complete
    if (HandleProcessingState())
    {
        RunIfNotReady();
        return;
    }

    // Process port activity
    if (!iPortActivityQueue.empty() && !FlushPending()) ///*&& (iInterfaceState==EPVMFNodeStarted || FlushPending())*/)
    {
        // If the port activity cannot be processed because a port is
        // busy, discard the activity and continue to process the next
        // activity in queue until getting to one that can be processed.
        while (!iPortActivityQueue.empty())
        {
            if (ProcessPortActivity()) break; //processed a port
        }
        //Re-schedule
        //if(iProcessingState == ProcessingState_NormalDataflow) RunIfNotReady();
        RunIfNotReady();
        return;
    }


    // If we get here we did not process any node commands, port activity, or decode.
    // Check for completion of a flush command...
    HandleRunFlush();
}

void PVMFProtocolEngineNode::HandleRunFlush()
{
    if (FlushPending() && iPortActivityQueue.empty())
    {
        uint32 i;
        //Debug check-- all the port queues should be empty at
        //this point.
        for (i = 0;i < iPortVector.size();i++)
        {
            if (iPortVector[i]->IncomingMsgQueueSize() > 0
                    || iPortVector[i]->OutgoingMsgQueueSize() > 0)
            {
                OSCL_ASSERT(false);
            }
        }

        //Flush is complete.  Go to prepared state.
        SetState(EPVMFNodePrepared);
        //resume port input so the ports can be re-started.
        for (i = 0;i < iPortVector.size();i++)
        {
            iPortVector[i]->ResumeInput();
        }
        CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
        RunIfNotReady();
    }
}

void PVMFProtocolEngineNode::SetProcessingState(PVProtocolEngineNodePrcoessingState aState)
{
    iProcessingState = aState;
    RunIfNotReady();
}


// Using state to handle different scenarios
bool PVMFProtocolEngineNode::HandleProcessingState()
{
    if (iProcessingState == ProcessingState_NormalDataflow)
    {
        return DispatchInternalEvent();
    }
    return false;
}

// The following method is (internal) event dispatcher, which is an important component for event-driven model
// to handle the interactions inside the node, between protocol engine and the node. All events are defined as
// PVProtocolEngineNodeInternalEventType in pvmf_protocol_engine_node_internal.h.
// Typical events are,

// ** init/prepar/start/seek/bitstreamSwitch command trigger the data flow (class NormalDataFlowHandler),
// ** multple events based on the callbacks from protocol engine
//		-- http header available (class HttpHeaderAvailableHandler) to complete start command
//		-- first data packet available (class FirstPacketAvailableHandler) to complete seek/bitstreamSwitch command
//		-- normal data packet available (class NormalDataAvailableHandler) to pass down to node output object, and then output data packets
//		-- protocol state complete (class ProtocolStateCompleteHandler) to complete init/prepare command
//		-- protocol state error (class ProtocolStateErrorHandler) to handle all the errors from protocol engine

// ** timer out event (will go to ProtocolStateErrorHandler) to complete any pending commands or report error event
// ** end of data processing, especially for after download complete, parser node still send resume request, (class EndOfDataProcessingHandler)
// ** by-pass server response for HEAD request in progressive download (class ServerResponseErrorBypassingHandler)

// 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
// typical polymophimic treatment.The dispatching logic is table-based, i.e the mapping between most events and their corresponding handlers is
// achieved by table look-up.

// aLatestEvent!=NULL means the event source sends the event without pushing it into the event queue
// so no need to dequeue the event from the event queue, and just process it. This way aims to save
// queueing and dequeuing operations on the queue.
bool PVMFProtocolEngineNode::DispatchInternalEvent(PVProtocolEngineNodeInternalEvent *aLatestEvent)
{
    if (iInternalEventQueue.empty() && !aLatestEvent) return false;

    PVProtocolEngineNodeInternalEvent aEvent = ((aLatestEvent != NULL) ? (*aLatestEvent) : (PVProtocolEngineNodeInternalEvent) iInternalEventQueue[0]);
    if (!aLatestEvent) iInternalEventQueue.erase(&(iInternalEventQueue.front()));

    if ((uint32)aEvent.iEventId >= (uint32)PVProtocolEngineNodeInternalEventType_IncomingMessageReady)
        iCurrEventHandler = iEventHandlers[EVENT_HANDLER_TOTAL-1];
    else
        iCurrEventHandler = iEventHandlers[(uint32)aEvent.iEventId];

    iCurrEventHandler->handle(aEvent);
    if (!iInternalEventQueue.empty()) return true; // true means this function will re-run again
    return false; // let specific event handler determine this function needs to be re-run again
}

inline bool PVMFProtocolEngineNode::IsDataFlowEventAlreadyInQueue(const PVProtocolEngineNodeInternalEventType aEventType)
{
    if (iInternalEventQueue.empty()) return false;

    for (uint32 i = 0; i < iInternalEventQueue.size(); i++)
    {
        if (iInternalEventQueue[i].iEventId == aEventType) return true;
    }
    return false;
}

void PVMFProtocolEngineNode::ProtocolStateComplete(const ProtocolStateCompleteInfo &aInfo)
{
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateComplete);
    iInterfacingObjectContainer->setProtocolStateCompleteInfo(aInfo);
    //aEvent.iEventInfo = (OsclAny*)iInterfacingObjectContainer->getProtocolStateCompleteInfo();
    DispatchInternalEvent(&aEvent);
}

void PVMFProtocolEngineNode::OutputDataAvailable(OUTPUT_DATA_QUEUE &aOutputQueue, ProtocolEngineOutputDataSideInfo& aSideInfo)
{
    OUTPUT_DATA_QUEUE *pOutput = &aOutputQueue;
    PVProtocolEngineNodeInternalEvent aEvent(aSideInfo, (OsclAny*)pOutput);
    DispatchInternalEvent(&aEvent);
}

void PVMFProtocolEngineNode::ProtocolStateError(int32 aErrorCode)
{
    if (iProtocol->isCurrentStateOptional())
    {
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing);
        DispatchInternalEvent(&aEvent);
    }
    else
    {
        ProtocolStateErrorInfo aInfo(aErrorCode);
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
        DispatchInternalEvent(&aEvent);
    }
}

bool PVMFProtocolEngineNode::GetBufferForRequest(PVMFSharedMediaDataPtr &aMediaData)
{
    return iNodeOutput->getBuffer(aMediaData);
}

void PVMFProtocolEngineNode::ProtocolRequestAvailable(uint32 aRequestType)
{
    uint32 aOutputType;
    if (aRequestType == ProtocolRequestType_Logging)
    {
        aOutputType = NodeOutputType_InputPortForLogging;
    }
    else
    {
        aOutputType = NodeOutputType_InputPortForData;
    }

    iNodeOutput->flushData(aOutputType);
}


void PVMFProtocolEngineNode::OutputBufferPoolFull()
{
    iProcessingState = ProcessingState_Idle; // hold off any data flow until the output buffer callback
}

void PVMFProtocolEngineNode::OutputBufferAvailable()
{
    if (iPortOut && !iPortOut->IsOutgoingQueueBusy())
    {
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByBufferAvailability);
        iInternalEventQueue.push_back(aEvent);
        SetProcessingState(ProcessingState_NormalDataflow);
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::OutputBufferAvailable() - MemCallBackReturn"));
    }

    if (iPortInForData)
    {
        if (iPortInForData->IncomingMsgQueueSize() > 0)
        {
            PVMFPortActivity activity(iPortInForData, PVMF_PORT_ACTIVITY_INCOMING_MSG);
            QueuePortActivity(activity);
        }
    }
}

void PVMFProtocolEngineNode::ReadyToUpdateDownloadControl()
{
    iProtocolContainer->doInfoUpdate(PROCESS_SUCCESS);
}

bool PVMFProtocolEngineNode::QueueOutgoingMsgSentSuccess(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::QueueOutgoingMsgSentSuccess() - Msg queued and sent successfully!, Port=0x%x", aPort));
    RerunForPostProcessAfterOutgoingMsgSent(aPort, aMsg);
    return true;
}


void PVMFProtocolEngineNode::TimeoutOccurred(int32 timerID, int32 timeoutInfo)
{
    OSCL_UNUSED_ARG(timeoutInfo);
    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",
                     timerID, (int32)iInterfaceState));

    iProtocolContainer->handleTimeout(timerID);
}

// create iProtocolContainer, iProtocol and iNodeOutput and all other protocol related projects
bool PVMFProtocolEngineNode::CreateProtocolObjects(const uint32 aProtocolType)
{
    AutoCleanup cleanup(this); // cleanup's destructor will automatically call DeleteProtocolObjects() if failure happens

    // create protocol container factory
    iProtocolContainerFactory = CreateProtocolContainerFactory(aProtocolType);
    if (!iProtocolContainerFactory) return false;

    // create protocol container
    iProtocolContainer = iProtocolContainerFactory->create(this);
    if (!iProtocolContainer) return false;

    // use protocol container to create all other protocol objects
    if (!iProtocolContainer->createProtocolObjects()) return false;

    cleanup.cancel();
    return true;
}

bool PVMFProtocolEngineNode::RecreateProtocolObjectsForProgressiveStreaming(OsclAny* aSourceData)
{
    if (!iProtocolContainer->isStreamingPlayback()) return true;

    // in case of progressive streaming
    DeleteProtocolObjects();
    if (!CreateProtocolObjects((uint32)PVHTTPPROTOCOL_PROGRESSIVE_STREAMING)) return false;

    // add source data again
    return iProtocolContainer->addSourceData(aSourceData);
}

void PVMFProtocolEngineNode::DeleteProtocolObjects()
{
    if (iProtocolContainer) iProtocolContainer->deleteProtocolObjects();
    OSCL_DELETE(iProtocolContainer);
    iProtocolContainer = NULL;
    OSCL_DELETE(iProtocolContainerFactory);
    iProtocolContainerFactory = NULL;
}

ProtocolContainerFactory* PVMFProtocolEngineNode::CreateProtocolContainerFactory(const uint32 aProtocolType)
{
    ProtocolContainerFactory *aFactory = NULL;
    switch (aProtocolType)
    {

#if defined(PV_PROTOCOL_ENGINE_NODE_PROGRESSIVE_DOWNLOAD_ENABLED) || defined(PV_PROTOCOL_ENGINE_NODE_PROGRESSIVE_STREAMING_ENABLED)
        case PVHTTPPROTOCOL_PROGRESSIVE_DOWNLOAD:
            aFactory = OSCL_NEW(ProgressiveDownloadContainerFactory, ());
            break;
#endif

#if defined(PV_PROTOCOL_ENGINE_NODE_PROGRESSIVE_STREAMING_ENABLED)
        case PVHTTPPROTOCOL_PROGRESSIVE_STREAMING:
            aFactory = OSCL_NEW(ProgressiveStreamingContainerFactory, ());
            break;
#endif


#if defined(PV_PROTOCOL_ENGINE_NODE_WMHTTPSTREAMING_ENABLED)
        case PVHTTPPROTOCOL_MS_HTTP_STREAMING:
            aFactory = OSCL_NEW(MsHttpStreamingContainerFactory, ());
            break;
#endif

        default:
            break;
    }
    return aFactory;
}


void PVMFProtocolEngineNode::ClearPorts(const bool aNeedDelete)
{
    // clear queued messages in ports
    uint32 i;
    for (i = 0; i < iPortVector.size(); i++) iPortVector[i]->ClearMsgQueues();

    // Discard any port activity events
    iPortActivityQueue.clear();

    if (aNeedDelete)
    {
        while (!iPortVector.empty())
        {
            PVMFProtocolEnginePort* port = iPortVector.front();
            iPortVector.Erase(&iPortVector.front());

            if (port == iPortInForData)	iPortInForData = NULL;
            if (port == iPortInForLogging) iPortInForLogging = NULL;
            if (port == iPortOut) iPortOut = NULL;
        }
        // Restore original port vector reserve.
        iPortVector.Reconstruct();
    }
}

void PVMFProtocolEngineNode::Clear(const bool aNeedDelete)
{
    if (iProtocolContainer) iProtocolContainer->doClear(aNeedDelete);
    if (aNeedDelete) DeleteProtocolObjects();

}

void PVMFProtocolEngineNode::StopClear()
{
    if (iProtocolContainer) iProtocolContainer->doStopClear();
}

void PVMFProtocolEngineNode::CancelClear()
{
    if (iProtocolContainer) iProtocolContainer->doCancelClear();
}

////////// PVMFDataSourceInitializationExtensionInterface implementation ////////////////////////
PVMFStatus PVMFProtocolEngineNode::SetSourceInitializationData(OSCL_wString& aSourceURL,
        PVMFFormatType& aSourceFormat,
        OsclAny* aSourceData)
{
    if ((aSourceFormat != PVMF_MIME_DATA_SOURCE_HTTP_URL) &&
            (aSourceFormat != PVMF_MIME_DATA_SOURCE_PVX_FILE)) return PVMFErrNotSupported;

    // create protocol objects
    if (!CreateProtocolObjects(GetProtocolType(aSourceFormat, aSourceData))) return PVMFErrNoMemory;

    // check and add source data
    if (!iProtocolContainer->addSourceData(aSourceData)) return PVMFFailure;

    // need to recreate protocol objects for progressive streaming based on source data
    if (!RecreateProtocolObjectsForProgressiveStreaming(aSourceData)) return PVMFErrNoMemory;

    // set download format
    if (iInterfacingObjectContainer) iInterfacingObjectContainer->setDownloadFormat(aSourceFormat);

    // set URI
    if (!iInterfacingObjectContainer->getURIObject().setURI(aSourceURL)) return PVMFFailure;


    // create and set iCfgFile
    if (!iProtocolContainer->createCfgFile(iInterfacingObjectContainer->getURIObject().getURI())) return PVMFFailure;
    return PVMFSuccess;
}


PVMFStatus PVMFProtocolEngineNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock)
{
    if (iDownloadControl)
    {
        iDownloadControl->setSupportObject((OsclAny *)aClientClock, DownloadControlSupportObjectType_EnginePlaybackClock);
        return PVMFSuccess;
    }
    return PVMFFailure;
}


uint32 PVMFProtocolEngineNode::GetProtocolType(PVMFFormatType& aSourceFormat, OsclAny* aSourceData)
{
    // TBD, for MS http streaming, a cfg file should still be passed in.
    // so could use iDownloadFormat instead
    // just use sourcedata to differentiate ms http streaming and download for a short-term solution
    if (!aSourceData)
        return PVHTTPPROTOCOL_MS_HTTP_STREAMING;
    else if (aSourceFormat == PVMF_MIME_DATA_SOURCE_PVX_FILE)
        return PVHTTPPROTOCOL_FASTTRACK_DOWNLOAD;
    else if (aSourceFormat == PVMF_MIME_DATA_SOURCE_HTTP_URL)
    {
        return PVHTTPPROTOCOL_PROGRESSIVE_DOWNLOAD;
    }

    return 0;
}

// From PVMIDatastreamuserInterface
void PVMFProtocolEngineNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory, int32 aFactoryTag, const PvmfMimeString* aFactoryConfig)
{
    OSCL_UNUSED_ARG(aFactoryTag);
    OSCL_UNUSED_ARG(aFactoryConfig);
    iInterfacingObjectContainer->setDataStreamFactory(&aFactory);
}


// From PVMFProtocolEngineNodeExtensionInterface
PVMFStatus PVMFProtocolEngineNode::GetHTTPHeader(uint8*& aHeader, uint32& aHeaderLen)
{
    iInterfacingObjectContainer->getHTTPHeader(aHeader, aHeaderLen);
    return PVMFSuccess;
}

bool PVMFProtocolEngineNode::GetSocketConfig(OSCL_String &aPortConfig)
{
    if (CheckUsingProxy(aPortConfig)) return true;
    return GetSocketConfigImp(iInterfacingObjectContainer->getURIObject(), aPortConfig);
}

bool PVMFProtocolEngineNode::GetSocketConfigForLogging(OSCL_String &aPortConfig)
{
    if (CheckUsingProxy(aPortConfig)) return true;
    return GetSocketConfigImp(iInterfacingObjectContainer->getLoggingURIObject(), aPortConfig);
}

bool PVMFProtocolEngineNode::GetSocketConfigImp(const INetURI &aURI, OSCL_String &aPortConfig)
{
    INetURI *pURI = &((INetURI &)aURI);
    if (pURI->empty()) return false;

    OSCL_HeapString<OsclMemAllocator> serverAddr;
    int32 serverPort = 0;
    if (!pURI->getHostAndPort(serverAddr, serverPort)) return false;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, \
                    (0, "PVMFProtocolEngineNode::GetSocketConfigImp(), serverAddr=%s , serverPort=%d", \
                     serverAddr.get_cstr(), serverPort));

    return ComposeSocketConfig(serverAddr, serverPort, aPortConfig);
}

bool PVMFProtocolEngineNode::ComposeSocketConfig(OSCL_String &aServerAddr, const uint32 aPortNum, OSCL_String &aPortConfig)
{
    // compose port config string: "TCP/remote_address=pvserveroha.pv.com;remote_port=554"
    uint32 tempBufSize = aServerAddr.get_size() + 64;
    OsclMemAllocator alloc;
    char *buffer = (char*)alloc.allocate(tempBufSize);
    if (!buffer) return false;
    oscl_snprintf(buffer, tempBufSize, "TCP/remote_address=");
    oscl_strcat(buffer, aServerAddr.get_cstr());
    OSCL_FastString port(_STRLIT_CHAR(";remote_port="));
    oscl_strcat(buffer, port.get_cstr());
    char portString[16];
    oscl_snprintf(portString, 16, "%d", aPortNum);
    oscl_strcat(buffer, (char*)portString);

    aPortConfig = OSCL_HeapString<OsclMemAllocator> (buffer, oscl_strlen(buffer));
    alloc.deallocate(buffer);
    return true;
}


bool PVMFProtocolEngineNode::CheckUsingProxy(OSCL_String &aPortConfig)
{
    uint32 aProxyPort = 0;
    OSCL_HeapString<OsclMemAllocator> aProxyName;
    if (!getProxy(aProxyName, aProxyPort)) return false;
    iInterfacingObjectContainer->getURIObject().setUsAbsoluteURI();
    iInterfacingObjectContainer->getLoggingURIObject().setUsAbsoluteURI();
    return ComposeSocketConfig(aProxyName, aProxyPort, aPortConfig);
}

bool PVMFProtocolEngineNode::getProxy(OSCL_String& aProxyName, uint32 &aProxyPort)
{
    if (!iProtocolContainer) return false;
    return iProtocolContainer->getProxy(aProxyName, aProxyPort);
}


bool PVMFProtocolEngineNode::SetUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable)
{
    // assume setsourceinit API already gets called
    if (!iUserAgentField) return false;
    return iUserAgentField->setUserAgent(aUserAgent, isOverwritable);
}

void PVMFProtocolEngineNode::SetHttpVersion(const uint32 aHttpVersion)
{
    if (iProtocolContainer) iProtocolContainer->setHttpVersion(aHttpVersion);
}

void PVMFProtocolEngineNode::SetHttpExtensionHeaderField(OSCL_String &aFieldKey, OSCL_String &aFieldValue, const HttpMethod aMethod, const bool aPurgeOnRedirect)
{
    if (iProtocolContainer) iProtocolContainer->setHttpExtensionHeaderField(aFieldKey, aFieldValue, aMethod, aPurgeOnRedirect);
}

void PVMFProtocolEngineNode::SetLoggingURL(OSCL_wString& aSourceURL)
{
    iInterfacingObjectContainer->setLoggingURI(aSourceURL);
}

void PVMFProtocolEngineNode::SetNetworkTimeout(const uint32 aTimeout)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkTimeout(), responseTimeout=%d", aTimeout));
    uint32 timeout = aTimeout;
    if ((int32)timeout < 0) timeout = 0x7fffffff;
    if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID, timeout);
}

void PVMFProtocolEngineNode::SetNetworkLoggingTimeout(const uint32 aTimeout)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SetNetworkLoggingTimeout(), loggingTimeout=%d", aTimeout));
    uint32 timeout = aTimeout;
    if ((int32)timeout < 0) timeout = 0x7fffffff;
    if (iNodeTimer) iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING, timeout);
}

bool PVMFProtocolEngineNode::IsWMServerVersion4()
{
    if (iProtocol)
    {
        return (iProtocol->getServerVersionNum() < DEFAULT_MS_HTTP_STREAMING_SERVER_VERSION);
    }
    return false;
}


void PVMFProtocolEngineNode::setFormatDownloadSupportInterface(PVMFFormatProgDownloadSupportInterface* download_support_interface)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setFormatDownloadSupportInterface() IN, download_support_interface=0x%x", download_support_interface));

    if (iDownloadControl && iDownloadProgess)
    {
        iDownloadControl->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface);
        iDownloadProgess->setSupportObject((OsclAny *)download_support_interface, DownloadControlSupportObjectType_SupportInterface);

        PVMFDownloadProgressInterface *aProgDownload = OSCL_STATIC_CAST(PVMFDownloadProgressInterface*, this);
        iDownloadControl->setSupportObject((OsclAny *)aProgDownload, DownloadControlSupportObjectType_ProgressInterface);
    }
}

void PVMFProtocolEngineNode::setClipDuration(const uint32 aClipDurationMsec)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::setClipDuration(), aClipDurationMsec = %dms", aClipDurationMsec));

    if (iDownloadControl) iDownloadControl->setClipDuration(aClipDurationMsec);
    if (iDownloadProgess) iDownloadProgess->setClipDuration(aClipDurationMsec);
}

OsclSharedPtr<PVMFMediaClock> PVMFProtocolEngineNode::getDownloadProgressClock()
{
    OsclSharedPtr<PVMFMediaClock> clock;
    iDownloadControl->getDownloadClock(clock);
    return clock;
}

void PVMFProtocolEngineNode::requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete)
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification() IN, currentNPTReadPosition=%d", currentNPTReadPosition));

    bool needSendUnderflowEvent = false;
    iDownloadControl->requestResumeNotification(currentNPTReadPosition, aDownloadComplete, needSendUnderflowEvent);
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::requestResumeNotification(), after iDownloadControl->requestResumeNotification(), currentNPTReadPosition=%d, needSendUnderflowEvent=%d, aDownloadComplete=%d",
                     currentNPTReadPosition, (uint32)needSendUnderflowEvent, (uint32)aDownloadComplete));

    // report underflow event for download incomplete
    // but only send it once, for multiple back to back requestResumeNotification
    if (!aDownloadComplete && needSendUnderflowEvent) ReportInfoEvent(PVMFInfoUnderflow);

    if (aDownloadComplete)  // end of processing
    {
        EndOfDataProcessingInfo *aInfo = iInterfacingObjectContainer->getEOPInfo();
        aInfo->clear();
        aInfo->iSendResumeNotification = true;
        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aInfo);
        iInternalEventQueue.push_back(aEvent);
        SetProcessingState(ProcessingState_NormalDataflow);
        RunIfNotReady();
    }

    // check the need of sending resume notification manually
    iProtocolContainer->checkSendResumeNotification();
}

void PVMFProtocolEngineNode::cancelResumeNotification()
{
    LOGINFODATAPATH((0, "PVMFProtocolEngineNode::cancelResumeNotification"));

    if (iDownloadControl != NULL)
    {
        iDownloadControl->cancelResumeNotification();
    }
}

bool PVMFProtocolEngineNode::SendPortMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging)
{
    // Create an output media command
    PVMFSharedMediaCmdPtr aCmdPtr = PVMFMediaCmd::createMediaCmd();

    // Set the input format ID
    aCmdPtr->setFormatID(aCmdId);

    // check format specific info
    if (!CheckFormatSpecificInfoForMediaCommand(aCmdPtr, aCmdId, isForLogging)) return false;

    // Convert to media message and send it out
    PVMFSharedMediaMsgPtr mediaMsgOut;
    convertToPVMFMediaCmdMsg(mediaMsgOut, aCmdPtr);
    PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut);
    if (status < PVMFSuccess) return false;
    if (status == PVMFSuccessOutgoingMsgSent)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::SendPortMediaCommand() - Msg queued and sent successfully!, Port=0x%x", aPort));
        RerunForPostProcessAfterOutgoingMsgSent(aPort, mediaMsgOut);
    }

    LogPortMediaCmdQueued(aPort, aCmdId);
    return true;
}

void PVMFProtocolEngineNode::RerunForPostProcessAfterOutgoingMsgSent(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg)
{
    // form PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully event
    OutgoingMsgSentSuccessInfo aInfo(aPort, aMsg);
    OutgoingMsgSentSuccessInfoVec *aVec = iInterfacingObjectContainer->getOutgoingMsgSentSuccessInfoVec();
    aVec->push_back(aInfo);
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully,
            (OsclAny*)aVec);
    iInternalEventQueue.push_back(aEvent);
    SetProcessingState(ProcessingState_NormalDataflow);
    RunIfNotReady();
}

void PVMFProtocolEngineNode::LogPortMediaCmdQueued(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId)
{
    // log message
    if (aCmdId == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RECONNECT SENT, Port=0x%x", aPort));
    }
    else if (aCmdId == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - EOS SENT, Port=0x%x", aPort));
    }
    else if (aCmdId == PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - RE_CONFIG SENT, Port=0x%x", aPort));
    }
    else if (aCmdId == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)
    {
        LOGINFODATAPATH((0, "PVMFProtocolEngineNode::LogPortMediaCmdQueued() - DISCONNECT SENT, Port=0x%x", aPort));
    }

    OSCL_UNUSED_ARG(aPort); // to avoid warning of unused variable 'aPort'

}

bool PVMFProtocolEngineNode::CheckFormatSpecificInfoForMediaCommand(PVMFSharedMediaCmdPtr &aCmdPtr, PVUid32 aCmdId, const bool isForLogging)
{
    if (aCmdId != PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID) return true;

    // for socket recconnect command, set port config as format specific info
    bool needAttachFormatSpecificInfo = false;
    OSCL_HeapString<OsclMemAllocator> aPortConfig;
    if (iInterfacingObjectContainer->getCurrNumRedirectTrials() > 0 || iInterfaceState == EPVMFNodePaused)
    {
        bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty();
        if (isForLogging && hasLoggingUrl)
        {
            if (!GetSocketConfigForLogging(aPortConfig)) return false;
        }
        else
        {
            if (!GetSocketConfig(aPortConfig)) return false;
        }
        needAttachFormatSpecificInfo = true;
    }
    else if (iInterfacingObjectContainer->isDownloadStreamingDone())
    {
        bool hasLoggingUrl = !iInterfacingObjectContainer->getLoggingURIObject().empty();
        if (hasLoggingUrl)
        {
            if (!GetSocketConfigForLogging(aPortConfig)) return false;
        }
        else
        {
            if (!GetSocketConfig(aPortConfig)) return false;
        }
        needAttachFormatSpecificInfo = true;
    }

    if (needAttachFormatSpecificInfo)
    {
        OsclRefCounterMemFrag socketConfigMemfrag;
        int32 err = 0;
        OSCL_TRY(err, socketConfigMemfrag = iPortConfigFSInfoAlloc->allocate(aPortConfig.get_size() + 1));
        if (err) return false;
        oscl_memcpy((char*)(socketConfigMemfrag.getMemFragPtr()), aPortConfig.get_cstr(), aPortConfig.get_size());
        char *ptr = (char*)socketConfigMemfrag.getMemFragPtr() + aPortConfig.get_size();
        *ptr = 0; // make it string
        aCmdPtr->setFormatSpecificInfo(socketConfigMemfrag);
    }
    return true;
}

OSCL_EXPORT_REF PVMFStatus PVMFProtocolEngineNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
{
    return iProtocolContainer->getMediaPresentationInfo(aInfo);
}

PVMFStatus PVMFProtocolEngineNode::SelectTracks(PVMFMediaPresentationInfo& aInfo)
{
    return iProtocolContainer->selectTracks(aInfo);
}

////////////////////////////////////////////////////////////////////////////////////
//////	ProtocolContainer implementation
////////////////////////////////////////////////////////////////////////////////////

// constructor
ProtocolContainer::ProtocolContainer(PVMFProtocolEngineNode *aNode) :
        iNode(aNode),
        iInterfacingObjectContainer(NULL)
{
    if (aNode) iInterfacingObjectContainer = aNode->iInterfacingObjectContainer;
    iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
}

bool ProtocolContainer::isObjectsReady()
{
    if (!iNode->iProtocol			||
            !iNode->iNodeOutput			||
            !iInterfacingObjectContainer ||
            iInterfacingObjectContainer->getURIObject().empty() ||
            !iInterfacingObjectContainer->getDataStreamFactory() ||
            !iNode->iPortInForData) return false;
    return true;
}

PVMFStatus ProtocolContainer::doPrepare()
{
    return initImpl();
}

PVMFStatus ProtocolContainer::initImpl()
{
    if (!isObjectsReady())
    {
        return PVMFErrNotReady;
    }

    // initialize output object
    int32 status = initNodeOutput();
    if (status != PVMFSuccess) return status;

    // initialize protocol object
    if (!initProtocol()) return PVMFFailure;

    // initialize download control object
    initDownloadControl();

    // start data flow
    // if the current socket connection is down, then do socket reconnect
    bool needSocketReconnect = !iNode->iInterfacingObjectContainer->isSocketConnectionUp();
    startDataFlowByCommand(needSocketReconnect);

    return PVMFPending;
}


bool ProtocolContainer::initProtocol()
{
    // then pass objects to protocol object (note that the order matters)
    iNode->iProtocol->setURI(iInterfacingObjectContainer->getURIObject());

    // update user-agent field
    if (!initProtocol_SetConfigInfo()) return false;
    iNode->iProtocol->setObserver(iNode);

    // protocol initialization and objects dispatch
    iNode->iProtocol->initialize();
    return true;
}

PVMFStatus ProtocolContainer::doStop()
{
    // send socket disconnect command if necessary
    sendSocketDisconnectCmd();

    // disable sending logging message, but try to disconnect socket
    // use end of processing event to streamline all end of processing cases for stop
    EndOfDataProcessingInfo *aEOPInfo = iNode->iInterfacingObjectContainer->getEOPInfo();
    aEOPInfo->clear();
    aEOPInfo->iForceStop = true;
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo);
    iNode->DispatchInternalEvent(&aEvent);

    return PVMFSuccess;
}

void ProtocolContainer::sendSocketDisconnectCmd()
{
    if (iNode->SendPortMediaCommand(iNode->iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID))
    {
        if (iNode->iPortInForData->Send())
        {
            LOGINFODATAPATH((0, "ProtocolContainer::doStop()->sendSocketDisconnectCmd(), Send() SUCCESS: MsgID=%d(SOCKET DISCONNECT)", (uint32)PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID));
        }
    }
}

void ProtocolContainer::startDataFlowByCommand(const bool needDoSocketReconnect)
{
    // flush out existing data at this point
    checkEOSMsgFromInputPort();
    iNode->iDataInQueue.clear();
    iNode->ClearPorts(); // clear any queued messages in ports

    // cancel all the existing timers
    iNode->iNodeTimer->clear();

    // disable info update at this point, will be enabled when new response comes in
    enableInfoUpdate(false);

    // socket reconnect
    if (needDoSocketReconnect) reconnectSocket();

    rescheduleNewDataFlow();
}

void ProtocolContainer::checkEOSMsgFromInputPort()
{
    if (iNode->iPortInForData->IncomingMsgQueueSize() == 0)  return;

    // input port has media message
    while (iNode->iPortInForData->IncomingMsgQueueSize() > 0)
    {
        PVMFSharedMediaMsgPtr msg;
        PVMFStatus status = iNode->iPortInForData->DequeueIncomingMsg(msg);
        if (status != PVMFSuccess) continue;
        if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
        {
            iInterfacingObjectContainer->updateSocketConnectFlags(true);
            return;
        }
    }
}

void ProtocolContainer::rescheduleNewDataFlow()
{
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowByCommand);
    iNode->iInternalEventQueue.push_back(aEvent);
    iNode->iProcessingState = ProcessingState_NormalDataflow;
    iNode->iInterfacingObjectContainer->setInputDataUnwanted(false);
    iNode->RunIfNotReady();
}

void ProtocolContainer::doClear(const bool aNeedDelete)
{
    // clear ports
    iNode->ClearPorts(aNeedDelete);

    // Clean up the internal stuff
    iNode->iDataInQueue.clear();
    clearInternalEventQueue();
    iNode->iInterfacingObjectContainer->clear();
    if (iNode->iNodeTimer) iNode->iNodeTimer->clear();
    //if(iNode->iDownloadControl) iNode->iDownloadControl->clear();
}

void ProtocolContainer::doStopClear()
{
    doClear();
    if (iNode->iDownloadControl) iNode->iDownloadControl->clear();
    iNode->iEventReport->clear();
}

void ProtocolContainer::doCancelClear()
{
    // clear ports
    iNode->ClearPorts();

    // Clean up the internal stuff
    iNode->iDataInQueue.clear();
    clearInternalEventQueue();
    //iNode->iInterfacingObjectContainer->clear();
    if (iNode->iNodeTimer) iNode->iNodeTimer->clear();
    if (iNode->iDownloadControl) iNode->iDownloadControl->clear();
    if (iNode->iEventReport) iNode->iEventReport->clear();

    // if re-do cancelled command, start from sending http request
    if (iNode->iProtocol) iNode->iProtocol->sendRequest();
}

void ProtocolContainer::clearInternalEventQueue()
{
    iNode->iInternalEventQueue.clear();
    OutgoingMsgSentSuccessInfoVec *aVec = iInterfacingObjectContainer->getOutgoingMsgSentSuccessInfoVec();
    aVec->clear();
}

bool ProtocolContainer::reconnectSocket(const bool aForceSocketReconnect)
{
    if (!aForceSocketReconnect)
    {
        // Do not force to do socket reconnect, and then need to check the possibility
        if (iInterfacingObjectContainer->isSocketReconnectCmdSent()) return true;
    }
    if (!iNode->SendPortMediaCommand(iNode->iPortInForData, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false;
    iNode->iProtocol->sendRequest();
    iInterfacingObjectContainer->setSocketReconnectCmdSent();
    return true;
}

bool ProtocolContainer::doEOS(const bool isTrueEOS)
{
    // download done
    if (isTrueEOS)
    {
        iNode->SendPortMediaCommand(iNode->iPortInForData, PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID);
    }
    else   // EOS packet hasn't been received, so re-connect socket
    {
        bool aForceSocketReconnect = false;
        if (!iNode->iInterfacingObjectContainer->isPrevSocketConnectionUp())
        {
            // the situation is, previous connection is down and the current connection is down.
            // then force reconnect
            aForceSocketReconnect = true;
        }
        reconnectSocket(aForceSocketReconnect);
    }

    return true;
}

uint32 ProtocolContainer::getBitMaskForHTTPMethod(const HttpMethod aMethod)
{
    uint32 bitMaskForHttpMethod = 0;
    if (aMethod == HTTP_GET) bitMaskForHttpMethod  = BITMASK_HTTPGET;
    if (aMethod == HTTP_POST) bitMaskForHttpMethod = BITMASK_HTTPPOST;
    if (aMethod == HTTP_HEAD) bitMaskForHttpMethod = BITMASK_HTTPHEAD;
    if (aMethod == HTTP_ALLMETHOD) bitMaskForHttpMethod = ~0;
    return bitMaskForHttpMethod;
}

bool ProtocolContainer::createProtocolObjects()
{
    // create iInterfacingObjectContainer
    iNode->iInterfacingObjectContainer = OSCL_NEW(InterfacingObjectContainer, ());
    if (!iNode->iInterfacingObjectContainer) return false;
    iInterfacingObjectContainer = iNode->iInterfacingObjectContainer;

    // create iPortConfigFSInfoAlloc for redirect port config
    iNode->iPortConfigFSInfoAlloc = OSCL_NEW(OsclRefCounterMemFragAlloc, (&iNode->iPortConfigMemPool));
    if (!iNode->iPortConfigFSInfoAlloc) return false;

    // create iNodeTimer
    if (!createNetworkTimer()) return false;

    // create specific event handlers
    if (!createEventHandlers()) return false;

    return true;
}

bool ProtocolContainer::createNetworkTimer()
{
    iNode->iNodeTimer = PVMFProtocolEngineNodeTimer::create(iNode);
    if (!iNode->iNodeTimer) return false;
    iNode->iNodeTimer->set(SERVER_RESPONSE_TIMER_ID);
    iNode->iNodeTimer->set(SERVER_INACTIVITY_TIMER_ID);
    iNode->iNodeTimer->set(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
    iNode->iNodeTimer->set(WALL_CLOCK_TIMER_ID);
    iNode->iNodeTimer->set(BUFFER_STATUS_TIMER_ID);
    return true;
}
bool ProtocolContainer::createEventHandlers()
{
    iNode->iEventHandlers[0] = OSCL_NEW(HttpHeaderAvailableHandler, (iNode));
    if (!iNode->iEventHandlers[0]) return false;
    iNode->iEventHandlers[1] = OSCL_NEW(FirstPacketAvailableHandler, (iNode));
    if (!iNode->iEventHandlers[1]) return false;
    iNode->iEventHandlers[2] = OSCL_NEW(NormalDataAvailableHandler, (iNode));
    if (!iNode->iEventHandlers[2]) return false;
    iNode->iEventHandlers[3] = OSCL_NEW(ProtocolStateCompleteHandler, (iNode));
    if (!iNode->iEventHandlers[3]) return false;
    iNode->iEventHandlers[4] = OSCL_NEW(EndOfDataProcessingHandler, (iNode));
    if (!iNode->iEventHandlers[4]) return false;
    iNode->iEventHandlers[5] = OSCL_NEW(ServerResponseErrorBypassingHandler, (iNode));
    if (!iNode->iEventHandlers[5]) return false;
    iNode->iEventHandlers[6] = OSCL_NEW(ProtocolStateErrorHandler, (iNode));
    if (!iNode->iEventHandlers[6]) return false;
    iNode->iEventHandlers[7] = OSCL_NEW(CheckResumeNotificationHandler, (iNode));
    if (!iNode->iEventHandlers[7]) return false;
    iNode->iEventHandlers[8] = OSCL_NEW(OutgoingMsgSentSuccessHandler, (iNode));
    if (!iNode->iEventHandlers[8]) return false;

    iNode->iEventHandlers[EVENT_HANDLER_TOTAL-1] = OSCL_NEW(NormalDataFlowHandler, (iNode));
    if (!iNode->iEventHandlers[EVENT_HANDLER_TOTAL-1]) return false;
    return true;
}

void ProtocolContainer::deleteProtocolObjects()
{
    if (iNode->iInterfacingObjectContainer)	OSCL_DELETE(iNode->iInterfacingObjectContainer);
    iNode->iInterfacingObjectContainer = NULL;
    if (iNode->iPortConfigFSInfoAlloc)		OSCL_DELETE(iNode->iPortConfigFSInfoAlloc);
    iNode->iPortConfigFSInfoAlloc = NULL;
    if (iNode->iNodeTimer)					OSCL_DELETE(iNode->iNodeTimer);
    iNode->iNodeTimer			  = NULL;

    if (iNode->iProtocol)					OSCL_DELETE(iNode->iProtocol);
    iNode->iProtocol			  = NULL;
    if (iNode->iNodeOutput)					OSCL_DELETE(iNode->iNodeOutput);
    iNode->iNodeOutput			  = NULL;
    if (iNode->iDownloadControl)				OSCL_DELETE(iNode->iDownloadControl);
    iNode->iDownloadControl		  = NULL;
    if (iNode->iDownloadProgess)				OSCL_DELETE(iNode->iDownloadProgess);
    iNode->iDownloadProgess		  = NULL;
    if (iNode->iUserAgentField)				OSCL_DELETE(iNode->iUserAgentField);
    iNode->iUserAgentField		  = NULL;
    if (iNode->iEventReport)					OSCL_DELETE(iNode->iEventReport);
    iNode->iEventReport			  = NULL;

    for (uint32 i = 0; i < EVENT_HANDLER_TOTAL; i++)
    {
        if (iNode->iEventHandlers[i]) OSCL_DELETE(iNode->iEventHandlers[i]);
        iNode->iEventHandlers[i] = NULL;
    }
}

void ProtocolContainer::handleTimeout(const int32 timerID)
{
    if (ignoreThisTimeout(timerID)) return;
    handleTimeoutErr(timerID);

    // currently for wm http streaming only
    handleTimeoutInPause(timerID);
    // may clean flags to cause handleTimeoutErr() to get excecuted, so move handleTimeoutErr() above
    handleTimeoutInDownloadStreamingDone(timerID);
}

bool ProtocolContainer::ignoreThisTimeout(const int32 timerID)
{
    // check the end processing status: EOS recved and whole session is done
    if (iNode->iInterfacingObjectContainer->isEOSAchieved() &&
            iNode->iInterfacingObjectContainer->isWholeSessionDone()) return true;

    // Next, all focus on checking server inactivity timeout
    if (timerID != (int32)SERVER_INACTIVITY_TIMER_ID) return false;

    // inactivity timeout should be ignored in the following cases:
    // (i)  input/output port queue still has data,
    // (ii) buffer full in progressive streaming
    if (iNode->iPortInForData)
    {
        if (iNode->iPortInForData->IncomingMsgQueueSize() > 0) return true;
    }
    if (iNode->iPortOut)
    {
        if (iNode->iPortOut->OutgoingMsgQueueSize() > 0) return true;
    }

    if (iNode->iNodeOutput)
    {
        if (iNode->iNodeOutput->getAvailableOutputSize() == 0) return true;
    }
    return false;
}

bool ProtocolContainer::handleTimeoutErr(const int32 timerID)
{
    if (iNode->iInterfacingObjectContainer->isDownloadStreamingDone() ||
            iNode->iInterfaceState == EPVMFNodePaused) return false;

    int32 timeoutErr = PVMFErrTimeout;
    if (timerID == SERVER_RESPONSE_TIMER_ID)   timeoutErr = PROCESS_TIMEOUT_SERVER_NO_RESPONCE;
    if (timerID == SERVER_INACTIVITY_TIMER_ID) timeoutErr = PROCESS_TIMEOUT_SERVER_INACTIVITY;

    ProtocolStateErrorInfo aInfo(timeoutErr);
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_ProtocolStateError, (OsclAny*)(&aInfo));
    iNode->DispatchInternalEvent(&aEvent);
    return true;
}

bool ProtocolContainer::handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler)
{
    bool aSessionDone = iNode->iInterfacingObjectContainer->isWholeSessionDone();
    bool aDownloadStreamingDone = iNode->iInterfacingObjectContainer->isDownloadStreamingDone();
    OSCL_UNUSED_ARG(aDownloadStreamingDone);
    bool aEOSArrived = iNode->iInterfacingObjectContainer->isEOSAchieved();

    iNode->iInterfacingObjectContainer->setInputDataUnwanted();
    if (aSessionDone)
    {
        // flush all the remaining output
        iNode->iNodeOutput->flushData();
        iNode->iNodeTimer->clear();
        if (aEOSArrived && iNode->iInterfacingObjectContainer->getOutputPortConnect())
        {
            iNode->iProtocolContainer->doEOS(); // true EOS
            return aEventHandler->completePendingCommand(aEvent);
        }
    }
    iNode->iProcessingState = ProcessingState_Idle;
    return aEventHandler->completePendingCommand(aEvent);
}

////////////////////////////////////////////////////////////////////////////////////
//////	PVProtocolEngineNodeInternalEventHandler implementation
////////////////////////////////////////////////////////////////////////////////////

PVProtocolEngineNodeInternalEventHandler::PVProtocolEngineNodeInternalEventHandler(PVMFProtocolEngineNode *aNode) : iNode(aNode)
{
    iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
}

bool PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(PVProtocolEngineNodeInternalEvent &aEvent)
{
    int32 errorCode = (int32)aEvent.iEventInfo;
    if (iNode->iCurrentCommand.size() > 0)
    {
        if (IsPVMFErrCode(errorCode))  // basic error event
        {
            iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), errorCode);
        }
        else   // extension error event
        {
            PVUuid uuid = PVProtocolEngineNodeErrorEventTypesUUID;
            int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode);
            char *errEventData = NULL;
            uint32 errEventDataLen = 0;
            handleErrResponse(basePVMFErrorCode, errorCode, errEventData, errEventDataLen);
            iNode->CommandComplete(iNode->iCurrentCommand, iNode->iCurrentCommand.front(), basePVMFErrorCode, errEventData, &uuid, &errorCode, errEventDataLen);
            LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d",
                             basePVMFErrorCode, errorCode));
        }
    }
    else
    {
        // report error event
        if (IsPVMFErrCode(errorCode))
            iNode->ReportErrorEvent(errorCode);
        else
        {
            int32 basePVMFErrorCode = getBasePVMFErrorReturnCode(errorCode, false); // false for error event
            char *errEventData = NULL;
            uint32 eventDataLen = 0;
            handleErrResponse(basePVMFErrorCode, errorCode, errEventData, eventDataLen);
            iNode->ReportErrorEvent(basePVMFErrorCode, errEventData, errorCode, eventDataLen);
            LOGINFODATAPATH((0, "PVProtocolEngineNodeInternalEventHandler::completePendingCommandWithError(), basePVMFErrorCode=%d, extensionErrorCode=%d",
                             basePVMFErrorCode, errorCode));
        }
    }

    iNode->SetState(EPVMFNodeError);
    iNode->StopClear();
    //iNode->iProcessingState = ProcessingState_Idle;

    if (!iNode->iInputCommands.empty())
    {
        if (iNode->IsAdded()) iNode->RunIfNotReady();
    }

    return true;
}

int32 PVProtocolEngineNodeInternalEventHandler::getBasePVMFErrorReturnCode(const int32 errorCode, const bool isForCommandComplete)
{
    int32 pvmfReturnCode = PVMFFailure;
    if (!isForCommandComplete) pvmfReturnCode = PVMFErrProcessing; // if not for command complete, should for error event
    if (iNode->iProtocolContainer->isHTTP409ForLowDiskSpace(errorCode)) pvmfReturnCode = PVMFLowDiskSpace;

    switch (errorCode)
    {
        case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerNoResponce:
        case PVProtocolEngineNodeErrorProcessingFailure_TimeoutServerInactivity:
            pvmfReturnCode = PVMFErrTimeout;
            break;

        case PVProtocolEngineNodeErrorHTTPErrorCode401:
        case PVProtocolEngineNodeErrorHTTPErrorCode407:
        case PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm:
            pvmfReturnCode = PVMFErrHTTPAuthenticationRequired;
            break;

        case PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType:
            pvmfReturnCode = PVMFErrNotSupported;
            break;

        case PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit:
            if (iNode->iInterfacingObjectContainer->getNumRedirectTrials() == 0)
            {
                pvmfReturnCode = PVMFErrRedirect;
            }
            break;
        default:
            break;
    }

    return pvmfReturnCode;
}

void PVProtocolEngineNodeInternalEventHandler::handleErrResponse(int32 &aBaseCode, int32 &errCode, char* &aEventData, uint32 &aEventDataLen)
{
    if (aBaseCode == PVMFErrRedirect)
    {
        handleRedirectErrResponse(aEventData, aEventDataLen);
    }
    else
    {
        handleAuthenErrResponse(errCode, aEventData, aEventDataLen);
        aBaseCode = getBasePVMFErrorReturnCode(errCode);
    }
}

void PVProtocolEngineNodeInternalEventHandler::handleAuthenErrResponse(int32 &aErrCode, char* &aEventData, uint32 &aEventDataLen)
{
    aEventData = NULL;
    aEventDataLen = 0;
    if (aErrCode == PVProtocolEngineNodeErrorHTTPErrorCode401)
    {
        if (false == iNode->iProtocol->isServerSendAuthenticationHeader())
        {
            aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_NoAuthenticationHeader;
            return;
        }

        if (false == iNode->iProtocol->isServerSupportBasicAuthentication())
        {
            aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_UnsupportedAuthenticationType;
            return;
        }

        if (iNode->iProtocol->getAuthenInfo(iAuthenInfoRealm))
        {
            aEventData = (char*)iAuthenInfoRealm.get_cstr();
            aEventDataLen = iAuthenInfoRealm.get_size() + 1; //Incremented by one to save c string terminating char ('\0')
        }
        else
        {
            aErrCode = PVProtocolEngineNodeErrorHTTPErrorCode401_InvalidRealm;
        }
    }
}

void PVProtocolEngineNodeInternalEventHandler::handleRedirectErrResponse(char* &aEventData, uint32 &aEventDataLen)
{
    aEventData = NULL;
    aEventDataLen = 0;
    // set the new url into info event
    OSCL_HeapString<OsclMemAllocator> newUrl;
    iNode->iProtocol->getRedirectURI(newUrl);

    // then set this value
    iNode->iInterfacingObjectContainer->setURI(newUrl, true);
    iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject());

    aEventData = (char*)iNode->iInterfacingObjectContainer->getURIObject().getURI().get_cstr();
    aEventDataLen = iNode->iInterfacingObjectContainer->getURIObject().getURI().get_size() + 1;
}

inline bool PVProtocolEngineNodeInternalEventHandler::isCurrEventMatchCurrPendingCommand(uint32 aCurrEventId)
{
    if (iNode->iCurrentCommand.empty()) return false;
    PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();

    // matching logic for event vs. pending command
    // init or prepare command
    if ((aCmd.iCmd == PVMF_GENERIC_NODE_INIT ||
            aCmd.iCmd == PVMF_GENERIC_NODE_PREPARE) &&
            (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete ||
             aCurrEventId == PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing)) return true;

    // start command
    if (aCmd.iCmd == PVMF_GENERIC_NODE_START &&
            aCurrEventId == PVProtocolEngineNodeInternalEventType_HttpHeaderAvailable) return true;

    //  stop command
    if (aCmd.iCmd == PVMF_GENERIC_NODE_STOP &&
            (aCurrEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateComplete ||
             aCurrEventId == PVProtocolEngineNodeInternalEventType_EndOfProcessing)) return true;

    // seek or bitstream switch command
    if ((aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_SEEK ||
            aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH) &&
            (aCurrEventId == PVProtocolEngineNodeInternalEventType_FirstPacketAvailable)) return true;

    return false; // no matching
}

// return value: true means completing pending command; false means no matching
bool PVProtocolEngineNodeInternalEventHandler::completePendingCommand(PVProtocolEngineNodeInternalEvent &aEvent)
{
    if (aEvent.iEventId == PVProtocolEngineNodeInternalEventType_ProtocolStateError)
    {
        return completePendingCommandWithError(aEvent);
    }
    if (!isCurrEventMatchCurrPendingCommand((uint32)aEvent.iEventId)) return false;

    PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();
    iNode->SetState(SetStateByCommand[aCmd.iCmd-(int32)PVMF_GENERIC_NODE_INIT]);
    iNode->CommandComplete(iNode->iCurrentCommand, aCmd, PVMFSuccess);
    return true;
}

bool PVProtocolEngineNodeInternalEventHandler::isBeingStopped(const int32 aStatus)
{
    // stopped, stop command is completed and node state is changed to prepared state
    if (iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
            iNode->iInterfaceState == EPVMFNodePrepared) return true;

    // being stopped, stop command is pending plus protcol state complete
    return (iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
            isStopCmdPending() &&
            isProtocolStateComplete(aStatus));
}

inline bool PVProtocolEngineNodeInternalEventHandler::isStopCmdPending()
{
    for (uint32 i = 0; i < iNode->iCurrentCommand.size(); i++)
    {
        if (iNode->iCurrentCommand[i].iCmd == PVMF_GENERIC_NODE_STOP) return true;
    }
    return false;
}

inline bool PVProtocolEngineNodeInternalEventHandler::isProtocolStateComplete(const int32 aStatus)
{
    return (aStatus == PROCESS_SUCCESS_END_OF_MESSAGE ||
            aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA ||
            aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED ||
            aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
}

bool ProtocolStateErrorHandler::needCompletePendingCommandAtThisRound(PVProtocolEngineNodeInternalEvent &aEvent)
{
    // get error code if necessary
    ProtocolStateErrorInfo *aInfo = (ProtocolStateErrorInfo *)aEvent.iEventInfo;
    if (aInfo->iUseInputErrorCode) iErrorCode = aInfo->iErrorCode;

    // check if complete pending command at this round is needed
    if (!aInfo->iUseInputErrorCode) return true; // use previous error code, for sure complete pending command
    return !iNode->iProtocolContainer->needSendEOSDuetoError(iErrorCode);
}

bool ProtocolStateErrorHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    if (!needCompletePendingCommandAtThisRound(aEvent))
    {
        // send EOS message to downstream node, and doesn't complete pending command at all
        iNode->StopClear();
        iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_EOS_FORMAT_ID); // enqueuing EOS should be successful
        return true;
    }

    int32 errorCode = iErrorCode;
    if (errorCode == 0) return true;
    if (NeedHandleContentRangeUnmatch(errorCode)) return true;

    if (errorCode < 0)
    {
        int32 nodeErrorEventTypeCode = (int32)PVProtocolEngineNodeErrorProcessingFailure - (PROCESS_ERROR_FIRST - errorCode);
        if (!IsPVMFErrCode(errorCode)) aEvent.iEventInfo = (OsclAny*)nodeErrorEventTypeCode; // convert to PVProtocolEngineNodeErrorEventType error code
        else aEvent.iEventInfo = (OsclAny*)errorCode;
        completePendingCommand(aEvent);
    }
    else
    {
        int32 errCode = checkRedirectHandling(errorCode);
        if (errCode == 0)
        {
            iErrorCode = 0;
            return true;
        }

        // command complete with error or error event
        aEvent.iEventInfo = (OsclAny*)errCode;
        completePendingCommand(aEvent);
    }

    return true;
}

// return value: 0 means caller needs to return immediately, not 0 means error
int32 ProtocolStateErrorHandler::checkRedirectHandling(const int32 aErrorCode)
{
    bool isInfoEvent = true;
    int32 errCode = parseServerResponseCode(aErrorCode, isInfoEvent);
    uint32 numRedirectTrials = iNode->iInterfacingObjectContainer->getNumRedirectTrials();
    uint32 numCurrRedirectTrials = iNode->iInterfacingObjectContainer->getCurrNumRedirectTrials();

    if (isInfoEvent && ++numCurrRedirectTrials <= numRedirectTrials)
    {
        iNode->iInterfacingObjectContainer->setCurrNumRedirectTrials(numCurrRedirectTrials);

        if (handleRedirect())
        {
            // set the new url into info event
            OSCL_HeapString<OsclMemAllocator> url(iNode->iInterfacingObjectContainer->getURIObject().getURI());
            iNode->ReportInfoEvent(PVMFInfoRemoteSourceNotification, (OsclAny*)(url.get_cstr()), errCode);
            return 0;
        }

        // treat it as error
        errCode = aErrorCode + PVProtocolEngineNodeErrorEventStart;
    }

    if (isInfoEvent && numCurrRedirectTrials > numRedirectTrials)
    {
        // redirect trials out of limit
        errCode = PVProtocolEngineNodeErrorHTTPRedirect_TrialsExceedLimit;
    }

    return errCode;
}


int32 ProtocolStateErrorHandler::parseServerResponseCode(const int32 aErrorCode, bool &isInfoEvent)
{
    isInfoEvent = true;
    int32 errCode = aErrorCode;
    // redirect code 3xx
    if (errCode >= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_START &&
            errCode <= (int32)PROTOCOLENGINE_REDIRECT_STATUS_CODE_END)
    {
        errCode += PVMFPROTOCOLENGINENODEInfo_Redirect;
    }
    else
    {
        errCode += PVProtocolEngineNodeErrorEventStart;
        isInfoEvent = false;
    }
    return errCode;
}

bool ProtocolStateErrorHandler::NeedHandleContentRangeUnmatch(const int32 aErrorCode)
{
    if (aErrorCode == PROCESS_CONTENT_RANGE_INFO_NOT_MATCH)
    {
        if (!handleContentRangeUnmatch()) return false;
        return true;
    }
    return false;
}

bool ProtocolStateErrorHandler::handleContentRangeUnmatch()
{
    return iNode->iProtocolContainer->handleContentRangeUnmatch();
}

bool ProtocolStateErrorHandler::handleRedirect()
{
    // Get redirect url
    OSCL_HeapString<OsclMemAllocator> newUrl;
    if (iNode->iProtocol->getRedirectURI(newUrl) && newUrl.get_size() > 0)
    {
        // then set info to protocol
        iNode->iInterfacingObjectContainer->setURI(newUrl, true);
        iNode->iProtocol->setURI(iNode->iInterfacingObjectContainer->getURIObject());
        iNode->iProtocolContainer->reconnectSocket();
        // Activate so processing will continue
        iNode->iEventReport->startRealDataflow();
        iNode->SetProcessingState(ProcessingState_NormalDataflow);
        return true;
    }
    return false;
}

bool HttpHeaderAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    // enable info update for download
    iNode->iProtocolContainer->enableInfoUpdate();

    // get Http header
    OUTPUT_DATA_QUEUE aHttpHeader = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData);
    uint32 headerLength = iNode->iInterfacingObjectContainer->setHttpHeader(aHttpHeader);
    bool status = true;
    if (iNode->iProtocol && headerLength > 0)
    {
        uint32 length = iNode->iProtocol->getContentLength();
        iNode->iInterfacingObjectContainer->setFileSize(length);
        iNode->iNodeOutput->setContentLength(length);
        status = iNode->iProtocolContainer->downloadUpdateForHttpHeaderAvailable();
    }

    // check PVMFInfoContentLength, PVMFErrContentTooLarge and PVMFInfoContentTruncated before completing the command
    iNode->iEventReport->checkContentInfoEvent(PROCESS_SUCCESS);

    // complete start command if it is not completed
    if (completePendingCommand(aEvent))
    {
        iNode->iEventReport->startRealDataflow();
    }

    return status;
}

bool FirstPacketAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    uint32 aFirstPacketNumber = (uint32)aEvent.iEventInfo;

    // first packet number is only needed in seek or bitstream switching
    if (iNode->iInterfaceState == EPVMFNodeStarted && iNode->iCurrentCommand.size() > 0)
    {
        PVMFProtocolEngineNodeCommand& aCmd = iNode->iCurrentCommand.front();

        // for bitstream switching command, guarantee completing command AFTER sending RE_CONFIG port command
        if (aFirstPacketNumber == 0xFFFFFFFF && aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH)
        {
            return completePendingCommand(aEvent);
        }

        //extract the parameters.
        uint64 aNPTInMS;
        uint32 *aFirstSeqNumAfterSeekOrSwitch;
        aCmd.PVMFProtocolEngineNodeCommand::Parse(aNPTInMS, aFirstSeqNumAfterSeekOrSwitch);
        *aFirstSeqNumAfterSeekOrSwitch = aFirstPacketNumber;

        // send RE_CONFIG port command or complete seek command
        if (aCmd.iCmd == PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH)
        {
            // send RE_CONFIG port command
            iNode->SendPortMediaCommand(iNode->iPortOut, PVMF_MEDIA_CMD_RE_CONFIG_FORMAT_ID);
        }
        else   // for seek command, complete the command
        {
            return completePendingCommand(aEvent);
        }
    }
    return true;
}
bool NormalDataAvailableHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    OUTPUT_DATA_QUEUE aOutputData;
    if (aEvent.iEventData) aOutputData = *((OUTPUT_DATA_QUEUE*)aEvent.iEventData);
    if (iNode->iNodeOutput) iNode->iNodeOutput->passDownNewOutputData(aOutputData, aEvent.iEventInfo);

    if (!iNode->IsDataFlowEventAlreadyInQueue(PVProtocolEngineNodeInternalEventType_OutputDataReady))
    {
        PVProtocolEngineNodeInternalEvent newEvent(PVProtocolEngineNodeInternalEventType_OutputDataReady);
        iNode->iInternalEventQueue.push_back(newEvent);
    }
    iNode->RunIfNotReady();
    return true;
}

bool ProtocolStateCompleteHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    bool aSessionDone = iNode->iInterfacingObjectContainer->isWholeSessionDone();
    bool aDownloadStreamingDone = iNode->iInterfacingObjectContainer->isDownloadStreamingDone();
    bool aEOSArrived = iNode->iInterfacingObjectContainer->isEOSAchieved();

    LOGINFODATAPATH((0, "ProtocolStateCompleteHandler::handle() : iNode->iInterfaceState = %d, sessionDone=%d,DownloadStreamingDone=%d,EOSArrived=%d",
                     iNode->iInterfaceState, (uint32)aSessionDone, (uint32)aDownloadStreamingDone, (uint32)aEOSArrived));

    OSCL_UNUSED_ARG(aSessionDone);
    OSCL_UNUSED_ARG(aDownloadStreamingDone);
    OSCL_UNUSED_ARG(aEOSArrived);
    return iNode->iProtocolContainer->handleProtocolStateComplete(aEvent, this);
}

bool NormalDataFlowHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    OSCL_UNUSED_ARG(aEvent);

    // First check and flush output data
    int32 statusFlushData = iNode->iNodeOutput->flushData();
    if (!flushDataPostProcessing(statusFlushData)) return false;

    // send reconnect cmd for logging request for stop or EOS packet received
    if (!handleEOSLogging()) return false;

    // Second, run state machine to continue data processing
    iNode->iProcessingState = ProcessingState_NormalDataflow;
    if (iNode->iDataInQueue.size() > 0) LOGINFODATAPATH((0, "NormalDataFlowHandler::handle() : iNode->iDataInQueue.size() = %d", iNode->iDataInQueue.size()));
    int32 status = iNode->iProtocol->runStateMachine(iNode->iDataInQueue);
    if (status < 0 || statusFlushData != PROCESS_SUCCESS || iNode->iInterfaceState == EPVMFNodeError) return false;

    // handle EOS
    if (handleEOS(status)) return true;

    // handle end of processing, e.g., stop
    if (handleEndOfProcessing(status)) return true;

    // check the next action, go to next protocol state
    return dataFlowContinue(status);
}

bool NormalDataFlowHandler::dataFlowContinue(const int32 aStatus)
{
    // info update for download and for streaming,
    if (!iNode->iProtocolContainer->doInfoUpdate(aStatus)) return false;

    // go to next protocol state for end of message in current protocol state
    // The reason for making this call explicit is, when end of message happens (protocol state complete),
    // the node still needs some information from current state to do some extra work, like the above
    // download control update and info events processing. If we make this call implicit or hidden and
    // right after ProtcolStateComplete(), then the above info processing would fail.
    if (isReadyGotoNextState(aStatus)) iNode->iProtocol->gotoNextState();


    if (iNode->iDataInQueue.empty() && iNode->iPortInForData->IncomingMsgQueueSize() > 0)
    {
        iNode->ProcessIncomingMsg(iNode->iPortInForData);
    }

    if (iNode->iDataInQueue.size() > 0)
    {
        if (!iNode->IsDataFlowEventAlreadyInQueue(PVProtocolEngineNodeInternalEventType_HasExtraInputData))
        {
            PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_HasExtraInputData);
            iNode->iInternalEventQueue.push_back(aEvent);
        }
        iNode->RunIfNotReady();
        return true;
    }

    if (aStatus == PROCESS_WAIT_FOR_INCOMING_DATA) return false;
    return true;
}

inline bool NormalDataFlowHandler::isReadyGotoNextState(const int32 aStatus)
{
    return (((aStatus == PROCESS_SUCCESS_END_OF_MESSAGE) || ((aStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED))) &&
            !iNode->iInterfacingObjectContainer->isWholeSessionDone() &&
            iNode->iInterfaceState != EPVMFNodePaused);
}

bool NormalDataFlowHandler::flushDataPostProcessing(const int32 aStatusFlushData)
{
    // status is ok or need sending new request, then no post processing
    if (aStatusFlushData == PROCESS_SUCCESS || iNode->iProtocol->isSendingNewRequest()) return true;

    // post processing only occur for output port failure
    if (aStatusFlushData == PROCESS_OUTPUT_TO_OUTPUT_PORT_FAILURE)
    {

        if (iNode->iNodeOutput->isPortBusy()) iNode->iProcessingState = ProcessingState_Idle;

        // since queuing mesage for port outgoing queue fails, check the connected port state and try send
        if (!iNode->iPortOut->IsConnectedPortBusy()) iNode->ProcessOutgoingMsg(iNode->iPortOut);

        // if port failure is due to no memory for media data, reset inactivity timer to prevent unnessary timeout
        if (!iNode->iPortOut->IsOutgoingQueueBusy() && // this means port failure is due to no memory
                iNode->iInterfaceState != EPVMFNodePaused &&
                (iNode->iDataInQueue.size() > 0 || iNode->iPortInForData->IncomingMsgQueueSize() > 0))
        {
            LOGINFODATAPATH((0, "NormalDataFlowHandler::flushDataPostProcessing() : iNode->iDataInQueue.size()=%d, iNode->iPortInForData->IncomingMsgQueueSize()=%d",
                             iNode->iDataInQueue.size(), iNode->iPortInForData->IncomingMsgQueueSize()));
            iNode->iNodeTimer->start(SERVER_INACTIVITY_TIMER_ID); // reset inactivity timer to prevent unnessary timeout
        }
    }
    return false;
}

bool NormalDataFlowHandler::handleEOSLogging()
{
    if (iNode->iInterfacingObjectContainer->isDownloadStreamingDone() &&
            !iSendSocketReconnect &&
            iNode->iPortInForLogging)
    {
        // reconnect first
        if (!iNode->SendPortMediaCommand(iNode->iPortInForLogging, PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)) return false;
        iNode->iProtocol->sendRequest();
        iSendSocketReconnect = true;

        // start stop/eos logging timer at this point to protect itself from the case where logging request
        // cannot be sent out due to connected port busy. For this case, logging timer timeout will help keep going
        iNode->iNodeTimer->start(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING);
        LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOSLogging() server stop/eos logging response timer starts! timerID=3, timeoutValue=%d",
                         iNode->iNodeTimer->getTimeout(SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING)));
    }
    else if (!iNode->iInterfacingObjectContainer->isDownloadStreamingDone())
    {
        // reset the flag
        iSendSocketReconnect = false;
    }
    return true;
}

bool NormalDataFlowHandler::handleEOS(const int32 aStatus)
{
    if (aStatus != PROCESS_SUCCESS_GOT_EOS) return false;

    if (//(iNode->iInterfaceState==EPVMFNodeStarted || iNode->iInterfaceState==EPVMFNodePrepared || iNode->iInterfaceState==EPVMFNodeInitialized) &&
        !iNode->iInterfacingObjectContainer->isDownloadStreamingDone())   // only issue socket reconnect during the streaming
    {
        LOGINFODATAPATH((0, "NormalDataFlowHandler::handleEOS() : status == PROCESS_SUCCESS_GOT_EOS"));
        iNode->iProtocolContainer->doEOS(false);

        PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_StartDataflowBySendRequestAction);
        iNode->iInternalEventQueue.push_back(aEvent);
        iNode->RunIfNotReady();
        return true;
    }

    return false;
}

bool NormalDataFlowHandler::handleEndOfProcessing(const int32 aStatus)
{
    if (!isBeingStopped(aStatus)) return false;

    // use end of processing event to streamline all end of processing cases for stop
    EndOfDataProcessingInfo *aEOPInfo = iNode->iInterfacingObjectContainer->getEOPInfo();
    aEOPInfo->clear();
    aEOPInfo->iStreamingDone = true;
    PVProtocolEngineNodeInternalEvent aEvent(PVProtocolEngineNodeInternalEventType_EndOfProcessing, (OsclAny*)aEOPInfo);
    iNode->DispatchInternalEvent(&aEvent);
    return true;
}

bool EndOfDataProcessingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo;
    if (!aInfo) return true;

    if (aInfo->iSendResumeNotification)
    {
        iNode->iDownloadControl->checkResumeNotification();
        iNode->iNodeTimer->clear();
        LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), send resume notification to parser node, for DOWNLOAD COMPLETE"));
    }
    if (aInfo->iExtraDataComeIn)
    {
        iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA);
        LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFUnexpectedData info event after DOWNLOAD COMPLETE"));
    }
    if (aInfo->iSendServerDisconnectEvent)
    {
        iNode->iEventReport->checkReportEvent(PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
        LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), check and send PVMFInfoSessionDisconnect info event after DOWNLOAD COMPLETE"));
    }
    if (aInfo->iStreamingDone || aInfo->iForceStop)
    {
        cleanupForStop(aEvent);
        LOGINFODATAPATH((0, "EndOfDataProcessingHandler::handle(), handle the remaining stuff for EOS or stop"));
    }

    aInfo->clear();
    iNode->iProcessingState = ProcessingState_Idle;
    return true;
}

void EndOfDataProcessingHandler::cleanupForStop(PVProtocolEngineNodeInternalEvent &aEvent)
{
    EndOfDataProcessingInfo *aInfo = (EndOfDataProcessingInfo*)aEvent.iEventInfo;
    if (isBeingStopped() || aInfo->iForceStop)
    {
        completePendingCommand(aEvent);
        iNode->iProtocol->stop(true);
        iNode->StopClear();
    }
}

bool ServerResponseErrorBypassingHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    completePendingCommand(aEvent);
    iNode->iProtocol->gotoNextState();
    //iNode->iProcessingState = ProcessingState_Idle;
    return true;
}

bool CheckResumeNotificationHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    OSCL_UNUSED_ARG(aEvent);

    // double check if the reposition request is pending or not
    if (iNode->IsRepositioningRequestPending()) return true;

    if (iNode->iDownloadControl->checkResumeNotification(false) == 1)   // false means download is not complete yet
    {
        LOGINFODATAPATH((0, "CheckResumeNotificationHandler::handle(), send resume notification to parser node, in case of MBDS getting full in progressive streaming"));
        // report data ready event
        iNode->iEventReport->sendDataReadyEvent();
    }
    return true;
}

bool OutgoingMsgSentSuccessHandler::handle(PVProtocolEngineNodeInternalEvent &aEvent)
{
    OutgoingMsgSentSuccessInfoVec *aVec = (OutgoingMsgSentSuccessInfoVec*)aEvent.iEventInfo;
    if (!aVec || aVec->empty()) return false;
    bool retVal = (iNode->PostProcessForMsgSentSuccess(aVec->front().iPort, aVec->front().iMsg) == PVMFSuccess);
    if (!aVec->empty()) aVec->erase(aVec->begin());
    return retVal;
}


////////////////////////////////////////////////////////////////////////////////////
//////	PVMFProtocolEngineNodeOutput implementation
////////////////////////////////////////////////////////////////////////////////////

// constructor
PVMFProtocolEngineNodeOutput::PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNodeOutputObserver *aObserver) :
        iPortIn(NULL),
        iContentDataMemPool(NULL),
        iMediaDataAlloc(NULL),
        iMediaDataMemPool("PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNode)",
                          PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM,
                          PVHTTPDOWNLOADOUTPUT_MEDIADATA_CHUNKSIZE),
        iObserver(aObserver),
        iCurrTotalOutputSize(0)

{
    iOutputFramesQueue.reserve(PVPROTOCOLENGINE_RESERVED_NUMBER_OF_FRAMES);
    iLogger = PVLogger::GetLoggerObject("PVMFProtocolEngineNode");
    iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
    iClockLogger = PVLogger::GetLoggerObject("clock");
    iMediaDataMemPool.enablenullpointerreturn();
}

PVMFProtocolEngineNodeOutput::~PVMFProtocolEngineNodeOutput()
{
    reset();
}

// reset
void PVMFProtocolEngineNodeOutput::reset()
{
    iPortIn = NULL;
    iLogger = NULL;
    iDataPathLogger = NULL;
    iClockLogger = NULL;
    iOutputFramesQueue.clear();
    iMediaData.Unbind();
    deleteMemPool();
}

void PVMFProtocolEngineNodeOutput::setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType)
{
    if (aObjectType == NodeOutputType_InputPortForData && aOutputObject) iPortIn = (PVMFProtocolEnginePort *)aOutputObject;
}


bool PVMFProtocolEngineNodeOutput::sendToPort(PVMFSharedMediaDataPtr &aMediaData, const uint32 aPortType)
{
    OSCL_UNUSED_ARG(aPortType);
    return sendToDestPort(aMediaData, iPortIn);
}

bool PVMFProtocolEngineNodeOutput::createMediaData(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize)
{
    // check if need to create memory pool
    int32 errcode = OsclErrNone;
    if (!iMediaDataAlloc)
    {
        errcode = createMemPool();
        if (errcode != PVMFSuccess) return false;
    }

    OsclSharedPtr<PVMFMediaDataImpl> mediadataImpl;
    errcode = 0;
    OSCL_TRY(errcode, mediadataImpl = iMediaDataAlloc->allocate(aRequestSize));
    if (errcode != OsclErrNone) return false;


    // Then wrap it around with PVMFMediaData
    iMediaData.Unbind();

    errcode = OsclErrNoResources;

    iMediaData = PVMFMediaData::createMediaData(mediadataImpl, &iMediaDataMemPool);

    if (iMediaData.GetRep() != NULL)
    {
        errcode = OsclErrNone;
    }

    if (errcode != OsclErrNone) return false;

    aMediaData = iMediaData;
    return true;
}

PVMFStatus PVMFProtocolEngineNodeOutput::createMemPool()
{
    // Create the memory pool
    int32 errcode = 0;
    OSCL_TRY(errcode, iContentDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVHTTPDOWNLOADOUTPUT_CONTENTDATA_POOLNUM)));
    if (errcode || iContentDataMemPool == NULL) return PVMFErrNoMemory;


    OSCL_TRY(errcode, iMediaDataAlloc = OSCL_NEW(PVMFSimpleMediaBufferCombinedAlloc, (iContentDataMemPool)));
    if (errcode || iMediaDataAlloc == NULL) return PVMFErrNoMemory;

    return PVMFSuccess;
}

void PVMFProtocolEngineNodeOutput::deleteMemPool()
{
    // Cleanup output media data memory pool
    if (iMediaDataAlloc != NULL)
    {
        OSCL_DELETE(iMediaDataAlloc);
        iMediaDataAlloc = NULL;
    }

    if (iContentDataMemPool != NULL)
    {
        OSCL_DELETE(iContentDataMemPool);
        iContentDataMemPool = NULL;
    }
}

bool PVMFProtocolEngineNodeOutput::sendToDestPort(PVMFSharedMediaDataPtr &aMediaData, PVMFProtocolEnginePort *aPort)
{
    // compute data frag size for log purposes
    uint32 dataSize = 0;
    uint32 numFrags = aMediaData->getNumFragments();
    for (uint32 i = 0; i < numFrags; i++)
    {
        OsclRefCounterMemFrag memFragIn;
        aMediaData->getMediaFragment(i, memFragIn);
        uint32 fragLen = memFragIn.getMemFrag().len;
        dataSize += fragLen;
    }

    // Send frame to downstream node
    PVMFSharedMediaMsgPtr mediaMsgOut;
    convertToPVMFMediaMsg(mediaMsgOut, aMediaData);

    LOGINFODATAPATH((0, "PVMFProtocolEngineNodeOutput::sendToDestPort() SEQNUM= %d, SIZE= %d, port = 0x%x",
                     mediaMsgOut->getSeqNum(), dataSize, aPort));

    PVMFStatus status = aPort->QueueOutgoingMsg(mediaMsgOut);
    if (status < PVMFSuccess) return false;
    if (status == PVMFSuccessOutgoingMsgSent)
    {
        return iObserver->QueueOutgoingMsgSentSuccess(aPort, mediaMsgOut);
    }
    return true;
}

bool PVMFProtocolEngineNodeOutput::passDownNewOutputData(OUTPUT_DATA_QUEUE &aOutputQueue, OsclAny* aSideInfo)
{
    OSCL_UNUSED_ARG(aSideInfo);
    int32 err = 0;
    OSCL_TRY(err, iOutputFramesQueue.push_back(aOutputQueue););
    return (err == 0);
}

int32 PVMFProtocolEngineNodeOutput::flushData(const uint32 aOutputType)
{
    if (iMediaData.GetRep() == NULL)  return PROCESS_SUCCESS;

    // send to port
    if (!sendToPort(iMediaData, aOutputType)) return PROCESS_OUTPUT_PORT_IS_BUSY;
    iMediaData.Unbind();
    return PROCESS_SUCCESS;
}

bool PVMFProtocolEngineNodeOutput::getBuffer(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize)
{
    if (!createMediaData(aMediaData, aRequestSize)) return false;
    return true;
}

void PVMFProtocolEngineNodeOutput::discardData(const bool aNeedReopen)
{
    OSCL_UNUSED_ARG(aNeedReopen);
    iOutputFramesQueue.clear();
    iMediaData.Unbind();
}

bool PVMFProtocolEngineNodeOutput::isPortBusy()
{
    return iPortIn->IsOutgoingQueueBusy();
}



////////////////////////////////////////////////////////////////////////////////////
//////	UserAgentField implementation
////////////////////////////////////////////////////////////////////////////////////
// constructor
UserAgentField::UserAgentField(OSCL_wString &aUserAgent, const bool isOverwritable)
{
    setUserAgent(aUserAgent, isOverwritable);
}

UserAgentField::UserAgentField(OSCL_String &aUserAgent, const bool isOverwritable)
{
    setUserAgent(aUserAgent, isOverwritable);
}

// set user agent
bool UserAgentField::setUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable)
{
    iOverwritable = isOverwritable;

    // check for empty string
    if (aUserAgent.get_size() == 0) return true;

    OsclMemAllocator alloc;
    char *buf = (char*)alloc.allocate(aUserAgent.get_size() + 1);
    if (!buf) return false;
    uint32 size = 0;
    if ((size = oscl_UnicodeToUTF8(aUserAgent.get_cstr(), aUserAgent.get_size(), buf, aUserAgent.get_size() + 1)) == 0)
    {
        alloc.deallocate(buf);
        return false;
    }
    iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size);
    alloc.deallocate(buf);
    return true;
}

bool UserAgentField::setUserAgent(OSCL_String &aUserAgent, const bool isOverwritable)
{
    iOverwritable = isOverwritable;
    // check for empty string
    if (aUserAgent.get_size() == 0) return true;

    iInputUserAgent = OSCL_HeapString<OsclMemAllocator> (aUserAgent.get_str(), aUserAgent.get_size());
    return true;
}

// get the actual user agent (not wide string version) based on overwrite mode or replace mode (set the input user agent to the default one)
bool UserAgentField::getUserAgent(OSCL_String &aUserAgent)
{
    if (iActualUserAgent.get_size() > 0)
    {
        aUserAgent = iActualUserAgent;
        return true;
    }

    // create iActualUserAgent at the first call
    if (iOverwritable && iInputUserAgent.get_size() > 0)
    {
        iActualUserAgent = iInputUserAgent;
    }
    else   // append
    {
        //OSCL_FastString defaultUserAgent(_STRLIT_CHAR("PVPlayer/4.0 (Beta release)"));
        OSCL_HeapString<OsclMemAllocator> defaultUserAgent;
        getDefaultUserAgent(defaultUserAgent);
        uint32 size = defaultUserAgent.get_size() + iInputUserAgent.get_size() + 1; // 1 => space
        OsclMemAllocator alloc;
        char *buf = (char*)alloc.allocate(size + 1);
        if (!buf) return false;
        oscl_memcpy(buf, defaultUserAgent.get_cstr(), defaultUserAgent.get_size());
        buf[defaultUserAgent.get_size()] = PROTOCOLENGINENODE_SPACE_ASCIICODE;
        if (iInputUserAgent.get_size() > 0)
        {
            oscl_memcpy(buf + defaultUserAgent.get_size() + 1, iInputUserAgent.get_cstr(), iInputUserAgent.get_size());
        }
        buf[size] = 0;
        iActualUserAgent = OSCL_HeapString<OsclMemAllocator> (buf, size);
        alloc.deallocate(buf);
    }
    aUserAgent = iActualUserAgent;
    return true;
}

////////////////////////////////////////////////////////////////////////////////////
//////	EventReporter implementation
////////////////////////////////////////////////////////////////////////////////////
EventReporter::EventReporter(PVMFProtocolEngineNode *aNode) : iNode(aNode)
{
    clear();
    if (aNode) iInterfacingObjectContainer = aNode->iInterfacingObjectContainer;
    iDataPathLogger = PVLogger::GetLoggerObject(NODEDATAPATHLOGGER_TAG);
}

void EventReporter::clear()
{
    iStarted = false;
}

void EventReporter::startRealDataflow()
{
    iStarted = true;
}


////////////////////////////////////////////////////////////////////////////////////
//////	InterfacingObjectContainer implementation
////////////////////////////////////////////////////////////////////////////////////

// constructor
InterfacingObjectContainer::InterfacingObjectContainer() :
        iDownloadFormat(PVMF_MIME_DATA_SOURCE_HTTP_URL),
        iDataStreamFactory(NULL),
        iNumBuffersInAllocator(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM),
        iNumRedirectTrials(PVPROTOCOLENGINE_DEFAULT_NUMBER_OF_REDIRECT_TRIALS),
        iNumBuffersInMediaDataPoolSMCalc(PVHTTPSTREAMINGOUTPUT_CONTENTDATA_POOLNUM),
        iCurrSocketConnection(true),
        iPrevSocketConnection(true),
        iLatestDataPacketNumSent(0),
        iOutputPortConnected(false)
{
    clear();
    iOutgoingMsgSentSuccessInfoVec.reserve(PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE / 4);
}

// set and get http header
uint32 InterfacingObjectContainer::setHttpHeader(OUTPUT_DATA_QUEUE &aHttpHeader)
{
    iHttpHeaderLength = 0;
    uint32 i = 0;
    char *ptr = (char*)iHttpHeaderBuffer;
    for (i = 0; i < aHttpHeader.size(); i++)
    {
        uint32 fragSize = aHttpHeader[i].getMemFragSize();
        oscl_memcpy(ptr, (char*)aHttpHeader[i].getMemFragPtr(), fragSize);
        iHttpHeaderLength += fragSize;
        ptr += fragSize;
    }
    iHttpHeaderBuffer[iHttpHeaderLength] = 0;
    return iHttpHeaderLength;
}

bool InterfacingObjectContainer::setStreamingProxy(OSCL_wString& aProxyName, const uint32 aProxyPort)
{
    if (aProxyName.get_size() == 0) return false;

    OsclMemAllocator alloc;
    char *buf = (char*)alloc.allocate(aProxyName.get_size() + 1);
    if (!buf) return false;
    uint32 size = oscl_UnicodeToUTF8(aProxyName.get_cstr(), aProxyName.get_size(), buf, aProxyName.get_size() + 1);
    if (size == 0)
    {
        alloc.deallocate(buf);
        return false;
    }
    iProxyName = OSCL_HeapString<OsclMemAllocator> (buf, size);
    iProxyPort = aProxyPort;
    alloc.deallocate(buf);
    return true;
}
void InterfacingObjectContainer::setNumBuffersInMediaDataPoolSMCalc(uint32 aVal)
{
    iNumBuffersInMediaDataPoolSMCalc = aVal;
}


////////////////////////////////////////////////////////////////////////////////////
//////	PVMFProtocolEngineNodeTimer implementation
////////////////////////////////////////////////////////////////////////////////////

PVMFProtocolEngineNodeTimer* PVMFProtocolEngineNodeTimer::create(OsclTimerObserver *aObserver)
{
    PVMFProtocolEngineNodeTimer *timer = OSCL_NEW(PVMFProtocolEngineNodeTimer, ());
    if (!timer) return NULL;
    if (!timer->construct(aObserver))
    {
        OSCL_DELETE(timer);
        return NULL;
    }
    return timer;
}

bool PVMFProtocolEngineNodeTimer::construct(OsclTimerObserver *aObserver)
{
    // create iWatchdogTimer
    iWatchdogTimer = OSCL_NEW(OsclTimer<PVMFProtocolEngineNodeAllocator>, ("ProtEngineNodeWatchdogTimer"));
    if (!iWatchdogTimer) return false;
    iWatchdogTimer->SetObserver(aObserver);
    iWatchdogTimer->SetFrequency(PVPROTOCOLENGINENODE_TIMER_FREQUENCY);

    int32 err = 0;
    OSCL_TRY(err, iTimerVec.reserve(DEFAULT_TIMER_VECTOR_RESERVE_NUMBER);)
    return (err ? false : true);
}

PVMFProtocolEngineNodeTimer::~PVMFProtocolEngineNodeTimer()
{
    if (iWatchdogTimer)
    {
        OSCL_DELETE(iWatchdogTimer);
        iWatchdogTimer = NULL;
    }

    iTimerVec.clear();
}

void PVMFProtocolEngineNodeTimer::set(const uint32 aTimerID, const int32 aTimeout)
{
    uint32 index = getTimerVectorIndex(aTimerID);
    if (index == 0xffffffff)
    {
        // attach the new timer
        uint32 timeout = aTimeout;
        if (timeout == 0) timeout = getDefaultTimeout(aTimerID);
        TimerUnit timerUnit(aTimerID, timeout);
        iTimerVec.push_back(timerUnit);
    }
    else
    {
        // existing timer
        uint32 timeout = iTimerVec[index].iTimeout;
        if (aTimeout > 0 || (aTimeout == 0 && aTimerID == SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING))
        {
            // for stop/eos logging timeout, allow zero timeout
            iTimerVec[index].iTimeout = aTimeout;
        }
        timeout = iTimerVec[index].iTimeout;
    }
}

uint32 PVMFProtocolEngineNodeTimer::getTimeout(const uint32 aTimerID)
{
    uint32 aTimeout = 0xffffffff;
    uint32 index = getTimerVectorIndex(aTimerID);
    if (index != 0xffffffff)
    {
        // existing timer
        aTimeout = iTimerVec[index].iTimeout;
    }
    return aTimeout;
}


void PVMFProtocolEngineNodeTimer::cancel(const uint32 aTimerID)
{
    uint32 index = getTimerVectorIndex(aTimerID);
    if (index != 0xffffffff)
    {
        // find this timer and cancel it
        iWatchdogTimer->Cancel(aTimerID);
    }
}

void PVMFProtocolEngineNodeTimer::clear()
{
    for (uint32 i = 0; i < iTimerVec.size(); i++)
    {
        iWatchdogTimer->Cancel(iTimerVec[i].iTimerID);
    }
}

void PVMFProtocolEngineNodeTimer::clearExcept(const uint32 aTimerID)
{
    for (uint32 i = 0; i < iTimerVec.size(); i++)
    {
        if (iTimerVec[i].iTimerID != aTimerID)
        {
            iWatchdogTimer->Cancel(iTimerVec[i].iTimerID);
        }
    }
}

bool PVMFProtocolEngineNodeTimer::start(const uint32 aTimerID, const int32 aTimeout)
{
    uint32 index = getTimerVectorIndex(aTimerID);
    if (index == 0xffffffff) return false;
    if (aTimeout) iTimerVec[index].iTimeout = aTimeout;
    if (iTimerVec[index].iTimeout == 0)
    {
        iTimerVec[index].iTimeout = getDefaultTimeout(aTimerID);
    }

    iWatchdogTimer->Cancel(iTimerVec[index].iTimerID);
    iWatchdogTimer->Request(iTimerVec[index].iTimerID, 0, iTimerVec[index].iTimeout);
    return true;
}

uint32 PVMFProtocolEngineNodeTimer::getDefaultTimeout(const uint32 aTimerID)
{
    switch (aTimerID)
    {
        case SERVER_RESPONSE_TIMER_ID:
            return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC;
        case SERVER_INACTIVITY_TIMER_ID:
            return DEFAULT_MAX_SERVER_INACTIVITY_DURATION_IN_SEC;
        case SERVER_KEEPALIVE_TIMER_ID:
            return DEFAULT_KEEPALIVE_TIMEOUT_IN_SEC;
        case SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING:
            return DEFAULT_MAX_SERVER_RESPONSE_DURATION_IN_SEC_FOR_STOPEOS_LOGGING;
        case WALL_CLOCK_TIMER_ID:
            return DEFAULT_WALLCLOCK_TIMEOUT_IN_SEC;
        case BUFFER_STATUS_TIMER_ID:
            return DEFAULT_BUFFER_STATUS_CLOCK_TIMEOUT_IN_SEC;
        default:
            break;
    }
    return 0;
}

uint32 PVMFProtocolEngineNodeTimer::getTimerVectorIndex(const uint32 aTimerID)
{
    for (uint32 i = 0; i < iTimerVec.size(); i++)
    {
        if (iTimerVec[i].iTimerID == aTimerID) return i;
    }
    return ~0;
}

