Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 
     19 #include "pvmf_socket_node.h"
     20 #include "oscl_string_utils.h"
     21 #include "pvmf_basic_errorinfomessage.h"
     22 #include "pvmf_errorinfomessage_extension.h"
     23 #include "pvmf_socket_node_events.h"
     24 #include "oscl_byte_order.h"
     25 #include "pvmf_protocol_engine_command_format_ids.h"
     26 #include "pvmf_media_cmd.h"
     27 #include "pvmf_media_msg_format_ids.h"
     28 #include "oscl_tickcount.h"
     29 #include "oscl_rand.h"
     30 #include "oscl_time.h"
     31 #include "pvmf_socket_node_tunables.h"
     32 #include "oscl_bin_stream.h"
     33 // Use default DLL entry point for Symbian
     34 #include "oscl_dll.h"
     35 
     36 //////////////////////////////////////////////////
     37 // PVMFSocketNodeMemPool
     38 //////////////////////////////////////////////////
     39 
     40 PVMFSocketNodeMemPool::PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs)
     41         : iMediaDataMemPool(NULL)
     42 {
     43     iMediaDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (aMemPoolNumBufs, MEDIA_DATA_CLASS_SIZE));
     44     iInternalAlloc = NULL;
     45     iSharedBufferAlloc = NULL;
     46     iMediaMsgAllocator = NULL;
     47     iMediaFragGroupAlloc = NULL;
     48     iMediaFragGroupAllocMempool = NULL;
     49 }
     50 
     51 void PVMFSocketNodeMemPool::CreateAllocators(const OSCL_HeapString<OsclMemAllocator>& iMime, uint32 aSize, uint32 aExpectedNumberOfBlocksPerBuffer, uint32 aResizeSize, uint32 aMaxNumResizes)
     52 {
     53     if (!iSharedBufferAlloc)
     54     {
     55         iSharedDataBufferInfo.Init(aSize, aExpectedNumberOfBlocksPerBuffer, aResizeSize, aMaxNumResizes);
     56         const uint32 maxAllocatorNameLen = 255;
     57         char allocatorName[maxAllocatorNameLen];
     58         const uint32 strLenForMimeName  = maxAllocatorNameLen - oscl_strlen("InternalSocketBuffer");
     59         oscl_strncpy(allocatorName, iMime.get_cstr(), strLenForMimeName);
     60         allocatorName[strLenForMimeName] = '\0';
     61         oscl_strcat(allocatorName, "InternalSocketBuffer");
     62         CreateDefaultDataBufferAllocator(allocatorName);
     63     }
     64 #if SNODE_ENABLE_UDP_MULTI_PACKET
     65     CreateUDPMultipleRecvAllocator();
     66 #endif
     67 }
     68 
     69 OsclMemPoolResizableAllocator* PVMFSocketNodeMemPool::CreateResizableDataBufferAllocator(const char* allocatorName)
     70 {
     71     OSCL_UNUSED_ARG(allocatorName);
     72     if (iMediaMsgAllocator)
     73     {
     74         /*
     75          * It may be possible that the allocator was binded to iInternalAlloc/iSharedBufferAlloc
     76          * So destruct it.
     77          * Deallocation of iInternalAlloc/iSharedBufferAlloc will be done as part of Reset/Destruction of node
     78          */
     79         OSCL_DELETE(iMediaMsgAllocator);
     80         iMediaMsgAllocator = NULL;
     81     }
     82 
     83     OSCL_ASSERT(iSharedBufferAlloc == NULL);
     84     if (iSharedBufferAlloc)
     85         return NULL;
     86 
     87 
     88     iSharedBufferAlloc = OSCL_NEW(OsclMemPoolResizableAllocator, (iSharedDataBufferInfo.iSize, (1 + iSharedDataBufferInfo.iMaxNumResizes),
     89                                   iSharedDataBufferInfo.iExpectedNumberOfBlocksPerBuffer));
     90     iSharedBufferAlloc->setMaxSzForNewMemPoolBuffer(iSharedDataBufferInfo.iResizeSize);
     91     iMediaMsgAllocator = OSCL_NEW(PVMFResizableSimpleMediaMsgAlloc, (iSharedBufferAlloc));
     92     return iSharedBufferAlloc;
     93 }
     94 
     95 void PVMFSocketNodeMemPool::CreateDefaultDataBufferAllocator(const char* allocatorName)
     96 {
     97     OSCL_UNUSED_ARG(allocatorName);
     98     if (iMediaMsgAllocator)
     99     {
    100         /*
    101          * It may be possible that the allocator was binded to iInternalAlloc/iSharedBufferAlloc
    102          * So destruct it.
    103          * Deallocation of iInternalAlloc/iSharedBufferAlloc will be done as part of Reset/Destruction of node
    104          */
    105         OSCL_DELETE(iMediaMsgAllocator);
    106         iMediaMsgAllocator = NULL;
    107     }
    108 
    109     OSCL_ASSERT(iInternalAlloc == NULL);
    110     if (iInternalAlloc)
    111         return;
    112 
    113     iInternalAlloc = OSCL_NEW(OsclMemPoolResizableAllocator, (iSharedDataBufferInfo.iSize, (1 + iSharedDataBufferInfo.iMaxNumResizes),
    114                               iSharedDataBufferInfo.iExpectedNumberOfBlocksPerBuffer));
    115     iInternalAlloc->setMaxSzForNewMemPoolBuffer(iSharedDataBufferInfo.iResizeSize);
    116     iMediaMsgAllocator = OSCL_NEW(PVMFResizableSimpleMediaMsgAlloc, (iInternalAlloc));
    117 }
    118 
    119 void PVMFSocketNodeMemPool::CreateUDPMultipleRecvAllocator()
    120 {
    121 #if SNODE_ENABLE_UDP_MULTI_PACKET
    122     //Create the multiple-receive allocator
    123     iMediaFragGroupAllocMempool
    124     = OSCL_NEW(OsclMemPoolFixedChunkAllocator
    125                , (SNODE_UDP_MULTI_FRAG_ALLOCATOR_MAX_MSGS)
    126               );
    127     iMediaFragGroupAlloc
    128     = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<PVMFSocketNodeAllocator>
    129                , (SNODE_UDP_MULTI_FRAG_ALLOCATOR_MAX_MSGS
    130                   , SNODE_UDP_MULTI_FRAG_ALLOCATOR_MAX_FRAGS_PER_MSG
    131                   , iMediaFragGroupAllocMempool)
    132               );
    133     iMediaFragGroupAlloc->create();
    134 #endif
    135 }
    136 
    137 uint32 PVMFSocketNodeMemPool::GetMaxSizeMediaMsgLen()
    138 {
    139     OsclMemPoolResizableAllocator* resizableAllocator = NULL;
    140 
    141     const uint32 wrappingOverhead = iMediaMsgAllocator->GetMediaMsgAllocationOverheadBytes();
    142 
    143     if (iSharedBufferAlloc)
    144     {
    145         resizableAllocator = OSCL_STATIC_CAST(OsclMemPoolResizableAllocator*, iSharedBufferAlloc);
    146     }
    147     else if (iInternalAlloc)
    148     {
    149         resizableAllocator = OSCL_STATIC_CAST(OsclMemPoolResizableAllocator*, iInternalAlloc);
    150     }
    151 
    152     if (resizableAllocator)
    153     {
    154         return (resizableAllocator->getLargestContiguousFreeBlockSize() - wrappingOverhead);
    155     }
    156 
    157     return 0;
    158 }
    159 
    160 void PVMFSocketNodeMemPool::DestroyAllocators()
    161 {
    162     if (iInternalAlloc != NULL)
    163     {
    164         iInternalAlloc->CancelFreeChunkAvailableCallback();
    165         iInternalAlloc->removeRef();
    166     }
    167     if (iSharedBufferAlloc != NULL)
    168     {
    169         iSharedBufferAlloc->CancelFreeChunkAvailableCallback();
    170         iSharedBufferAlloc->removeRef();
    171     }
    172     if (iMediaMsgAllocator)
    173     {
    174         OSCL_DELETE(iMediaMsgAllocator);
    175         iMediaMsgAllocator = NULL;
    176     }
    177 #if SNODE_ENABLE_UDP_MULTI_PACKET
    178     DestroyUDPMultipleRecvAllocator();
    179 #endif
    180 }
    181 
    182 void PVMFSocketNodeMemPool::DestroyUDPMultipleRecvAllocator()
    183 {
    184 #if SNODE_ENABLE_UDP_MULTI_PACKET
    185     if (iMediaFragGroupAlloc)
    186     {
    187         iMediaFragGroupAlloc->removeRef();
    188         iMediaFragGroupAlloc = NULL;
    189     }
    190     if (iMediaFragGroupAllocMempool)
    191     {
    192         iMediaFragGroupAllocMempool->removeRef();
    193         iMediaFragGroupAllocMempool = NULL;
    194     }
    195 #endif
    196 }
    197 
    198 //////////////////////////////////////////////////
    199 // SocketNodeStats
    200 //////////////////////////////////////////////////
    201 
    202 #if(ENABLE_SOCKET_NODE_STATS)
    203 void SocketNodeStats::Log(PVMFPortVector<PVMFSocketPort, PVMFSocketNodeAllocator>& aPortVec)
    204 {
    205     if (iLogged)
    206         return;//prevent multiple logging.
    207     if (!iLogger)
    208         return;//prevent logging after thread logoff.
    209     iLogged = true;
    210 
    211     PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
    212                     (0, "SocketNodeStats:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
    213 
    214     PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
    215                     (0, "SocketNodeStats: %8d Num Run", iNumRun));
    216     PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
    217                     (0, "SocketNodeStats: %8d Num QueueNodeCmd", iNumQueueNodeCmd));
    218 
    219     PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
    220                     (0, "SocketNodeStats: %8d Num Bind", iNumBind));
    221 
    222     for (uint32 i = 0; i < aPortVec.size(); i++)
    223     {
    224         if (aPortVec[i]->iConfig)
    225             aPortVec[i]->iConfig->iPortStats.Log(iLogger, aPortVec[i]->iConfig->iMime);
    226     }
    227 
    228     PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
    229                     (0, "SocketNodeStats:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
    230 }
    231 #endif //ENABLE_SOCKET_NODE_STATS
    232 
    233 //////////////////////////////////////////////////
    234 // SocketPortConfig
    235 //////////////////////////////////////////////////
    236 
    237 void SocketPortConfig::CreateAllocators(uint32 aSize, uint32 aExpectedNumberOfBlocksPerBuffer, uint32 aResizeSize, uint32 aMaxNumResizes)
    238 {
    239     iMemPool->CreateAllocators(iMime, aSize, aExpectedNumberOfBlocksPerBuffer, aResizeSize, aMaxNumResizes);
    240 }
    241 
    242 void SocketPortConfig::CleanupMemPools(Oscl_DefAlloc& aAlloc)
    243 {
    244     if (iMemPool)
    245     {
    246         iMemPool->DestroyAllocators();
    247         iMemPool->~PVMFSocketNodeMemPool();
    248         aAlloc.deallocate((OsclAny*)(iMemPool));
    249         iMemPool = NULL;
    250     }
    251 }
    252 
    253 //////////////////////////////////////////////////
    254 // End SocketPortConfig
    255 //////////////////////////////////////////////////
    256 
    257 //////////////////////////////////////////////////
    258 // Standard Node APIs
    259 //////////////////////////////////////////////////
    260 
    261 OSCL_EXPORT_REF PVMFSocketNode::PVMFSocketNode(int32 aPriority)
    262         : OsclActiveObject(aPriority, "PVMFSocketNode")
    263         , TIMEOUT_CONNECT(30000)
    264         , TIMEOUT_SEND(3000)
    265         , TIMEOUT_SENDTO(3000)
    266         , TIMEOUT_RECV(-1)
    267         , TIMEOUT_RECVFROM(-1)
    268         , TIMEOUT_SHUTDOWN(10000)
    269         , UDP_PORT_RANGE(2000)
    270         , MAX_UDP_PACKET_SIZE(MAX_SOCKET_BUFFER_SIZE)
    271         , MIN_UDP_PACKET_SIZE(MIN_SOCKET_BUFFER_SIZE)
    272 {
    273     iLogger = NULL;
    274     iDataPathLogger = NULL;
    275     iDataPathLoggerRTP = NULL;
    276     iDataPathLoggerRTCP = NULL;
    277     iOsclErrorTrapImp = NULL;
    278     iSockServ = NULL;
    279     iMaxTcpRecvBufferSize = SNODE_DEFAULT_SOCKET_TCP_BUFFER_SIZE;
    280     iMaxTcpRecvBufferCount = SNODE_DEFAULT_SOCKET_TCP_BUFFER_COUNT;
    281     iSocketID = 0;
    282     iCommandErrorCode = PVMFSocketNodeErrorEventStart;
    283     iErrorEventErrorCode = PVMFSocketNodeErrorEventStart;
    284     iExtensionInterface = NULL;
    285     iInSocketCallback = false;
    286     iNumStopPortActivityPending = (-1);//inactive.
    287 
    288     int32 err;
    289     OSCL_TRY(err,
    290 
    291              //Create the input command queue.  Use a reserve to avoid lots of
    292              //dynamic memory allocation.
    293              iPendingCmdQueue.Construct(PVMF_SOCKET_NODE_COMMAND_ID_START,
    294                                         PVMF_SOCKET_NODE_COMMAND_VECTOR_RESERVE);
    295 
    296              //Create the "current command" queue.  It will only contain one
    297              //command at a time, so use a reserve of 1.
    298              iCurrentCmdQueue.Construct(0, 1);
    299              iCancelCmdQueue.Construct(0, 1);
    300 
    301              //Create the port vector.
    302              iPortVector.Construct(PVMF_SOCKET_NODE_PORT_VECTOR_RESERVE);
    303 
    304              //Set the node capability data.
    305              //This node can support an unlimited number of ports.
    306              iCapability.iCanSupportMultipleInputPorts = true;
    307              iCapability.iCanSupportMultipleOutputPorts = true;
    308              iCapability.iHasMaxNumberOfPorts = false;
    309              iCapability.iMaxNumberOfPorts = 0;//no maximum
    310 
    311              iCapability.iInputFormatCapability.push_back(PVMF_MIME_INET_UDP);
    312              iCapability.iInputFormatCapability.push_back(PVMF_MIME_INET_TCP);
    313 
    314              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_INET_TCP);
    315              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_INET_UDP);
    316 
    317              iDnsCache.NewL();
    318 
    319             );
    320 
    321     if (err != OsclErrNone)
    322     {
    323         //if a leave happened, cleanup and re-throw the error
    324         iPendingCmdQueue.clear();
    325         iCurrentCmdQueue.clear();
    326         iCancelCmdQueue.clear();
    327         iPortVector.clear();
    328         iCapability.iInputFormatCapability.clear();
    329         iCapability.iOutputFormatCapability.clear();
    330         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
    331         OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
    332         OSCL_LEAVE(err);
    333     }
    334 }
    335 
    336 
    337 OSCL_EXPORT_REF PVMFSocketNode::~PVMFSocketNode()
    338 {
    339 #if(ENABLE_SOCKET_NODE_STATS)
    340     iSocketNodeStats.Log(iPortVector);
    341 #endif
    342 
    343     Cancel();
    344 
    345     //thread logoff
    346     if (IsAdded())
    347         RemoveFromScheduler();
    348 
    349     if (iExtensionInterface)
    350     {
    351         iExtensionInterface->removeRef();
    352     }
    353 
    354     /* Cleanup allocated ports */
    355     CleanupPorts();
    356     iPortVector.clear();
    357     CleanupClosedTCPSockets();
    358     CleanupClosedUDPSockets();
    359     CleanupClosedDNS();
    360     //Cleanup commands
    361     //The command queues are self-deleting, but we want to
    362     //notify the observer of unprocessed commands.
    363     while (!iCurrentCmdQueue.empty())
    364     {
    365         CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFFailure);
    366     }
    367     while (!iPendingCmdQueue.empty())
    368     {
    369         CommandComplete(iPendingCmdQueue, iPendingCmdQueue.front(), PVMFFailure);
    370     }
    371     while (!iCancelCmdQueue.empty())
    372     {
    373         CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFFailure);
    374     }
    375     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Goin to delete Sock Serv"));
    376     if (iSockServ)
    377     {
    378         iSockServ->Close();
    379         iSockServ->~OsclSocketServ();
    380         iAlloc.deallocate(iSockServ);
    381         iSockServ = NULL;
    382     }
    383     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:~PVMFSocketNode out"));
    384 }
    385 
    386 
    387 //Do thread-specific node creation and go to "Idle" state.
    388 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::ThreadLogon()
    389 {
    390     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:ThreadLogon"));
    391 
    392     switch (iInterfaceState)
    393     {
    394         case EPVMFNodeCreated:
    395             if (!IsAdded())
    396                 AddToScheduler();
    397             iLogger = PVLogger::GetLoggerObject("PVMFSocketNode");
    398             iDataPathLogger = PVLogger::GetLoggerObject("datapath.socketnode");
    399             iDataPathLoggerRTP = PVLogger::GetLoggerObject("datapath.socketnode.rtp");
    400             iDataPathLoggerRTCP = PVLogger::GetLoggerObject("datapath.socketnode.rtcp");
    401             iOsclErrorTrapImp = OsclErrorTrap::GetErrorTrapImp();
    402             SetState(EPVMFNodeIdle);
    403             return PVMFSuccess;
    404         default:
    405             return PVMFErrInvalidState;
    406     }
    407 }
    408 
    409 //Do thread-specific node cleanup and go to "Created" state.
    410 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::ThreadLogoff()
    411 {
    412     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:ThreadLogoff"));
    413 
    414     switch (iInterfaceState)
    415     {
    416         case EPVMFNodeIdle:
    417         {
    418             if (IsAdded())
    419                 RemoveFromScheduler();
    420             iLogger = NULL;
    421             iDataPathLogger = NULL;
    422             iDataPathLoggerRTP = NULL;
    423             iDataPathLoggerRTCP = NULL;
    424             iOsclErrorTrapImp = NULL;
    425             SetState(EPVMFNodeCreated);
    426 #if(ENABLE_SOCKET_NODE_STATS)
    427             iSocketNodeStats.Logoff();
    428 #endif
    429             return PVMFSuccess;
    430         }
    431         // break;   This break statement was removed to avoid compiler warning for Unreachable Code
    432 
    433         default:
    434             return PVMFErrInvalidState;
    435             // break;   This break statement was removed to avoid compiler warning for Unreachable Code
    436     }
    437 }
    438 
    439 //retrieve node capabilities.
    440 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::GetCapability(PVMFNodeCapability& aNodeCapability)
    441 {
    442     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:GetCapability"));
    443     aNodeCapability = iCapability;
    444     return PVMFSuccess;
    445 }
    446 
    447 //retrieve a port iterator.
    448 OSCL_EXPORT_REF PVMFPortIter* PVMFSocketNode::GetPorts(const PVMFPortFilter* aFilter)
    449 {
    450     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:GetPorts"));
    451 
    452     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
    453     iPortVector.Reset();
    454     return &iPortVector;
    455 }
    456 
    457 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
    458         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    459         bool aExactUuidsOnly,
    460         const OsclAny* aContext)
    461 {
    462     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:QueryUUID"));
    463 
    464     PVMFSocketNodeCommand cmd;
    465     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    466     return QueueCommandL(cmd);
    467 }
    468 
    469 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
    470         PVInterface*& aInterfacePtr,
    471         const OsclAny* aContext)
    472 {
    473     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:QueryInterface"));
    474 
    475     PVMFSocketNodeCommand cmd;
    476     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    477     return QueueCommandL(cmd);
    478 }
    479 
    480 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
    481 {
    482     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:RequestPort"));
    483     PVMFSocketNodeCommand cmd;
    484     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
    485     return QueueCommandL(cmd);
    486 }
    487 
    488 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
    489 {
    490     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:ReleasePort"));
    491     PVMFSocketNodeCommand cmd;
    492     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    493     return QueueCommandL(cmd);
    494 }
    495 
    496 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Init(PVMFSessionId s, const OsclAny* aContext)
    497 {
    498     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Init"));
    499     PVMFSocketNodeCommand cmd;
    500     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    501     return QueueCommandL(cmd);
    502 }
    503 
    504 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
    505 {
    506     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Init"));
    507     PVMFSocketNodeCommand cmd;
    508     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    509     return QueueCommandL(cmd);
    510 }
    511 
    512 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Start(PVMFSessionId s, const OsclAny* aContext)
    513 {
    514     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Start"));
    515     PVMFSocketNodeCommand cmd;
    516     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    517     return QueueCommandL(cmd);
    518 }
    519 
    520 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Stop(PVMFSessionId s, const OsclAny* aContext)
    521 {
    522     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Stop"));
    523     PVMFSocketNodeCommand cmd;
    524     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    525     return QueueCommandL(cmd);
    526 }
    527 
    528 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Flush(PVMFSessionId s, const OsclAny* aContext)
    529 {
    530     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Flush"));
    531     PVMFSocketNodeCommand cmd;
    532     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    533     return QueueCommandL(cmd);
    534 }
    535 
    536 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Pause(PVMFSessionId s, const OsclAny* aContext)
    537 {
    538     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Pause"));
    539     PVMFSocketNodeCommand cmd;
    540     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    541     return QueueCommandL(cmd);
    542 }
    543 
    544 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::Reset(PVMFSessionId s, const OsclAny* aContext)
    545 {
    546     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:Reset"));
    547     PVMFSocketNodeCommand cmd;
    548     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    549     return QueueCommandL(cmd);
    550 }
    551 
    552 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
    553 {
    554     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:CancelAllCommands"));
    555     PVMFSocketNodeCommand cmd;
    556     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    557     return QueueCommandL(cmd);
    558 }
    559 
    560 OSCL_EXPORT_REF PVMFCommandId PVMFSocketNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
    561 {
    562     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:CancelCommand"));
    563     PVMFSocketNodeCommand cmd;
    564     cmd.PVMFSocketNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    565     return QueueCommandL(cmd);
    566 }
    567 
    568 //Port activity handler
    569 void PVMFSocketNode::HandlePortActivity(const PVMFPortActivity &aActivity)
    570 {
    571     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    572                     (0, "0x%x PVMFSocketNode::HandlePortActivity IN: port=0x%x, type=%d",
    573                      this, aActivity.iPort, aActivity.iType));
    574 
    575     switch (aActivity.iType)
    576     {
    577 
    578         case PVMF_PORT_ACTIVITY_CONNECT:
    579         {
    580             PVMFSocketPort* sockPort = OSCL_STATIC_CAST(PVMFSocketPort*, aActivity.iPort);
    581             OSCL_ASSERT(sockPort && sockPort->iConfig);
    582             SocketPortConfig& aSockConfig = *sockPort->iConfig;
    583             aSockConfig.CreateAllocators(iMaxTcpRecvBufferSize *(iMaxTcpRecvBufferCount - 1), iMaxTcpRecvBufferCount - 1, iMaxTcpRecvBufferSize, 1);
    584 #if(ENABLE_SOCKET_NODE_STATS)
    585             aSockConfig.iPortStats.iNumPortEventConnect++;
    586 #endif
    587 
    588             //Receives may have been blocked waiting on the port to be connected, so check here.
    589             //Note: This is a known use case for HTTP streaming, where the port request and connect
    590             //can happen after the node start
    591             if (CanReceive(aSockConfig))
    592                 StartRecvOperation(aSockConfig);
    593         }
    594         break;
    595 
    596         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
    597         {
    598             PVMFSocketPort* sockPort = (PVMFSocketPort*)(aActivity.iPort);
    599             OSCL_ASSERT(sockPort && sockPort->iConfig);
    600             SocketPortConfig& aSockConfig = *sockPort->iConfig;
    601 
    602 #if(ENABLE_SOCKET_NODE_STATS)
    603             aSockConfig.iPortStats.iNumPortEventIncomingMsg++;
    604 #endif
    605 
    606             //Try to process this message now.
    607             if (CanProcessIncomingMsg(aSockConfig))
    608                 ProcessIncomingMsg(aSockConfig);
    609             //Otherwise, ignore this event now.  Other code will check
    610             //the input queue as needed.
    611         }
    612         break;
    613 
    614         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
    615         {
    616             PVMFSocketPort* sockPort = (PVMFSocketPort*)(aActivity.iPort);
    617             OSCL_ASSERT(sockPort && sockPort->iConfig);
    618             SocketPortConfig& aSockConfig = *sockPort->iConfig;
    619 
    620 #if(ENABLE_SOCKET_NODE_STATS)
    621             aSockConfig.iPortStats.iNumPortEventConnectedPortReady++;
    622 #endif
    623 
    624             //See if the port was waiting on this event, and if so, continue processing.
    625 
    626             if (aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_WaitOnConnectedPort)
    627             {
    628 #if(ENABLE_SOCKET_NODE_STATS)
    629                 aSockConfig.iPortStats.EndConnectTime(aSockConfig.iState.iConnectOperation);
    630 #endif
    631                 ConnectOperationComplete(aSockConfig, PVMFSuccess, NULL);
    632             }
    633 
    634             if (aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnConnectedPort)
    635             {
    636 #if(ENABLE_SOCKET_NODE_STATS)
    637                 aSockConfig.iPortStats.EndRecvTime(aSockConfig.iState.iRecvOperation);
    638 #endif
    639                 RecvOperationComplete(aSockConfig, PVMFSuccess, NULL);
    640             }
    641 
    642             //Otherwise ignore this event now.  Other code will check connected
    643             //port status as needed.
    644         }
    645         break;
    646 
    647         default:
    648             //all other events can be ignored.
    649             break;
    650     }
    651 }
    652 
    653 //////////////////////////////////////////////////
    654 // End Standard Node APIs
    655 //////////////////////////////////////////////////
    656 
    657 //////////////////////////////////////////////////
    658 // Additional Public APIs unique to Socket Node
    659 //////////////////////////////////////////////////
    660 
    661 OSCL_EXPORT_REF bool PVMFSocketNode::GetPortConfig(PVMFPortInterface &aPort, OsclNetworkAddress &aLocalAdd, OsclNetworkAddress &aRemoteAdd)
    662 {
    663     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::GetPortConfig IN"));
    664     aLocalAdd.ipAddr.Set("0.0.0.0");
    665     aLocalAdd.port = 0;
    666 
    667     aRemoteAdd.ipAddr.Set("");
    668     aRemoteAdd.port = 0;
    669 
    670     for (uint32 i = 0; i < iPortVector.size(); i++)
    671     {
    672         if (iPortVector[i]->iConfig
    673                 && iPortVector[i]->iConfig->iPVMFPort == &aPort)
    674         {
    675             aLocalAdd = iPortVector[i]->iConfig->iAddr.iLocalAdd;
    676             aRemoteAdd = iPortVector[i]->iConfig->iAddr.iRemoteAdd;
    677             return true;
    678         }
    679     }
    680     return false;
    681 }
    682 
    683 OSCL_EXPORT_REF bool PVMFSocketNode::SetPortConfig(PVMFPortInterface &aPort, OsclNetworkAddress aLocalAdd, OsclNetworkAddress aRemoteAdd)
    684 {
    685     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::SetPortConfig IN"));
    686     for (uint32 i = 0; i < iPortVector.size(); i++)
    687     {
    688         if (iPortVector[i]->iConfig
    689                 && iPortVector[i]->iConfig->iPVMFPort == &aPort)
    690         {
    691             iPortVector[i]->iConfig->iAddr.iLocalAdd = aLocalAdd;
    692             iPortVector[i]->iConfig->iAddr.iRemoteAdd = aRemoteAdd;
    693             return true;
    694         }
    695     }
    696     return false;
    697 }
    698 
    699 //////////////////////////////////////////////////
    700 // End Additional Public APIs unique to Socket Node
    701 //////////////////////////////////////////////////
    702 
    703 
    704 //Create UDP sockets on consecutive ports.
    705 //This is needed because 3GPP streaming servers require consecutive ports.
    706 //If successfully created, the sockets are saved in the "allocated port" vector.
    707 //The created sockets will be associated with PVMF ports later during RequestPort
    708 //commands.
    709 PVMFStatus PVMFSocketNode::AllocateConsecutivePorts(PvmfMimeString* aPortConfig,
    710         uint32& aLowerPortNum,
    711         uint32& aHigherPortNum, uint32& aStartPortNum)
    712 {
    713     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::AllocateConsecutivePorts IN"));
    714 
    715     //used in case of 3GPP streaming to allocate consecutive udp ports
    716     //for rtp and rtcp.
    717     //lower port number = rtp => PVMF_SOCKET_NODE_PORT_TYPE_SOURCE
    718     //higher port number = rtcp => PVMF_SOCKET_NODE_PORT_TYPE_SINK
    719     aLowerPortNum = 0;
    720     aHigherPortNum = 0;
    721 
    722     uint32 startSockID = iSocketID;
    723 
    724     PVMFStatus status = PVMFFailure;
    725 
    726     SocketPortConfig* lower_sock_config = OSCL_NEW(SocketPortConfig, ());
    727     SocketPortConfig* higher_sock_config = OSCL_NEW(SocketPortConfig, ());
    728 
    729     for (int maxNumOfBind = UDP_PORT_RANGE; maxNumOfBind >= 0; maxNumOfBind--)
    730     {
    731         OSCL_HeapString<OsclMemAllocator> rtpportConfigWithMime;
    732         rtpportConfigWithMime += aPortConfig->get_cstr();
    733         rtpportConfigWithMime += _STRLIT_CHAR("/rtp");
    734         ParseTransportConfig(&rtpportConfigWithMime,
    735                              lower_sock_config->iAddr,
    736                              lower_sock_config->iMime);
    737         //this should only be UDP
    738         if (lower_sock_config->iAddr.iProtocol != INET_UDP)
    739         {
    740             status = PVMFErrArgument;
    741             goto Exit;
    742         }
    743         lower_sock_config->iContainer = this;
    744         lower_sock_config->iAddr.iLocalAdd.port = aStartPortNum;
    745         lower_sock_config->iSockId = startSockID++;
    746         lower_sock_config->iRTP = true;
    747 
    748         if (NULL == (lower_sock_config->iUDPSocket = (OsclUDPSocket*)CreateOsclSocketAndBind(lower_sock_config->iAddr, lower_sock_config->iSockId)))
    749         {
    750             status = PVMFFailure;
    751             goto Exit;
    752         }
    753 
    754         OSCL_HeapString<OsclMemAllocator> rtcpportConfigWithMime;
    755         rtcpportConfigWithMime += aPortConfig->get_cstr();
    756         rtcpportConfigWithMime += _STRLIT_CHAR("/rtcp");
    757 
    758         ParseTransportConfig(&rtcpportConfigWithMime,
    759                              higher_sock_config->iAddr,
    760                              higher_sock_config->iMime);
    761         //this should only be UDP
    762         if (higher_sock_config->iAddr.iProtocol != INET_UDP)
    763         {
    764             status = PVMFErrArgument;
    765             goto Exit;
    766         }
    767         higher_sock_config->iContainer = this;
    768         higher_sock_config->iAddr.iLocalAdd.port =
    769             lower_sock_config->iAddr.iLocalAdd.port + 1;
    770         higher_sock_config->iSockId = startSockID++;
    771         higher_sock_config->iRTCP = true;
    772 
    773         if (NULL == (higher_sock_config->iUDPSocket = (OsclUDPSocket*)CreateOsclSocketAndBind(higher_sock_config->iAddr, higher_sock_config->iSockId)))
    774         {
    775             status = PVMFFailure;
    776             goto Exit;
    777         }
    778 
    779         //We were able to create and bind, now see whether we got consecutive ports or not.
    780         if (higher_sock_config->iAddr.iLocalAdd.port ==
    781                 (lower_sock_config->iAddr.iLocalAdd.port + 1))
    782         {
    783             aLowerPortNum = lower_sock_config->iAddr.iLocalAdd.port;
    784             lower_sock_config->iPVMFPort = NULL;
    785             lower_sock_config->iTag = PVMF_SOCKET_NODE_PORT_TYPE_SOURCE;
    786             iAllocatedPortVector.push_back(lower_sock_config);
    787 
    788             aHigherPortNum = higher_sock_config->iAddr.iLocalAdd.port;
    789             higher_sock_config->iPVMFPort = NULL;
    790             higher_sock_config->iTag = PVMF_SOCKET_NODE_PORT_TYPE_SINK;
    791             iAllocatedPortVector.push_back(higher_sock_config);
    792 
    793             iSocketID = startSockID;
    794 
    795             aStartPortNum = higher_sock_config->iAddr.iLocalAdd.port + 1;
    796 
    797             status = PVMFSuccess;
    798             goto Exit;
    799         }
    800         else
    801         {
    802             //Delete and try again
    803             OsclUDPSocket* udpSocket1 = lower_sock_config->iUDPSocket;
    804             udpSocket1->~OsclUDPSocket();
    805             iAlloc.deallocate(udpSocket1);
    806             lower_sock_config->iUDPSocket = NULL;
    807 
    808             OsclUDPSocket* udpSocket2 = higher_sock_config->iUDPSocket;
    809             udpSocket2->~OsclUDPSocket();
    810             iAlloc.deallocate(udpSocket2);
    811             higher_sock_config->iUDPSocket = NULL;
    812 
    813             aStartPortNum = higher_sock_config->iAddr.iLocalAdd.port + 1;
    814             startSockID = iSocketID;
    815         }
    816     }//for max port bind attempts
    817 
    818 
    819     status = PVMFFailure;
    820 
    821 Exit:
    822     if (status != PVMFSuccess)
    823     {
    824         OSCL_DELETE(lower_sock_config);
    825         OSCL_DELETE(higher_sock_config);
    826     }
    827     return status;
    828 }
    829 
    830 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::SetMaxTCPRecvBufferSize(uint32 aBufferSize)
    831 {
    832     if ((aBufferSize > 0) && (aBufferSize < SNODE_DEFAULT_MAX_TCP_RECV_BUFFER_SIZE))
    833     {
    834         iMaxTcpRecvBufferSize = aBufferSize;
    835         return PVMFSuccess;
    836     }
    837     return PVMFErrArgument;
    838 }
    839 
    840 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::GetMaxTCPRecvBufferSize(uint32& aSize)
    841 {
    842     aSize = iMaxTcpRecvBufferSize;
    843     return PVMFSuccess;
    844 }
    845 
    846 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::SetMaxTCPRecvBufferCount(uint32 aCount)
    847 {
    848     iMaxTcpRecvBufferCount = aCount;
    849     return PVMFSuccess;
    850 }
    851 
    852 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::GetMaxTCPRecvBufferCount(uint32& aCount)
    853 {
    854     aCount = iMaxTcpRecvBufferCount;
    855     return PVMFSuccess;
    856 }
    857 
    858 OsclMemPoolResizableAllocator* PVMFSocketNode::CreateSharedBuffer(const PVMFPortInterface* aPort , uint32 aBufferSize, uint32 aExpectedNumberOfBlocksPerBuffer, uint32 aResizeSize, uint32 aMaxNumResizes)
    859 {
    860     //validate input params if required..
    861     OSCL_ASSERT(aPort);
    862     if (!aPort)
    863         return NULL;
    864 
    865     //If data buffer for the port is already created and is existing, then destroy the prev buffer and create new one (with requested attributes).
    866     //CreateResizableDataBufferAllocator func will take care of this.
    867     SocketPortConfig* portConfig = OSCL_STATIC_CAST(PVMFSocketPort*, aPort)->iConfig;
    868     PVMFSocketNodeMemPool * portMemPool = portConfig->iMemPool;
    869     portMemPool->iSharedDataBufferInfo.Init(aBufferSize, aExpectedNumberOfBlocksPerBuffer, aResizeSize, aMaxNumResizes);
    870     return portMemPool->CreateResizableDataBufferAllocator(portConfig->iMime.get_cstr());
    871 }
    872 ///////////////////////////
    873 // End Socket Extension Interface
    874 ///////////////////////////
    875 
    876 
    877 //////////////////////////////////////
    878 // Incoming Message Handlers
    879 //////////////////////////////////////
    880 
    881 //Tell whether it's possible to process an incoming message on a port.
    882 bool PVMFSocketNode::CanProcessIncomingMsg(SocketPortConfig& aSockConfig)
    883 {
    884     return
    885         //node is started
    886         iInterfaceState == EPVMFNodeStarted
    887         //port has input messages
    888         && aSockConfig.iPVMFPort && aSockConfig.iPVMFPort->IncomingMsgQueueSize() > 0
    889         //port is not busy with any sequence
    890         && aSockConfig.iState.iSequence == EPVSocketPortSequence_None;
    891 }
    892 
    893 //Process an incoming message on this port.
    894 //Assume caller already verified "can process incoming msg".
    895 void PVMFSocketNode::ProcessIncomingMsg(SocketPortConfig& aSockConfig)
    896 {
    897     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::ProcessIncomingMsg: aPort=0x%x", aSockConfig.iPVMFPort));
    898 
    899     //Dequeue the incoming message
    900     PVMFSharedMediaMsgPtr msg;
    901     PVMFStatus status = aSockConfig.iPVMFPort->DequeueIncomingMsg(msg);
    902     if (status != PVMFSuccess)
    903     {
    904         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::ProcessIncomingDataMsg: Error - DequeueIncomingMsg failed"));
    905         ReportErrorEvent(PVMFErrPortProcessing);
    906         return ;
    907     }
    908 
    909     //calling logic should prevent processing a message when some other sequence
    910     //is active on the port
    911     OSCL_ASSERT(aSockConfig.iState.iSequence == EPVSocketPortSequence_None);
    912 
    913     //Handle 3 types of messages
    914     if (msg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_CONNECT_FORMAT_ID)
    915     {
    916 #if(ENABLE_SOCKET_NODE_STATS)
    917         aSockConfig.iPortStats.iNumDequeueIncomingConnectMsg++;
    918 #endif
    919         //Connect message
    920         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ProcessIncomingMsg - CONNECT SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_cstr()));
    921 
    922         //Parse the address
    923         OsclRefCounterMemFrag newSockAddr;
    924         msg->getFormatSpecificInfo(newSockAddr);
    925         if (newSockAddr.getMemFragPtr())
    926         {
    927             if (!ParseTransportConfig((char*)newSockAddr.getMemFragPtr(),
    928                                       newSockAddr.getMemFragSize(),
    929                                       aSockConfig.iAddr,
    930                                       aSockConfig.iMime))
    931             {
    932                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::ProcessIncomingMsg: ERROR - Invalid port config"));
    933                 ReportSocketNodeError(PVMFErrPortProcessing, PVMFSocketNodeErrorInvalidPortTag);
    934                 return ;
    935             }
    936         }
    937 
    938         //Start the sequence
    939         StartSequence(aSockConfig, EPVSocketPortSequence_InputConnectMsg);
    940     }
    941     else if (msg->getFormatID() == PVMF_MEDIA_CMD_SOCKET_DISCONNECT_FORMAT_ID)
    942     {
    943 #if(ENABLE_SOCKET_NODE_STATS)
    944         aSockConfig.iPortStats.iNumDequeueIncomingDisconnectMsg++;
    945 #endif
    946         //Disconnect message
    947         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ProcessIncomingMsg - DISCONNECT msg - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_cstr()));
    948 
    949         //Start the sequence
    950         StartSequence(aSockConfig, EPVSocketPortSequence_InputDisconnectMsg);
    951     }
    952     else if (msg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID)
    953     {
    954 #if(ENABLE_SOCKET_NODE_STATS)
    955         aSockConfig.iPortStats.iNumDequeueIncomingDataMsg++;
    956 #endif
    957         //Media Data message
    958         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ProcessIncomingMsg - MEDIA DATA msg - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_cstr()));
    959 
    960         //calling logic should prevent any simultaneous send/connect
    961         OSCL_ASSERT(aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_None);
    962 
    963         //Start the sequence
    964         StartSequence(aSockConfig, EPVSocketPortSequence_InputDataMsg, (OsclAny*)&msg);
    965     }
    966     else
    967     {
    968         //unexpected message type
    969         ReportErrorEvent(PVMFErrPortProcessing);
    970     }
    971 }
    972 
    973 
    974 //////////////////////////////////////
    975 // End Incoming Message Handlers
    976 //////////////////////////////////////
    977 
    978 //////////////////////////////////////
    979 // Connect Operation Handlers
    980 //////////////////////////////////////
    981 
    982 
    983 //Start the given "connect" operation on the port.
    984 //If the connect fails, this will call "connect operation complete" and continue to
    985 //the next operation.
    986 PVMFStatus PVMFSocketNode::StartConnectOperation(SocketPortConfig& aSockConfig, TPVSocketPortConnectOperation aOperation)
    987 {
    988     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::StartConnectOperation() In Operation %d", aOperation));
    989 
    990     //connect operation should be idle now.
    991     OSCL_ASSERT(aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_None);
    992 
    993     //Update the state
    994     aSockConfig.iState.iConnectOperation = aOperation;
    995 
    996     PVMFStatus status = PVMFFailure;
    997 
    998     switch (aOperation)
    999     {
   1000         case EPVSocketPortConnectOperation_GetHostByName:
   1001         {
   1002             //This is the beginning of TCP socket create/connect.
   1003 
   1004             //this should be TCP.
   1005             OSCL_ASSERT(aSockConfig.iAddr.iProtocol == INET_TCP);
   1006 
   1007             //Any old socket should be cleaned up or else queued for cleanup at this point.
   1008             OSCL_ASSERT(!aSockConfig.iTCPSocket);
   1009 
   1010             //Create the socket
   1011             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, Creating socket - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1012             aSockConfig.iTCPSocket = (OsclTCPSocket*)CreateOsclSocketAndBind(aSockConfig.iAddr, aSockConfig.iSockId);
   1013             if (!aSockConfig.iTCPSocket)
   1014             {
   1015                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, Creating socket FAILED - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1016                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartConnectOperation: ERROR - CreateSocket()"));
   1017                 if (aSockConfig.iState.iSequence == EPVSocketPortSequence_RequestPort)
   1018                 {
   1019                     iCommandErrorCode = PVMFSocketNodeErrorSocketFailure;
   1020                 }
   1021                 else
   1022                 {
   1023                     ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   1024                 }
   1025                 status = PVMFErrResource;
   1026                 break;
   1027             }
   1028 
   1029             //see if DNS is needed
   1030             if (OsclValidInetAddr(aSockConfig.iAddr.iRemoteHost.get_cstr()))
   1031             {
   1032                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, DNS is not needed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1033                 aSockConfig.iAddr.iRemoteAdd.ipAddr.Set(aSockConfig.iAddr.iRemoteHost.get_cstr());
   1034                 status = PVMFSuccess;//no lookup needed-- continue to next operation.
   1035                 break;
   1036             }
   1037 
   1038             //DNS lookup needed.
   1039             //see if we can use the DNS cache instead of an actual lookup
   1040             aSockConfig.iAddr.iRemoteAdd.ipAddr.Set("");
   1041             if (iDnsCache.QueryGetHostByName(aSockConfig.iAddr.iRemoteHost.get_str(), (char*)aSockConfig.iAddr.iRemoteAdd.ipAddr.Str(), aSockConfig.iAddr.iRemoteAdd.ipAddr.MaxLen()))
   1042             {
   1043                 //DNS cache lookup success
   1044                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, DNS cache lookup success - SockId=%d, Mime=%s, Host=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iAddr.iRemoteHost.get_str()));
   1045                 status = PVMFSuccess;//no lookup needed-- continue to next operation.
   1046                 break;
   1047             }
   1048 
   1049             //Create DNS object
   1050             if (!aSockConfig.iDNS)
   1051             {
   1052                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, Creating DNS object - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1053                 aSockConfig.iDNS = OsclDNS::NewL(iAlloc, *iSockServ, *this, aSockConfig.iSockId);
   1054                 if (!aSockConfig.iDNS)
   1055                 {
   1056                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation GetHostByName, Creating DNS FAILED - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1057                     PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartConnectOperation: ERROR - Create DNS()"));
   1058                     if (aSockConfig.iState.iSequence == EPVSocketPortSequence_RequestPort)
   1059                     {
   1060                         iCommandErrorCode = PVMFSocketNodeError_DNSLookup;
   1061                     }
   1062                     else
   1063                     {
   1064                         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeError_DNSLookup);
   1065                     }
   1066                     status = PVMFErrResource;
   1067                     break;
   1068                 }
   1069             }
   1070 
   1071             //start the asynchronous DNS operation.
   1072 
   1073 #if(ENABLE_SOCKET_NODE_STATS)
   1074             aSockConfig.iPortStats.iNumGetHostByName++;
   1075             aSockConfig.iPortStats.StartConnectTime(aSockConfig.iState.iConnectOperation);
   1076 #endif
   1077 
   1078             TPVDNSEvent aEvent = aSockConfig.iDNS->GetHostByName(aSockConfig.iAddr.iRemoteHost.get_str(),
   1079                                  aSockConfig.iAddr.iRemoteAdd, -1);
   1080             if (EPVDNSPending != aEvent)
   1081             {
   1082                 aSockConfig.iState.iConnectOperation = EPVSocketPortConnectOperation_None;
   1083                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation: GetHostByName Failed - SockId=%d, Mime=%s, Host=%s",
   1084                                                   aSockConfig.iSockId, aSockConfig.iMime.get_str(),
   1085                                                   aSockConfig.iAddr.iRemoteHost.get_str()));
   1086                 if (aSockConfig.iState.iSequence == EPVSocketPortSequence_RequestPort)
   1087                 {
   1088                     iCommandErrorCode = PVMFSocketNodeError_DNSLookup;
   1089                 }
   1090                 else
   1091                 {
   1092                     ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeError_DNSLookup);
   1093                 }
   1094                 status = PVMFErrResource;
   1095                 break;
   1096             }
   1097 
   1098             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation: Waiting On DNS - SockId=%d, Mime=%s, Host=%s",
   1099                                               aSockConfig.iSockId, aSockConfig.iMime.get_str(),
   1100                                               aSockConfig.iAddr.iRemoteHost.get_str()));
   1101 #if (ENABLE_SOCKET_NODE_DEBUG_INFO_EVENT)
   1102             ReportInfoEvent(PVMFSocketNodeInfoEventRequestedDNSResolution);
   1103 #endif
   1104             status = PVMFPending;
   1105             //wait on the DNS lookup to complete in HandleDNSEvent callback
   1106         }
   1107         break;
   1108 
   1109         case EPVSocketPortConnectOperation_Connect:
   1110             //Initiate a socket connect, after DNS lookup was successful or address is already IP.
   1111             //Will return "pending" or an error.
   1112         {
   1113             if (!aSockConfig.iTCPSocket)
   1114             {
   1115                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation: ERROR socket already exists - SockId=%d, Mime=%s",
   1116                                                   aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1117                 status = PVMFFailure;//unexpected
   1118                 break;
   1119             }
   1120 
   1121             //start the asynchronous connect operation.
   1122 
   1123 #if(ENABLE_SOCKET_NODE_STATS)
   1124             aSockConfig.iPortStats.iNumConnect++;
   1125             aSockConfig.iPortStats.StartConnectTime(aSockConfig.iState.iConnectOperation);
   1126 #endif
   1127 
   1128             TPVSocketEvent ret = aSockConfig.iTCPSocket->Connect(aSockConfig.iAddr.iRemoteAdd, TIMEOUT_CONNECT);
   1129             if (ret != EPVSocketPending)
   1130             {
   1131                 //failure
   1132                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation: Starting Connect FAILED - SockId=%d, Mime=%s, RemoteIP=%s",
   1133                                                   aSockConfig.iSockId, aSockConfig.iMime.get_str(),
   1134                                                   (char*)(aSockConfig.iAddr.iRemoteAdd.ipAddr.Str())));
   1135                 if (aSockConfig.iState.iSequence == EPVSocketPortSequence_RequestPort)
   1136                 {
   1137                     iCommandErrorCode = PVMFSocketNodeError_TCPSocketConnect;
   1138                 }
   1139                 else
   1140                 {
   1141                     ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeError_TCPSocketConnect);
   1142                 }
   1143                 status = PVMFErrResource;
   1144                 break;
   1145             }
   1146             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartConnectOperation - Socket Connect Pending...SockId=%d, Mime=%s, RemoteIP=%s"
   1147                                               , aSockConfig.iSockId, aSockConfig.iMime.get_str(),
   1148                                               (char*)(aSockConfig.iAddr.iRemoteAdd.ipAddr.Str())));
   1149 #if (ENABLE_SOCKET_NODE_DEBUG_INFO_EVENT)
   1150             ReportInfoEvent(PVMFSocketNodeInfoEventConnectRequestPending);
   1151 #endif
   1152             status = PVMFPending;
   1153             //wait on the socket connect to complete in HandleSocketEvent callback
   1154         }
   1155         break;
   1156 
   1157         case EPVSocketPortConnectOperation_Shutdown:
   1158         {
   1159             if (!aSockConfig.iTCPSocket)
   1160             {
   1161                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation: ERROR socket already exists - SockId=%d, Mime=%s",
   1162                                                   aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1163                 status = PVMFFailure;//unexpected
   1164                 break;
   1165             }
   1166 
   1167             //Initiate a socket shutdown.
   1168 #if(ENABLE_SOCKET_NODE_STATS)
   1169             aSockConfig.iPortStats.iNumShutdown++;
   1170             aSockConfig.iPortStats.StartConnectTime(aSockConfig.iState.iConnectOperation);
   1171 #endif
   1172             TPVSocketEvent ret = aSockConfig.iTCPSocket->Shutdown(EPVSocketBothShutdown, TIMEOUT_SHUTDOWN);
   1173             if (ret == EPVSocketPending)
   1174             {
   1175                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation - Shutdown Pending...SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1176                 status = PVMFPending;
   1177                 //wait on the socket shutdown to complete in HandleSocketEvent callback
   1178             }
   1179             else
   1180             {
   1181                 status = PVMFFailure;
   1182                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartConnectOperation - Shutdown FAILED - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1183             }
   1184         }
   1185         break;
   1186 
   1187         case EPVSocketPortConnectOperation_WaitOnConnectedPort:
   1188             if (aSockConfig.iPVMFPort
   1189                     && aSockConfig.iPVMFPort->IsOutgoingQueueBusy())
   1190             {
   1191 #if(ENABLE_SOCKET_NODE_STATS)
   1192                 aSockConfig.iPortStats.iNumWaitOnConnectedPort++;
   1193                 aSockConfig.iPortStats.StartConnectTime(aSockConfig.iState.iConnectOperation);
   1194 #endif
   1195                 status = PVMFPending;
   1196                 //wait for CONNECTED_PORT_READY event in HandlePortActivity
   1197             }
   1198             else
   1199             {
   1200                 status = PVMFSuccess;//nothing needed.
   1201             }
   1202             break;
   1203 
   1204         case EPVSocketPortConnectOperation_WaitOnSendRecvIdle:
   1205             if (aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None
   1206                     && aSockConfig.iState.iSendOperation == EPVSocketPortSendOperation_None)
   1207             {
   1208                 //send/recv are already idle.
   1209                 status = PVMFSuccess;
   1210             }
   1211             else
   1212             {
   1213 #if(ENABLE_SOCKET_NODE_STATS)
   1214                 aSockConfig.iPortStats.iNumWaitOnSendRecvIdle++;
   1215                 aSockConfig.iPortStats.StartConnectTime(aSockConfig.iState.iConnectOperation);
   1216 #endif
   1217                 status = PVMFPending;
   1218                 //wait for send/recv completion (in RecvOperationComplete or SendOperationComplete)
   1219             }
   1220             break;
   1221 
   1222         default:
   1223             //add code to handle this case
   1224             status = PVMFFailure;
   1225             OSCL_ASSERT(0);
   1226             break;
   1227     }
   1228 
   1229     //Handle synchronous completion or failure.
   1230     if (status != PVMFPending)
   1231         status = ConnectOperationComplete(aSockConfig, status, NULL);
   1232 
   1233     return status;
   1234 }
   1235 
   1236 //The current connect operation is complete.
   1237 //Continue with the next operation, or finish the sequence.
   1238 //The status is in "aStatus".  If there was a socket callback, the result is in "aSocketActivity".
   1239 PVMFStatus PVMFSocketNode::ConnectOperationComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
   1240 {
   1241     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::ConnectOperationComplete() in"));
   1242 
   1243     //status should never be "pending" here
   1244     OSCL_ASSERT(aStatus != PVMFPending);
   1245 
   1246     PVMFStatus status = aStatus;
   1247 
   1248     TPVSocketPortConnectOperation curOp = aSockConfig.iState.iConnectOperation;
   1249     aSockConfig.iState.iConnectOperation = EPVSocketPortConnectOperation_None;
   1250     aSockConfig.iState.iConnectOperationStatus = aStatus;
   1251     aSockConfig.iState.iConnectOperationCanceled = false;
   1252 
   1253 
   1254     switch (curOp)
   1255     {
   1256         case EPVSocketPortConnectOperation_None:
   1257             //unexpected.
   1258             break;
   1259 
   1260         case EPVSocketPortConnectOperation_GetHostByName:
   1261             //TCP Get Host By Name is complete
   1262 
   1263             //catch completion of connect cancel during the cleanup sequence
   1264             if (aSockConfig.iState.iSequence == EPVSocketPortSequence_SocketCleanup)
   1265             {
   1266                 //Continue the shutdown sequence
   1267                 status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Shutdown);
   1268                 break;
   1269             }
   1270             //else normal connect sequence.
   1271 
   1272             if (aStatus == PVMFSuccess)
   1273             {
   1274                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete GetHostByName Success - SockId=%d, Mime=%s Host= %s", aSockConfig.iSockId, aSockConfig.iMime.get_str()
   1275                                                   , aSockConfig.iAddr.iRemoteHost.get_str()));
   1276                 //Save lookup results in the DNS cache
   1277                 if (aSocketActivity)
   1278                 {
   1279                     iDnsCache.UpdateCacheRecord(aSockConfig.iAddr.iRemoteHost.get_str(), (char*)aSockConfig.iAddr.iRemoteAdd.ipAddr.Str());
   1280                 }
   1281 
   1282                 //DNS Lookup is always followed by a Connect
   1283                 status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Connect);
   1284             }
   1285             else
   1286             {
   1287                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete GetHostByName FAILED - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1288                 //If DNS lookup failed, then fail the current sequence with
   1289                 //an error.
   1290                 switch (aSockConfig.iState.iSequence)
   1291                 {
   1292                     case EPVSocketPortSequence_RequestPort:
   1293                         //report the error in the command complete
   1294                         iCommandErrorCode = PVMFSocketNodeError_DNSLookup;
   1295                         break;
   1296                     default:
   1297                         //report the error in an error message
   1298                         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeError_DNSLookup);
   1299                         break;
   1300                 }
   1301                 //Fail the sequence.
   1302                 SequenceComplete(aSockConfig, aStatus);
   1303             }
   1304             break;
   1305 
   1306         case EPVSocketPortConnectOperation_Connect:
   1307             //TCP Connect is complete
   1308 
   1309             //catch completion of connect cancel during the cleanup sequence
   1310             if (aSockConfig.iState.iSequence == EPVSocketPortSequence_SocketCleanup)
   1311             {
   1312                 //Continue the shutdown sequence
   1313                 status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Shutdown);
   1314                 break;
   1315             }
   1316             //else normal connect sequence.
   1317 
   1318             if (aStatus == PVMFSuccess)
   1319             {
   1320                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete Connect Success - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1321             }
   1322             else
   1323             {
   1324                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete Connect FAILED - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1325                 //Report connect errors.
   1326                 switch (aSockConfig.iState.iSequence)
   1327                 {
   1328                     case EPVSocketPortSequence_RequestPort:
   1329                         //for a node command, we report the error in the node command completion message
   1330                         iCommandErrorCode = PVMFSocketNodeError_TCPSocketConnect;
   1331                         break;
   1332                     case EPVSocketPortSequence_InputConnectMsg:
   1333                     default:
   1334                         //for other sequences, we report the error in an error message.
   1335                         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeError_TCPSocketConnect);
   1336                         break;
   1337                 }
   1338             }
   1339             //Connect complete is always the end of a sequence.
   1340             SequenceComplete(aSockConfig, aStatus);
   1341             break;
   1342 
   1343         case EPVSocketPortConnectOperation_Shutdown:
   1344             //TCP Shutdown is complete
   1345 
   1346             if (aStatus == PVMFSuccess)
   1347             {
   1348                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete Shutdown Success - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1349             }
   1350             else
   1351             {
   1352                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::ConnectOperationComplete Shutdown FAILED - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1353                 if (aSocketActivity)
   1354                 {
   1355                     PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::ConnectOperationComplete: ERROR aEvent=%d, Ln %d", aSocketActivity->iEvent, __LINE__));
   1356                 }
   1357             }
   1358 
   1359             //Note: ignore shutdown failures and just continue onto the
   1360             //next operation.
   1361 
   1362             //Shutdown is followed by waiting for send/recv to go idle.
   1363 
   1364             //On most OS the shutdown command is sufficient to cause send/recv to complete,
   1365             //but on some it doesn't, so cancel any outstanding send/recv op here.
   1366             CancelSendOperation(aSockConfig);
   1367             CancelRecvOperation(aSockConfig);
   1368 
   1369             status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_WaitOnSendRecvIdle);
   1370             break;
   1371 
   1372         case EPVSocketPortConnectOperation_WaitOnConnectedPort:
   1373             //TCP Wait on connected port is complete.
   1374 
   1375             //Proceed to send the EOS and close the socket
   1376             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::ConnectOperationComplete WaitOnConnectedPort Calling CleanupTCP - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1377             CleanupTCP(aSockConfig);
   1378 
   1379             //Check the sequence...
   1380             switch (aSockConfig.iState.iSequence)
   1381             {
   1382                 case EPVSocketPortSequence_InputConnectMsg:
   1383                     //a disconnect is followed by a host lookup + connect
   1384                     //for an input connect message
   1385                     status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_GetHostByName);
   1386                     break;
   1387 
   1388                 default:
   1389                     //for all other sequences, this is the end
   1390                     SequenceComplete(aSockConfig, PVMFSuccess);
   1391                     status = PVMFSuccess;
   1392                     break;
   1393             }
   1394             break;
   1395 
   1396         case EPVSocketPortConnectOperation_WaitOnSendRecvIdle:
   1397             //UDP or TCP "Wait on Send/Recv Idle" is complete.
   1398 
   1399             //If TCP, wait on connected port to send EOS
   1400             if (aSockConfig.iTCPSocket)
   1401             {
   1402                 status = StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_WaitOnConnectedPort);
   1403             }
   1404             //If UDP, proceed to close & delete
   1405             else if (aSockConfig.iUDPSocket)
   1406             {
   1407                 CleanupUDP(aSockConfig);
   1408                 //This is the end of the sequence.
   1409                 SequenceComplete(aSockConfig, PVMFSuccess);
   1410                 status = PVMFSuccess;
   1411             }
   1412             else
   1413             {
   1414                 //unexpected, but end the sequence anyway.
   1415                 SequenceComplete(aSockConfig, PVMFSuccess);
   1416                 status = PVMFSuccess;
   1417             }
   1418             break;
   1419 
   1420 
   1421         default:
   1422             OSCL_ASSERT(0);//unexpected, add code for this case.
   1423             break;
   1424     }
   1425     return status;
   1426 }
   1427 
   1428 PVMFStatus PVMFSocketNode::CancelConnectOperation(SocketPortConfig& aSockConfig)
   1429 {
   1430     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::CancelConnectOperation() In"));
   1431 
   1432     PVMFStatus status = PVMFSuccess;
   1433 
   1434     switch (aSockConfig.iState.iConnectOperation)
   1435     {
   1436         case EPVSocketPortConnectOperation_None:
   1437             break;
   1438 
   1439         case EPVSocketPortConnectOperation_GetHostByName:
   1440             if (aSockConfig.iDNS)
   1441             {
   1442                 if (!aSockConfig.iState.iConnectOperationCanceled)
   1443                 {
   1444                     aSockConfig.iState.iConnectOperationCanceled = true;
   1445                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelConnectOperation Calling CancelGetHostByName - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1446                     aSockConfig.iDNS->CancelGetHostByName();
   1447                 }
   1448                 status = PVMFPending;
   1449                 //wait for host lookup to complete in HandleDNSEvent
   1450             }
   1451             break;
   1452 
   1453         case EPVSocketPortConnectOperation_Connect:
   1454             if (aSockConfig.iTCPSocket)
   1455             {
   1456                 if (!aSockConfig.iState.iConnectOperationCanceled)
   1457                 {
   1458                     aSockConfig.iState.iConnectOperationCanceled = true;
   1459                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelConnectOperation Calling CancelConnect - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1460                     aSockConfig.iTCPSocket->CancelConnect();
   1461                 }
   1462                 status = PVMFPending;
   1463                 //wait for connect to complete in HandleSocketEvent
   1464             }
   1465             break;
   1466 
   1467         case EPVSocketPortConnectOperation_Shutdown:
   1468             if (aSockConfig.iTCPSocket)
   1469             {
   1470                 if (!aSockConfig.iState.iConnectOperationCanceled)
   1471                 {
   1472                     aSockConfig.iState.iConnectOperationCanceled = true;
   1473                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelConnectOperation Calling CancelShutdown - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1474                     aSockConfig.iTCPSocket->CancelShutdown();
   1475                 }
   1476                 status = PVMFPending;
   1477                 //wait for shutdown to complete in HandleSocketEvent
   1478             }
   1479             break;
   1480 
   1481         case EPVSocketPortConnectOperation_WaitOnConnectedPort:
   1482             //just clear the state
   1483             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelConnectOperation Cancelling WaitOnConnectedPort - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1484             aSockConfig.iState.iConnectOperation = EPVSocketPortConnectOperation_None;
   1485             break;
   1486 
   1487         case EPVSocketPortConnectOperation_WaitOnSendRecvIdle:
   1488             //just clear the state
   1489             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelConnectOperation Cancelling WaitOnSendRecvIdle - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1490             aSockConfig.iState.iConnectOperation = EPVSocketPortConnectOperation_None;
   1491             break;
   1492 
   1493         default:
   1494             OSCL_ASSERT(0);//add code for this case
   1495             status = PVMFFailure;
   1496             break;
   1497     }
   1498     return status;
   1499 }
   1500 
   1501 //////////////////////////////////////
   1502 // End Connect Operation Handlers
   1503 //////////////////////////////////////
   1504 
   1505 //////////////////////////////////
   1506 // Receive Operation Handlers
   1507 //////////////////////////////////
   1508 
   1509 //Tell if it's possible to initiate a recv or recvfrom operation
   1510 //on this port.
   1511 bool PVMFSocketNode::CanReceive(SocketPortConfig& aSockConfig)
   1512 {
   1513     return
   1514         //node is started
   1515         iInterfaceState == EPVMFNodeStarted
   1516         //port is connected
   1517         && aSockConfig.iPVMFPort && aSockConfig.iPVMFPort->IsConnected()
   1518         //socket exists (gets created during request port or connect sequence)
   1519         && (aSockConfig.iUDPSocket || aSockConfig.iTCPSocket)
   1520         //port is not busy with any sequence other than sending data
   1521         && (aSockConfig.iState.iSequence == EPVSocketPortSequence_None
   1522             || aSockConfig.iState.iSequence == EPVSocketPortSequence_InputDataMsg)
   1523         //port is not busy with any receive operation.
   1524         && aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None
   1525         //there's no node stop going on.
   1526         && iNumStopPortActivityPending < 0;
   1527 }
   1528 
   1529 //Enter the "wait on memory" state
   1530 void PVMFSocketNode::StartRecvWaitOnMemory(SocketPortConfig& aSockConfig, int32 aSize)
   1531 {
   1532     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::StartRecvWaitOnMemory() In"));
   1533 
   1534     aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnMemory;
   1535 
   1536 #if(ENABLE_SOCKET_NODE_STATS)
   1537     aSockConfig.iPortStats.iNumWaitOnMemory++;
   1538     aSockConfig.iPortStats.StartRecvTime(aSockConfig.iState.iRecvOperation);
   1539 #endif
   1540 
   1541     if (aSize)
   1542     {//wait on data buffer
   1543         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvWaitOnMemory, wait on data buffer - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1544         if (aSockConfig.iMemPool->iSharedBufferAlloc)
   1545         {
   1546             aSockConfig.iMemPool->iSharedBufferAlloc->notifyfreeblockavailable(aSockConfig, aSize, NULL);
   1547         }
   1548         else
   1549         {
   1550             if (aSockConfig.iMemPool->iInternalAlloc)
   1551                 aSockConfig.iMemPool->iInternalAlloc->notifyfreeblockavailable(aSockConfig, aSize, NULL);
   1552         }
   1553     }
   1554     else
   1555     {//wait on media data wrapper
   1556         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvWaitOnMemory, wait on data wrapper - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1557         aSockConfig.iMemPool->iMediaDataMemPool->notifyfreechunkavailable(aSockConfig, NULL);
   1558     }
   1559 }
   1560 
   1561 //Enter the "wait on connected port" state
   1562 void PVMFSocketNode::StartRecvWaitOnConnectedPort(SocketPortConfig& aSockConfig, PVMFSocketActivity& aSocketActivity)
   1563 {
   1564     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::StartRecvWaitOnConnectedPort() In"));
   1565 
   1566     //outgoing queue is busy-- must queue this event for later processing
   1567 
   1568     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvWaitOnConnectedPort, wait for connected port - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1569 
   1570     switch (aSocketActivity.iFxn)
   1571     {
   1572         case EPVSocketRecv:
   1573         case EPVSocketRecvFrom:
   1574 #if(ENABLE_SOCKET_NODE_STATS)
   1575             aSockConfig.iPortStats.iNumQueueSocketRecv++;
   1576 #endif
   1577             aSockConfig.iSocketRecvActivity.Set(aSocketActivity.iStatus
   1578                                                 , aSocketActivity.iId
   1579                                                 , aSocketActivity.iFxn
   1580                                                 , aSocketActivity.iEvent
   1581                                                 , aSocketActivity.iError);
   1582             break;
   1583         default:
   1584             OSCL_ASSERT(false);//invalid input arg.
   1585             break;
   1586     }
   1587 
   1588     //current state shoudl be idle
   1589     OSCL_ASSERT(aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None);
   1590 
   1591     aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_WaitOnConnectedPort;
   1592 
   1593 #if(ENABLE_SOCKET_NODE_STATS)
   1594     aSockConfig.iPortStats.iNumWaitOnConnectedPort++;
   1595     aSockConfig.iPortStats.StartRecvTime(aSockConfig.iState.iRecvOperation);
   1596 #endif
   1597 
   1598 }
   1599 
   1600 //Start a receive operation on the port's socket.
   1601 //Assume the caller already verified that the port can receive now.
   1602 //If there is a failure, this routine will call the "recv operation complete" routine to
   1603 //do error handling or continue to the next state.
   1604 PVMFStatus PVMFSocketNode::StartRecvOperation(SocketPortConfig& aSockConfig)
   1605 {
   1606     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::StartRecvOperation() In"));
   1607 
   1608     //caller should have verified we can receive data right now.
   1609     OSCL_ASSERT(aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None);
   1610 
   1611     //there should be either a UDP or TCP socket on this port and a memory pool.
   1612     if (!aSockConfig.iTCPSocket && !aSockConfig.iUDPSocket)
   1613     {
   1614         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartRecvOperation ERROR no socket - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1615         return PVMFFailure;
   1616     }
   1617     if (!aSockConfig.iMemPool)
   1618     {
   1619         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartRecvOperation ERROR no mem pool - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1620         return PVMFFailure;
   1621     }
   1622 
   1623     PVMFStatus status = PVMFFailure;
   1624 
   1625     if (aSockConfig.iUDPSocket)
   1626     {
   1627         aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_RecvFrom;
   1628 
   1629         //Create the memory buffer
   1630 
   1631         int32 memSize;
   1632         int32 multiRecvLimitBytes = 0;
   1633         switch (aSockConfig.iMemPool->iPortTag)
   1634         {
   1635             case PVMF_SOCKET_NODE_PORT_TYPE_SOURCE:
   1636                 //source tag is used for RTP
   1637 #if SNODE_ENABLE_UDP_MULTI_PACKET
   1638                 //must allocate enough space for the max bytes per receive plus
   1639                 //one more max size packet, since we can't peek ahead to see
   1640                 //how much data is on the socket.
   1641                 memSize = SNODE_UDP_MULTI_MAX_BYTES_PER_RECV + MAX_UDP_PACKET_SIZE;
   1642                 //this is the amt of "free space" required to continue receiving
   1643                 //additional packets. Use the max packet size to avoid truncated
   1644                 //packets.
   1645                 multiRecvLimitBytes = MAX_UDP_PACKET_SIZE;
   1646 #else
   1647                 //for single packet recvs.
   1648                 memSize = MAX_UDP_PACKET_SIZE;
   1649 #endif
   1650                 break;
   1651             case PVMF_SOCKET_NODE_PORT_TYPE_SINK:
   1652                 //sink tag is used for RTCP
   1653             default:
   1654                 memSize = MAX_FEEDBACK_SOCKET_BUFFER_SIZE;
   1655                 break;
   1656         }
   1657 
   1658         //Socket node provides the buffer to receive the data on the socket
   1659         //Socket node gets this from the mem pool.
   1660         //It may be possible that socket node may not be able to get the
   1661         //buffer of required size from the mempool
   1662         //If we are not able to get the packets from the OS, then the packets
   1663         //received from server will eventually be lost.
   1664         //In general, streaming server will be sending the UDP packets of small size
   1665         //(say 2048 bytes.. = MIN_UDP_PACKET_SIZE)
   1666         //So its better to attempt to allocate the memory of size
   1667         //SNODE_UDP_MULTI_MIN_BYTES_PER_RECV + MIN_UDP_PACKET_SIZE/MIN_UDP_PACKET_SIZE
   1668         //in such cases.
   1669 
   1670         const int32 largestMediaMsgSz = aSockConfig.iMemPool->GetMaxSizeMediaMsgLen();
   1671 
   1672         PVMF_SOCKETNODE_LOGINFO((0, "PVMFSocketNode::StartRecvOperation - MaxSizeMediMsg  %d memSize %d", largestMediaMsgSz, memSize));
   1673 
   1674         if (memSize > largestMediaMsgSz)
   1675         {
   1676 #if SNODE_ENABLE_UDP_MULTI_PACKET
   1677             multiRecvLimitBytes = MIN_UDP_PACKET_SIZE;
   1678 
   1679             const int32 minBufferToContinueRecv = (SNODE_UDP_MULTI_MIN_BYTES_PER_RECV + MIN_UDP_PACKET_SIZE);
   1680 
   1681             if (largestMediaMsgSz >= minBufferToContinueRecv)
   1682             {
   1683                 memSize = largestMediaMsgSz;
   1684             }
   1685             else
   1686             {
   1687                 memSize = minBufferToContinueRecv;
   1688             }
   1689 #else
   1690             if (largestMediaMsgSz >= MIN_UDP_PACKET_SIZE)
   1691             {
   1692                 memSize = largestMediaMsgSz;
   1693             }
   1694             else
   1695             {
   1696                 memSize = MIN_UDP_PACKET_SIZE;
   1697             }
   1698 #endif
   1699             PVMF_SOCKETNODE_LOGINFO((0, "PVMFSocketNode::StartRecvOperation - Resizing Mem Request Attributes## NewSz %d recvLimitBytes %d", memSize, multiRecvLimitBytes));
   1700         }
   1701 
   1702         //Create the media data impl.
   1703         int32 err;
   1704         OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl;
   1705         err = GetMediaDataImpl(aSockConfig, mediaDataImpl, memSize);
   1706         if (err != OsclErrNone)
   1707         {
   1708             StartRecvWaitOnMemory(aSockConfig, memSize);
   1709             status = PVMFPending;
   1710             //wait on memory pool callback "notifyfreechunkavailable"
   1711             goto Exit;
   1712         }
   1713 
   1714         //Create the media data buffer.
   1715         err = CreateMediaData(aSockConfig, mediaDataImpl);
   1716         if (err != OsclErrNone)
   1717         {
   1718             StartRecvWaitOnMemory(aSockConfig);
   1719             status = PVMFPending;
   1720             //wait on memory pool callback "notifyfreechunkavailable"
   1721             goto Exit;
   1722         }
   1723 
   1724         // Retrieve memory fragment to write to
   1725         OsclRefCounterMemFrag refCtrMemFragOut;
   1726         aSockConfig.iPendingRecvMediaData->getMediaFragment(0, refCtrMemFragOut);
   1727 
   1728         //Issue the Oscl socket request
   1729 
   1730 #if(ENABLE_SOCKET_NODE_STATS)
   1731         aSockConfig.iPortStats.iNumRecvFrom++;
   1732         aSockConfig.iPortStats.StartRecvTime(EPVSocketPortRecvOperation_RecvFrom);
   1733 #endif
   1734 
   1735         TPVSocketEvent retVal = aSockConfig.iUDPSocket->RecvFrom((uint8*)refCtrMemFragOut.getMemFragPtr()
   1736                                 , refCtrMemFragOut.getCapacity()
   1737                                 , aSockConfig.iSourceAddr
   1738                                 , TIMEOUT_RECVFROM
   1739                                 , multiRecvLimitBytes
   1740                                 , &aSockConfig.iRecvFromPacketLen);
   1741 
   1742         if (EPVSocketPending != retVal)
   1743         {
   1744             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::RecvFrom() failed retVal=%d Ln %d", retVal, __LINE__));
   1745             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvOperation RecvFrom FAILED - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1746             status = PVMFFailure;
   1747             goto Exit;
   1748         }
   1749         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvOperation RecvFrom Pending - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1750         status = PVMFPending;
   1751         //wait on the socket callback HandleSocketEvent
   1752     }
   1753 
   1754     else if (aSockConfig.iTCPSocket)
   1755     {
   1756         aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_Recv;
   1757 
   1758         //Allocate memory
   1759         int32 err;
   1760         OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl;
   1761         mediaDataImpl = aSockConfig.iMemPool->getMediaDataImpl(iMaxTcpRecvBufferSize);
   1762         if (NULL == mediaDataImpl.GetRep())
   1763         {
   1764             StartRecvWaitOnMemory(aSockConfig, iMaxTcpRecvBufferSize);
   1765             status = PVMFPending;
   1766             //wait on memory pool callback "notifyfreechunkavailable"
   1767             goto Exit;
   1768         }
   1769 
   1770         OSCL_TRY(err,
   1771                  aSockConfig.iPendingRecvMediaData = PVMFMediaData::createMediaData(mediaDataImpl, aSockConfig.iMemPool->iMediaDataMemPool););
   1772         if (err != OsclErrNone)
   1773         {
   1774             StartRecvWaitOnMemory(aSockConfig);
   1775             status = PVMFPending;
   1776             //wait on memory pool callback "notifyfreechunkavailable"
   1777             goto Exit;
   1778         }
   1779 
   1780         // Retrieve memory fragment to write to
   1781         OsclRefCounterMemFrag refCtrMemFragOut;
   1782         aSockConfig.iPendingRecvMediaData->getMediaFragment(0, refCtrMemFragOut);
   1783 
   1784         //Issue the Oscl socket request.
   1785 
   1786 #if(ENABLE_SOCKET_NODE_STATS)
   1787         aSockConfig.iPortStats.iNumRecv++;
   1788         aSockConfig.iPortStats.StartRecvTime(EPVSocketPortRecvOperation_Recv);
   1789 #endif
   1790 
   1791         TPVSocketEvent retVal = aSockConfig.iTCPSocket->Recv((uint8*)refCtrMemFragOut.getMemFragPtr()
   1792                                 , refCtrMemFragOut.getCapacity()
   1793                                 , TIMEOUT_RECV);
   1794         if (EPVSocketPending != retVal)
   1795         {
   1796             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::Recv() failed retVal=%d Ln %d", retVal, __LINE__));
   1797             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartRecvOperation Recv FAILED - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1798             status = PVMFFailure;
   1799             goto Exit;
   1800         }
   1801         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartRecvOperation Recv Pending - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1802         status = PVMFPending;
   1803         //wait on HandleSocketEvent callback.
   1804     }
   1805     else
   1806     {
   1807         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartRecvOperation() Unexpected error, no socket"));
   1808     }
   1809 
   1810 Exit:
   1811     //Handle synchronous completion or failure.
   1812 
   1813     if (status != PVMFPending
   1814             && status != PVMFFailure)
   1815     {
   1816         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartRecvOperation: Error. status=%d", status));
   1817     }
   1818 
   1819     if (status != PVMFPending)
   1820         status = RecvOperationComplete(aSockConfig, status, NULL);
   1821 
   1822     return status;
   1823 }
   1824 
   1825 //The current recv operation is complete.  Process the result and continue with the next operation.
   1826 //The status is in "aStatus".
   1827 //If there was a socket callback, the result is in "aSocketActivity".
   1828 PVMFStatus PVMFSocketNode::RecvOperationComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
   1829 {
   1830     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::RecvOperationComplete() In"));
   1831 
   1832     //status should never be pending here
   1833     OSCL_ASSERT(aStatus != PVMFPending);
   1834 
   1835     PVMFStatus status = aStatus;
   1836     bool recvOperationCanceled = aSockConfig.iState.iRecvOperationCanceled;
   1837 
   1838     //Update the state
   1839     TPVSocketPortRecvOperation curOp = aSockConfig.iState.iRecvOperation;
   1840     aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_None;
   1841     aSockConfig.iState.iRecvOperationStatus = aStatus;
   1842     aSockConfig.iState.iRecvOperationCanceled = false;
   1843 
   1844     switch (curOp)
   1845     {
   1846         case EPVSocketPortRecvOperation_WaitOnMemory:
   1847             //a memory wait is complete.
   1848             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::RecvOperationComplete WaitOnMemory - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1849             break;
   1850 
   1851         case EPVSocketPortRecvOperation_WaitOnConnectedPort:
   1852             //a port wait is complete
   1853             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::RecvOperationComplete WaitOnConnectedPort - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1854 
   1855             //there may be a prior recv or recvfrom result that was waiting on this
   1856             if (aSockConfig.iSocketRecvActivity.iValid)
   1857             {
   1858                 aSockConfig.iSocketRecvActivity.iValid = false;
   1859 
   1860                 switch (aSockConfig.iSocketRecvActivity.iFxn)
   1861                 {
   1862                     case EPVSocketRecv:
   1863                         HandleRecvComplete(aSockConfig
   1864                                            , aSockConfig.iSocketRecvActivity.iStatus
   1865                                            , &aSockConfig.iSocketRecvActivity, recvOperationCanceled);
   1866                         break;
   1867                     case EPVSocketRecvFrom:
   1868                         HandleRecvFromComplete(aSockConfig
   1869                                                , aSockConfig.iSocketRecvActivity.iStatus
   1870                                                , &aSockConfig.iSocketRecvActivity, recvOperationCanceled);
   1871                         break;
   1872                     default:
   1873                         OSCL_ASSERT(0);//invalid arg
   1874                         break;
   1875                 }
   1876             }
   1877             break;
   1878 
   1879         case EPVSocketPortRecvOperation_Recv:
   1880             //TCP receive is complete
   1881             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::RecvOperationComplete Recv - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1882 
   1883             HandleRecvComplete(aSockConfig, aStatus, aSocketActivity, recvOperationCanceled);
   1884             break;
   1885 
   1886         case EPVSocketPortRecvOperation_RecvFrom:
   1887             //UDP receive from is complete
   1888             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::RecvOperationComplete RecvFrom - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1889 
   1890             HandleRecvFromComplete(aSockConfig, aStatus, aSocketActivity, recvOperationCanceled);
   1891             break;
   1892 
   1893         default:
   1894             OSCL_ASSERT(0);//add code for this case
   1895             break;
   1896     }
   1897 
   1898     //Receive may have been blocked waiting on this operation to complete,
   1899     //so start/resume receives now if possible
   1900     if (CanReceive(aSockConfig))
   1901         status = StartRecvOperation(aSockConfig);
   1902 
   1903     //Detect connect "Wait on send/recv idle" complete
   1904     if (aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_WaitOnSendRecvIdle
   1905             && aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None
   1906             && aSockConfig.iState.iSendOperation == EPVSocketPortSendOperation_None)
   1907     {
   1908         ConnectOperationComplete(aSockConfig, PVMFSuccess, NULL);
   1909     }
   1910 
   1911     return status;
   1912 }
   1913 
   1914 //Cancel any current receive operation.
   1915 //Return Success if the operation is canceled or Pending if we need to wait.
   1916 PVMFStatus PVMFSocketNode::CancelRecvOperation(SocketPortConfig& aSockConfig)
   1917 {
   1918     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::CancelRecvOperation() In"));
   1919 
   1920     PVMFStatus status = PVMFSuccess;
   1921 
   1922     switch (aSockConfig.iState.iRecvOperation)
   1923     {
   1924         case EPVSocketPortRecvOperation_None:
   1925             break;
   1926 
   1927         case EPVSocketPortRecvOperation_Recv:
   1928             if (aSockConfig.iTCPSocket)
   1929             {
   1930                 if (!aSockConfig.iState.iRecvOperationCanceled)
   1931                 {
   1932                     aSockConfig.iState.iRecvOperationCanceled = true;
   1933                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelRecvOperation Calling CancelRecv - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1934                     aSockConfig.iTCPSocket->CancelRecv();
   1935                 }
   1936                 status = PVMFPending;
   1937                 //wait on recv to complete in HandleSocketEvent
   1938             }
   1939             break;
   1940 
   1941         case EPVSocketPortRecvOperation_RecvFrom:
   1942             if (aSockConfig.iUDPSocket)
   1943             {
   1944                 if (!aSockConfig.iState.iRecvOperationCanceled)
   1945                 {
   1946                     aSockConfig.iState.iRecvOperationCanceled = true;
   1947                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelRecvOperation Calling CancelRecvFrom - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1948                     aSockConfig.iUDPSocket->CancelRecvFrom();
   1949                 }
   1950                 status = PVMFPending;
   1951                 //wait on recvfrom to complete in HandleSocketEvent
   1952             }
   1953             break;
   1954 
   1955         case EPVSocketPortRecvOperation_WaitOnConnectedPort:
   1956             //just clear the state
   1957             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelRecvOperation Cancelling WaitOnConnectedPort - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1958             aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_None;
   1959             //also discard the received data and the associated recv activity
   1960             if (aSockConfig.iSocketRecvActivity.iValid)
   1961                 aSockConfig.iSocketRecvActivity.iValid = false;
   1962             if (aSockConfig.iPendingRecvMediaData.GetRep())
   1963                 aSockConfig.iPendingRecvMediaData.Unbind();
   1964             break;
   1965 
   1966         case EPVSocketPortRecvOperation_WaitOnMemory:
   1967             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelRecvOperation Cancelling WaitOnMemory - SockId=%d, Mime=%s ", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   1968             if (aSockConfig.iMemPool != NULL)
   1969             {
   1970                 if (aSockConfig.iMemPool->iInternalAlloc)
   1971                     aSockConfig.iMemPool->iInternalAlloc->CancelFreeChunkAvailableCallback();
   1972                 if (aSockConfig.iMemPool->iSharedBufferAlloc)
   1973                     aSockConfig.iMemPool->iSharedBufferAlloc->CancelFreeChunkAvailableCallback();
   1974             }
   1975             //clear the state
   1976             aSockConfig.iState.iRecvOperation = EPVSocketPortRecvOperation_None;
   1977             break;
   1978 
   1979         default:
   1980             OSCL_ASSERT(0);//add code for this case
   1981             status = PVMFFailure;
   1982             break;
   1983     }
   1984     return status;
   1985 }
   1986 
   1987 //a memory pool callback
   1988 void SocketPortConfig::freechunkavailable(OsclAny* aContextData)
   1989 {
   1990 #if(ENABLE_SOCKET_NODE_STATS)
   1991     iPortStats.iNumFreeChunkCallback++;
   1992 #endif
   1993     OSCL_UNUSED_ARG(aContextData);
   1994 
   1995     //complete the "wait on memory" state
   1996     if (iState.iRecvOperation == EPVSocketPortRecvOperation_WaitOnMemory)
   1997     {
   1998 #if(ENABLE_SOCKET_NODE_STATS)
   1999         iPortStats.EndRecvTime(iState.iRecvOperation);
   2000 #endif
   2001         iContainer->RecvOperationComplete(*this, PVMFSuccess, NULL);
   2002     }
   2003 }
   2004 
   2005 void SocketPortConfig::freeblockavailable(OsclAny* aContextData)
   2006 {
   2007     freechunkavailable(aContextData);
   2008 }
   2009 
   2010 //Handler for a "recv" complete.  This handles two input cases:
   2011 // - Operation failed to initiate.  Status will be in aStatus and aSocketActivity will be NULL.
   2012 // - Operation completed asynchronously via HandleSocketEvent callback. Status will be in aStatus
   2013 //   and socket callback result will be in aSocketActivity.
   2014 //
   2015 //The end result of processing will be one of the following:
   2016 // - Received data sent to connected port
   2017 // - Result queued on socket activity queue for later processing.
   2018 // - Error or cancellation processed.
   2019 void PVMFSocketNode::HandleRecvComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity, bool aRecvOperationCanceled)
   2020 {
   2021     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::HandleRecvComplete() In"));
   2022 
   2023     //operation should be complete when this is called.
   2024     OSCL_ASSERT(aStatus != PVMFPending);
   2025 
   2026 
   2027     int32 sockActivityEvent = aSocketActivity->iEvent;
   2028     PVMFStatus status = aStatus;
   2029 
   2030     int32 tmplen;
   2031     aSockConfig.iTCPSocket->GetRecvData(&tmplen);
   2032 
   2033     // If data length is <= zero and aSocketActivity->iEvent is EPVSocketSuccess, it should be treated as failure.
   2034     // On some platforms, its possible to get data length as zero and aSocketActivity->iEvent as EPVSocketSuccess.
   2035     if (EPVSocketSuccess == sockActivityEvent && tmplen <= 0)
   2036     {
   2037         PVMF_SOCKETNODE_LOGINFO((0, "PVMFSocketNode::HandleRecvFromComplete() Sucessful Recv With Zero Length. Treating as failure."));
   2038 
   2039         sockActivityEvent = EPVSocketFailure;
   2040         status = PVMFFailure;
   2041     }
   2042 
   2043     //If there's no socket activity input, then this must be a failure in initiating
   2044     //a Recv operation.
   2045     if (!aSocketActivity)
   2046     {
   2047         OSCL_ASSERT(status != PVMFSuccess);
   2048         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: Request Failed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2049         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   2050         //release media data
   2051         if (aSockConfig.iPendingRecvMediaData.GetRep())
   2052             aSockConfig.iPendingRecvMediaData.Unbind();
   2053         return;
   2054     }
   2055 
   2056     //Otherwise this is a result from Oscl Sockets of a Recv call.
   2057 
   2058     //See whether we can send this data to the connected port
   2059     if (sockActivityEvent == EPVSocketSuccess)
   2060     {
   2061         if (!aSockConfig.iPVMFPort
   2062                 || !aSockConfig.iPVMFPort->IsConnected())
   2063         {
   2064             //port already disconnected-- just discard the data
   2065             if (aSockConfig.iPendingRecvMediaData.GetRep())
   2066                 aSockConfig.iPendingRecvMediaData.Unbind();
   2067             return;
   2068         }
   2069         if (aSockConfig.iPVMFPort->IsOutgoingQueueBusy())
   2070         {
   2071             //wait on port so we can send recv data.
   2072             StartRecvWaitOnConnectedPort(aSockConfig, *aSocketActivity);
   2073             return;
   2074         }
   2075     }
   2076 
   2077     //If we get here then it's time to process the recv result.
   2078 
   2079     //Release media data on failure
   2080     if (status != PVMFSuccess)
   2081     {
   2082         if (aSockConfig.iPendingRecvMediaData.GetRep())
   2083             aSockConfig.iPendingRecvMediaData.Unbind();
   2084     }
   2085 
   2086     switch (sockActivityEvent)
   2087     {
   2088         case EPVSocketSuccess:
   2089         {
   2090             //Get data length and set media buffer size
   2091             int32 len;
   2092             aSockConfig.iTCPSocket->GetRecvData(&len);
   2093             aSockConfig.iPendingRecvMediaData->setMediaFragFilledLen(0, len);
   2094 
   2095             // Resize the buffer
   2096             if (aSockConfig.iMemPool)
   2097             {
   2098                 OsclSharedPtr<PVMFMediaDataImpl> mediaMsgImpl;
   2099                 aSockConfig.iPendingRecvMediaData->getMediaDataImpl(mediaMsgImpl);
   2100                 aSockConfig.iMemPool->resizeSocketDataBuffer(mediaMsgImpl);
   2101             }
   2102             else
   2103             {
   2104                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleRecvComplete() ERROR:mempool not found"));
   2105                 OSCL_ASSERT(0);
   2106                 return ;
   2107             }
   2108 
   2109             // set system time as timestamp
   2110             TimeValue currentTime;
   2111             currentTime.set_to_current_time();
   2112             int32 currentMilliSec = currentTime.to_msec();
   2113             aSockConfig.iPendingRecvMediaData->setTimestamp((PVMFTimestamp)currentMilliSec);
   2114 
   2115             //queue to next port
   2116             PVMFSharedMediaMsgPtr aMediaMsgPtr;
   2117             convertToPVMFMediaMsg(aMediaMsgPtr, aSockConfig.iPendingRecvMediaData);
   2118 
   2119 #if(ENABLE_SOCKET_NODE_STATS)
   2120             aSockConfig.iPortStats.iNumQueueOutgoingTCPMsg++;
   2121 #endif
   2122             PVMFStatus status = aSockConfig.iPVMFPort->QueueOutgoingMsg(aMediaMsgPtr);
   2123             if (status != PVMFSuccess)
   2124             {
   2125                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: QueueOutgoingMsg Failed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2126                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleRecvComplete() ERROR:%d, Outgoing queue size=%d. Data discarded!", status, aSockConfig.iPVMFPort->OutgoingMsgQueueSize()));
   2127                 ReportErrorEvent(PVMFErrPortProcessing);
   2128                 return ;
   2129             }
   2130 
   2131             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::HandleRecvComplete: Request Succcess  - SockId=%d, Mime=%s, Len=%d", aSockConfig.iSockId, aSockConfig.iMime.get_str(), len));
   2132         }
   2133         break;
   2134 
   2135         case EPVSocketTimeout:
   2136         {
   2137             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: Request TimedOut - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2138             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleRecvComplete() ERROR EPVSocketTimeout Ln %d", __LINE__));
   2139             ReportSocketNodeError(PVMFErrTimeout, PVMFSocketNodeErrorSocketTimeOut);
   2140         }
   2141         break;
   2142 
   2143         case EPVSocketCancel:
   2144             //On some OS we may get EPVSocketCancel for recv failures, so check whether this
   2145             //was response to a cancel command or not.
   2146             if (aRecvOperationCanceled)
   2147             {
   2148                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: Request Cancelled - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2149                 PVMF_SOCKETNODE_LOGINFO((0, "PVMFSocketNode::HandleRecvComplete() EPVSocketCancel"));
   2150                 break;
   2151             }
   2152             //else fallthrough to the failure processing...
   2153         case EPVSocketFailure:
   2154         {
   2155             //After a receive failure, we may need to do a TCP shutdown.
   2156             //Check what else is currently happening on the port.
   2157             switch (aSockConfig.iState.iSequence)
   2158             {
   2159                 case EPVSocketPortSequence_RequestPort:
   2160                 case EPVSocketPortSequence_InputConnectMsg:
   2161                 case EPVSocketPortSequence_InputDisconnectMsg:
   2162                 case EPVSocketPortSequence_SocketCleanup:
   2163                     //some of these conditions may be impossible, but in any case,
   2164                     //it doesn't make sense to start a shutdown sequence during
   2165                     //any of these.  Ignore the error.
   2166                     PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: Request Failed, ignoring - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2167                     break;
   2168 
   2169                 case EPVSocketPortSequence_None:
   2170                 case EPVSocketPortSequence_InputDataMsg:
   2171                     //for these cases, start a shutdown sequence
   2172                     PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvComplete: Request Failed, starting shutdown sequence - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2173 
   2174                     //start the sequence
   2175                     StartSequence(aSockConfig, EPVSocketPortSequence_SocketCleanup);
   2176                     break;
   2177 
   2178                 default:
   2179                     //need code to handle this case.
   2180                     OSCL_ASSERT(0);
   2181                     break;
   2182             }
   2183         }
   2184         break;
   2185 
   2186         default:
   2187             OSCL_ASSERT(0);
   2188             break;
   2189     }
   2190 }
   2191 
   2192 //Handler for a "recv from" complete.  This handles two input cases:
   2193 // - Operation failed to initiate.  Status will be in aStatus and aSocketActivity will be NULL.
   2194 // - Operation completed asynchronously via HandleSocketEvent callback. Status will be in aStatus
   2195 //   and socket callback result will be in aSocketActivity.
   2196 //
   2197 //The end result of processing will be one of the following:
   2198 // - Received data sent to connected port
   2199 // - Result queued on socket activity queue for later processing.
   2200 // - Error or cancellation processed.
   2201 void PVMFSocketNode::HandleRecvFromComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity, bool aRecvOperationCanceled)
   2202 {
   2203     OSCL_UNUSED_ARG(aStatus);
   2204     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::HandleRecvFromComplete() In"));
   2205 
   2206     //operation should be complete when this is called.
   2207     OSCL_ASSERT(aStatus != PVMFPending);
   2208 
   2209     //If there's no socket activity input, then this must be a failure in initiating
   2210     //a RecvFrom operation.
   2211     if (!aSocketActivity)
   2212     {
   2213         OSCL_ASSERT(aStatus != PVMFSuccess);
   2214         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Request Failed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2215         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   2216         //release media data
   2217         if (aSockConfig.iPendingRecvMediaData.GetRep())
   2218             aSockConfig.iPendingRecvMediaData.Unbind();
   2219         return;
   2220     }
   2221 
   2222     //Otherwise this is a result from Oscl Sockets of a RecvFrom call.
   2223 
   2224     //Handle "truncated packet" error, in which case we still have data even though
   2225     //the result is EPVSocketFailure.
   2226     int32 dataLen = 0;
   2227     uint8* dataPtr = NULL;
   2228     if (aSocketActivity->iEvent == EPVSocketFailure
   2229             || aSocketActivity->iEvent == EPVSocketSuccess)
   2230     {
   2231         if (aSockConfig.iUDPSocket)
   2232             dataPtr = aSockConfig.iUDPSocket->GetRecvData(&dataLen);
   2233 #if(ENABLE_SOCKET_NODE_STATS)
   2234         aSockConfig.iPortStats.iNumRecvFromPackets += aSockConfig.iRecvFromPacketLen.size();
   2235         if (aSockConfig.iRecvFromPacketLen.size() > aSockConfig.iPortStats.iMaxRecvFromPackets)
   2236             aSockConfig.iPortStats.iMaxRecvFromPackets = aSockConfig.iRecvFromPacketLen.size();
   2237 #endif
   2238     }
   2239 
   2240     //Handle cases where we got some data
   2241     if (dataLen > 0)
   2242     {
   2243         //See if we can pass this data along to the connected port.  If not, then queue the
   2244         //result for later processing.
   2245         if (aSockConfig.iPVMFPort->IsOutgoingQueueBusy())
   2246         {
   2247             //outgoing queue is busy-- must queue this for later.
   2248             StartRecvWaitOnConnectedPort(aSockConfig, *aSocketActivity);
   2249         }
   2250         else
   2251         {
   2252             //report truncated packet.
   2253             if (aSocketActivity->iEvent == EPVSocketFailure)
   2254             {
   2255                 PVUuid eventuuid = PVMFSocketNodeEventTypeUUID;
   2256                 int32 infocode = PVMFSocketNodeInfoEventPacketTruncated;
   2257                 ReportInfoEvent(PVMFErrCorrupt, NULL, &eventuuid, &infocode);
   2258             }
   2259 
   2260             //set the media buffer size.
   2261             aSockConfig.iPendingRecvMediaData->setMediaFragFilledLen(0, dataLen);
   2262 
   2263             //resize the buffer.
   2264             if (aSockConfig.iMemPool)
   2265             {
   2266                 OsclSharedPtr<PVMFMediaDataImpl> mediaMsgImpl;
   2267                 aSockConfig.iPendingRecvMediaData->getMediaDataImpl(mediaMsgImpl);
   2268                 aSockConfig.iMemPool->resizeSocketDataBuffer(mediaMsgImpl);
   2269             }
   2270             else
   2271             {
   2272                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketNode::HandleRecvFromComplete() ERROR:mempool not found"));
   2273                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: ERROR mempool not found - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2274                 return;//unexpected, cleanup
   2275             }
   2276 
   2277 #if SNODE_ENABLE_UDP_MULTI_PACKET
   2278             //The media buffer may contain multiple UDP packets.  We need to
   2279             //re-package these into a media frag group.
   2280 
   2281             //Allocate a new media frag group.
   2282             int32 err;
   2283             OsclSharedPtr< PVMFMediaDataImpl > mediaFragGroup;
   2284             err = Allocate(aSockConfig, mediaFragGroup);
   2285             if (err != OsclErrNone)
   2286             {
   2287                 //Unexpected error.  With current usage by JB node, this pool should
   2288                 //never run out.
   2289                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Unexpected mempool error - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2290                 ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   2291                 //release media data
   2292                 if (aSockConfig.iPendingRecvMediaData.GetRep())
   2293                     aSockConfig.iPendingRecvMediaData.Unbind();
   2294                 return;
   2295             }
   2296 
   2297             //get the single frag data buffer pointer.
   2298             OsclRefCounterMemFrag singleFrag;
   2299             aSockConfig.iPendingRecvMediaData->getMediaFragment(0, singleFrag);
   2300 
   2301             for (uint32 i = 0; i < aSockConfig.iRecvFromPacketLen.size(); dataPtr += aSockConfig.iRecvFromPacketLen[i++])
   2302             {
   2303                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::HandleRecvFromComplete: Fragment %d Len %d - SockId=%d, Mime=%s"
   2304                                                   , i, aSockConfig.iRecvFromPacketLen[i], aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2305                 //Create a new fragment with the existing refcount
   2306                 //and the proper packet boundaries.
   2307                 OsclRefCounterMemFrag multiFrag(singleFrag);
   2308                 //now adjust the single frag to the actual packet boundary.
   2309                 multiFrag.getMemFrag().ptr = dataPtr;
   2310                 multiFrag.getMemFrag().len = aSockConfig.iRecvFromPacketLen[i];
   2311                 mediaFragGroup->appendMediaFragment(multiFrag);
   2312 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
   2313                 if (aSockConfig.iRTP)
   2314                 {
   2315                     LogRTPHeaderFields(aSockConfig, multiFrag);
   2316                 }
   2317                 else if (aSockConfig.iRTCP)
   2318                 {
   2319                     LogRTCPHeaderFields(aSockConfig, multiFrag);
   2320                 }
   2321 #endif
   2322             }
   2323 
   2324             //Replace the original media data message with the new one.
   2325             //since we've linked the new frags to the original refcounter, we
   2326             //can just unbind the current message then re-allocate it with the
   2327             //new data.
   2328             aSockConfig.iPendingRecvMediaData.Unbind();
   2329             err = CreateMediaData(aSockConfig, mediaFragGroup);
   2330             if (err != OsclErrNone)
   2331             {
   2332                 //unexpected since we just freed one message
   2333                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Unexpected mempool error - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2334                 ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   2335                 return;
   2336             }
   2337 
   2338 #else //SNODE_ENABLE_UDP_MULTI_PACKET
   2339 
   2340 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
   2341             if (aSockConfig.iRTP)
   2342             {
   2343                 OsclRefCounterMemFrag memfrag;
   2344                 aSockConfig.iPendingRecvMediaData->getMediaFragment(0, memfrag);
   2345                 LogRTPHeaderFields(aSockConfig, memfrag);
   2346             }
   2347             else if (aSockConfig.iRTCP)
   2348             {
   2349                 OsclRefCounterMemFrag memfrag;
   2350                 aSockConfig.iPendingRecvMediaData->getMediaFragment(0, memfrag);
   2351                 LogRTCPHeaderFields(aSockConfig, memfrag);
   2352             }
   2353 #endif
   2354 
   2355 #endif //SNODE_ENABLE_UDP_MULTI_PACKET
   2356 
   2357             //push the received data to the connected port
   2358             PVMFSharedMediaMsgPtr mediaMsgPtr;
   2359             convertToPVMFMediaMsg(mediaMsgPtr, aSockConfig.iPendingRecvMediaData);
   2360 
   2361 #if(ENABLE_SOCKET_NODE_STATS)
   2362             aSockConfig.iPortStats.iNumQueueOutgoingUDPMsg++;
   2363 #endif
   2364             PVMFStatus status = aSockConfig.iPVMFPort->QueueOutgoingMsg(mediaMsgPtr);
   2365             if (status != PVMFSuccess)
   2366             {
   2367                 //should never get here because we already checked outgoign queue earlier.
   2368                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleRecvFromComplete() ERROR:%d, Outgoing queue size=%d. Data discarded!", status, aSockConfig.iPVMFPort->OutgoingMsgQueueSize()));
   2369                 ReportErrorEvent(PVMFInfoOverflow);
   2370             }
   2371 
   2372             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::HandleRecvFromComplete: Request Succcess - SockId=%d, Mime=%s, Len=%d", aSockConfig.iSockId, aSockConfig.iMime.get_str(), dataLen));
   2373         }
   2374     }
   2375     else
   2376     {
   2377         //handle error, cancel, and timeout cases.
   2378 
   2379         //release media data.
   2380         if (aSockConfig.iPendingRecvMediaData.GetRep())
   2381             aSockConfig.iPendingRecvMediaData.Unbind();
   2382 
   2383         //report error events.
   2384         switch (aSocketActivity->iEvent)
   2385         {
   2386             case EPVSocketCancel:
   2387                 //On some OS we may get EPVSocketCancel for recv failures, so check whether this
   2388                 //was response to a cancel command or not.
   2389                 if (aRecvOperationCanceled)
   2390                 {
   2391                     PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Request Cancelled - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2392                     break;
   2393                 }
   2394                 //else fallthrough to failure processing...
   2395             case EPVSocketFailure:
   2396                 //report RTP failures.
   2397                 //Note: do not report RTCP errors, because some servers send zero-byte packets
   2398                 //and we want to be tolerant of that case.
   2399                 if (aSockConfig.iTag == PVMF_SOCKET_NODE_PORT_TYPE_SOURCE)
   2400                 {
   2401                     PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Request Failed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2402                     ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorSocketFailure);
   2403                 }
   2404                 break;
   2405 
   2406             case EPVSocketTimeout:
   2407             {
   2408                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::HandleRecvFromComplete: Request TimedOut - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2409                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleRecvFromComplete() ERROR EPVSocketTimeout Ln %d", __LINE__));
   2410                 ReportSocketNodeError(PVMFErrTimeout, PVMFSocketNodeErrorSocketTimeOut);
   2411             }
   2412             break;
   2413 
   2414             default:
   2415                 break;
   2416         }
   2417     }
   2418 }
   2419 
   2420 //////////////////////////////////
   2421 // End Receive Operation Handlers
   2422 //////////////////////////////////
   2423 
   2424 
   2425 //////////////////////////////////
   2426 // Send Operation Handlers
   2427 //////////////////////////////////
   2428 
   2429 
   2430 //Start a send operation on the port's socket.
   2431 //Assume the caller already verified that the port can send now.
   2432 //If there is a failure, this routine will call the "send operation complete" routine to
   2433 //do error handling or continue to the next state.
   2434 PVMFStatus PVMFSocketNode::StartSendOperation(SocketPortConfig& aSockConfig, PVMFSharedMediaMsgPtr& aMsg)
   2435 {
   2436     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::StartSendOperation() In"));
   2437 
   2438     //caller should have verified we can send now.
   2439     OSCL_ASSERT(aSockConfig.iState.iSendOperation == EPVSocketPortSendOperation_None);
   2440 
   2441     //caller should provide a media data message as input
   2442     OSCL_ASSERT(aMsg->getFormatID() == PVMF_MEDIA_MSG_DATA_FORMAT_ID);
   2443 
   2444     //there should be either a UDP or TCP socket on this port
   2445     if (!aSockConfig.iTCPSocket && !aSockConfig.iUDPSocket)
   2446     {
   2447         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartSendOperation ERROR no socket - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2448         return PVMFFailure;
   2449     }
   2450 
   2451     aSockConfig.iPVMFPort->iNumFramesConsumed++;
   2452 
   2453     // Retrieve memory fragment to write to
   2454     if (aSockConfig.iPendingSendMediaData.GetRep())
   2455         aSockConfig.iPendingSendMediaData.Unbind();
   2456 
   2457     convertToPVMFMediaData(aSockConfig.iPendingSendMediaData, aMsg);
   2458     OsclRefCounterMemFrag refCtrMemFragOut;
   2459     aSockConfig.iPendingSendMediaData->getMediaFragment(0, refCtrMemFragOut);
   2460     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartSendOperation - SockId=%d, Mime=%s, Len=%d", aSockConfig.iSockId, aSockConfig.iMime.get_str(), refCtrMemFragOut.getMemFragSize()));
   2461 
   2462     PVMFStatus status = PVMFFailure;
   2463 
   2464     if (aSockConfig.iUDPSocket)
   2465     {
   2466         aSockConfig.iState.iSendOperation = EPVSocketPortSendOperation_SendTo;
   2467 
   2468 #if(ENABLE_SOCKET_NODE_STATS)
   2469         aSockConfig.iPortStats.iNumSendTo++;
   2470         aSockConfig.iPortStats.StartSendTime(aSockConfig.iState.iSendOperation);
   2471 #endif
   2472         TPVSocketEvent retVal = aSockConfig.iUDPSocket->SendTo((uint8*)refCtrMemFragOut.getMemFragPtr()
   2473                                 , refCtrMemFragOut.getMemFragSize()
   2474                                 , aSockConfig.iAddr.iRemoteAdd
   2475                                 , TIMEOUT_SENDTO);
   2476 
   2477         if (retVal == EPVSocketPending)
   2478             status = PVMFPending;//wait on HandleSocketEvent callback
   2479         else
   2480             status = PVMFFailure;
   2481 
   2482         if (PVMFPending != status)
   2483         {
   2484             //error
   2485             PVMF_SOCKETNODE_LOGERROR((0, "0x%x PVMFSocketNode::SendTo() failed retVal=%d Ln %d", this, retVal, __LINE__));
   2486             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartSendOperation: UDP - Error. status=%d", status));
   2487             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartSendOperation SendTo FAILED - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2488         }
   2489         else
   2490         {
   2491             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartSendOperation SendTo Pending - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2492         }
   2493     }
   2494 
   2495     else if (aSockConfig.iTCPSocket)
   2496     {
   2497         aSockConfig.iState.iSendOperation = EPVSocketPortSendOperation_Send;
   2498 
   2499 #if(ENABLE_SOCKET_NODE_STATS)
   2500         aSockConfig.iPortStats.iNumSend++;
   2501         aSockConfig.iPortStats.StartSendTime(aSockConfig.iState.iSendOperation);
   2502 #endif
   2503         TPVSocketEvent retVal = aSockConfig.iTCPSocket->Send((uint8*)refCtrMemFragOut.getMemFragPtr(),
   2504                                 refCtrMemFragOut.getMemFragSize(),
   2505                                 TIMEOUT_SEND);
   2506 
   2507         if (retVal == EPVSocketPending)
   2508             status = PVMFPending;//wait on HandleSocketEvent callback
   2509         else
   2510             status = PVMFFailure;
   2511 
   2512         if (PVMFPending != status)
   2513         {
   2514             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::StartSendOperation: TCP - Error. status=%d", status));
   2515             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::StartSendOperation Calling Send FAILED - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2516         }
   2517         else
   2518         {
   2519             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartSendOperation Send Pending - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2520         }
   2521     }
   2522 
   2523     //Handle synchronous completion or failures
   2524     if (status != PVMFPending)
   2525         status = SendOperationComplete(aSockConfig, status, NULL);
   2526 
   2527     return status;
   2528 }
   2529 
   2530 //The current send operation is complete and status is in "aStatus".
   2531 //If there was a socket callback, the result is in "aSocketActivity".
   2532 //Process the result and continue with the next operation if needed.
   2533 PVMFStatus PVMFSocketNode::SendOperationComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus, PVMFSocketActivity* aSocketActivity)
   2534 {
   2535     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::SendOperationComplete()"));
   2536 
   2537     OSCL_ASSERT(aStatus != PVMFPending);
   2538 
   2539     PVMFStatus status = aStatus;
   2540 
   2541     //Update the send state
   2542     TPVSocketPortSendOperation curOp = aSockConfig.iState.iSendOperation;
   2543     aSockConfig.iState.iSendOperation = EPVSocketPortSendOperation_None;
   2544     aSockConfig.iState.iSendOperationStatus = aStatus;
   2545     aSockConfig.iState.iSendOperationCanceled = false;
   2546 
   2547     //Release the media buffer after each send operation, regardless of success/fail.
   2548     if (aSockConfig.iPendingSendMediaData.GetRep() != NULL)
   2549         aSockConfig.iPendingSendMediaData.Unbind();
   2550 
   2551     if (aSocketActivity)
   2552     {
   2553         //Datapath logging
   2554         switch (aSocketActivity->iEvent)
   2555         {
   2556             case EPVSocketSuccess:
   2557                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::SendOperationComplete - Success - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2558                 break;
   2559             case EPVSocketTimeout:
   2560                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::SendOperationComplete - TimeOut - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2561                 break;
   2562             case EPVSocketFailure:
   2563                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::SendOperationComplete - Failed - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2564                 break;
   2565             case EPVSocketCancel:
   2566                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::SendOperationComplete - Cancelled - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2567                 break;
   2568             default:
   2569                 OSCL_ASSERT(0);
   2570                 break;
   2571         }
   2572     }
   2573 
   2574     //report TCP errors.
   2575     if (aStatus != PVMFSuccess
   2576             && curOp == EPVSocketPortSendOperation_Send)
   2577     {
   2578         PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::SendOperationComplete - Send Failed - "
   2579                                           "SockId=%d, Mime=%s, Operaton=%d",
   2580                                           aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iState.iSendOperation));
   2581         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::SendOperationComplete: Send/SendTo() ERROR status=%d, Ln %d", status, __LINE__));
   2582         ReportSocketNodeError(PVMFErrResource, PVMFSocketNodeErrorTCPSocketSendError);
   2583     }
   2584 
   2585     //This completes an input data message sequence
   2586     if (aSockConfig.iState.iSequence == EPVSocketPortSequence_InputDataMsg)
   2587         SequenceComplete(aSockConfig, aStatus);
   2588 
   2589     //Detect connect "Wait on send/recv idle" complete
   2590     if (aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_WaitOnSendRecvIdle
   2591             && aSockConfig.iState.iRecvOperation == EPVSocketPortRecvOperation_None
   2592             && aSockConfig.iState.iSendOperation == EPVSocketPortSendOperation_None)
   2593     {
   2594         ConnectOperationComplete(aSockConfig, PVMFSuccess, NULL);
   2595     }
   2596 
   2597     return status;
   2598 }
   2599 
   2600 //Cancel the current send operation.
   2601 //Return Success if the operation is canceled, or Pending if we need to wait.
   2602 PVMFStatus PVMFSocketNode::CancelSendOperation(SocketPortConfig& aSockConfig)
   2603 {
   2604     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::CancelSendOperation()"));
   2605 
   2606     PVMFStatus status = PVMFSuccess;
   2607 
   2608     switch (aSockConfig.iState.iSendOperation)
   2609     {
   2610         case EPVSocketPortSendOperation_None:
   2611             break;
   2612 
   2613         case EPVSocketPortSendOperation_Send:
   2614             if (aSockConfig.iTCPSocket)
   2615             {
   2616                 if (!aSockConfig.iState.iSendOperationCanceled)
   2617                 {
   2618                     aSockConfig.iState.iSendOperationCanceled = true;
   2619                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelSendOperation Calling CancelSend - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2620                     aSockConfig.iTCPSocket->CancelSend();
   2621                 }
   2622                 status = PVMFPending;
   2623                 //wait on send to complete in HandleSocketEvent
   2624             }
   2625             break;
   2626 
   2627         case EPVSocketPortSendOperation_SendTo:
   2628             if (aSockConfig.iUDPSocket)
   2629             {
   2630                 if (!aSockConfig.iState.iSendOperationCanceled)
   2631                 {
   2632                     aSockConfig.iState.iSendOperationCanceled = true;
   2633                     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CancelSendOperation Calling CancelSendTo - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2634                     aSockConfig.iUDPSocket->CancelSendTo();
   2635                 }
   2636                 status = PVMFPending;
   2637                 //wait on sendto to complete in HandleSocketEvent
   2638             }
   2639             break;
   2640 
   2641         default:
   2642             OSCL_ASSERT(0);
   2643             status = PVMFFailure;
   2644             break;
   2645     }
   2646     return status;
   2647 }
   2648 
   2649 //////////////////////////////////
   2650 // End Send Operation Handlers
   2651 //////////////////////////////////
   2652 
   2653 //////////////////////////////////////
   2654 // Sequence Handler
   2655 //////////////////////////////////////
   2656 static const char* const TPVSocketPortSequenceStr[] =
   2657 {
   2658     "EPVSocketPortSequence_None"
   2659     , "EPVSocketPortSequence_RequestPort"
   2660     , "EPVSocketPortSequence_InputConnectMsg"
   2661     , "EPVSocketPortSequence_InputDataMsg"
   2662     , "EPVSocketPortSequence_InputDisconnectMsg"
   2663     , "EPVSocketPortSequence_SocketCleanup"
   2664     , "EPVSocketPortSequence_Last"
   2665 } ;
   2666 
   2667 //Start a sequence on a port.
   2668 //This routine will complete all steps possible unless some operation has
   2669 //asynchronous completion.
   2670 //This call may actually complete the sequence.
   2671 //This routine documents the series of steps for each sequence.
   2672 PVMFStatus PVMFSocketNode::StartSequence(SocketPortConfig& aSockConfig, TPVSocketPortSequence aSequence, OsclAny* aParam)
   2673 {
   2674     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartSequence, '%s' - SockId=%d, Mime=%s"
   2675                                       , TPVSocketPortSequenceStr[aSequence]
   2676                                       , aSockConfig.iSockId, aSockConfig.iMime.get_cstr()));
   2677 
   2678     //Set the sequence.
   2679     aSockConfig.iState.iSequence = aSequence;
   2680 
   2681     switch (aSequence)
   2682     {
   2683         case EPVSocketPortSequence_RequestPort:
   2684             //Sequence:
   2685             // 1. GetHostByName,
   2686             // 2. Connect
   2687             // 3. Command complete.
   2688 
   2689             return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_GetHostByName);
   2690 
   2691         case EPVSocketPortSequence_InputConnectMsg:
   2692             //Sequence:
   2693             // If already connected,
   2694             // 1. Shutdown
   2695             // 2. Cancel send/recv operation if needed.
   2696             // 3. Wait for send/recv idle if needed.
   2697             // 4. Wait for connected port if needed.
   2698             // 5. Close socket + send EOS to connected port + delete socket
   2699             //      or add to cleanup queue & trigger AO.
   2700             // 6. Create
   2701             // 7. GetHostByName
   2702             // 8. Connect
   2703             // Else if not already connected,
   2704             // 1. GetHostByName
   2705             // 2. Connect
   2706 
   2707             if (aSockConfig.iTCPSocket)
   2708             {
   2709                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::StartSequence - Disconnecting before Connect SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_cstr()));
   2710                 return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Shutdown);
   2711             }
   2712             else
   2713             {
   2714                 return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_GetHostByName);
   2715             }
   2716             break;
   2717 
   2718         case EPVSocketPortSequence_InputDataMsg:
   2719             //Sequence:
   2720             // 1. Send
   2721 
   2722             OSCL_ASSERT(aParam);
   2723             return StartSendOperation(aSockConfig, *((PVMFSharedMediaMsgPtr*)aParam));
   2724 
   2725         case EPVSocketPortSequence_InputDisconnectMsg:
   2726             //Sequence:
   2727             // 1. Shutdown
   2728             // 2. Cancel send/recv operation if needed.
   2729             // 3. Wait for send/recv idle if needed.
   2730             // 4. Wait for connected port if needed.
   2731             // 5. Close socket + send EOS to connected port + delete socket
   2732             //      or add to cleanup queue & trigger AO.
   2733 
   2734             return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Shutdown);
   2735 
   2736         case EPVSocketPortSequence_SocketCleanup:
   2737             if (aSockConfig.iTCPSocket)
   2738             {
   2739                 //TCP Shutdown Sequence:
   2740                 // 1. Cancel current connect operation if needed.
   2741                 // 2. Cancel send/recv operation if needed.
   2742                 // 3. Shutdown
   2743                 // 4. Wait for send/recv idle if needed.
   2744                 // 5. Wait for connected port if needed.
   2745                 // 6. Close socket + send EOS to connected port + delete socket
   2746                 //      or add to cleanup queue & trigger AO.
   2747 
   2748                 if (aSockConfig.iState.iConnectOperation == EPVSocketPortConnectOperation_Shutdown)
   2749                 {
   2750                     return PVMFPending;//wait on completion in HandleSocketEvent
   2751                 }
   2752                 if (CancelConnectOperation(aSockConfig) == PVMFPending)
   2753                 {
   2754                     return PVMFPending;//wait on connect operation to cancel
   2755                     //(in HandleSocketEvent or HandleDNSEvent)
   2756                 }
   2757                 else
   2758                 {
   2759                     //Go ahead and start any send/recv cancel since they can happen simultaneously
   2760                     //with the Shutdown operation.
   2761                     CancelRecvOperation(aSockConfig);
   2762                     CancelSendOperation(aSockConfig);
   2763 
   2764                     return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_Shutdown);
   2765                 }
   2766             }
   2767             else if (aSockConfig.iUDPSocket)
   2768             {
   2769                 //UDP Shutdown Sequence:
   2770                 // 1. Cancel all current operations
   2771                 // 2. Wait for send/recv idle if needed.
   2772                 // 3. Close socket + delete socket or add to cleanup queue & trigger AO.
   2773 
   2774                 switch (aSockConfig.iState.iConnectOperation)
   2775                 {
   2776                     case EPVSocketPortConnectOperation_WaitOnSendRecvIdle:
   2777                         //keep waiting for completion (in RecvOperationComplete or SendOperationComplete)
   2778                         return PVMFPending;
   2779 
   2780                     case EPVSocketPortConnectOperation_None:
   2781 
   2782                         CancelRecvOperation(aSockConfig);
   2783                         CancelSendOperation(aSockConfig);
   2784 
   2785                         return StartConnectOperation(aSockConfig, EPVSocketPortConnectOperation_WaitOnSendRecvIdle);
   2786 
   2787                     default:
   2788                         //unexpected
   2789                         OSCL_ASSERT(0);
   2790                         return PVMFFailure;
   2791 
   2792                 }
   2793             }
   2794             //else
   2795             {
   2796                 //nothing needed.
   2797                 SequenceComplete(aSockConfig, PVMFSuccess);
   2798                 return PVMFSuccess;
   2799             }
   2800             break;
   2801 
   2802         default:
   2803             //add code to handle this case
   2804             OSCL_ASSERT(0);
   2805             return PVMFFailure;
   2806     }
   2807 }
   2808 
   2809 //The current multi-operation sequence is complete.
   2810 //Process the result and continue with the next operation if needed.
   2811 void PVMFSocketNode::SequenceComplete(SocketPortConfig& aSockConfig, PVMFStatus aStatus)
   2812 {
   2813     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::SequenceComplete() Sequence %d Status %d ", aSockConfig.iState.iSequence, aStatus));
   2814 
   2815     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::SequenceComplete '%s' - SockId=%d, Mime=%s"
   2816                                       , TPVSocketPortSequenceStr[aSockConfig.iState.iSequence]
   2817                                       , aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   2818 
   2819     //Update the state
   2820     TPVSocketPortSequence curSequence = aSockConfig.iState.iSequence;
   2821     aSockConfig.iState.iSequence = EPVSocketPortSequence_None;
   2822     aSockConfig.iState.iSequenceStatus = aStatus;
   2823 
   2824     switch (curSequence)
   2825     {
   2826         case EPVSocketPortSequence_RequestPort:
   2827             //may need to complete the node command
   2828             if (iCurrentCmdQueue.size()
   2829                     && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
   2830             {
   2831                 //@TODO would be nice to cleanup the allocated port in case of a failure.
   2832                 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), aStatus, iRequestedPort);
   2833             }
   2834             break;
   2835 
   2836         case EPVSocketPortSequence_InputConnectMsg:
   2837         case EPVSocketPortSequence_InputDisconnectMsg:
   2838         case EPVSocketPortSequence_InputDataMsg:
   2839             //If we've just completed an input port message, this may complete a node Flush command
   2840             if (!iCurrentCmdQueue.empty()
   2841                     && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_FLUSH)
   2842             {
   2843                 //Flush is done when all input ports are empty.
   2844                 for (uint32 i = 0; i < iPortVector.size(); i++)
   2845                 {
   2846                     if (iPortVector[i]->IncomingMsgQueueSize() > 0)
   2847                         return;//keep waiting
   2848                 }
   2849                 //All ports empty-- complete the Flush.
   2850                 CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
   2851             }
   2852             break;
   2853 
   2854 
   2855         case EPVSocketPortSequence_SocketCleanup:
   2856             //When socket cleanup is complete, decrement the "stop node activity"
   2857             //counter and look for completion of all ports.
   2858 
   2859             //This port is done-- decrement the counter
   2860             iNumStopPortActivityPending--;
   2861 
   2862             //When counter reaches zero, all ports are done and the sequence is complete.
   2863             if (iNumStopPortActivityPending == 0)
   2864             {
   2865                 //Reset the counter to the "idle" value.
   2866                 iNumStopPortActivityPending = (-1);
   2867 
   2868                 //There may be a Reset or CancelAll command waiting on
   2869                 //this to complete.
   2870                 if (!iCurrentCmdQueue.empty()
   2871                         && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_RESET)
   2872                 {
   2873                     CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFSuccess);
   2874                 }
   2875                 else if (!iCancelCmdQueue.empty()
   2876                          && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELALLCOMMANDS)
   2877                 {
   2878                     CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
   2879                 }
   2880                 //ports may be cleaned up now, so exit this routine now to
   2881                 //avoid a crash from further port processing.
   2882                 return;
   2883             }
   2884             break;
   2885 
   2886         default:
   2887             break;
   2888     }
   2889 
   2890 
   2891     //All sequences other than input data message will
   2892     //block receive operations, so may need to start or resume receives now.
   2893     if (curSequence != EPVSocketPortSequence_InputDataMsg
   2894             && (aStatus == PVMFSuccess)
   2895             && CanReceive(aSockConfig))
   2896     {
   2897         StartRecvOperation(aSockConfig);
   2898     }
   2899 
   2900     //Input message processing may have been blocked waiting on
   2901     //this sequence to complete, so resume now.
   2902     if (CanProcessIncomingMsg(aSockConfig)
   2903             && (aStatus == PVMFSuccess))
   2904     {
   2905         ProcessIncomingMsg(aSockConfig);
   2906     }
   2907 }
   2908 
   2909 //////////////////////////////////////
   2910 // End Sequence Handler
   2911 //////////////////////////////////////
   2912 
   2913 
   2914 //////////////////////////////////////
   2915 // Command Handlers
   2916 //////////////////////////////////////
   2917 
   2918 //See if we can process a new input command right now.
   2919 bool PVMFSocketNode::CanProcessCommand()
   2920 {
   2921     //We may need to wait on
   2922     //1) a new command to arrive
   2923     //2) some prior command to complete
   2924     //Note: this allows a Cancel to interrupt the current command, but it does
   2925     //not allow a Cancel to interrupt another cancel.
   2926     return (!iPendingCmdQueue.empty()
   2927             && (iCurrentCmdQueue.empty()
   2928                 || (iPendingCmdQueue.front().hipri() && iCancelCmdQueue.empty())));
   2929 }
   2930 
   2931 //Process an input command.
   2932 void PVMFSocketNode::ProcessCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
   2933 {
   2934     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNodeCommand::ProcessCommand() in"));
   2935 
   2936     PVMFStatus status = PVMFFailure;
   2937     iCommandErrorCode = PVMFSocketNodeErrorEventStart; //no error
   2938 
   2939     if (aCmd.hipri())
   2940     {
   2941         //calling logic should prevent multiple cancels in progress.
   2942         OSCL_ASSERT(iCancelCmdQueue.empty());
   2943 
   2944         switch (aCmd.iCmd)
   2945         {
   2946             case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
   2947                 status = DoCancelAllCommands(aCmd);
   2948                 break;
   2949 
   2950             case PVMF_GENERIC_NODE_CANCELCOMMAND:
   2951                 status = DoCancelCommand(aCmd);
   2952                 break;
   2953 
   2954             default://unknown command type
   2955                 status = PVMFFailure;
   2956                 break;
   2957         }
   2958 
   2959         //If the command was not finished in this call, then move it to the
   2960         //"cancel cmd" queue where it will remain until it is completed.
   2961         if (status == PVMFPending)
   2962         {
   2963             //move the new cmd to the "cancel cmd" queue where it will
   2964             //remain until complete.
   2965             int32 err;
   2966             OSCL_TRY(err, iCancelCmdQueue.StoreL(aCmd););
   2967 
   2968             //we reserved space in the CancelCmdQueue already, so
   2969             //it should not be possible to fail here.
   2970             OSCL_ASSERT(err == OsclErrNone);
   2971 
   2972             //erase the original command
   2973             aCmdQ.Erase(&aCmd);
   2974         }
   2975         else
   2976         {
   2977             CommandComplete(aCmdQ, aCmd, status, NULL);
   2978         }
   2979     }
   2980     else
   2981     {
   2982         //calling logic should prevent multiple commands in progress.
   2983         OSCL_ASSERT(iCurrentCmdQueue.empty());
   2984 
   2985         OsclAny* eventData = NULL;
   2986 
   2987         switch (aCmd.iCmd)
   2988         {
   2989             case PVMF_GENERIC_NODE_QUERYUUID:
   2990                 status = DoQueryUuid(aCmd);
   2991                 break;
   2992 
   2993             case PVMF_GENERIC_NODE_QUERYINTERFACE:
   2994                 status = DoQueryInterface(aCmd);
   2995                 break;
   2996 
   2997             case PVMF_GENERIC_NODE_REQUESTPORT:
   2998             {
   2999                 iRequestedPort = NULL;
   3000                 status = DoRequestPort(aCmd, iRequestedPort);
   3001                 eventData = iRequestedPort;
   3002                 break;
   3003             }
   3004 
   3005             case PVMF_GENERIC_NODE_RELEASEPORT:
   3006                 status = DoReleasePort(aCmd);
   3007                 break;
   3008 
   3009             case PVMF_GENERIC_NODE_INIT:
   3010                 status = DoInit(aCmd);
   3011                 break;
   3012 
   3013             case PVMF_GENERIC_NODE_PREPARE:
   3014                 status = DoPrepare(aCmd);
   3015                 if (status == PVMFSuccess)
   3016                 {
   3017                     ChangeExternalState(EPVMFNodePrepared);
   3018                 }
   3019                 break;
   3020 
   3021             case PVMF_GENERIC_NODE_START:
   3022                 status = DoStart(aCmd);
   3023                 break;
   3024 
   3025             case PVMF_GENERIC_NODE_STOP:
   3026                 status = DoStop(aCmd);
   3027                 break;
   3028 
   3029             case PVMF_GENERIC_NODE_FLUSH:
   3030                 status = DoFlush(aCmd);
   3031                 break;
   3032 
   3033             case PVMF_GENERIC_NODE_PAUSE:
   3034                 status = DoPause(aCmd);
   3035                 break;
   3036 
   3037             case PVMF_GENERIC_NODE_RESET:
   3038                 status = DoReset(aCmd);
   3039                 break;
   3040 
   3041             default://unknown command type
   3042                 status = PVMFFailure;
   3043                 break;
   3044         }
   3045 
   3046         //If the command was not finished in this call, then move it to the
   3047         //"current cmd" queue where it will remain until it is completed.
   3048         if (status == PVMFPending)
   3049         {
   3050             //move the new cmd to the "current cmd" queue where it will
   3051             //remain until complete.
   3052             int32 err;
   3053             OSCL_TRY(err, iCurrentCmdQueue.StoreL(aCmd););
   3054 
   3055             //we reserved space in the CurrentCmdQueue already, so
   3056             //it should not be possible to fail here.
   3057             OSCL_ASSERT(err == OsclErrNone);
   3058 
   3059             //erase the original command
   3060             aCmdQ.Erase(&aCmd);
   3061         }
   3062         else
   3063         {
   3064             CommandComplete(aCmdQ, aCmd, status, eventData);
   3065         }
   3066     }
   3067 }
   3068 
   3069 //Called to complete a node command.
   3070 void PVMFSocketNode::CommandComplete(PVMFSocketNodeCmdQ& aCmdQ,
   3071                                      PVMFSocketNodeCommand& aCmd,
   3072                                      PVMFStatus aStatus,
   3073                                      OsclAny* aEventData,
   3074                                      PVUuid* aEventUUID,
   3075                                      int32* aEventCode)
   3076 
   3077 {
   3078     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
   3079                     , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
   3080 
   3081     //See whether command processing was blocked on entry to this routine, so we can
   3082     //decide later whether it's necessary to trigger the AO to resume processsing.
   3083     bool canProcess = CanProcessCommand();
   3084 
   3085     PVMFStatus status = aStatus;
   3086 
   3087     //do standard state changes & other cmd completion.
   3088     if (aStatus == PVMFSuccess)
   3089     {
   3090         switch (aCmd.iCmd)
   3091         {
   3092             case PVMF_GENERIC_NODE_INIT:
   3093                 ChangeExternalState(EPVMFNodeInitialized);
   3094                 break;
   3095 
   3096             case PVMF_GENERIC_NODE_PREPARE:
   3097                 ChangeExternalState(EPVMFNodePrepared);
   3098                 break;
   3099 
   3100             case PVMF_GENERIC_NODE_START:
   3101                 ChangeExternalState(EPVMFNodeStarted);
   3102                 break;
   3103 
   3104             case PVMF_GENERIC_NODE_STOP:
   3105                 ChangeExternalState(EPVMFNodePrepared);
   3106 
   3107 #if(ENABLE_SOCKET_NODE_STATS)
   3108                 //dump the stats.
   3109                 iSocketNodeStats.Log(iPortVector);
   3110 #endif
   3111                 break;
   3112 
   3113             case PVMF_GENERIC_NODE_PAUSE:
   3114                 ChangeExternalState(EPVMFNodePaused);
   3115                 break;
   3116 
   3117             case PVMF_GENERIC_NODE_RESET:
   3118                 ChangeExternalState(EPVMFNodeCreated);
   3119 
   3120                 //Complete the reset command.
   3121                 {
   3122 #if(ENABLE_SOCKET_NODE_STATS)
   3123                     iSocketNodeStats.Log(iPortVector);
   3124 #endif
   3125                     //cleanup all ports.
   3126                     CleanupPorts();
   3127                     //go back to Idle state
   3128                     iPortVector.Reconstruct();
   3129                     SetState(EPVMFNodeIdle);
   3130                 }
   3131                 break;
   3132 
   3133             case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
   3134                 //Complete the reset command.
   3135             {
   3136 #if(ENABLE_SOCKET_NODE_STATS)
   3137                 iSocketNodeStats.Log(iPortVector);
   3138 #endif
   3139                 //Since "cancel all" is effectively used as a Reset,
   3140                 //go ahead and cleanup all ports.
   3141                 CleanupPorts();
   3142             }
   3143             break;
   3144             default:
   3145                 break;
   3146         }
   3147     }
   3148 
   3149     //create extended error message if an explicit error was provided in args
   3150     PVInterface* extif = NULL;
   3151     PVMFBasicErrorInfoMessage* errormsg = NULL;
   3152     if (aEventUUID && aEventCode)
   3153     {
   3154         errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
   3155         extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
   3156     }
   3157     //else if no error input, see if "command error code" was set.
   3158     else if (iCommandErrorCode != PVMFSocketNodeErrorEventStart)
   3159     {
   3160         PVUuid eventuuid = PVMFSocketNodeEventTypeUUID;
   3161         errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (iCommandErrorCode, eventuuid, NULL));
   3162         extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
   3163     }
   3164 
   3165     //create response
   3166     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, status, extif, aEventData);
   3167     PVMFSessionId session = aCmd.iSession;
   3168 
   3169     //Erase the command from the queue.
   3170     aCmdQ.Erase(&aCmd);
   3171 
   3172     //Report completion to the session observer.
   3173     ReportCmdCompleteEvent(session, resp);
   3174 
   3175     if (errormsg)
   3176     {
   3177         errormsg->removeRef();
   3178     }
   3179     iCommandErrorCode = PVMFSocketNodeErrorEventStart;//reset.
   3180 
   3181     //See if there was a pending cancel waiting on the current command to
   3182     //complete.
   3183     if (!iCancelCmdQueue.empty()
   3184             && iCancelCmdQueue.front().iCmd == PVMF_GENERIC_NODE_CANCELCOMMAND)
   3185     {
   3186         CommandComplete(iCancelCmdQueue, iCancelCmdQueue.front(), PVMFSuccess);
   3187     }
   3188 
   3189     //May need to resume command handling if the AO was blocked
   3190     //waiting on asynchronous command completion, but it's unblocked now.
   3191     if (!canProcess
   3192             && CanProcessCommand()
   3193             && IsAdded())
   3194     {
   3195         RunIfNotReady();
   3196     }
   3197 }
   3198 
   3199 void PVMFSocketNode::ReportErrorEvent(PVMFEventType aEventType,
   3200                                       OsclAny* aEventData,
   3201                                       PVUuid* aEventUUID,
   3202                                       int32* aEventCode)
   3203 {
   3204     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR,
   3205                     (0, "PVMFSocketNode:NodeErrorEvent Type %d Data %d"
   3206                      , aEventType, aEventData));
   3207 
   3208     if (aEventUUID && aEventCode)
   3209     {
   3210         PVMFBasicErrorInfoMessage* eventmsg =
   3211             OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
   3212         PVMFAsyncEvent asyncevent(PVMFErrorEvent,
   3213                                   aEventType,
   3214                                   NULL,
   3215                                   OSCL_STATIC_CAST(PVInterface*, eventmsg),
   3216                                   aEventData,
   3217                                   NULL,
   3218                                   0);
   3219         PVMFNodeInterface::ReportErrorEvent(asyncevent);
   3220         eventmsg->removeRef();
   3221     }
   3222     else
   3223     {
   3224         PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
   3225     }
   3226 }
   3227 
   3228 void PVMFSocketNode::ReportInfoEvent(PVMFEventType aEventType,
   3229                                      OsclAny* aEventData,
   3230                                      PVUuid* aEventUUID,
   3231                                      int32* aEventCode)
   3232 {
   3233     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   3234                     (0, "PVMFSocketNode:NodeInfoEvent Type %d Data %d"
   3235                      , aEventType, aEventData));
   3236 
   3237     if (aEventUUID && aEventCode)
   3238     {
   3239         PVMFBasicErrorInfoMessage* eventmsg =
   3240             OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL));
   3241         PVMFAsyncEvent asyncevent(PVMFInfoEvent,
   3242                                   aEventType,
   3243                                   NULL,
   3244                                   OSCL_STATIC_CAST(PVInterface*, eventmsg),
   3245                                   aEventData,
   3246                                   NULL,
   3247                                   0);
   3248         PVMFNodeInterface::ReportInfoEvent(asyncevent);
   3249         eventmsg->removeRef();
   3250     }
   3251     else
   3252     {
   3253         PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
   3254     }
   3255 }
   3256 
   3257 PVMFCommandId PVMFSocketNode::QueueCommandL(PVMFSocketNodeCommand& aCmd)
   3258 {
   3259     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::QueueCommandL()"));
   3260 
   3261 #if(ENABLE_SOCKET_NODE_STATS)
   3262     iSocketNodeStats.iNumQueueNodeCmd++;
   3263 #endif
   3264 
   3265     PVMFCommandId id;
   3266 
   3267     id = iPendingCmdQueue.AddL(aCmd);
   3268 
   3269     //This may be a processing trigger.
   3270     //Wakeup the AO if needed.
   3271     if (IsAdded()
   3272             && CanProcessCommand())
   3273     {
   3274         RunIfNotReady();
   3275     }
   3276 
   3277     return id;
   3278 }
   3279 
   3280 PVMFStatus PVMFSocketNode::DoReset(PVMFSocketNodeCommand& aCmd)
   3281 {
   3282     OSCL_UNUSED_ARG(aCmd);
   3283     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoReset()"));
   3284 
   3285     /* This node allows a reset from any state */
   3286 
   3287     return DoStopNodeActivity();
   3288 }
   3289 
   3290 PVMFStatus PVMFSocketNode::DoQueryUuid(PVMFSocketNodeCommand& aCmd)
   3291 {
   3292     //This node supports Query UUID from any state
   3293 
   3294     OSCL_String* mimetype;
   3295     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
   3296     bool exactmatch;
   3297     aCmd.PVMFSocketNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
   3298 
   3299     //Try to match the input mimetype against any of
   3300     //the custom interfaces for this node
   3301 
   3302     //Match against custom interface1...
   3303     if (*mimetype == PVMF_SOCKET_NODE_EXTENSION_INTERFACE_MIMETYPE
   3304             //also match against base mimetypes for custom interface1,
   3305             //unless exactmatch is set.
   3306             || (!exactmatch && *mimetype == PVMF_SOCKET_NODE_MIMETYPE)
   3307             || (!exactmatch && *mimetype == PVMF_SOCKET_NODE_BASEMIMETYPE))
   3308     {
   3309 
   3310         PVUuid uuid(PVMF_SOCKET_NODE_EXTENSION_INTERFACE_UUID);
   3311         uuidvec->push_back(uuid);
   3312     }
   3313     return PVMFSuccess;
   3314 }
   3315 
   3316 bool PVMFSocketNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
   3317 {
   3318     iface = NULL;
   3319     if (uuid == PVUuid(PVMF_SOCKET_NODE_EXTENSION_INTERFACE_UUID))
   3320     {
   3321         if (!iExtensionInterface)
   3322         {
   3323             iExtensionInterface = OSCL_NEW(PVMFSocketNodeExtensionInterfaceImpl, (this));
   3324         }
   3325         if (iExtensionInterface)
   3326         {
   3327             return (iExtensionInterface->queryInterface(uuid, iface));
   3328         }
   3329         else
   3330         {
   3331             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::queryInterface: Error - Out of memory"));
   3332             OSCL_LEAVE(OsclErrNoMemory);
   3333             return false;
   3334         }
   3335     }
   3336     else
   3337     {
   3338         return false;
   3339     }
   3340 }
   3341 
   3342 PVMFStatus PVMFSocketNode::DoQueryInterface(PVMFSocketNodeCommand&  aCmd)
   3343 {
   3344     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   3345                     (0, "PVMFSocketNode::DoQueryInterface"));
   3346 
   3347     PVUuid* uuid;
   3348     PVInterface** ptr;
   3349     aCmd.PVMFSocketNodeCommandBase::Parse(uuid, ptr);
   3350     if (*uuid == PVUuid(PVMF_SOCKET_NODE_EXTENSION_INTERFACE_UUID))
   3351     {
   3352         if (!iExtensionInterface)
   3353         {
   3354             iExtensionInterface = OSCL_NEW(PVMFSocketNodeExtensionInterfaceImpl, (this));
   3355         }
   3356         if (iExtensionInterface)
   3357         {
   3358             if (iExtensionInterface->queryInterface(*uuid, *ptr))
   3359             {
   3360                 return PVMFSuccess;
   3361             }
   3362             else
   3363             {
   3364                 return PVMFErrNotSupported;
   3365             }
   3366         }
   3367         else
   3368         {
   3369             return PVMFErrNoMemory;
   3370         }
   3371     }
   3372     else
   3373     {//not supported
   3374         *ptr = NULL;
   3375         return PVMFErrNotSupported;
   3376     }
   3377 }
   3378 
   3379 PVMFStatus PVMFSocketNode::DoRequestPort(PVMFSocketNodeCommand& aCmd, PVMFSocketPort* &aPort)
   3380 {
   3381     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::DoRequestPort() In"));
   3382 
   3383     //retrieve port tag.
   3384     int32 tag;
   3385     OSCL_String* portconfig;
   3386     aCmd.PVMFSocketNodeCommandBase::Parse(tag, portconfig);
   3387     //validate the tag...
   3388     switch (tag)
   3389     {
   3390         case PVMF_SOCKET_NODE_PORT_TYPE_SOURCE:
   3391         case PVMF_SOCKET_NODE_PORT_TYPE_SINK:
   3392         case PVMF_SOCKET_NODE_PORT_TYPE_PASSTHRU:
   3393             break;
   3394         default:
   3395             //bad port tag
   3396             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: Error - Invalid port tag"));
   3397             iCommandErrorCode = PVMFSocketNodeErrorInvalidPortTag;
   3398             return PVMFErrArgument;
   3399     }
   3400 
   3401     SOCKET_ADDR sock_add;
   3402     sock_add.iTag = tag;
   3403     OSCL_HeapString<OsclMemAllocator> mime;
   3404     if (!ParseTransportConfig(portconfig, sock_add, mime))
   3405     {
   3406         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: ERROR - Invalid port config"));
   3407         iCommandErrorCode = PVMFSocketNodeErrorInvalidPortTag;
   3408         return PVMFErrArgument;
   3409     }
   3410 
   3411     PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::DoRequestPort tag %d config %s",
   3412                                       tag, portconfig->get_cstr()));
   3413 
   3414     switch (sock_add.iProtocol)
   3415     {
   3416         case INET_TCP:
   3417         {
   3418             //Create a new port with no socket.
   3419 
   3420             PVMFStatus status = AddPort(tag, aPort);
   3421             if (status != PVMFSuccess)
   3422                 return status;
   3423 
   3424             //create the socket config
   3425 
   3426             SocketPortConfig* sock_config = OSCL_NEW(SocketPortConfig, ());
   3427             aPort->iConfig = sock_config;
   3428             sock_config->iPVMFPort = aPort;
   3429 
   3430             sock_config->iMime = mime;
   3431             sock_config->iContainer = this;
   3432             sock_config->iSockId = iSocketID++;
   3433             sock_config->iTag = tag;
   3434             sock_config->iAddr = sock_add;
   3435 
   3436             //create the mem pool
   3437             PVMFSocketNodeMemPool* memPool;
   3438             status = AllocatePortMemPool(tag, memPool);
   3439             if (status == PVMFSuccess)
   3440                 sock_config->iMemPool = memPool;
   3441             if (status != PVMFSuccess)
   3442                 return status;
   3443 
   3444             //optionally create the socket and launch the connect sequence.
   3445             if (oscl_strstr(portconfig->get_cstr(), ";no-connect-on-create") != NULL)
   3446             {
   3447                 //if "no create on connect" was selected then port creation is complete now.
   3448                 status = PVMFSuccess;
   3449             }
   3450             else
   3451             {
   3452                 //else create the socket and launch the connect sequence.
   3453                 OSCL_ASSERT(sock_config->iState.iSequence == EPVSocketPortSequence_None);
   3454                 status = StartSequence(*sock_config, EPVSocketPortSequence_RequestPort);
   3455                 //may need to wait on connect completion here, or else there could
   3456                 //be an error.
   3457             }
   3458             return status;
   3459         }
   3460 
   3461         case INET_UDP:
   3462         {
   3463             //We should have already created this UDP socket in a call to AllocateConsecutivePorts.
   3464             SocketPortConfig* sockConfig = FindSocketPortConfig(sock_add);
   3465             if (!sockConfig)
   3466             {
   3467                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: ERROR - Invalid protocol for port request"));
   3468                 return PVMFFailure;
   3469             }
   3470 
   3471             //The udp socket was already created using AllocateConsecutivePorts(),
   3472             //the but PVMFPort and memory pool were not yet created.
   3473 
   3474             //Allocate a new PVMF port
   3475 
   3476             PVMFStatus status = AddPort(tag, aPort);
   3477             if (status == PVMFSuccess)
   3478             {
   3479                 PVMFSocketNodeMemPool* memPool = NULL;
   3480                 status = AllocatePortMemPool(tag, memPool);
   3481                 if (status == PVMFSuccess)
   3482                     sockConfig->iMemPool = memPool;
   3483             }
   3484 
   3485             if (status != PVMFSuccess)
   3486             {
   3487                 //put the port config back in the allocated port vector
   3488                 iAllocatedPortVector.push_back(sockConfig);
   3489                 return status;
   3490             }
   3491 
   3492             //move the sock config to the PVMF port vector and link the config
   3493             //back to the port.
   3494             aPort->iConfig = sockConfig;
   3495             sockConfig->iPVMFPort = aPort;
   3496 
   3497             return status;
   3498         }
   3499         break;
   3500         default:
   3501             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: ERROR - Invalid protocol for port request"));
   3502             return PVMFFailure;
   3503     }
   3504     PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: ERROR - Invalid protocol for port request"));
   3505     return PVMFFailure;
   3506 }
   3507 
   3508 //Release ports is a do-nothing for this node.
   3509 PVMFStatus PVMFSocketNode::DoReleasePort(PVMFSocketNodeCommand& aCmd)
   3510 {
   3511     OSCL_UNUSED_ARG(aCmd);
   3512     return PVMFSuccess;
   3513 }
   3514 
   3515 PVMFStatus PVMFSocketNode::DoInit(PVMFSocketNodeCommand& aCmd)
   3516 {
   3517     OSCL_UNUSED_ARG(aCmd);
   3518 
   3519     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoInit() In"));
   3520 
   3521     if (iInterfaceState != EPVMFNodeIdle)
   3522     {
   3523         return PVMFErrInvalidState;
   3524     }
   3525 
   3526 #if(ENABLE_SOCKET_NODE_STATS)
   3527     iSocketNodeStats.Init();
   3528 #endif
   3529 
   3530     PVMFStatus status = PVMFSuccess;
   3531 
   3532     //Create socket server session
   3533     if (NULL == iSockServ)
   3534     {
   3535         int32 err;
   3536         OSCL_TRY(err, iSockServ = OsclSocketServ::NewL(iAlloc););
   3537         if (err || (iSockServ ==  NULL))
   3538         {
   3539             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   3540                             (0, "PVMFSocketNode::DoInit: ERROR. OsclSocketServ::NewL() fail Ln %d", __LINE__));
   3541 
   3542             iCommandErrorCode = PVMFSocketNodeErrorSocketServerCreateError;
   3543             status =  PVMFErrNoResources;
   3544         }
   3545         else
   3546         {
   3547             if (iSockServ->Connect() == OsclErrNone)
   3548             {
   3549                 status = PVMFSuccess;
   3550             }
   3551             else
   3552             {
   3553                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   3554                                 (0, "PVMFSocketNode::DoInit: ERROR. OsclSocketServ::Connect() fail Ln %d", __LINE__));
   3555 
   3556                 iCommandErrorCode = PVMFSocketNodeErrorSocketServConnectError;
   3557                 status = PVMFErrResource;
   3558             }
   3559         }
   3560     }
   3561     return status;
   3562 }
   3563 
   3564 //Prepare is a do-nothing for this node.
   3565 PVMFStatus PVMFSocketNode::DoPrepare(PVMFSocketNodeCommand& aCmd)
   3566 {
   3567     OSCL_UNUSED_ARG(aCmd);
   3568     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::DoPrepare() In"));
   3569 
   3570     if (iInterfaceState != EPVMFNodeInitialized)
   3571     {
   3572         return PVMFErrInvalidState;
   3573     }
   3574     return PVMFSuccess;
   3575 }
   3576 
   3577 PVMFStatus PVMFSocketNode::DoStart(PVMFSocketNodeCommand& aCmd)
   3578 {
   3579     OSCL_UNUSED_ARG(aCmd);
   3580 
   3581     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::DoStart() In"));
   3582     /*
   3583      * If the node is already started just return success - multiple starts can happen with
   3584      * flow control (auto-pause / auto-resume) scenarios
   3585      */
   3586     if (iInterfaceState == EPVMFNodeStarted)
   3587     {
   3588         return PVMFSuccess;//already started.
   3589     }
   3590 
   3591     if (iInterfaceState != EPVMFNodePrepared &&
   3592             iInterfaceState != EPVMFNodePaused)
   3593     {
   3594         return PVMFErrInvalidState;
   3595     }
   3596 
   3597     //We need to update the node state before
   3598     //we can get things going.
   3599     TPVMFNodeInterfaceState curState = iInterfaceState;
   3600     ChangeExternalState(EPVMFNodeStarted);
   3601 
   3602     PVMFStatus status = PVMFSuccess;
   3603     for (uint32 i = 0; i < iPortVector.size(); i++)
   3604     {
   3605         SocketPortConfig* sockConfig = iPortVector[i]->iConfig;
   3606         if (sockConfig)
   3607         {
   3608             //Start handling incoming messages
   3609             if (CanProcessIncomingMsg(*sockConfig))
   3610                 ProcessIncomingMsg(*sockConfig);
   3611 
   3612             //Start the receives.
   3613             if (CanReceive(*sockConfig))
   3614             {
   3615                 status = StartRecvOperation(*sockConfig);
   3616                 //receive may be pending, but we don't block
   3617                 //the start command for it.
   3618                 if (status == PVMFPending)
   3619                 {
   3620                     status = PVMFSuccess;
   3621                 }
   3622                 else if (status != PVMFSuccess)
   3623                 {
   3624                     //fail the command if any individual startups fail.
   3625                     //restore the old node state.
   3626                     ChangeExternalState(curState);
   3627                     break;//out of for loop
   3628                 }
   3629             }
   3630         }
   3631     }
   3632     return status;
   3633 }
   3634 
   3635 PVMFStatus PVMFSocketNode::DoStop(PVMFSocketNodeCommand& aCmd)
   3636 {
   3637     OSCL_UNUSED_ARG(aCmd);
   3638 
   3639     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoStop() In"));
   3640 
   3641     if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
   3642     {
   3643         return PVMFErrInvalidState;
   3644     }
   3645 
   3646     //Stop will essentially just stop the receive operations and input port processing,
   3647     //since those handlers check the node state.  Current operations will not be
   3648     //interrupted.
   3649     return PVMFSuccess;
   3650 }
   3651 
   3652 //Stop all current socket/DNS activity and clear port messages.
   3653 //Return PVMFSuccess if everything is stopped, or else PVMFPending if some
   3654 //ports still have operations pending.
   3655 //
   3656 //Also update the global "iNumStopNodeActivityPending"
   3657 //with the number of ports that still have operations pending
   3658 PVMFStatus PVMFSocketNode::DoStopNodeActivity()
   3659 {
   3660     //note that "iNumStopNodeActivityPending" uses the value (-1) to indicate idle state,
   3661     //or N...0 to countdown how many ports we're waiting on.
   3662 
   3663     //Note: in case there's already a "stop node activity" going on, just
   3664     //return the status.
   3665     if (iNumStopPortActivityPending > 0)
   3666         return PVMFPending; //keep waiting on completion (in SequenceComplete)
   3667 
   3668     //Notify all PVMF ports to suspend their input, and discard any current messages.
   3669     for (uint32 i = 0; i < iPortVector.size(); i++)
   3670     {
   3671         iPortVector[i]->SuspendInput();
   3672         iPortVector[i]->ClearMsgQueues();
   3673     }
   3674 
   3675     //Stop socket activity on all ports.
   3676     {
   3677         uint32 nPortsPending = 0;
   3678         for (uint32 i = 0; i < iPortVector.size(); i++)
   3679         {
   3680             SocketPortConfig* portConfig = iPortVector[i]->iConfig;
   3681             if (portConfig)
   3682             {
   3683                 // discard any saved socket activity events
   3684                 portConfig->iSocketRecvActivity.iValid = false;
   3685 
   3686                 // start a shutdown sequence on the port
   3687                 // look at what else might be happening currently.
   3688 
   3689                 //if a request port is going on, be sure to complete the command,
   3690                 //although we will interrupt the current processing.
   3691                 if (portConfig->iState.iSequence == EPVSocketPortSequence_RequestPort
   3692                         && iCurrentCmdQueue.size()
   3693                         && iCurrentCmdQueue.front().iCmd == PVMF_GENERIC_NODE_REQUESTPORT)
   3694                 {
   3695                     //@TODO would be nice to cleanup the allocated port in case of a failure.
   3696                     CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled, NULL);
   3697                 }
   3698                 //for any other sequence, we will just interrupt it with the shutdown.
   3699 
   3700                 //if a cleanup is already underway, just keep waiting for it to complete,
   3701                 //else start a new sequence
   3702                 if (portConfig->iState.iSequence == EPVSocketPortSequence_SocketCleanup)
   3703                 {
   3704                     nPortsPending++;
   3705                 }
   3706                 else if (StartSequence(*portConfig, EPVSocketPortSequence_SocketCleanup) == PVMFPending)
   3707                 {
   3708                     nPortsPending++;
   3709                 }
   3710             }
   3711         }
   3712 
   3713         if (nPortsPending > 0)
   3714             iNumStopPortActivityPending = nPortsPending;
   3715     }
   3716 
   3717     if (iNumStopPortActivityPending > 0)
   3718         return PVMFPending; //wait on completion in SequenceComplete.
   3719 
   3720     return PVMFSuccess;
   3721 }
   3722 
   3723 //Flush is implemented for this node, but hasn't been tested.
   3724 PVMFStatus PVMFSocketNode::DoFlush(PVMFSocketNodeCommand& aCmd)
   3725 {
   3726     OSCL_UNUSED_ARG(aCmd);
   3727 
   3728     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoFlush() In"));
   3729 
   3730     if ((iInterfaceState != EPVMFNodeStarted) && (iInterfaceState != EPVMFNodePaused))
   3731     {
   3732         return PVMFErrInvalidState;
   3733     }
   3734 
   3735     //Notify all ports to suspend their input, then
   3736     //wait on completion of processing of current input.
   3737     PVMFStatus status = PVMFSuccess;
   3738     {
   3739         for (uint32 i = 0; i < iPortVector.size(); i++)
   3740         {
   3741             iPortVector[i]->SuspendInput();
   3742             if (status != PVMFPending
   3743                     && iPortVector[i]->IncomingMsgQueueSize() > 0)
   3744             {
   3745                 status = PVMFPending;//Wait on this queue to empty.
   3746                 //Completion is detected in SequenceComplete.
   3747             }
   3748         }
   3749     }
   3750 
   3751     return status;
   3752 }
   3753 
   3754 //Pause is a do-nothing for this node.
   3755 PVMFStatus PVMFSocketNode::DoPause(PVMFSocketNodeCommand& aCmd)
   3756 {
   3757     OSCL_UNUSED_ARG(aCmd);
   3758 
   3759     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoPause() In"));
   3760 
   3761     /*
   3762      * If the node is already paused just return success - multiple pause can happen with
   3763      * flow control (auto-pause / auto-resume) scenarios
   3764      */
   3765     if (iInterfaceState == EPVMFNodePaused)
   3766     {
   3767         return PVMFSuccess;
   3768     }
   3769 
   3770     if (iInterfaceState != EPVMFNodeStarted)
   3771     {
   3772         return PVMFErrInvalidState;
   3773     }
   3774 
   3775     return PVMFSuccess;
   3776 }
   3777 
   3778 PVMFStatus PVMFSocketNode::DoCancelCommand(PVMFSocketNodeCommand& aCmd)
   3779 {
   3780     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoCancelCommand() Called"));
   3781 
   3782     // extract the command ID from the parameters.
   3783     PVMFCommandId cmdId;
   3784     aCmd.PVMFSocketNodeCommandBase::Parse(cmdId);
   3785 
   3786     // first check "current" command if any
   3787     // it's safe to assume the "current cmd queue" is only 1-deep.
   3788     if (!iCurrentCmdQueue.empty()
   3789             && iCurrentCmdQueue.front().iId == cmdId)
   3790     {
   3791         return DoCancelCurrentCommand(iCurrentCmdQueue, iCurrentCmdQueue.front());
   3792         //wait on current command to complete.  The cancel command
   3793         //will ultimately be completed in the "CommandComplete" for the current command.
   3794     }
   3795 
   3796     // next see if the command is still queued in the "pending command queue"
   3797     {
   3798         // start at element 1 since this cancel command is element 0
   3799         PVMFSocketNodeCommand* cmd = iPendingCmdQueue.FindById(cmdId, 1);
   3800         if (cmd)
   3801         {
   3802             // cancel the queued command.  Note this will complete out-of-order.
   3803             CommandComplete(iPendingCmdQueue, *cmd, PVMFErrCancelled);
   3804             // no further action is required.
   3805             return PVMFSuccess;
   3806         }
   3807     }
   3808 
   3809     //this command fails if the given command is not queued or in progress.
   3810     return PVMFErrArgument;
   3811 }
   3812 
   3813 PVMFStatus PVMFSocketNode::DoCancelAllCommands(PVMFSocketNodeCommand& aCmd)
   3814 {
   3815     OSCL_UNUSED_ARG(aCmd);
   3816     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoCancelCommand() IN"));
   3817 
   3818     //This is not a conventional "cancel all" implementation.
   3819     //Streaming manager currently expects this call to shutdown all activity.
   3820     //It would really be more correct to use node Reset for this.
   3821 
   3822     PVMFStatus status = DoStopNodeActivity();
   3823 
   3824     //Since node activity is suspended, just go ahead and forcibly cancel any other
   3825     //pending commands now.  There could be a Reset, a Flush, or a RequestPort
   3826     //happening.
   3827     if (!iCurrentCmdQueue.empty())
   3828         CommandComplete(iCurrentCmdQueue, iCurrentCmdQueue.front(), PVMFErrCancelled);
   3829 
   3830     //Cancel all other pending commands, except for this one which is
   3831     //element 0 in the queue
   3832     for (uint32 i = 1; i < iPendingCmdQueue.size(); i++)
   3833         CommandComplete(iPendingCmdQueue, iPendingCmdQueue[i], PVMFErrCancelled);
   3834 
   3835     //May need to wait on completion of StopNodeActivity.
   3836     return status;
   3837 }
   3838 
   3839 //This routine must cancel the currently executing node command.
   3840 //It only needs to handle those commands that may have asynchronous completion.
   3841 PVMFStatus PVMFSocketNode::DoCancelCurrentCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd)
   3842 {
   3843     OSCL_UNUSED_ARG(aCmdQ);
   3844     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::DoCancelCurrentCommand()"));
   3845     switch (aCmd.iCmd)
   3846     {
   3847 
   3848         case PVMF_GENERIC_NODE_REQUESTPORT:
   3849             //there may be a connect operation pending-- cancel it.
   3850         {
   3851             if (iRequestedPort)
   3852             {
   3853                 SocketPortConfig* sockConfig = iRequestedPort->iConfig;
   3854                 if (sockConfig
   3855                         && sockConfig->iState.iConnectOperation != EPVSocketPortConnectOperation_None)
   3856                 {
   3857                     CancelConnectOperation(*sockConfig);
   3858                     return PVMFPending;//wait on the operation to complete
   3859                     //in HandleSocketEvent or HandleDNSEvent
   3860                 }
   3861             }
   3862             //shouldn't get here...
   3863             return PVMFFailure;
   3864         }
   3865         break;
   3866 
   3867         case PVMF_GENERIC_NODE_RESET:
   3868             //it's too complicated to cancel a reset, so just wait on completion
   3869             return PVMFPending;
   3870 
   3871         case PVMF_GENERIC_NODE_FLUSH:
   3872             //to cancel a flush, just discard all remaining port messages
   3873             //and keep waiting on completion of current message.
   3874         {
   3875             for (uint32 i = 0; i < iPortVector.size(); i++)
   3876                 iPortVector[i]->ClearMsgQueues();
   3877         }
   3878         return PVMFPending;//keep waiting on flush completion in SequenceComplete.
   3879 
   3880         case PVMF_GENERIC_NODE_CANCELCOMMAND:
   3881         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
   3882             //these have asynchronous completion, but the command handling prevents
   3883             //processing a cancel during a cancel, so we shouldn't get here.
   3884             OSCL_ASSERT(0);
   3885             return PVMFFailure;
   3886 
   3887         default:
   3888             //no other node commands have asynchronous completion, so this is unexpected.
   3889             OSCL_ASSERT(0);
   3890             return PVMFFailure;
   3891     }
   3892 }
   3893 
   3894 //////////////////////////////////////
   3895 // End Command Handlers
   3896 //////////////////////////////////////
   3897 
   3898 
   3899 //////////////////////////////////////
   3900 // DNS & Socket Callbacks
   3901 //////////////////////////////////////
   3902 
   3903 OSCL_EXPORT_REF void PVMFSocketNode::HandleDNSEvent(int32 aId, TPVDNSFxn aFxn, TPVDNSEvent aEvent, int32 aError)
   3904 {
   3905     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::HandleDNSEvent() In aId=%d, aFxn=%d, aEvent=%d, aError=%d", aId, aFxn, aEvent, aError));
   3906 
   3907     iInSocketCallback = true;
   3908 
   3909     if (aEvent != EPVDNSSuccess)
   3910     {
   3911         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleDNSEvent: Error - Failure"));
   3912     }
   3913 
   3914     //Note: since the DNS object ID is identical to the socket ID, we can lookup the
   3915     //socket port config using the DNS ID.
   3916     SocketPortConfig* sockConfigPtr = FindSocketPortConfig((uint32)aId);
   3917     if (!sockConfigPtr)
   3918     {
   3919         //it's possible the DNS object was already delete-- so just fail gracefully.
   3920         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleDNSEvent: Error - Invalid Socket ID"));
   3921     }
   3922     else
   3923     {
   3924 
   3925 #if(ENABLE_SOCKET_NODE_STATS)
   3926         sockConfigPtr->iPortStats.iNumDNSCallback++;
   3927 #endif
   3928 
   3929         //create socket activity
   3930         PVMFSocketActivity activity((aEvent == EPVDNSSuccess) ? PVMFSuccess : PVMFFailure, aId, aFxn, aEvent, aError);
   3931 
   3932         //Call the appropriate handler
   3933         switch (aFxn)
   3934         {
   3935             case EPVDNSGetHostByName:
   3936                 OSCL_ASSERT(sockConfigPtr->iState.iConnectOperation == EPVSocketPortConnectOperation_GetHostByName);
   3937 #if(ENABLE_SOCKET_NODE_STATS)
   3938                 if (aEvent == EPVDNSSuccess)
   3939                     sockConfigPtr->iPortStats.EndConnectTime(sockConfigPtr->iState.iConnectOperation);
   3940 #endif
   3941                 ConnectOperationComplete(*sockConfigPtr, activity.iStatus, &activity);
   3942                 break;
   3943 
   3944             default:
   3945                 OSCL_ASSERT(0);//unexpected
   3946                 break;
   3947         }
   3948     }
   3949 
   3950     iInSocketCallback = false;
   3951 }
   3952 
   3953 
   3954 //This is the callback from Oscl Sockets for socket operation completion.
   3955 OSCL_EXPORT_REF  void PVMFSocketNode::HandleSocketEvent(int32 aId, TPVSocketFxn aFxn, TPVSocketEvent aEvent, int32 aError)
   3956 {
   3957     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSocketNode::HandleSocketEvent() In aId=%d, aFxn=%d, aEvent=%d, aError=%d", aId, aFxn, aEvent, aError));
   3958 
   3959     iInSocketCallback = true;
   3960 
   3961     SocketPortConfig* sockConfigPtr = FindSocketPortConfig((uint32)aId);
   3962     if (!sockConfigPtr)
   3963     {
   3964         //it's possible the socket was already deleted-- so just fail gracefully.
   3965         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleSocketEvent: Error - Invalid Socket ID"));
   3966     }
   3967     else
   3968     {
   3969         if (aEvent != EPVSocketSuccess)
   3970         {
   3971             PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::HandleSocketEvent: Error - Event=%d, SockId=%d, Mime=%s",
   3972                                       aEvent, aId, sockConfigPtr->iMime.get_cstr()));
   3973         }
   3974 #if(ENABLE_SOCKET_NODE_STATS)
   3975         sockConfigPtr->iPortStats.iNumSocketCallback++;
   3976 #endif
   3977         //create socket activity
   3978         PVMFSocketActivity activity((aEvent == EPVSocketSuccess) ? PVMFSuccess : PVMFFailure, aId, aFxn, aEvent, aError);
   3979 
   3980         //Call the appropriate handler
   3981         switch (aFxn)
   3982         {
   3983             case EPVSocketRecvFrom:
   3984             case EPVSocketRecv:
   3985                 OSCL_ASSERT(sockConfigPtr->iState.iRecvOperation == EPVSocketPortRecvOperation_Recv
   3986                             || sockConfigPtr->iState.iRecvOperation == EPVSocketPortRecvOperation_RecvFrom);
   3987 #if(ENABLE_SOCKET_NODE_STATS)
   3988                 if (aEvent == EPVSocketSuccess)
   3989                     sockConfigPtr->iPortStats.EndRecvTime(sockConfigPtr->iState.iRecvOperation);
   3990 #endif
   3991                 RecvOperationComplete(*sockConfigPtr, activity.iStatus, &activity);
   3992                 break;
   3993 
   3994             case EPVSocketSendTo:
   3995             case EPVSocketSend:
   3996                 OSCL_ASSERT(sockConfigPtr->iState.iSendOperation == EPVSocketPortSendOperation_Send
   3997                             || sockConfigPtr->iState.iSendOperation == EPVSocketPortSendOperation_SendTo);
   3998 #if(ENABLE_SOCKET_NODE_STATS)
   3999                 if (aEvent == EPVSocketSuccess)
   4000                     sockConfigPtr->iPortStats.EndSendTime(sockConfigPtr->iState.iSendOperation);
   4001 #endif
   4002                 SendOperationComplete(*sockConfigPtr, activity.iStatus, &activity);
   4003                 break;
   4004 
   4005             case EPVSocketConnect:
   4006                 OSCL_ASSERT(sockConfigPtr->iState.iConnectOperation == EPVSocketPortConnectOperation_Connect);
   4007 #if(ENABLE_SOCKET_NODE_STATS)
   4008                 if (aEvent == EPVSocketSuccess)
   4009                     sockConfigPtr->iPortStats.EndConnectTime(sockConfigPtr->iState.iConnectOperation);
   4010 #endif
   4011                 ConnectOperationComplete(*sockConfigPtr, activity.iStatus, &activity);
   4012                 break;
   4013 
   4014             case EPVSocketShutdown:
   4015                 OSCL_ASSERT(sockConfigPtr->iState.iConnectOperation == EPVSocketPortConnectOperation_Shutdown);
   4016 #if(ENABLE_SOCKET_NODE_STATS)
   4017                 if (aEvent == EPVSocketSuccess)
   4018                     sockConfigPtr->iPortStats.EndConnectTime(sockConfigPtr->iState.iConnectOperation);
   4019 #endif
   4020                 ConnectOperationComplete(*sockConfigPtr, activity.iStatus, &activity);
   4021                 break;
   4022 
   4023             default:
   4024                 OSCL_ASSERT(0);//unexpected
   4025                 break;
   4026         }
   4027     }
   4028 
   4029     iInSocketCallback = false;
   4030 }
   4031 
   4032 //////////////////////////////////////
   4033 // End DNS & Socket Callbacks
   4034 //////////////////////////////////////
   4035 
   4036 ///////////////////////
   4037 // Low-level port processing
   4038 ///////////////////////
   4039 
   4040 //Allocate a node port and add it to the port vector.
   4041 PVMFStatus PVMFSocketNode::AddPort(int32 tag, PVMFSocketPort* &port)
   4042 {
   4043     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::AddPort() In"));
   4044     int32 err;
   4045     OsclAny *ptr = NULL;
   4046     OSCL_TRY(err, ptr = iPortVector.Allocate(););
   4047     if (err != OsclErrNone || !ptr)
   4048     {
   4049         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::AddPort: ERROR - err=%d Ln %d", err, __LINE__));
   4050         return PVMFErrNoMemory;
   4051     }
   4052 
   4053     port = new(ptr) PVMFSocketPort((int32)tag,
   4054                                    this,
   4055                                    DEFAULT_DATA_QUEUE_CAPACITY,
   4056                                    DEFAULT_DATA_QUEUE_CAPACITY,
   4057                                    DEFAULT_READY_TO_RECEIVE_THRESHOLD_PERCENT,
   4058                                    //the output queue is empty because
   4059                                    //this node pushes data directly to the
   4060                                    //connecte port's input.
   4061                                    0, 0, 0);
   4062 
   4063     //Add the port to the port vector.
   4064     OSCL_TRY(err, iPortVector.AddL(port););
   4065     if (err != OsclErrNone)
   4066     {
   4067         iPortVector.DestructAndDealloc(port);
   4068         return PVMFErrNoMemory;
   4069     }
   4070     return PVMFSuccess;
   4071 }
   4072 
   4073 //Allocate a memory pool for the input port config.
   4074 //When finished, the port config is updated with the
   4075 //mempool and the port tag.
   4076 PVMFStatus PVMFSocketNode::AllocatePortMemPool(int32 tag, PVMFSocketNodeMemPool* & aMemPool)
   4077 {
   4078     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::AllocatePortMemPool() In"));
   4079     aMemPool = NULL;
   4080     OsclAny *MemPtr = NULL;
   4081     int32 err;
   4082     OSCL_TRY(err, MemPtr = iAlloc.ALLOCATE(sizeof(PVMFSocketNodeMemPool)););
   4083     if ((err != OsclErrNone) || (MemPtr == NULL))
   4084     {
   4085         PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: PVMFSocketNodeMemPool Allocate Failed Ln %d", err, __LINE__));
   4086         return PVMFErrNoMemory;
   4087     }
   4088 
   4089     switch (tag)
   4090     {
   4091         case PVMF_SOCKET_NODE_PORT_TYPE_SOURCE:
   4092             //source tag is used for RTP
   4093         {
   4094             int32 errcode = 0;
   4095             errcode = SocketPlacementNew(aMemPool, MemPtr, DEFAULT_NUM_MEDIA_MSGS_IN_JITTER_BUFFER);
   4096             if (errcode != OsclErrNone)
   4097             {
   4098                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: PVMFSocketNodeMemPool Construct Failed Ln %d", err, __LINE__));
   4099                 iAlloc.deallocate(MemPtr);
   4100                 return PVMFErrNoMemory;
   4101             }
   4102         }
   4103         break;
   4104         case PVMF_SOCKET_NODE_PORT_TYPE_SINK:
   4105         case PVMF_SOCKET_NODE_PORT_TYPE_PASSTHRU:
   4106             //sink tag is used for RTCP
   4107         {
   4108             int32 errcode = 0;
   4109             errcode = SocketPlacementNew(aMemPool, MemPtr, SNODE_DEFAULT_NUMBER_MEDIADATA_IN_MEMPOOL);
   4110             if (errcode != OsclErrNone)
   4111             {
   4112                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::DoRequestPort: PVMFSocketNodeMemPool Construct Failed Ln %d", err, __LINE__));
   4113                 iAlloc.deallocate(MemPtr);
   4114                 return PVMFErrNoMemory;
   4115             }
   4116         }
   4117         break;
   4118 
   4119         default://unexpected-- caller already validated the tag.
   4120             iAlloc.deallocate(MemPtr);
   4121             return PVMFFailure;
   4122             break;
   4123     }
   4124     aMemPool->iPortTag = tag;
   4125     return PVMFSuccess;
   4126 }
   4127 
   4128 
   4129 //Lookup the socket port config entry, given a socket address.
   4130 //If the entry is in the "allocated port" vector, it will be erased, so
   4131 //it's up to the caller to make sure it gets deleted or moved.
   4132 SocketPortConfig* PVMFSocketNode::FindSocketPortConfig(SOCKET_ADDR& aSockAddr)
   4133 {
   4134     uint32 i;
   4135     //search the allocated port vector
   4136     for (i = 0; i < iAllocatedPortVector.size(); i++)
   4137     {
   4138         if (iAllocatedPortVector[i]
   4139                 && MatchSocketAddr(aSockAddr, *iAllocatedPortVector[i]))
   4140         {
   4141             //erase it from the vector before returning to the caller.
   4142             SocketPortConfig* elem = iAllocatedPortVector[i];
   4143             iAllocatedPortVector.erase(&iAllocatedPortVector[i]);
   4144             return elem;
   4145         }
   4146     }
   4147     //search the port vector
   4148     for (i = 0; i < iPortVector.size(); i++)
   4149     {
   4150         if (iPortVector[i]->iConfig
   4151                 && MatchSocketAddr(aSockAddr, *iPortVector[i]->iConfig))
   4152         {
   4153             return iPortVector[i]->iConfig;
   4154         }
   4155     }
   4156     return NULL;
   4157 }
   4158 
   4159 //return "true" if input socket address matches port config
   4160 bool PVMFSocketNode::MatchSocketAddr(SOCKET_ADDR& aSockAddr, SocketPortConfig& aSockConfig)
   4161 {
   4162     return (aSockConfig.iAddr.iProtocol == aSockAddr.iProtocol
   4163             && aSockConfig.iAddr.iRemoteAdd.port == aSockAddr.iRemoteAdd.port
   4164             && aSockConfig.iAddr.iRemoteHost == aSockAddr.iRemoteHost
   4165             && aSockConfig.iTag == aSockAddr.iTag
   4166             //local address may or may not be specified-- ignore if not.
   4167             && (!aSockAddr.iLocalAdd.port
   4168                 || (aSockConfig.iAddr.iLocalAdd.port == aSockAddr.iLocalAdd.port)));
   4169 }
   4170 
   4171 //Lookup the socket port config entry, given a socket ID.
   4172 SocketPortConfig* PVMFSocketNode::FindSocketPortConfig(uint32 aId)
   4173 {
   4174     for (uint32 i = 0; i < iPortVector.size(); i++)
   4175     {
   4176         if (iPortVector[i]->iConfig
   4177                 && iPortVector[i]->iConfig->iSockId == aId)
   4178         {
   4179             return iPortVector[i]->iConfig;
   4180         }
   4181     }
   4182     return NULL;
   4183 }
   4184 
   4185 //Create a socket using the given socket ID and protocol.
   4186 //For UDP, this will also attempt to bind, incrementing port numbers until
   4187 //either success or maximum attempts is reached.  This has the side effect
   4188 //of updating the port number in the local address.
   4189 //It returns a pointer to the socket cast as OsclAny*.
   4190 OsclAny* PVMFSocketNode::CreateOsclSocketAndBind(SOCKET_ADDR &aSockAdd, uint32 aSockId)
   4191 {
   4192     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::CreateOsclSocketAndBind() In"));
   4193     //create the socket server session if it doesn't exist yet.
   4194     if (iSockServ == NULL)
   4195     {
   4196         int32 err;
   4197         OSCL_TRY(err, iSockServ = OsclSocketServ::NewL(iAlloc););
   4198         if (err || (iSockServ ==  NULL))
   4199         {
   4200             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketNode::CreateSocket() ERROR- iSockServ=0x%x, err=%d, Ln %d", iSockServ, err, __LINE__));
   4201             return NULL;
   4202         }
   4203         if (iSockServ->Connect() != OsclErrNone)
   4204         {
   4205             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketNode::CreateSocket() ERROR Connect(), Ln %d", __LINE__));
   4206             return NULL;
   4207         }
   4208     }
   4209 
   4210     switch (aSockAdd.iProtocol)
   4211     {
   4212         case INET_UDP:
   4213         {
   4214             int32 err;
   4215             OsclUDPSocket *UDPSocket = NULL;
   4216             OSCL_TRY(err, UDPSocket = OsclUDPSocket::NewL(iAlloc, *iSockServ, this, aSockId););
   4217             if (err || (UDPSocket ==  NULL))
   4218             {
   4219                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketNode::CreateSocket() ERROR- UDPSocket=0x%x, err=%d, Ln %d", UDPSocket, err, __LINE__));
   4220                 return NULL;
   4221             }
   4222 
   4223             //Bind this socket to the address
   4224             bool bBindOK = false;
   4225             int maxNumOfBind = UDP_PORT_RANGE;
   4226             while (maxNumOfBind-- > 0)
   4227             {
   4228 #if(ENABLE_SOCKET_NODE_STATS)
   4229                 iSocketNodeStats.iNumBind++;
   4230 #endif
   4231                 if (UDPSocket->Bind(aSockAdd.iLocalAdd) == EPVSocketSuccess)
   4232                 {
   4233                     bBindOK = true;
   4234                     break;
   4235                 }
   4236                 aSockAdd.iLocalAdd.port++;
   4237             };
   4238 
   4239             //If bind failed, delete the socket.
   4240             if (!bBindOK)
   4241             {
   4242                 UDPSocket->~OsclUDPSocket();
   4243                 iAlloc.deallocate(UDPSocket);
   4244 
   4245                 UDPSocket = NULL;
   4246             }
   4247             return UDPSocket;
   4248         }
   4249 
   4250         case INET_TCP:
   4251         {
   4252 
   4253             int32 err;
   4254             OsclTCPSocket *TCPSocket = NULL;
   4255 
   4256             OSCL_TRY(err, TCPSocket = OsclTCPSocket::NewL(iAlloc, *iSockServ, this, aSockId););
   4257             if (err || (TCPSocket ==  NULL))
   4258             {
   4259                 return NULL;
   4260             }
   4261             return TCPSocket;
   4262         }
   4263 
   4264         default:
   4265             return NULL;
   4266     }
   4267 }
   4268 
   4269 //This finishes up a TCP socket cleanup, after the socket shutdown
   4270 //is complete.
   4271 void PVMFSocketNode::CleanupTCP(SocketPortConfig& aSockConfig)
   4272 {
   4273     if (aSockConfig.iTCPSocket)
   4274     {
   4275         //Close the socket.  This will free the OS-level resources.  This
   4276         //socket object cannot be re-used.
   4277         aSockConfig.iTCPSocket->Close();
   4278         PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupTCP - Socket Closed - SockId=%d, Mime=%s, Port=0x%x", aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iPVMFPort));
   4279 
   4280         //Send EOS.  To avoid multiple EOS we only do this when the
   4281         //socket is still open.
   4282         if (aSockConfig.iPVMFPort
   4283                 && aSockConfig.iPVMFPort->IsConnected())
   4284         {
   4285             PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
   4286             sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
   4287             PVMFSharedMediaMsgPtr mediaMsgOut;
   4288             convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
   4289 #if(ENABLE_SOCKET_NODE_STATS)
   4290             aSockConfig.iPortStats.iNumQueueOutgoingEOSMsg++;
   4291 #endif
   4292             PVMFStatus status = aSockConfig.iPVMFPort->QueueOutgoingMsg(mediaMsgOut);
   4293             //There's no recovery from a queue busy condition here.
   4294             //We assume the caller already waited on the connected port before
   4295             //calling this routine.
   4296             if (status != PVMFSuccess)
   4297             {
   4298                 PVMF_SOCKETNODE_LOGERROR((0, "PVMFSocketNode::SendPVMFEOS() ERROR:%d, Outgoing queue size=%d. Data discarded!", status, aSockConfig.iPVMFPort->OutgoingMsgQueueSize()));
   4299                 ReportErrorEvent(PVMFErrPortProcessing);
   4300                 PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode::CleanupTCP - EOS Send FAILED - SockId=%d, Mime=%s, Port=0x%x", aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iPVMFPort));
   4301             }
   4302             else
   4303             {
   4304                 PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupTCP - EOS Sent - SockId=%d, Mime=%s, Port=0x%x", aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iPVMFPort));
   4305             }
   4306         }
   4307 
   4308         if (iInSocketCallback)
   4309         {
   4310             //prevent deleting an object from within its own Run.
   4311             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupTCP - queueing old socket for deletion - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   4312             iClosedTCPSocketVector.push_back(aSockConfig.iTCPSocket);
   4313             aSockConfig.iTCPSocket = NULL;
   4314             RunIfNotReady();//schedule the AO to delete the socket.
   4315         }
   4316         else
   4317         {
   4318             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupTCP - Deleting socket - SockId=%d, Mime=%s, Port=0x%x", aSockConfig.iSockId, aSockConfig.iMime.get_str(), aSockConfig.iPVMFPort));
   4319             aSockConfig.iTCPSocket->~OsclTCPSocket();
   4320             iAlloc.deallocate(aSockConfig.iTCPSocket);
   4321             aSockConfig.iTCPSocket = NULL;
   4322         }
   4323     }
   4324 
   4325     //cleanup media messages
   4326     //(this must happen *after* the optional EOS)
   4327     if (aSockConfig.iPendingRecvMediaData.GetRep() != NULL)
   4328         aSockConfig.iPendingRecvMediaData.Unbind();
   4329     if (aSockConfig.iPendingSendMediaData.GetRep() != NULL)
   4330         aSockConfig.iPendingSendMediaData.Unbind();
   4331 }
   4332 
   4333 //Cancel and/or delete UDP socket
   4334 void PVMFSocketNode::CleanupUDP(SocketPortConfig& aSockConfig)
   4335 {
   4336     //delete
   4337     if (aSockConfig.iUDPSocket)
   4338     {
   4339         if (iInSocketCallback)
   4340         {
   4341             //prevent deleting an object from within its own Run.
   4342             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupTCP - queueing old socket for deletion - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   4343             iClosedUDPSocketVector.push_back(aSockConfig.iUDPSocket);
   4344             aSockConfig.iUDPSocket = NULL;
   4345             RunIfNotReady();//schedule the AO to delete the socket.
   4346         }
   4347         else
   4348         {
   4349             aSockConfig.iUDPSocket->~OsclUDPSocket();
   4350             iAlloc.deallocate(aSockConfig.iUDPSocket);
   4351             aSockConfig.iUDPSocket = NULL;
   4352         }
   4353     }
   4354 
   4355     //cleanup media messages when socket is deleted
   4356     if (aSockConfig.iPendingRecvMediaData.GetRep() != NULL)
   4357         aSockConfig.iPendingRecvMediaData.Unbind();
   4358     if (aSockConfig.iPendingSendMediaData.GetRep() != NULL)
   4359         aSockConfig.iPendingSendMediaData.Unbind();
   4360 }
   4361 
   4362 void PVMFSocketNode::CleanupDNS(SocketPortConfig& aSockConfig)
   4363 {
   4364     if (aSockConfig.iDNS)
   4365     {
   4366         if (iInSocketCallback)
   4367         {
   4368             //prevent deleting an object from within its own Run.
   4369             PVMF_SOCKETNODE_LOGDATATRAFFIC_I((0, "PVMFSocketNode::CleanupDNS - queueing old DNS for deletion - SockId=%d, Mime=%s", aSockConfig.iSockId, aSockConfig.iMime.get_str()));
   4370             iClosedDNSVector.push_back(aSockConfig.iDNS);
   4371             aSockConfig.iDNS = NULL;
   4372             RunIfNotReady();//schedule the AO to delete the object.
   4373         }
   4374         else
   4375         {
   4376             aSockConfig.iDNS->~OsclDNS();
   4377             iAlloc.deallocate(aSockConfig.iDNS);
   4378             aSockConfig.iDNS = NULL;
   4379         }
   4380     }
   4381 }
   4382 
   4383 //A synchronous cleanup routine for all ports.
   4384 //It is assumed that all sockets are idle when this is called.
   4385 //This is used in node destructor, and in completion of
   4386 //Reset and Cancel All commands.
   4387 void PVMFSocketNode::CleanupPorts()
   4388 {
   4389     // Cleanup port vector
   4390     while (!iPortVector.empty())
   4391     {
   4392         SocketPortConfig* it = iPortVector.front()->iConfig;
   4393         if (it)
   4394         {
   4395             //unlink the PVMFPort so we won't try to send any EOS msg
   4396             //during the TCP cleanup.
   4397             it->iPVMFPort = NULL;
   4398             CleanupTCP(*it);
   4399             CleanupUDP(*it);
   4400             CleanupDNS(*it);
   4401             it->CleanupMemPools(iAlloc);
   4402             OSCL_DELETE(it);
   4403             iPortVector.front()->iConfig = NULL;
   4404         }
   4405         iPortVector.Erase(&iPortVector.front());
   4406     }
   4407     // Cleanup allocated ports (these may have bound UDP sockets
   4408     // but don't have any PVMF ports).
   4409     while (!iAllocatedPortVector.empty())
   4410     {
   4411         SocketPortConfig* it = iAllocatedPortVector.front();
   4412         CleanupTCP(*it);
   4413         CleanupUDP(*it);
   4414         CleanupDNS(*it);
   4415         it->CleanupMemPools(iAlloc);
   4416         OSCL_DELETE(it);
   4417         iAllocatedPortVector.erase(&iAllocatedPortVector.front());
   4418     }
   4419 }
   4420 
   4421 void PVMFSocketNode::CleanupClosedTCPSockets()
   4422 {
   4423     while (!iClosedTCPSocketVector.empty())
   4424     {
   4425         OsclTCPSocket* obj = iClosedTCPSocketVector.front();
   4426         obj->~OsclTCPSocket();
   4427         iAlloc.deallocate(obj);
   4428         iClosedTCPSocketVector.erase(&iClosedTCPSocketVector.front());
   4429     }
   4430 }
   4431 
   4432 void PVMFSocketNode::CleanupClosedUDPSockets()
   4433 {
   4434     while (!iClosedUDPSocketVector.empty())
   4435     {
   4436         OsclUDPSocket* obj = iClosedUDPSocketVector.front();
   4437         obj->~OsclUDPSocket();
   4438         iAlloc.deallocate(obj);
   4439         iClosedUDPSocketVector.erase(&iClosedUDPSocketVector.front());
   4440     }
   4441 }
   4442 
   4443 void PVMFSocketNode::CleanupClosedDNS()
   4444 {
   4445     while (!iClosedDNSVector.empty())
   4446     {
   4447         OsclDNS* obj = iClosedDNSVector.front();
   4448         obj->~OsclDNS();
   4449         iAlloc.deallocate(obj);
   4450         iClosedDNSVector.erase(&iClosedDNSVector.front());
   4451     }
   4452 }
   4453 
   4454 bool PVMFSocketNode::ParseTransportConfig(OSCL_String *aPortConfig,
   4455         SOCKET_ADDR &aSockConfig,
   4456         OSCL_String& aMime)
   4457 {
   4458     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::ParseTransportConfig() In"));
   4459     char* head = aPortConfig->get_str();
   4460     int32 len = aPortConfig->get_size();
   4461     return ParseTransportConfig(head, len, aSockConfig, aMime);
   4462 }
   4463 
   4464 bool PVMFSocketNode::ParseTransportConfig(char *aPortConfig,
   4465         int32 aLen,
   4466         SOCKET_ADDR &aSockConfig,
   4467         OSCL_String& aMime)
   4468 {
   4469     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::ParseTransportConfig() In"));
   4470     char* head = aPortConfig;
   4471     int32 len = aLen;
   4472 
   4473     char *tail = head + len;
   4474 
   4475     if (oscl_strstr(head, "TCP"))
   4476         aSockConfig.iProtocol = INET_TCP;
   4477     else if (oscl_strstr(head, "UDP"))
   4478         aSockConfig.iProtocol = INET_UDP;
   4479     else
   4480         return false;//invalid protocol.
   4481 
   4482     //for future extension
   4483     aSockConfig.iLocalAdd.ipAddr.Set("0.0.0.0");    //INADDR_ANY
   4484 
   4485     aSockConfig.iRemoteAdd.ipAddr.Set("");
   4486 
   4487     OSCL_StackString<128> address("remote_address=");
   4488 
   4489     char *tmpHead = OSCL_CONST_CAST(char*, oscl_strstr(head, address.get_cstr()));
   4490     if (tmpHead)
   4491     {
   4492         tmpHead += address.get_size();
   4493         char *tmpTail = OSCL_CONST_CAST(char*, oscl_strstr(tmpHead, ";"));
   4494         if (tmpTail == NULL)
   4495         {
   4496             tmpTail = tail;
   4497         }
   4498         char tmpChar = *tmpTail;
   4499         *tmpTail = '\0';
   4500         aSockConfig.iRemoteAdd.ipAddr.Set(tmpHead);
   4501 
   4502         OSCL_HeapString<PVMFSocketNodeAllocator> tmpServerName(tmpHead, (tmpTail - tmpHead));
   4503         aSockConfig.iRemoteHost = tmpServerName;
   4504 
   4505         *tmpTail = tmpChar;
   4506     }
   4507 
   4508     {
   4509         TimeValue current_time;
   4510         current_time.set_to_current_time();
   4511         uint32 my_seed = current_time.get_sec();
   4512 
   4513         OsclRand random_num;
   4514         random_num.Seed(my_seed);
   4515         int32 first = random_num.Rand();
   4516         uint32 myport = (first & 0x1FFF) + 0x2000;  //start from 8192
   4517         aSockConfig.iLocalAdd.port = (myport >> 1) << 1;    //start from even;
   4518     }
   4519     OSCL_StackString<128> client_port("client_port=");
   4520     tmpHead = OSCL_CONST_CAST(char*, oscl_strstr(head, client_port.get_cstr()));
   4521     if (tmpHead)
   4522     {
   4523         tmpHead += client_port.get_size();
   4524         char *tmpTail = OSCL_CONST_CAST(char*, oscl_strstr(tmpHead, ";"));
   4525         if (tmpTail == NULL)
   4526         {
   4527             tmpTail = tail;
   4528         }
   4529         char tmpChar = *tmpTail;
   4530         *tmpTail = '\0';
   4531 
   4532         uint32 atoi_tmp;
   4533         if (PV_atoi(tmpHead, 'd', atoi_tmp))
   4534         {
   4535             aSockConfig.iLocalAdd.port = atoi_tmp;
   4536         }
   4537         *tmpTail = tmpChar;
   4538     }
   4539 
   4540     aSockConfig.iRemoteAdd.port = 0;
   4541     OSCL_StackString<128> server_port("remote_port=");
   4542     tmpHead = OSCL_CONST_CAST(char*, oscl_strstr(head, server_port.get_cstr()));
   4543     if (tmpHead)
   4544     {
   4545         tmpHead += server_port.get_size();
   4546         char *tmpTail = OSCL_CONST_CAST(char*, oscl_strstr(tmpHead, ";"));
   4547         if (tmpTail == NULL)
   4548         {
   4549             tmpTail = tail;
   4550         }
   4551 
   4552         char tmpChar = *tmpTail;
   4553         *tmpTail = '\0';
   4554 
   4555         uint32 atoi_tmp;
   4556         if (PV_atoi(tmpHead, 'd', atoi_tmp))
   4557         {
   4558             aSockConfig.iRemoteAdd.port = atoi_tmp;
   4559         }
   4560         *tmpTail = tmpChar;
   4561     }
   4562 
   4563     OSCL_StackString<128> mime("mime=");
   4564     tmpHead = OSCL_CONST_CAST(char*, oscl_strstr(head, mime.get_cstr()));
   4565     if (tmpHead)
   4566     {
   4567         tmpHead += mime.get_size();
   4568         char *tmpTail = OSCL_CONST_CAST(char*, oscl_strstr(tmpHead, ";"));
   4569         if (tmpTail == NULL)
   4570         {
   4571             tmpTail = tail;
   4572         }
   4573         aMime += tmpHead;
   4574     }
   4575     return true;
   4576 }
   4577 
   4578 ///////////////////////
   4579 // End Low-level port processing
   4580 ///////////////////////
   4581 
   4582 
   4583 //////////////////////////////
   4584 // Logging & Diagnostics
   4585 //////////////////////////////
   4586 
   4587 void PVMFSocketNode::LogRTPHeaderFields(SocketPortConfig& aSockConfig,
   4588                                         OsclRefCounterMemFrag& memFragIn)
   4589 {
   4590     OSCL_UNUSED_ARG(aSockConfig);
   4591     uint8* rtpHeader = NULL;
   4592     uint32 rtpPacketLen = 0;
   4593 
   4594     /* Get start of RTP packet */
   4595     rtpHeader    = (uint8*)(memFragIn.getMemFrag().ptr);
   4596     rtpPacketLen = memFragIn.getMemFrag().len;
   4597 
   4598     if ((rtpHeader != NULL) && (rtpPacketLen > 0))
   4599     {
   4600         /* is this a legal data packet? */
   4601         if (rtpPacketLen <= 12)
   4602         {
   4603             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode - illegal RTP pkt size"));
   4604         }
   4605 
   4606         /* Parse RTP version */
   4607         uint8  rtpVersion = (((*rtpHeader) & 0xC0) >> 6);
   4608         if (rtpVersion != 2)
   4609         {
   4610             PVMF_SOCKETNODE_LOGDATATRAFFIC_E((0, "PVMFSocketNode illegal rtp version"));
   4611         }
   4612 
   4613         /* Check for padding */
   4614         uint8 pbit = (((*rtpHeader) & 0x20) >> 5);
   4615         uint8 numPaddingOctets = 0;
   4616         if (pbit)
   4617         {
   4618             numPaddingOctets = *(rtpHeader + (rtpPacketLen - 1));
   4619         }
   4620 
   4621         // skip over xbit, csrc and mbit
   4622         rtpHeader++;
   4623 
   4624         rtpHeader++;
   4625 
   4626         /* Parse sequence number */
   4627         uint16 seqNum16 = 0;
   4628         oscl_memcpy((char *)&seqNum16, rtpHeader, sizeof(seqNum16));
   4629         big_endian_to_host((char *)&seqNum16, sizeof(seqNum16));
   4630         rtpHeader += 2;
   4631 
   4632         /* Parse rtp time stamp */
   4633         uint32 ts32 = 0;
   4634         oscl_memcpy((char *)&ts32, rtpHeader, sizeof(ts32));
   4635         big_endian_to_host((char *)&ts32, sizeof(ts32));
   4636         rtpHeader += 4;
   4637 
   4638         /* Parse SSRC */
   4639         uint32 ssrc32 = 0;
   4640         oscl_memcpy((char *)&ssrc32, rtpHeader, sizeof(ssrc32));
   4641         big_endian_to_host((char *)&ssrc32, sizeof(ssrc32));
   4642         rtpHeader += 4;
   4643 
   4644         PVMF_SOCKETNODE_LOGDATATRAFFIC_RTP((0, "SN-RTP - Mime=%s, ssrc=%d, seq=%d, ts=%d, len=%d",
   4645                                             aSockConfig.iMime.get_cstr(), ssrc32, (uint32)seqNum16, (PVMFTimestamp)ts32, rtpPacketLen));
   4646     }
   4647 }
   4648 
   4649 void PVMFSocketNode::LogRTCPHeaderFields(SocketPortConfig& aSockConfig,
   4650         OsclRefCounterMemFrag& memFragIn)
   4651 {
   4652     OSCL_UNUSED_ARG(aSockConfig);
   4653     const uint8 SR_PACKET_TYPE = 200;
   4654     const uint8 RR_PACKET_TYPE = 201;
   4655     const uint8 SDES_PACKET_TYPE = 202;
   4656     const uint8 BYE_PACKET_TYPE = 203;
   4657     const uint8 APP_PACKET_TYPE = 204;
   4658     uint8* rtcpHeader = NULL;
   4659     int32 rtcpPacketLen = 0;
   4660 
   4661     /* Get start of RTP packet */
   4662     rtcpHeader    = (uint8*)(memFragIn.getMemFrag().ptr);
   4663     rtcpPacketLen = (int32)(memFragIn.getMemFrag().len);
   4664 
   4665     if ((rtcpHeader != NULL) && (rtcpPacketLen > 0))
   4666     {
   4667         while (rtcpPacketLen > 0)
   4668         {
   4669             OsclBinIStreamBigEndian inStream;
   4670             inStream.Attach(rtcpHeader, rtcpPacketLen);
   4671             uint8 tempChar;
   4672             inStream >> tempChar;
   4673             if (inStream.fail())
   4674             {
   4675                 PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, Invalid RTCP Packet",
   4676                                                      aSockConfig.iMime.get_cstr()));
   4677                 return;
   4678             }
   4679             // read the type
   4680             uint8 payloadType;
   4681             uint16 rtcpLength;
   4682             inStream >> payloadType;
   4683             inStream >> rtcpLength;
   4684             if (inStream.fail())
   4685             {
   4686                 PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, Invalid RTCP Packet Headers",
   4687                                                      aSockConfig.iMime.get_cstr()));
   4688                 return;
   4689             }
   4690             switch (payloadType)
   4691             {
   4692                 case SR_PACKET_TYPE:
   4693                 {
   4694                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP_SR RECVD",
   4695                                                          aSockConfig.iMime.get_cstr()));
   4696                 }
   4697                 break;
   4698 
   4699                 case RR_PACKET_TYPE:
   4700                 {
   4701                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP_RR RECVD",
   4702                                                          aSockConfig.iMime.get_cstr()));
   4703                 }
   4704                 break;
   4705 
   4706                 case SDES_PACKET_TYPE:
   4707                 {
   4708                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP_SDES_PKT RECVD",
   4709                                                          aSockConfig.iMime.get_cstr()));
   4710                 }
   4711                 break;
   4712 
   4713                 case BYE_PACKET_TYPE:
   4714                 {
   4715                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP_BYE RECVD",
   4716                                                          aSockConfig.iMime.get_cstr()));
   4717                 }
   4718                 break;
   4719 
   4720                 case APP_PACKET_TYPE:
   4721                 {
   4722                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP_APP_PKT RECVD",
   4723                                                          aSockConfig.iMime.get_cstr()));
   4724                 }
   4725                 break;
   4726 
   4727                 default:
   4728                     break;
   4729             }
   4730             rtcpPacketLen -= (rtcpLength + 1) * 4;
   4731             rtcpHeader += (rtcpLength + 1) * 4;
   4732             if (rtcpLength)
   4733             {
   4734                 inStream.seekFromCurrentPosition((rtcpLength*4));
   4735                 if (inStream.fail())
   4736                 {
   4737                     PVMF_SOCKETNODE_LOGDATATRAFFIC_RTCP((0, "SN-RTCP - Mime=%s, RTCP Packet Read Failed",
   4738                                                          aSockConfig.iMime.get_cstr()));
   4739                     return;
   4740                 }
   4741             }
   4742         } //end of while loop
   4743     }
   4744 }
   4745 
   4746 //////////////////////////////
   4747 // End Logging & Diagnostics
   4748 //////////////////////////////
   4749 
   4750 
   4751 ///////////////////////////////////
   4752 // AO
   4753 ///////////////////////////////////
   4754 
   4755 void PVMFSocketNode::Run()
   4756 {
   4757     PVMF_SOCKETNODE_LOGSTACKTRACE((0, "PVMFSocketNode::Run() In"));
   4758 
   4759 #if(ENABLE_SOCKET_NODE_STATS)
   4760     iSocketNodeStats.iNumRun++;
   4761 #endif
   4762 
   4763     if (!iClosedTCPSocketVector.empty())
   4764         CleanupClosedTCPSockets();
   4765     if (!iClosedUDPSocketVector.empty())
   4766         CleanupClosedUDPSockets();
   4767     if (!iClosedDNSVector.empty())
   4768         CleanupClosedDNS();
   4769 
   4770     //Process node commands
   4771     while (CanProcessCommand())
   4772         ProcessCommand(iPendingCmdQueue, iPendingCmdQueue.front());
   4773 }
   4774 
   4775 int32 PVMFSocketNode::SocketPlacementNew(PVMFSocketNodeMemPool *& aMemPool, OsclAny *aMemPtr, int32 aMemPoolNumBufs)
   4776 {
   4777     int32 errcode = 0;
   4778     OSCL_TRY(errcode, aMemPool = OSCL_PLACEMENT_NEW(aMemPtr, PVMFSocketNodeMemPool(aMemPoolNumBufs);));
   4779     return errcode;
   4780 }
   4781 
   4782 int32 PVMFSocketNode::CreateMediaData(SocketPortConfig& aSockConfig, OsclSharedPtr< PVMFMediaDataImpl > &aMediaptr)
   4783 {
   4784     int32 err = 0;
   4785     OSCL_TRY_NO_TLS(iOsclErrorTrapImp, err,
   4786                     aSockConfig.iPendingRecvMediaData = PVMFMediaData::createMediaData(aMediaptr, aSockConfig.iMemPool->iMediaDataMemPool););
   4787     return err;
   4788 }
   4789 
   4790 int32 PVMFSocketNode::Allocate(SocketPortConfig &aSockConfig, OsclSharedPtr< PVMFMediaDataImpl > &aMediaFragGroup)
   4791 {
   4792 #if SNODE_ENABLE_UDP_MULTI_PACKET
   4793     int32 err = 0;
   4794     OSCL_TRY_NO_TLS(iOsclErrorTrapImp, err,
   4795                     aMediaFragGroup = aSockConfig.iMemPool->iMediaFragGroupAlloc->allocate(););
   4796     return err;
   4797 #else
   4798     return OsclErrNotSupported;
   4799 #endif
   4800 }
   4801 
   4802 int32 PVMFSocketNode::GetMediaDataImpl(SocketPortConfig& aSockConfig, OsclSharedPtr<PVMFMediaDataImpl> &aMediaDataImpl, int32 aMemSize)
   4803 {
   4804     int32 err = 0;
   4805     aMediaDataImpl = aSockConfig.iMemPool->getMediaDataImpl(aMemSize);
   4806     if (NULL == aMediaDataImpl.GetRep())
   4807     {
   4808         err = OsclErrNoMemory;
   4809     }
   4810     return err;
   4811 }
   4812 
   4813