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