/* ------------------------------------------------------------------
 * Copyright (C) 1998-2010 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_clientserver_socket_node.h"
#include "oscl_string_utils.h"
#include "pvmf_basic_errorinfomessage.h"
#include "pvmf_errorinfomessage_extension.h"
#include "oscl_byte_order.h"
#include "pvmf_media_cmd.h"
#include "pvmf_media_msg_format_ids.h"
#include "oscl_tickcount.h"
#include "oscl_rand.h"
#include "oscl_time.h"
#include "oscl_bin_stream.h"

// Use default DLL entry point for Symbian
#include "oscl_dll.h"

//////////////////////////////////////////////////
// Standard Node APIs
//////////////////////////////////////////////////

OSCL_EXPORT_REF PVMFClientServerSocketNode::PVMFClientServerSocketNode(OsclTCPSocket* aSocketHandle, int32 aPriority)
        : OsclActiveObject(aPriority, "PVMFClientServerSocketNode")
        , iSockServ(NULL)
        , TIMEOUT_CONNECT(-1)
        , TIMEOUT_SEND(-1)
        , TIMEOUT_RECV(-1)
        , TIMEOUT_SHUTDOWN(-1)
        , iSocketHandle(aSocketHandle)
        , iSockConfig(NULL)
{
    iLogger = NULL;
    iDataPathLogger = NULL;
    iOsclErrorTrapImp = NULL;
    iExtensionRefCount = 0;
    iMaxTcpRecvBufferSize = SNODE_DEFAULT_SOCKET_TCP_BUFFER_SIZE;
    iMaxTcpRecvBufferCount = SNODE_DEFAULT_SOCKET_TCP_BUFFER_COUNT;
    iSocketID = 0;
    iCommandErrorCode = PVMFSocketNodeErrorEventStart;
    iErrorEventErrorCode = PVMFSocketNodeErrorEventStart;

    iPVMFPort = NULL;
    iNumStopPortActivityPending = (-1);//inactive.

    int32 err;
    OSCL_TRY(err,

             iPendingCmdQueue.Construct(PVMF_SOCKET_NODE_COMMAND_ID_START,
                                        PVMF_SOCKET_NODE_COMMAND_VECTOR_RESERVE);

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

    if (err != OsclErrNone)
    {
        //if a leave happened, cleanup and re-throw the error
        iPendingCmdQueue.clear();
        iCurrentCmdQueue.clear();
        iCancelCmdQueue.clear();
        if (iPVMFPort)
        {
            iPVMFPort->Disconnect();
            delete iPVMFPort;
            iPVMFPort = NULL;
        }
        OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
        OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
        OSCL_LEAVE(err);
    }
}


OSCL_EXPORT_REF PVMFClientServerSocketNode::~PVMFClientServerSocketNode()
{
    Cancel();

    //thread logoff
    if (IsAdded())
        RemoveFromScheduler();

    /* Cleanup allocated ports */
    CleanupPorts();

    //Cleanup commands
    while (!iCurrentCmdQueue.empty())
    {
        CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFFailure);
    }
    while (!iPendingCmdQueue.empty())
    {
        CommandComplete(iPendingCmdQueue, iPendingCmdQueue.front(), PVMFFailure);
    }
    while (!iCancelCmdQueue.empty())
    {
        CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFFailure);
    }
}


OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::ThreadLogon()
{
    switch (iInterfaceState)
    {
        case EPVMFNodeCreated:
            if (!IsAdded())
                AddToScheduler();
            iLogger = PVLogger::GetLoggerObject("PVMFClientServerSocketNode");
            iDataPathLogger = PVLogger::GetLoggerObject("datapath.socketnode");
            iOsclErrorTrapImp = OsclErrorTrap::GetErrorTrapImp();
            SetState(EPVMFNodeIdle);
            return PVMFSuccess;
        default:
            return PVMFErrInvalidState;
    }
}


OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::ThreadLogoff()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:ThreadLogoff"));

    switch (iInterfaceState)
    {
        case EPVMFNodeIdle:
        {
            if (IsAdded())
                RemoveFromScheduler();
            iLogger = NULL;
            iDataPathLogger = NULL;
            iOsclErrorTrapImp = NULL;
            SetState(EPVMFNodeCreated);
            return PVMFSuccess;
        }
        default:
            return PVMFErrInvalidState;
    }
}


OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetCapability(PVMFNodeCapability& aNodeCapability)
{
    OSCL_UNUSED_ARG(aNodeCapability);
    return PVMFSuccess;
}

OSCL_EXPORT_REF PVMFPortIter* PVMFClientServerSocketNode::GetPorts(const PVMFPortFilter* aFilter)
{
    OSCL_UNUSED_ARG(aFilter);
    //retrive a port iterator
    return (PVMFPortIter*)iPVMFPort;
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
        PVInterface*& aInterfacePtr,
        const OsclAny* aContext)
{
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:RequestPort"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:ReleasePort"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Init(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Init"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Init"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Start(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Start"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Stop(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Stop"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Flush(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Flush"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Pause(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Pause"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::Reset(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:Reset"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:CancelAllCommands"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    return QueueCommandL(cmd);
}

OSCL_EXPORT_REF PVMFCommandId PVMFClientServerSocketNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode:CancelCommand"));
    PVMFSocketNodeCommand cmd;
    cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    return QueueCommandL(cmd);
}

//Port activity handler
void PVMFClientServerSocketNode::HandlePortActivity(const PVMFPortActivity &aActivity)
{
    PVMFClientServerSocketPort* sockPort = NULL;
    switch (aActivity.iType)
    {
        case PVMF_PORT_ACTIVITY_CONNECT:
        {
            sockPort = OSCL_STATIC_CAST(PVMFClientServerSocketPort*, aActivity.iPort);
            OSCL_ASSERT(sockPort && sockPort->iConfig);
            *iSockConfig = *sockPort->iConfig;

            setSocketPortMemAllocator(aActivity.iPort, sockPort->iAllocSharedPtr);

            //Receives may have been blocked waiting on the port to be connected, so check here.
            if (CanReceive())
                StartRecvOperation();
        }
        break;

        case PVMF_PORT_ACTIVITY_INCOMING_MSG:
        {
            sockPort = (PVMFClientServerSocketPort*)(aActivity.iPort);
            OSCL_ASSERT(sockPort && sockPort->iConfig);

            //Try to process this message now.
            if (CanProcessIncomingMsg())
                ProcessIncomingMsg();
            //Otherwise, ignore this event now.  Other code will check
            //the input queue as needed.
        }
        break;

        case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
        {
            sockPort = (PVMFClientServerSocketPort*)(aActivity.iPort);
            OSCL_ASSERT(sockPort && sockPort->iConfig);
            SocketPortConfig& aSockConfig = *sockPort->iConfig;

            if (aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnConnectedPort)
            {
                RecvOperationComplete(PVMFSuccess, NULL);
            }

            //Otherwise ignore this event now.  Other code will check connected
            //port status as needed.
        }
        break;

        default:
            //all other events can be ignored.
            break;
    }
}


OSCL_EXPORT_REF void PVMFClientServerSocketNode::addRef()
{
    ++iExtensionRefCount;
}

OSCL_EXPORT_REF void PVMFClientServerSocketNode::removeRef()
{
    --iExtensionRefCount;
}

OSCL_EXPORT_REF bool PVMFClientServerSocketNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
{
    OSCL_UNUSED_ARG(uuid);
    OSCL_UNUSED_ARG(iface);
    return false;
}

void PVMFClientServerSocketNode::Run()
{
    //Process node commands
    while (CanProcessCommand())
        ProcessCommand(iPendingCmdQueue, iPendingCmdQueue.front());
}


bool PVMFClientServerSocketNode::CanProcessCommand()
{
    return (!iPendingCmdQueue.empty()
            && (iCurrentCmdQueue.empty()
                || (iPendingCmdQueue.front().hipri() && iCancelCmdQueue.empty())));
}

//Process an input command.
void PVMFClientServerSocketNode::ProcessCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNodeCommand::ProcessCommand() in"));

    PVMFStatus status = PVMFFailure;
    iCommandErrorCode = PVMFSocketNodeErrorEventStart; //no error

    if (aCmd.hipri())
    {
        //calling logic should prevent multiple cancels in progress.
        OSCL_ASSERT(iCancelCmdQueue.empty());

        switch (aCmd.iCmd)
        {
            case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
                status = DoCancelAllCommands(aCmd);
                break;

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

            default://unknown command type
                status = PVMFFailure;
                break;
        }

        //If the command was not finished in this call, then move it to the
        //"cancel cmd" queue where it will remain until it is completed.
        if (status == PVMFPending)
        {
            //move the new cmd to the "cancel cmd" queue where it will
            //remain until complete.
            int32 err;
            OSCL_TRY(err, iCancelCmdQueue.StoreL(aCmd););

            //we reserved space in the CancelCmdQueue already, so
            //it should not be possible to fail here.
            OSCL_ASSERT(err == OsclErrNone);

            //erase the original command
            aCmdQ.Erase(&aCmd);
        }
        else
        {
            CommandComplete(aCmdQ, aCmd, status, NULL);
        }
    }
    else
    {
        //calling logic should prevent multiple commands in progress.
        OSCL_ASSERT(iCurrentCmdQueue.empty());

        OsclAny* eventData = NULL;

        switch (aCmd.iCmd)
        {
            case PVMF_GENERIC_NODE_QUERYINTERFACE:
                status = DoQueryInterface(aCmd);
                break;

            case PVMF_GENERIC_NODE_REQUESTPORT:
            {
                status = DoRequestPort(aCmd);
                eventData = iPVMFPort;
                break;
            }

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

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

            case PVMF_GENERIC_NODE_PREPARE:
                status = DoPrepare(aCmd);
                if (status == PVMFSuccess)
                {
                    ChangeExternalState(EPVMFNodePrepared);
                }
                break;

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

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

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

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

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

            default://unknown command type
                status = PVMFFailure;
                break;
        }

        if (status == PVMFPending)
        {
            int32 err;
            OSCL_TRY(err, iCurrentCmdQueue.StoreL(aCmd););
            OSCL_ASSERT(err == OsclErrNone);

            //erase the original command
            aCmdQ.Erase(&aCmd);
        }
        else
        {
            CommandComplete(aCmdQ, aCmd, status, eventData);
        }
    }
}

//Called to complete a node command.
void PVMFClientServerSocketNode::CommandComplete(PVMFSocketNodeCmdQ& aCmdQ,
        PVMFSocketNodeCommand& aCmd,
        PVMFStatus aStatus,
        OsclAny* aEventData,
        PVUuid* aEventUUID,
        int32* aEventCode)

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

    bool canProcess = CanProcessCommand();

    PVMFStatus status = aStatus;

    if (aStatus == PVMFSuccess)
    {
        switch (aCmd.iCmd)
        {
            case PVMF_GENERIC_NODE_INIT:
                ChangeExternalState(EPVMFNodeInitialized);
                break;

            case PVMF_GENERIC_NODE_PREPARE:
                ChangeExternalState(EPVMFNodePrepared);
                break;

            case PVMF_GENERIC_NODE_START:
                ChangeExternalState(EPVMFNodeStarted);
                break;

            case PVMF_GENERIC_NODE_STOP:
                ChangeExternalState(EPVMFNodePrepared);
                break;

            case PVMF_GENERIC_NODE_PAUSE:
                ChangeExternalState(EPVMFNodePaused);
                break;

            case PVMF_GENERIC_NODE_RESET:
                ChangeExternalState(EPVMFNodeCreated);

                //Complete the reset command.
                {
                    //cleanup all ports.
                    CleanupPorts();
                    SetState(EPVMFNodeIdle);
                }
                break;

            case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
                //Complete the reset command.
            {
                //Since "cancel all" is effectively used as a Reset,
                //go ahead and cleanup all ports.
                CleanupPorts();
            }
            break;
            default:
                break;
        }
    }

    PVInterface* extif = NULL;
    PVMFBasicErrorInfoMessage* errormsg = NULL;
    if (aEventUUID && aEventCode)
    {
        errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
        extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
    }
    //else if no error input, see if "command error code" was set.
    else if (iCommandErrorCode != PVMFSocketNodeErrorEventStart)
    {
        PVUuid eventuuid = PVMFSocketNodeEventTypeUUID;
        errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (iCommandErrorCode, eventuuid, NULL));
        extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
    }

    //create response
    PVMFCmdResp resp(aCmd.iId, aCmd.iContext, status, extif, aEventData);
    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();
    }
    iCommandErrorCode = PVMFSocketNodeErrorEventStart;//reset.

    //See if there was a pending cancel waiting on the current command to
    //complete.
    if (!iCancelCmdQueue.empty()
            && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELCOMMAND)
    {
        CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
    }

    //May need to resume command handling if the AO was blocked
    //waiting on asynchronous command completion, but it's unblocked now.
    if (!canProcess
            && CanProcessCommand()
            && IsAdded())
    {
        RunIfNotReady();
    }
}

PVMFCommandId PVMFClientServerSocketNode::QueueCommandL(PVMFSocketNodeCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::QueueCommandL()"));
    PVMFCommandId id;

    id = iPendingCmdQueue.AddL(aCmd);

    //This may be a processing trigger.
    //Wakeup the AO if needed.
    if (IsAdded()
            && CanProcessCommand())
    {
        RunIfNotReady();
    }

    return id;
}

//This is the callback from Oscl Sockets for socket operation completion.
OSCL_EXPORT_REF  void PVMFClientServerSocketNode::HandleSocketEvent(int32 aId, TPVSocketFxn aFxn, TPVSocketEvent aEvent, int32 aError)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::HandleSocketEvent() In aId=%d, aFxn=%d, aEvent=%d, aError=%d", aId, aFxn, aEvent, aError));

    if (iSockConfig && aEvent == EPVSocketSuccess)
    {
        PVMFSocketActivity activity((aEvent == EPVSocketSuccess) ? PVMFSuccess : PVMFFailure, aId, aFxn, aEvent, aError);

        //Call the appropriate handler
        switch (aFxn)
        {
            case EPVSocketRecv:
                OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_Recv);

                RecvOperationComplete(activity.iStatus, &activity);
                break;

            case EPVSocketSend:
                OSCL_ASSERT(iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_Send);

                SendOperationComplete(activity.iStatus, &activity);
                break;

            case EPVSocketShutdown:
                //OSCL_ASSERT(iSockConfig->iState.iConnectOperation==EPVSocketPortConnectOperation_Shutdown);
                SequenceComplete(PVMFSuccess);
                //ConnectOperationComplete(activity.iStatus,&activity);
                break;

            default:
                OSCL_ASSERT(0);//unexpected
                break;
        }
    }
    else if (aEvent == EPVSocketCancel)
    {
        switch (aFxn)
        {
            case EPVSocketRecv:
                if (iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_Send
                        && iSockConfig->iState.iSendOperationCanceled == false)
                {//if does hv anything to send, cancel it
                    CancelSendOperation();
                }
                else
                {   //shutdown
                    CloseSocketConnection();
                }
                break;

            case EPVSocketSend:
                if (iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_Recv
                        && iSockConfig->iState.iRecvOperationCanceled == false)
                {
                    CancelRecvOperation();
                }
                else
                {
                    //shutdown
                    CloseSocketConnection();
                }
                break;

            case EPVSocketShutdown:
                //quite difficult to cancel shutdown
                break;

            default:
                OSCL_ASSERT(0);//unexpected
                break;
        }
    }
    else
    {//failure
        switch (aFxn)
        {
            case EPVSocketRecv:
                iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
                iSockConfig->iState.iRecvOperationCanceled = true;
                break;

            case EPVSocketSend:
                iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_None;
                iSockConfig->iState.iSendOperationCanceled = true;
                break;

            case EPVSocketShutdown:
            default:
                OSCL_ASSERT(0);//unexpected
                break;
        }
    }
}


//Allocate a node port and add it to the port vector.
PVMFStatus PVMFClientServerSocketNode::AddPort(int32 tag)
{
    iPVMFPort = new PVMFClientServerSocketPort((int32)tag,
            this,
            DEFAULT_DATA_QUEUE_CAPACITY,
            DEFAULT_DATA_QUEUE_CAPACITY,
            DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
            //the output queue is empty because
            //this node pushes data directly to the
            //connecte port's input.
            0, 0, 0);

    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::AllocatePortMemPool(int32 tag, PVMFSocketNodeMemPool* & aMemPool)
{
    aMemPool = NULL;
    OsclAny *MemPtr = NULL;
    MemPtr = iAlloc.ALLOCATE(sizeof(PVMFSocketNodeMemPool));
    if (MemPtr == NULL)
    {
        return PVMFErrNoMemory;
    }

    int32 errcode = 0;
    OSCL_TRY(errcode, aMemPool = OSCL_PLACEMENT_NEW(MemPtr, PVMFSocketNodeMemPool(SNODE_DEFAULT_NUMBER_MEDIADATA_IN_MEMPOOL);));
    if (errcode != OsclErrNone)
    {
        PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::DoRequestPort: PVMFSocketNodeMemPool Construct Failed Ln %d", errcode, __LINE__));
        iAlloc.deallocate(MemPtr);
        return PVMFErrNoMemory;
    }

    aMemPool->iPortTag = tag;
    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::CancelSendOperation()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::CancelSendOperation()"));

    PVMFStatus status = PVMFSuccess;

    switch (iSockConfig->iState.iSendOperation)
    {
        case EPVSocketPortSendOperation_None:
            break;

        case EPVSocketPortSendOperation_Send:
            if (iSockConfig->iTCPSocket)
            {
                if (!iSockConfig->iState.iSendOperationCanceled)
                {
                    iSockConfig->iState.iSendOperationCanceled = true;
                    iSockConfig->iTCPSocket->CancelSend();
                }
                status = PVMFPending;
                //wait on send to complete in HandleSocketEvent
            }
            break;

        default:
            OSCL_ASSERT(0);
            status = PVMFFailure;
            break;
    }
    return status;
}


PVMFStatus PVMFClientServerSocketNode::DoStopNodeActivity()
{
    if (iNumStopPortActivityPending > 0)
        return PVMFPending;

    //Stop socket activity on all ports.
    uint32 nPortsPending = 0;
    if (iSockConfig)
    {
        // discard any saved socket activity events
        iSockConfig->iSocketRecvActivity.iValid = false;

        //if a request port is going on, be sure to complete the command,
        //although we will interrupt the current processing.
        if (iSockConfig->iState.iSequence == EPVSocketPortSequence_RequestPort
                && iCurrentCmdQueue.size()
                && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
        {
            CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled, NULL);
        }

        //if a cleanup is already underway, just keep waiting for it to complete,
        //else start a new sequence
        if (iSockConfig->iState.iSequence == EPVSocketPortSequence_SocketCleanup)
        {
            nPortsPending++;
        }
        else if (StartSequence(iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup) == PVMFPending)
        {
            nPortsPending++;
        }
    }

    if (nPortsPending > 0)
        iNumStopPortActivityPending = nPortsPending;

    if (iNumStopPortActivityPending > 0)
        return PVMFPending; //wait on completion in SequenceComplete.

    return PVMFSuccess;
}

//Flush is implemented for this node, but hasn't been tested.
PVMFStatus PVMFClientServerSocketNode::DoFlush(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoFlush() In"));

    if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
    {
        return PVMFErrInvalidState;
    }

    PVMFStatus status = PVMFSuccess;
    {
        iPVMFPort->SuspendInput();
        if (status != PVMFPending
                && iPVMFPort->IncomingMsgQueueSize() > 0)
        {
            status = PVMFPending;//Wait on this queue to empty.
            //Completion is detected in SequenceComplete.
        }
    }
    return status;
}

//Pause is a do-nothing for this node.
PVMFStatus PVMFClientServerSocketNode::DoPause(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoPause() In"));

    if (iInterfaceState == EPVMFNodePaused)
    {
        return PVMFSuccess;
    }

    if (iInterfaceState != EPVMFNodeStarted)
    {
        return PVMFErrInvalidState;
    }

    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::DoReset(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoReset()"));

    /* This node allows a reset from any state */

    return DoStopNodeActivity();
}

PVMFStatus PVMFClientServerSocketNode::DoQueryInterface(PVMFSocketNodeCommand&  aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    return PVMFSuccess;
}

PVMFStatus PVMFClientServerSocketNode::DoRequestPort(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    //retrieve port tag.
    int32 tag;
    OSCL_String* portconfig;
    aCmd.PVMFSocketNodeCommandBase::Parse(tag, portconfig);

    PVMFStatus status = AddPort(tag);
    if (status != PVMFSuccess)
        return status;

    //create the socket config
    iSockConfig = OSCL_NEW(SocketPortConfig, ());
    iPVMFPort->iConfig = iSockConfig;
    iSockConfig->iPVMFPort = iPVMFPort;

    iSockConfig->iContainer = this;
    iSockConfig->iSockId = iSocketID++;
    iSockConfig->iTag = tag;
    iSockConfig->iTCPSocket = iSocketHandle;

    //create the mem pool
    PVMFSocketNodeMemPool* memPool;
    status = AllocatePortMemPool(tag, memPool);
    if (status == PVMFSuccess)
        iSockConfig->iMemPool = memPool;
    return status;
}


//Release ports is a do-nothing for this node.
PVMFStatus PVMFClientServerSocketNode::DoReleasePort(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::DoInit(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    if (iInterfaceState != EPVMFNodeIdle)
    {
        return PVMFErrInvalidState;
    }
    return PVMFSuccess;
}


//Prepare is a do-nothing for this node.
PVMFStatus PVMFClientServerSocketNode::DoPrepare(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::DoPrepare() In"));

    if (iInterfaceState != EPVMFNodeInitialized)
    {
        return PVMFErrInvalidState;
    }
    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::DoStart(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    if (iInterfaceState == EPVMFNodeStarted)
    {
        return PVMFSuccess;//already started.
    }

    if (iInterfaceState != EPVMFNodePrepared &&
            iInterfaceState != EPVMFNodePaused)
    {
        return PVMFErrInvalidState;
    }

    TPVMFNodeInterfaceState curState = iInterfaceState;
    ChangeExternalState(EPVMFNodeStarted);

    PVMFStatus status = PVMFSuccess;
    if (iSockConfig)
    {
        //Start handling incoming messages
        if (CanProcessIncomingMsg())
            ProcessIncomingMsg();

        //Start the receives.
        if (CanReceive())
        {
            status = StartRecvOperation();
            if (status == PVMFPending)
            {
                status = PVMFSuccess;
            }
            else if (status != PVMFSuccess)
            {
                ChangeExternalState(curState);
            }
        }
    }
    return status;
}



PVMFStatus PVMFClientServerSocketNode::DoStop(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoStop() In"));

    if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
    {
        return PVMFErrInvalidState;
    }
    return PVMFSuccess;
}


PVMFStatus PVMFClientServerSocketNode::DoCancelCommand(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoCancelCommand() Called"));

    // extract the command ID from the parameters.
    PVMFCommandId cmdId;
    aCmd.PVMFSocketNodeCommandBase::Parse(cmdId);

    if (!iCurrentCmdQueue.empty()
            && iCurrentCmdQueue.front().iId == cmdId)
    {
        return DoCancelCurrentCommand(iCurrentCmdQueue, iCurrentCmdQueue.front());
        //wait on current command to complete.  The cancel command
        //will ultimately be completed in the "CommandComplete" for the current command.
    }

    {
        // start at element 1 since this cancel command is element 0
        PVMFSocketNodeCommand* cmd = iPendingCmdQueue.FindById(cmdId, 1);
        if (cmd)
        {
            // cancel the queued command.  Note this will complete out-of-order.
            CommandComplete(iPendingCmdQueue, *cmd, PVMFErrCancelled);
            // no further action is required.
            return PVMFSuccess;
        }
    }

    //this command fails if the given command is not queued or in progress.
    return PVMFErrArgument;
}

PVMFStatus PVMFClientServerSocketNode::DoCancelAllCommands(PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVMFStatus status = DoStopNodeActivity();

    if (!iCurrentCmdQueue.empty())
        CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled);

    //Cancel all other pending commands, except for this one which is
    //element 0 in the queue
    for (uint32 i = 1; i < iPendingCmdQueue.size(); i++)
        CommandComplete(iPendingCmdQueue, iPendingCmdQueue[i], PVMFErrCancelled);

    //May need to wait on completion of StopNodeActivity.
    return status;
}


PVMFStatus PVMFClientServerSocketNode::DoCancelCurrentCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmdQ);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::DoCancelCurrentCommand()"));
    switch (aCmd.iCmd)
    {

        case PVMF_GENERIC_NODE_REQUESTPORT:
            //there may be a connect operation pending-- cancel it.
        {
            if (iPVMFPort)
            {
                //SocketPortConfig* iSockConfig=iRequestedPort->iConfig;
                if (iSockConfig)
                {
                    //  CancelConnectOperation();
                    return PVMFPending;//wait on the operation to complete
                    //in HandleSocketEvent or HandleDNSEvent
                }
            }
            //shouldn't get here...
            return PVMFFailure;
        }
        break;

        case PVMF_GENERIC_NODE_RESET:
            //it's too complicated to cancel a reset, so just wait on completion
            return PVMFPending;

        case PVMF_GENERIC_NODE_FLUSH:
            //to cancel a flush, just discard all remaining port messages
            //and keep waiting on completion of current message.
        {
            iPVMFPort->ClearMsgQueues();
        }
        return PVMFPending;//keep waiting on flush completion in SequenceComplete.

        case PVMF_GENERIC_NODE_CANCELCOMMAND:
        case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
            //these have asynchronous completion, but the command handling prevents
            //processing a cancel during a cancel, so we shouldn't get here.
            OSCL_ASSERT(0);
            return PVMFFailure;

        default:
            //no other node commands have asynchronous completion, so this is unexpected.
            OSCL_ASSERT(0);
            return PVMFFailure;
    }
}

PVMFStatus PVMFClientServerSocketNode::CancelRecvOperation()
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::CancelRecvOperation() In"));

    PVMFStatus status = PVMFSuccess;

    switch (iSockConfig->iState.iRecvOperation)
    {
        case EPVSocketPortRecvOperation_None:
            break;

        case EPVSocketPortRecvOperation_Recv:
            if (iSockConfig->iTCPSocket)
            {
                if (!iSockConfig->iState.iRecvOperationCanceled)
                {
                    iSockConfig->iState.iRecvOperationCanceled = true;
                    iSockConfig->iTCPSocket->CancelRecv();
                }
                status = PVMFPending;
                //wait on recv to complete in HandleSocketEvent
            }
            break;

        case EPVSocketPortRecvOperation_WaitOnConnectedPort:
            //just clear the state
            iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
            //also discard the received data and the associated recv activity
            if (iSockConfig->iSocketRecvActivity.iValid)
                iSockConfig->iSocketRecvActivity.iValid = false;
            if (iSockConfig->iPendingRecvMediaData.GetRep())
                iSockConfig->iPendingRecvMediaData.Unbind();
            break;

        case EPVSocketPortRecvOperation_WaitOnMemory:
            if (iSockConfig->iMemPool != NULL)
                iSockConfig->iMemPool->CancelFreeChunkAvailableCallback();
            //clear the state
            iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
            break;

        default:
            OSCL_ASSERT(0);//add code for this case
            status = PVMFFailure;
            break;
    }
    return status;
}

//a memory pool callback
void SocketPortConfig::freechunkavailable(OsclAny* aContextData)
{
    OSCL_UNUSED_ARG(aContextData);
    //complete the "wait on memory" state
    if (iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnMemory)
    {
        iContainer->RecvOperationComplete(PVMFSuccess, NULL);   //*this,
    }
}


void PVMFClientServerSocketNode::CleanupTCP()
{
    //cleanup media messages
    if (iSockConfig->iPendingRecvMediaData.GetRep() != NULL)
    {
        iSockConfig->iPendingRecvMediaData.Unbind();

    }
    if (iSockConfig->iPendingSendMediaData.GetRep() != NULL)
    {
        iSockConfig->iPendingSendMediaData.Unbind();
    }
}


void PVMFClientServerSocketNode::CleanupPorts()
{
    if (iPVMFPort)
    {
        SocketPortConfig* it = iPVMFPort->iConfig;
        if (it)
        {
            //unlink the PVMFPort so we won't try to send any EOS msg
            //during the TCP cleanup.
            it->iPVMFPort = NULL;
            it->CleanupMemPools();
            OSCL_DELETE(it);
            iPVMFPort->iConfig = NULL;
        }

        iPVMFPort->Disconnect();
        delete iPVMFPort;
        iPVMFPort = NULL;
    }
}


PVMFSocketNodeMemPool::PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs)
        : iMediaDataMemPool(NULL)
{
    iMediaDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (aMemPoolNumBufs, MEDIA_DATA_CLASS_SIZE));
    iInternalAlloc = NULL;
}


void SocketPortConfig::DoSetSocketPortMemAllocator(PVLogger* aLogger, OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)
{
    if (aAlloc.GetRep())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, aLogger, PVLOGMSG_INFO, (0, "SocketPortConfig::DoSetSocketPortMemAllocator() Using input mem allocator"));
        /*
         * Deletion of any previously created allocators is handled as part of
         * reset / node delete. So just re-assign the shared ptr here.
         */
        if (iMemPool->iSocketAllocSharedPtr.GetRep() != NULL)
        {
            iMemPool->iSocketAllocSharedPtr.Unbind();
        }
        iMemPool->iSocketAllocSharedPtr = aAlloc;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, aLogger, PVLOGMSG_INFO, (0, "SocketPortConfig::DoSetSocketPortMemAllocator() no mem allocator. Create one"));

        uint aligned_socket_alloc_size = oscl_mem_aligned_size(sizeof(PVMFSMSharedBufferAllocWithReSize));

        uint aligned_refcnt_size =  oscl_mem_aligned_size(sizeof(OsclRefCounterSA<PVMFSharedSocketDataBufferAllocCleanupSA>));

        OsclMemAllocator my_alloc;
        uint8 *my_ptr = (uint8*) my_alloc.ALLOCATE(aligned_refcnt_size + aligned_socket_alloc_size);
        OsclRefCounter *my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA<PVMFSharedSocketDataBufferAllocCleanupSA>(my_ptr));
        my_ptr += aligned_refcnt_size;

        // allow one resize for a maximum mempool size of TCP_BUFFER_SIZE*TCP_BUFFER_IN_MEMPOOL
        iMemPool->iInternalAlloc = OSCL_NEW(PVMFSMSharedBufferAllocWithReSize, (
                                                iContainer->iMaxTcpRecvBufferSize * (iContainer->iMaxTcpRecvBufferCount - 1), "TCPsocketBuffer",
                                                1, iContainer->iMaxTcpRecvBufferSize));

        PVMFSharedSocketDataBufferAlloc *alloc_ptr = OSCL_PLACEMENT_NEW(my_ptr, PVMFSharedSocketDataBufferAlloc(iMemPool->iInternalAlloc));

        OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> shared_alloc(alloc_ptr, my_refcnt);
        iMemPool->iSocketAllocSharedPtr = shared_alloc;
    }
}

void SocketPortConfig::CleanupMemPools()
{
    if (iMemPool->iInternalAlloc != NULL)
    {
        iMemPool->iInternalAlloc->DecrementKeepAliveCount();
        uint32 numOutStandingBuffers =
            iMemPool->iInternalAlloc->getNumOutStandingBuffers();
        if (numOutStandingBuffers == 0)
        {
            OSCL_DELETE((iMemPool->iInternalAlloc));
            iMemPool->iInternalAlloc = NULL;
        }
    }
    PVMFSocketNodeAllocator alloc;
    iMemPool->~PVMFSocketNodeMemPool();
    alloc.deallocate((OsclAny*)(iMemPool));
    iMemPool = NULL;
}


void PVMFClientServerSocketNode::ReportErrorEvent(PVMFEventType aEventType,
        OsclAny* aEventData,
        PVUuid* aEventUUID,
        int32* aEventCode)
{
    if (aEventUUID && aEventCode)
    {
        PVMFBasicErrorInfoMessage* eventmsg =
            OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
        PVMFAsyncEvent asyncevent(PVMFErrorEvent,
                                  aEventType,
                                  NULL,
                                  OSCL_STATIC_CAST(PVInterface*, eventmsg),
                                  aEventData,
                                  NULL,
                                  0);
        PVMFNodeInterface::ReportErrorEvent(asyncevent);
        eventmsg->removeRef();
    }
    else
    {
        PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
    }
}

void PVMFClientServerSocketNode::ReportInfoEvent(PVMFEventType aEventType,
        OsclAny* aEventData,
        PVUuid* aEventUUID,
        int32* aEventCode)
{
    if (aEventUUID && aEventCode)
    {
        PVMFBasicErrorInfoMessage* eventmsg =
            OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
        PVMFAsyncEvent asyncevent(PVMFInfoEvent,
                                  aEventType,
                                  NULL,
                                  OSCL_STATIC_CAST(PVInterface*, eventmsg),
                                  aEventData,
                                  NULL,
                                  0);
        PVMFNodeInterface::ReportInfoEvent(asyncevent);
        eventmsg->removeRef();
    }
    else
    {
        PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
    }
}

OSCL_EXPORT_REF bool PVMFClientServerSocketNode::setSocketPortMemAllocator(PVMFPortInterface* aInPort,
        OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc)
{

    PVMFClientServerSocketPort* aPort = OSCL_STATIC_CAST(PVMFClientServerSocketPort*, aInPort);
    SocketPortConfig* tmpSockConfig = (aPort) ? aPort->iConfig : NULL;
    if (NULL != tmpSockConfig)
    {
        tmpSockConfig->DoSetSocketPortMemAllocator(iLogger, aAlloc);
        return true;
    }
    return false;
}


bool PVMFClientServerSocketNode::CanProcessIncomingMsg()
{
    return
        //node is started
        iInterfaceState == EPVMFNodeStarted
        //port has input messages
        && iSockConfig->iPVMFPort && iSockConfig->iPVMFPort->IncomingMsgQueueSize() > 0
        //port is not busy with any sequence
        && iSockConfig->iState.iSequence == EPVSocketPortSequence_None;
}


void PVMFClientServerSocketNode::ProcessIncomingMsg()
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::ProcessIncomingMsg: aPort=0x%x", iSockConfig->iPVMFPort));

    //Dequeue the incoming message
    PVMFSharedMediaMsgPtr msg;
    PVMFStatus status = iSockConfig->iPVMFPort->DequeueIncomingMsg(msg);
    if (status != PVMFSuccess)
    {
        PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::ProcessIncomingDataMsg: Error - DequeueIncomingMsg failed"));
        ReportErrorEvent(PVMFErrPortProcessing);
        return ;
    }

    OSCL_ASSERT(iSockConfig->iState.iSequence == EPVSocketPortSequence_None);

    //Handle 3 types of messages
    if (msg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)
    {
        //Disconnect message
        StartSequence(EPVSocketPortSequence_InputDisconnectMsg);
    }
    else if (msg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID)
    {
        //Start the sequence
        StartSequence(EPVSocketPortSequence_InputDataMsg, (OsclAny*)&msg);
    }
    else
    {
        //unexpected message type
        ReportErrorEvent(PVMFErrPortProcessing);
    }
}


PVMFStatus PVMFClientServerSocketNode::StartSendOperation(PVMFSharedMediaMsgPtr& aMsg)
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartSendOperation() In"));

    //caller should have verified we can send now.
    OSCL_ASSERT(iSockConfig->iState.iSendOperation == EPVSocketPortSendOperation_None);

    //caller should provide a media data message as input
    OSCL_ASSERT(aMsg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID);

    //there should be either a UDP or TCP socket on this port
    if (!iSockConfig->iTCPSocket)
    {
        return PVMFFailure;
    }

    // Retrieve memory fragment to write to
    if (iSockConfig->iPendingSendMediaData.GetRep())
        iSockConfig->iPendingSendMediaData.Unbind();

    convertToPVMFMediaData(iSockConfig->iPendingSendMediaData, aMsg);
    OsclRefCounterMemFrag refCtrMemFragOut;
    iSockConfig->iPendingSendMediaData->getMediaFragment(0, refCtrMemFragOut);

    PVMFStatus status = PVMFFailure;

    if (iSockConfig->iTCPSocket)
    {
        iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_Send;

        TPVSocketEvent retVal = iSockConfig->iTCPSocket->Send((uint8*)refCtrMemFragOut.getMemFragPtr(),
                                refCtrMemFragOut.getMemFragSize(),
                                TIMEOUT_SEND);

        if (retVal == EPVSocketPending)
            status = PVMFPending;//wait on HandleSocketEvent callback
        else
            status = PVMFFailure;

        if (PVMFPending != status)
        {
            PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartSendOperation: TCP - Error. status=%d", status));
        }
    }

    //Handle synchronous completion or failures
    if (status != PVMFPending)
        status = SendOperationComplete(status, NULL);

    return status;
}


PVMFStatus PVMFClientServerSocketNode::SendOperationComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::SendOperationComplete()"));

    OSCL_ASSERT(aStatus != PVMFPending);

    PVMFStatus status = aStatus;

    //Update the send state
    TPVSocketPortSendOperation curOp = iSockConfig->iState.iSendOperation;
    iSockConfig->iState.iSendOperation = EPVSocketPortSendOperation_None;
    iSockConfig->iState.iSendOperationStatus = aStatus;
    iSockConfig->iState.iSendOperationCanceled = false;

    //Release the media buffer after each send operation, regardless of success/fail.
    if (iSockConfig->iPendingSendMediaData.GetRep() != NULL)
        iSockConfig->iPendingSendMediaData.Unbind();

    if (aSocketActivity)
    {
        //Datapath logging
        switch (aSocketActivity->iEvent)
        {
            case EPVSocketSuccess:
                //PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0,"PVMFClientServerSocketNode::SendOperationComplete - Success - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
                break;
            case EPVSocketTimeout:
                //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - TimeOut - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
                break;
            case EPVSocketFailure:
                //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - Failed - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
                break;
            case EPVSocketCancel:
                //PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0,"PVMFClientServerSocketNode::SendOperationComplete - Cancelled - SockId=%d, Mime=%s", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
                break;
            default:
                OSCL_ASSERT(0);
                break;
        }
    }

    //report TCP errors.
    if (aStatus != PVMFSuccess
            && curOp == EPVSocketPortSendOperation_Send)
    {
        ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorTCPSocketSendError);
    }

    //This completes an input data message sequence
    if (iSockConfig->iState.iSequence == EPVSocketPortSequence_InputDataMsg)
        SequenceComplete(aStatus);
    return status;
}


bool PVMFClientServerSocketNode::CanReceive()
{
    return
        //node is started
        iInterfaceState == EPVMFNodeStarted
        //port is connected
        && iSockConfig->iPVMFPort && iSockConfig->iPVMFPort->IsConnected()
        //socket exists (gets created during request port or connect sequence)
        && (iSockConfig->iTCPSocket)
        //port is not busy with any sequence other than sending data
        && (iSockConfig->iState.iSequence == EPVSocketPortSequence_None
            || iSockConfig->iState.iSequence == EPVSocketPortSequence_InputDataMsg)
        //port is not busy with any receive operation.
        && iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None
        //there's no node stop going on.
        && iNumStopPortActivityPending < 0;
}

//Enter the "wait on memory" state
void PVMFClientServerSocketNode::StartRecvWaitOnMemory(int32 aSize)
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvWaitOnMemory() In"));

    iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnMemory;

    if (aSize)
    {//wait on data buffer
        iSockConfig->iMemPool->notifyfreechunkavailable(*iSockConfig, aSize, NULL);
    }
    else
    {//wait on media data wrapper
        iSockConfig->iMemPool->iMediaDataMemPool->notifyfreechunkavailable(*iSockConfig, NULL);
    }
}

//Enter the "wait on connected port" state
void PVMFClientServerSocketNode::StartRecvWaitOnConnectedPort(PVMFSocketActivity& aSocketActivity)
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvWaitOnConnectedPort() In"));

    //outgoing queue is busy-- must queue this event for later processing
    switch (aSocketActivity.iFxn)
    {
        case EPVSocketRecv:
        case EPVSocketRecvFrom:
            iSockConfig->iSocketRecvActivity.Set(aSocketActivity.iStatus
                                                 , aSocketActivity.iId
                                                 , aSocketActivity.iFxn
                                                 , aSocketActivity.iEvent
                                                 , aSocketActivity.iError);
            break;
        default:
            OSCL_ASSERT(false);//invalid input arg.
            break;
    }

    //current state shoudl be idle
    OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None);

    iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnConnectedPort;
}


PVMFStatus PVMFClientServerSocketNode::StartRecvOperation()
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::StartRecvOperation() In"));

    //caller should have verified we can receive data right now.
    OSCL_ASSERT(iSockConfig->iState.iRecvOperation == EPVSocketPortRecvOperation_None);

    //there should be either a UDP or TCP socket on this port and a memory pool.
    if (!iSockConfig->iTCPSocket)
    {
        return PVMFFailure;
    }
    if (!iSockConfig->iMemPool)
    {
        return PVMFFailure;
    }

    PVMFStatus status = PVMFFailure;

    if (iSockConfig->iTCPSocket)
    {
        iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_Recv;

        //Allocate memory
        int32 err;
        OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl;
        OSCL_TRY(err,
                 mediaDataImpl = iSockConfig->iMemPool->getMediaDataImpl(iMaxTcpRecvBufferSize););
        if (err != OsclErrNone)
        {
            StartRecvWaitOnMemory(iMaxTcpRecvBufferSize);
            status = PVMFPending;
            //wait on memory pool callback "notifyfreechunkavailable"
        }

        else
        {
            OSCL_TRY(err, iSockConfig->iPendingRecvMediaData = PVMFMediaData::createMediaData(
                         mediaDataImpl, iSockConfig->iMemPool->iMediaDataMemPool););
            if (err != OsclErrNone)
            {
                StartRecvWaitOnMemory();
                status = PVMFPending;
                //wait on memory pool callback "notifyfreechunkavailable"
            }

            else
            {
                // Retrieve memory fragment to write to
                OsclRefCounterMemFrag refCtrMemFragOut;
                iSockConfig->iPendingRecvMediaData->getMediaFragment(0, refCtrMemFragOut);

                //Issue the Oscl socket request
                TPVSocketEvent retVal = iSockConfig->iTCPSocket->Recv((uint8*)refCtrMemFragOut.getMemFragPtr()
                                        , refCtrMemFragOut.getCapacity()
                                        , TIMEOUT_RECV);
                if (EPVSocketPending != retVal)
                {
                    status = PVMFFailure;
                }
                else
                {
                    status = PVMFPending;
                    //wait on HandleSocketEvent callback.
                }
            }
        }
    }
    else    //for (iTCPSocket==NULL)
    {
        PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartRecvOperation() Unexpected error, no socket"));
    }

    //Handle synchronous completion or failure.
    if (status != PVMFPending
            && status != PVMFFailure)
    {
        PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::StartRecvOperation: Error. status=%d", status));
    }

    if (status != PVMFPending)
        status = RecvOperationComplete(status, NULL);

    return status;
}

PVMFStatus PVMFClientServerSocketNode::RecvOperationComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
{
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::RecvOperationComplete() In"));

    //status should never be pending here
    OSCL_ASSERT(aStatus != PVMFPending);

    PVMFStatus status = aStatus;
    bool recvOperationCanceled = iSockConfig->iState.iRecvOperationCanceled;

    //check the condition of reset here
    if (iSockConfig->iState.iSequence == EPVSocketPortSequence_SocketCleanup
            || recvOperationCanceled)
    {
        return PVMFSuccess;
    }

    //Update the state
    TPVSocketPortRecvOperation curOp = iSockConfig->iState.iRecvOperation;
    iSockConfig->iState.iRecvOperation = EPVSocketPortRecvOperation_None;
    iSockConfig->iState.iRecvOperationStatus = aStatus;
    iSockConfig->iState.iRecvOperationCanceled = false;

    switch (curOp)
    {
        case EPVSocketPortRecvOperation_WaitOnMemory:
            //a memory wait is complete.
            //PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFClientServerSocketNode::RecvOperationComplete WaitOnMemory - SockId=%d, Mime=%s ", iSockConfig->iSockId, iSockConfig->iMime.get_str()));
            break;

        case EPVSocketPortRecvOperation_WaitOnConnectedPort:
            //a port wait is complete
            if (iSockConfig->iSocketRecvActivity.iValid)
            {
                iSockConfig->iSocketRecvActivity.iValid = false;

                switch (iSockConfig->iSocketRecvActivity.iFxn)
                {
                    case EPVSocketRecv:
                        HandleRecvComplete(iSockConfig->iSocketRecvActivity.iStatus
                                           , &iSockConfig->iSocketRecvActivity, recvOperationCanceled);
                        break;
                    default:
                        OSCL_ASSERT(0);//invalid arg
                        break;
                }
            }
            break;

        case EPVSocketPortRecvOperation_Recv:
            HandleRecvComplete(aStatus, aSocketActivity, recvOperationCanceled);
            break;

        default:
            OSCL_ASSERT(0);//add code for this case
            break;
    }

    if (CanReceive())
        status = StartRecvOperation();

    return status;
}


void PVMFClientServerSocketNode::HandleRecvComplete(PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity, bool aRecvOperationCanceled)
{
    OSCL_UNUSED_ARG(aRecvOperationCanceled);
    PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFClientServerSocketNode::HandleRecvComplete() In"));

    //operation should be complete when this is called.
    OSCL_ASSERT(aStatus != PVMFPending);

    //If there's no socket activity input, then this must be a failure in initiating
    //a Recv operation.
    if (!aSocketActivity || !iSockConfig->iPVMFPort
            || !iSockConfig->iPVMFPort->IsConnected())
    {
        //OSCL_ASSERT(aStatus != PVMFSuccess);
        ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
        //release media data
        if (iSockConfig->iPendingRecvMediaData.GetRep())
            iSockConfig->iPendingRecvMediaData.Unbind();
        return;
    }

    if (aSocketActivity->iEvent == EPVSocketSuccess)
    {
        if (iSockConfig->iPVMFPort->IsOutgoingQueueBusy())
        {
            //wait on port so we can send recv data.
            StartRecvWaitOnConnectedPort(*aSocketActivity);
            return;
        }
    }

    //If we get here then it's time to process the recv result.

    //Release media data on failure
    if (aStatus != PVMFSuccess)
    {
        if (iSockConfig->iPendingRecvMediaData.GetRep())
            iSockConfig->iPendingRecvMediaData.Unbind();
    }

    switch (aSocketActivity->iEvent)
    {
        case EPVSocketSuccess:
        {
            //Get data length and set media buffer size
            int32 len;
            iSockConfig->iTCPSocket->GetRecvData(&len);
            if (len <= 0)
            {
                PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::HandleRecvComplete - Sucessful Recv With Zero Length"));
                OSCL_ASSERT(false);
            }
            iSockConfig->iPendingRecvMediaData->setMediaFragFilledLen(0, len);

            // Resize the buffer
            if (iSockConfig->iMemPool)
            {
                OsclSharedPtr<PVMFMediaDataImpl> mediaMsgImpl;
                iSockConfig->iPendingRecvMediaData->getMediaDataImpl(mediaMsgImpl);
                iSockConfig->iMemPool->resizeSocketDataBuffer(mediaMsgImpl);
            }
            else
            {
                PVMF_SOCKETNODE_LOGERROR((0, "PVMFClientServerSocketNode::HandleRecvComplete() ERROR:mempool not found"));
                OSCL_ASSERT(0);
                return ;
            }

            //queue to next port
            PVMFSharedMediaMsgPtr aMediaMsgPtr;
            convertToPVMFMediaMsg(aMediaMsgPtr, iSockConfig->iPendingRecvMediaData);

            PVMFStatus status = iSockConfig->iPVMFPort->QueueOutgoingMsg(aMediaMsgPtr);
            if (status != PVMFSuccess)
            {
                ReportErrorEvent(PVMFErrPortProcessing);
                return ;
            }
        }
        break;

        case EPVSocketTimeout:
        {
            ReportSocketNodeError(PVMFErrTimeout, PVMFSocketNodeErrorSocketTimeOut);
        }
        break;

        case EPVSocketCancel:
            break;

        case EPVSocketFailure:
        {
            //After a receive failure, we may need to do a TCP shutdown.
            //Check what else is currently happening on the port.
            switch (iSockConfig->iState.iSequence)
            {
                case EPVSocketPortSequence_RequestPort:
                case EPVSocketPortSequence_InputDisconnectMsg:
                case EPVSocketPortSequence_SocketCleanup:
                    break;

                case EPVSocketPortSequence_None:
                case EPVSocketPortSequence_InputDataMsg:
                    //for these cases, start a shutdown sequence
                    //start the sequence
                    iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup;
                    StartSequence(EPVSocketPortSequence_SocketCleanup);
                    break;

                default:
                    //need code to handle this case.
                    OSCL_ASSERT(0);
                    break;
            }
        }
        break;

        default:
            OSCL_ASSERT(0);
            break;
    }
}



OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::SetMaxTCPRecvBufferSize(uint32 aBufferSize)
{
    if ((aBufferSize > 0) && (aBufferSize < SNODE_DEFAULT_MAX_TCP_RECV_BUFFER_SIZE))
    {
        iMaxTcpRecvBufferSize = aBufferSize;
        return PVMFSuccess;
    }
    return PVMFErrArgument;
}

OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetMaxTCPRecvBufferSize(uint32& aSize)
{
    aSize = iMaxTcpRecvBufferSize;
    return PVMFSuccess;
}

OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::SetMaxTCPRecvBufferCount(uint32 aBufferSize)
{
    iMaxTcpRecvBufferCount = aBufferSize;
    return PVMFSuccess;
}

OSCL_EXPORT_REF PVMFStatus PVMFClientServerSocketNode::GetMaxTCPRecvBufferCount(uint32& aSize)
{
    aSize = iMaxTcpRecvBufferCount;
    return PVMFSuccess;
}

PVMFStatus PVMFClientServerSocketNode::StartSequence(TPVSocketPortSequence aSequence, OsclAny* aParam)
{
    PVMFStatus status = PVMFFailure;
    //Set the sequence.
    iSockConfig->iState.iSequence = aSequence;

    switch (aSequence)
    {
        case EPVSocketPortSequence_InputDataMsg:
        {
            OSCL_ASSERT(aParam);
            return StartSendOperation(*((PVMFSharedMediaMsgPtr*)aParam));
        }

        case EPVSocketPortSequence_InputDisconnectMsg:
        {
            status = CloseSocketConnection();
        }
        break;

        case EPVSocketPortSequence_SocketCleanup:
            if (iSockConfig->iTCPSocket)
            {
                //CancelRecvOperation();
                //CancelSendOperation();
                status = CloseSocketConnection();
            }
            break;

        default:
        {
            OSCL_ASSERT(0);
            return PVMFFailure;
        }
    }

    if (status != PVMFPending)
    {
        //nothing needed.
        SequenceComplete(PVMFSuccess);
        return PVMFSuccess;
    }
    return status;
}



PVMFStatus PVMFClientServerSocketNode::CloseSocketConnection()
{
    PVMFStatus status;
    iSockConfig->iState.iSequence = EPVSocketPortSequence_SocketCleanup;
    if (!iSockConfig->iTCPSocket)
    {
        status = PVMFFailure;//unexpected
        return status;
    }
    //Initiate a socket shutdown.
    TPVSocketEvent ret = iSockConfig->iTCPSocket->Shutdown(EPVSocketBothShutdown, TIMEOUT_SHUTDOWN);
    if (ret == EPVSocketPending)
    {
        status = PVMFPending;
        //wait on the socket shutdown to complete in HandleSocketEvent callback
    }
    else
    {
        status = PVMFFailure;
    }
    return status;
}


void PVMFClientServerSocketNode::SequenceComplete(PVMFStatus aStatus)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFClientServerSocketNode::SequenceComplete() Sequence %d Status %d ", iSockConfig->iState.iSequence, aStatus));

    TPVSocketPortSequence curSequence = iSockConfig->iState.iSequence;
    iSockConfig->iState.iSequence = EPVSocketPortSequence_None;
    iSockConfig->iState.iSequenceStatus = aStatus;

    switch (curSequence)
    {
        case EPVSocketPortSequence_RequestPort:
            //may need to complete the node command
            if (iCurrentCmdQueue.size()
                    && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
            {
                CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), aStatus, iPVMFPort);
            }
            break;

        case EPVSocketPortSequence_InputDisconnectMsg:
        case EPVSocketPortSequence_InputDataMsg:
            //If we've just completed an input port message, this may complete a node Flush command
            if (!iCurrentCmdQueue.empty()
                    && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_FLUSH)
            {
                //Flush is done when all input ports are empty.
                if (iPVMFPort->IncomingMsgQueueSize() > 0)
                    return;//keep waiting
                CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
            }
            break;


        case EPVSocketPortSequence_SocketCleanup:
        {
            iPVMFPort->SuspendInput();
            iPVMFPort->ClearMsgQueues();

            CleanupPorts();
            //This port is done-- decrement the counter
            iNumStopPortActivityPending--;

            //When counter reaches zero, all ports are done and the sequence is complete.
            if (iNumStopPortActivityPending == 0)
            {
                //Reset the counter to the "idle" value.
                iNumStopPortActivityPending = (-1);

                //There may be a Reset or CancelAll command waiting on
                //this to complete.
                if (!iCurrentCmdQueue.empty()
                        && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_RESET)
                {
                    CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
                }
                else if (!iCancelCmdQueue.empty()
                         && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELALLCOMMANDS)
                {
                    CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
                }
                return;
            }
        }
        break;

        default:
            break;
    }

    if (curSequence != EPVSocketPortSequence_InputDataMsg
            && CanReceive())
    {
        StartRecvOperation();
    }

    if (CanProcessIncomingMsg())
        ProcessIncomingMsg();
}
