• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs)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 
CreateAllocators(const OSCL_HeapString<OsclMemAllocator> & iMime,uint32 aSize,uint32 aExpectedNumberOfBlocksPerBuffer,uint32 aResizeSize,uint32 aMaxNumResizes)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 
CreateResizableDataBufferAllocator(const char * allocatorName)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 
CreateDefaultDataBufferAllocator(const char * allocatorName)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 
CreateUDPMultipleRecvAllocator()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 
GetMaxSizeMediaMsgLen()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 
DestroyAllocators()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 
DestroyUDPMultipleRecvAllocator()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)
Log(PVMFPortVector<PVMFSocketPort,PVMFSocketNodeAllocator> & aPortVec)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 
CreateAllocators(uint32 aSize,uint32 aExpectedNumberOfBlocksPerBuffer,uint32 aResizeSize,uint32 aMaxNumResizes)237 void SocketPortConfig::CreateAllocators(uint32 aSize, uint32 aExpectedNumberOfBlocksPerBuffer, uint32 aResizeSize, uint32 aMaxNumResizes)
238 {
239     iMemPool->CreateAllocators(iMime, aSize, aExpectedNumberOfBlocksPerBuffer, aResizeSize, aMaxNumResizes);
240 }
241 
CleanupMemPools(Oscl_DefAlloc & aAlloc)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 
PVMFSocketNode(int32 aPriority)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 
~PVMFSocketNode()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.
ThreadLogon()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.
ThreadLogoff()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.
GetCapability(PVMFNodeCapability & aNodeCapability)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.
GetPorts(const PVMFPortFilter * aFilter)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 
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)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 
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)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 
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)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 
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)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 
Init(PVMFSessionId s,const OsclAny * aContext)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 
Prepare(PVMFSessionId s,const OsclAny * aContext)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 
Start(PVMFSessionId s,const OsclAny * aContext)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 
Stop(PVMFSessionId s,const OsclAny * aContext)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 
Flush(PVMFSessionId s,const OsclAny * aContext)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 
Pause(PVMFSessionId s,const OsclAny * aContext)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 
Reset(PVMFSessionId s,const OsclAny * aContext)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 
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)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 
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)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
HandlePortActivity(const PVMFPortActivity & aActivity)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 
GetPortConfig(PVMFPortInterface & aPort,OsclNetworkAddress & aLocalAdd,OsclNetworkAddress & aRemoteAdd)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 
SetPortConfig(PVMFPortInterface & aPort,OsclNetworkAddress aLocalAdd,OsclNetworkAddress aRemoteAdd)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.
AllocateConsecutivePorts(PvmfMimeString * aPortConfig,uint32 & aLowerPortNum,uint32 & aHigherPortNum,uint32 & aStartPortNum)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 
SetMaxTCPRecvBufferSize(uint32 aBufferSize)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 
GetMaxTCPRecvBufferSize(uint32 & aSize)840 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::GetMaxTCPRecvBufferSize(uint32& aSize)
841 {
842     aSize = iMaxTcpRecvBufferSize;
843     return PVMFSuccess;
844 }
845 
SetMaxTCPRecvBufferCount(uint32 aCount)846 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::SetMaxTCPRecvBufferCount(uint32 aCount)
847 {
848     iMaxTcpRecvBufferCount = aCount;
849     return PVMFSuccess;
850 }
851 
GetMaxTCPRecvBufferCount(uint32 & aCount)852 OSCL_EXPORT_REF PVMFStatus PVMFSocketNode::GetMaxTCPRecvBufferCount(uint32& aCount)
853 {
854     aCount = iMaxTcpRecvBufferCount;
855     return PVMFSuccess;
856 }
857 
CreateSharedBuffer(const PVMFPortInterface * aPort,uint32 aBufferSize,uint32 aExpectedNumberOfBlocksPerBuffer,uint32 aResizeSize,uint32 aMaxNumResizes)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.
CanProcessIncomingMsg(SocketPortConfig & aSockConfig)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".
ProcessIncomingMsg(SocketPortConfig & aSockConfig)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.
StartConnectOperation(SocketPortConfig & aSockConfig,TPVSocketPortConnectOperation aOperation)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".
ConnectOperationComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus,PVMFSocketActivity * 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 
CancelConnectOperation(SocketPortConfig & aSockConfig)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.
CanReceive(SocketPortConfig & aSockConfig)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
StartRecvWaitOnMemory(SocketPortConfig & aSockConfig,int32 aSize)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
StartRecvWaitOnConnectedPort(SocketPortConfig & aSockConfig,PVMFSocketActivity & aSocketActivity)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.
StartRecvOperation(SocketPortConfig & aSockConfig)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".
RecvOperationComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus,PVMFSocketActivity * 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.
CancelRecvOperation(SocketPortConfig & aSockConfig)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
freechunkavailable(OsclAny * aContextData)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 
freeblockavailable(OsclAny * aContextData)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.
HandleRecvComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity,bool aRecvOperationCanceled)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.
HandleRecvFromComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity,bool aRecvOperationCanceled)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.
StartSendOperation(SocketPortConfig & aSockConfig,PVMFSharedMediaMsgPtr & aMsg)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.
SendOperationComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus,PVMFSocketActivity * aSocketActivity)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.
CancelSendOperation(SocketPortConfig & aSockConfig)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.
StartSequence(SocketPortConfig & aSockConfig,TPVSocketPortSequence aSequence,OsclAny * aParam)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.
SequenceComplete(SocketPortConfig & aSockConfig,PVMFStatus aStatus)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.
CanProcessCommand()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.
ProcessCommand(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd)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.
CommandComplete(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
QueueCommandL(PVMFSocketNodeCommand & aCmd)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 
DoReset(PVMFSocketNodeCommand & aCmd)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 
DoQueryUuid(PVMFSocketNodeCommand & aCmd)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 
queryInterface(const PVUuid & uuid,PVInterface * & iface)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 
DoQueryInterface(PVMFSocketNodeCommand & aCmd)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 
DoRequestPort(PVMFSocketNodeCommand & aCmd,PVMFSocketPort * & aPort)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.
DoReleasePort(PVMFSocketNodeCommand & aCmd)3509 PVMFStatus PVMFSocketNode::DoReleasePort(PVMFSocketNodeCommand& aCmd)
3510 {
3511     OSCL_UNUSED_ARG(aCmd);
3512     return PVMFSuccess;
3513 }
3514 
DoInit(PVMFSocketNodeCommand & aCmd)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.
DoPrepare(PVMFSocketNodeCommand & aCmd)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 
DoStart(PVMFSocketNodeCommand & aCmd)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 
DoStop(PVMFSocketNodeCommand & aCmd)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
DoStopNodeActivity()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.
DoFlush(PVMFSocketNodeCommand & aCmd)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.
DoPause(PVMFSocketNodeCommand & aCmd)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 
DoCancelCommand(PVMFSocketNodeCommand & aCmd)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 
DoCancelAllCommands(PVMFSocketNodeCommand & aCmd)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.
DoCancelCurrentCommand(PVMFSocketNodeCmdQ & aCmdQ,PVMFSocketNodeCommand & aCmd)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 
HandleDNSEvent(int32 aId,TPVDNSFxn aFxn,TPVDNSEvent aEvent,int32 aError)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.
HandleSocketEvent(int32 aId,TPVSocketFxn aFxn,TPVSocketEvent aEvent,int32 aError)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.
AddPort(int32 tag,PVMFSocketPort * & port)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.
AllocatePortMemPool(int32 tag,PVMFSocketNodeMemPool * & aMemPool)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.
FindSocketPortConfig(SOCKET_ADDR & aSockAddr)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
MatchSocketAddr(SOCKET_ADDR & aSockAddr,SocketPortConfig & aSockConfig)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.
FindSocketPortConfig(uint32 aId)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*.
CreateOsclSocketAndBind(SOCKET_ADDR & aSockAdd,uint32 aSockId)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.
CleanupTCP(SocketPortConfig & aSockConfig)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
CleanupUDP(SocketPortConfig & aSockConfig)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 
CleanupDNS(SocketPortConfig & aSockConfig)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.
CleanupPorts()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 
CleanupClosedTCPSockets()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 
CleanupClosedUDPSockets()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 
CleanupClosedDNS()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 
ParseTransportConfig(OSCL_String * aPortConfig,SOCKET_ADDR & aSockConfig,OSCL_String & aMime)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 
ParseTransportConfig(char * aPortConfig,int32 aLen,SOCKET_ADDR & aSockConfig,OSCL_String & aMime)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 
LogRTPHeaderFields(SocketPortConfig & aSockConfig,OsclRefCounterMemFrag & memFragIn)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 
LogRTCPHeaderFields(SocketPortConfig & aSockConfig,OsclRefCounterMemFrag & memFragIn)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 
Run()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 
SocketPlacementNew(PVMFSocketNodeMemPool * & aMemPool,OsclAny * aMemPtr,int32 aMemPoolNumBufs)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 
CreateMediaData(SocketPortConfig & aSockConfig,OsclSharedPtr<PVMFMediaDataImpl> & aMediaptr)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 
Allocate(SocketPortConfig & aSockConfig,OsclSharedPtr<PVMFMediaDataImpl> & aMediaFragGroup)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 
GetMediaDataImpl(SocketPortConfig & aSockConfig,OsclSharedPtr<PVMFMediaDataImpl> & aMediaDataImpl,int32 aMemSize)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