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