| /* ------------------------------------------------------------------ |
| * Copyright (C) 2008 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #ifndef PVMF_SOCKET_NODE_H_INCLUDED |
| #define PVMF_SOCKET_NODE_H_INCLUDED |
| |
| #ifndef OSCL_BASE_H_INCLUDED |
| #include "oscl_base.h" |
| #endif |
| #ifndef OSCLCONFIG_IO_H_INCLUDED |
| #include "osclconfig_io.h" |
| #endif |
| #ifndef OSCL_FILE_IO_H_INCLUDED |
| #include "oscl_file_io.h" |
| #endif |
| #ifndef OSCL_PRIQUEUE_H_INCLUDED |
| #include "oscl_priqueue.h" |
| #endif |
| #ifndef OSCL_SCHEDULER_AO_H_INCLUDED |
| #include "oscl_scheduler_ao.h" |
| #endif |
| #ifndef OSCL_SOCKET_TYPES_H_INCLUDED |
| #include "oscl_socket_types.h" |
| #endif |
| #ifndef OSCL_SOCKET_H_INCLUDED |
| #include "oscl_socket.h" |
| #endif |
| #ifndef OSCL_DNS_H_INCLUDED |
| #include "oscl_dns.h" |
| #endif |
| #include "oscl_tickcount.h" |
| #include "oscl_mem_mempool.h" |
| |
| #ifndef PVMF_FORMAT_TYPE_H_INCLUDED |
| #include "pvmf_format_type.h" |
| #endif |
| #ifndef PVMF_SIMPLE_MEDIA_BUFFER_H_INCLUDED |
| #include "pvmf_simple_media_buffer.h" |
| #endif |
| #ifndef PVMF_MEDIA_DATA_H_INCLUDED |
| #include "pvmf_media_data.h" |
| #endif |
| #ifndef PVMF_NODE_INTERFACE_H_INCLUDED |
| #include "pvmf_node_interface.h" |
| #endif |
| |
| #ifndef PVMI_DATA_STREAM_INTERFACE_H_INCLUDED |
| #include "pvmi_data_stream_interface.h" |
| #endif |
| |
| #include "pvmf_node_utils.h" |
| #include "pvmf_socket_port.h" |
| |
| #ifndef PVMF_SOCKET_NODE_EXTENSION_INTERFACE_H_INCLUDED |
| #include "pvmf_socket_node_extension_interface.h" |
| #endif |
| |
| #ifndef PVMF_SM_TUNABLES_H_INCLUDED |
| #include "pvmf_sm_tunables.h" |
| #endif |
| |
| #include "pvmf_socket_node_events.h" |
| #include "pvmf_media_frag_group.h" |
| |
| //Enable socket node stats unless this is a release build. |
| #include "osclconfig.h" |
| #if(OSCL_RELEASE_BUILD) |
| #define ENABLE_SOCKET_NODE_STATS 0 |
| #else |
| #define ENABLE_SOCKET_NODE_STATS 1 |
| #endif |
| |
| //Logger macros |
| #define PVMF_SOCKETNODE_LOGSTACKTRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_STACK_TRACE,m); |
| #define PVMF_SOCKETNODE_LOGINFO(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_INFO,m); |
| #define PVMF_SOCKETNODE_LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); |
| #define PVMF_SOCKETNODE_LOGWARNING(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_WARNING,m); |
| #define PVMF_SOCKETNODE_LOGDATATRAFFIC_I(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_INFO,m); |
| #define PVMF_SOCKETNODE_LOGDATATRAFFIC_E(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_ERR,m); |
| |
| //memory allocator type for this node. |
| typedef OsclMemAllocator PVMFSocketNodeAllocator; |
| |
| //Node command type. |
| typedef PVMFGenericNodeCommand<PVMFSocketNodeAllocator> PVMFSocketNodeCommandBase; |
| class PVMFSocketNodeCommand: public PVMFSocketNodeCommandBase |
| { |
| public: |
| |
| }; |
| |
| //Default vector reserve size |
| #define PVMF_SOCKET_NODE_COMMAND_VECTOR_RESERVE 10 |
| |
| //Starting value for command IDs |
| #define PVMF_SOCKET_NODE_COMMAND_ID_START 6000 |
| |
| class PVLogger; |
| class PVMFSocketPort; |
| |
| /** |
| * Mem pool class |
| */ |
| class PVMFSocketNodeMemPool |
| { |
| public: |
| PVMFSocketNodeMemPool(uint32 aMemPoolNumBufs = DEFAULT_NUM_MEDIA_MSGS_IN_JITTER_BUFFER); |
| |
| virtual ~PVMFSocketNodeMemPool() |
| { |
| if (iMediaDataMemPool != NULL) |
| { |
| iMediaDataMemPool->removeRef(); |
| iMediaDataMemPool = NULL; |
| } |
| }; |
| |
| OsclSharedPtr<PVMFMediaDataImpl> getMediaDataImpl(uint32 size) |
| { |
| return (iSocketAllocSharedPtr->createSharedBuffer(size)); |
| } |
| |
| void resizeSocketDataBuffer(OsclSharedPtr<PVMFMediaDataImpl>& aSharedBuffer) |
| { |
| if (iSocketAllocSharedPtr.GetRep() != NULL) |
| { |
| iSocketAllocSharedPtr->ResizeMemoryFragment(aSharedBuffer); |
| } |
| } |
| |
| void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& aObserver, |
| uint32 aSize, |
| OsclAny* aContextData = NULL) |
| { |
| if (iSocketAllocSharedPtr.GetRep() != NULL) |
| { |
| iSocketAllocSharedPtr->notifyfreechunkavailable(aObserver, aSize, aContextData); |
| } |
| } |
| |
| void CancelFreeChunkAvailableCallback() |
| { |
| if (iSocketAllocSharedPtr.GetRep() != NULL) |
| { |
| iSocketAllocSharedPtr->CancelFreeChunkAvailableCallback(); |
| } |
| } |
| |
| OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> iSocketAllocSharedPtr; |
| |
| // Memory pool for media data objects |
| OsclMemPoolFixedChunkAllocator* iMediaDataMemPool; |
| |
| int32 iPortTag; |
| |
| // Allocator created in this node, for TCP only. |
| // (For UDP, the JB node owns the allocator and passes |
| // it in during the call to setSocketPortMemAllocator) |
| PVMFSMSharedBufferAllocWithReSize* iInternalAlloc; |
| |
| // Allocator for multiple receives, for UDP only. |
| PVMFMediaFragGroupCombinedAlloc<PVMFSocketNodeAllocator>* iMediaFragGroupAlloc; |
| OsclMemPoolFixedChunkAllocator* iMediaFragGroupAllocMempool; |
| }; |
| |
| /* |
| ** Socket address structure |
| */ |
| |
| enum PROTOCOL |
| { |
| INVALID_PROTOCOL, |
| INET_TCP, |
| INET_UDP |
| }; |
| |
| struct SOCKET_ADDR |
| { |
| PROTOCOL iProtocol; |
| |
| OsclNetworkAddress iLocalAdd; |
| OsclNetworkAddress iRemoteAdd; |
| |
| OSCL_HeapString<PVMFSocketNodeAllocator> iRemoteHost; //could be either DNS or ip address |
| |
| //each socket maps to a port, hence a port tag is needed for unique identification |
| int32 iTag; |
| }; |
| |
| class PVMFSocketNode; |
| |
| /* |
| ** Socket activity class is used to save Oscl socket or DNS results |
| */ |
| class PVMFSocketActivity |
| { |
| public: |
| PVMFSocketActivity(): iValid(false) |
| { |
| } |
| PVMFSocketActivity(PVMFStatus aStatus, int32 aId, int32 aFxn, int32 aEvent, int32 aError) |
| { |
| Set(aStatus, aId, aFxn, aEvent, aError); |
| } |
| void Set(PVMFStatus aStatus, int32 aId, int32 aFxn, int32 aEvent, int32 aError) |
| { |
| iValid = true; |
| iStatus = aStatus; |
| iId = aId; |
| iFxn = aFxn; |
| iEvent = aEvent; |
| iError = aError; |
| } |
| bool iValid; |
| PVMFStatus iStatus; |
| int32 iId; |
| int32 iFxn; |
| int32 iEvent; |
| int32 iError; |
| |
| private: |
| |
| }; |
| |
| |
| /* |
| ** The Socket port state keeps track of the Connect, Receive, and Send operations on |
| ** a port, including wait states. Note there may be simultaneous send & receive on |
| ** a port, so it is necessary to keep separate status. Connect operations cannot |
| ** be concurrent with either send or receive operations, but for simplicity, the |
| ** connect status is also maintained separately. |
| ** |
| ** The port state also contains information about sequences of operations. |
| */ |
| |
| //Individual asynchronous operations and wait states that make up a connect or |
| //disconnect sequence. |
| enum TPVSocketPortConnectOperation |
| { |
| EPVSocketPortConnectOperation_None |
| , EPVSocketPortConnectOperation_GetHostByName |
| , EPVSocketPortConnectOperation_Connect |
| , EPVSocketPortConnectOperation_Shutdown |
| , EPVSocketPortConnectOperation_WaitOnConnectedPort //for sending EOS during disconnect. |
| , EPVSocketPortConnectOperation_WaitOnSendRecvIdle //for shutdown & cleanup. |
| , EPVSocketPortConnectOperation_Last |
| }; |
| |
| //Individual asynchronous operations and wait states that make up a send sequence. |
| enum TPVSocketPortSendOperation |
| { |
| EPVSocketPortSendOperation_None |
| , EPVSocketPortSendOperation_Send |
| , EPVSocketPortSendOperation_SendTo |
| , EPVSocketPortSendOperation_Last |
| }; |
| |
| //Individual asynchronous operations and wait states that make up a receive sequence. |
| enum TPVSocketPortRecvOperation |
| { |
| EPVSocketPortRecvOperation_None |
| , EPVSocketPortRecvOperation_Recv |
| , EPVSocketPortRecvOperation_RecvFrom |
| , EPVSocketPortRecvOperation_WaitOnConnectedPort |
| , EPVSocketPortRecvOperation_WaitOnMemory |
| , EPVSocketPortRecvOperation_Last |
| }; |
| |
| //Sequences that may require multiple asynchronous operations |
| //and/or wait states. There can only be one of these sequences active |
| //on a port at a time. For definitions of the operations that make |
| //up these sequences, please see the comments in the StartSequence |
| //implementation. |
| enum TPVSocketPortSequence |
| { |
| EPVSocketPortSequence_None |
| , EPVSocketPortSequence_RequestPort |
| , EPVSocketPortSequence_InputConnectMsg |
| , EPVSocketPortSequence_InputDataMsg |
| , EPVSocketPortSequence_InputDisconnectMsg |
| , EPVSocketPortSequence_SocketCleanup |
| , EPVSocketPortSequence_Last |
| }; |
| |
| class SocketNodePortStats; |
| |
| class SocketPortState |
| { |
| public: |
| SocketPortState(): iSequence(EPVSocketPortSequence_None) |
| , iSequenceStatus(PVMFSuccess) |
| , iConnectOperation(EPVSocketPortConnectOperation_None) |
| , iConnectOperationStatus(PVMFSuccess) |
| , iConnectOperationCanceled(false) |
| , iSendOperation(EPVSocketPortSendOperation_None) |
| , iSendOperationStatus(PVMFSuccess) |
| , iSendOperationCanceled(false) |
| , iRecvOperation(EPVSocketPortRecvOperation_None) |
| , iRecvOperationStatus(PVMFSuccess) |
| , iRecvOperationCanceled(false) |
| {} |
| |
| TPVSocketPortSequence iSequence; |
| PVMFStatus iSequenceStatus; |
| |
| TPVSocketPortConnectOperation iConnectOperation; |
| PVMFStatus iConnectOperationStatus; |
| bool iConnectOperationCanceled; |
| |
| TPVSocketPortSendOperation iSendOperation; |
| PVMFStatus iSendOperationStatus; |
| bool iSendOperationCanceled; |
| |
| TPVSocketPortRecvOperation iRecvOperation; |
| PVMFStatus iRecvOperationStatus; |
| bool iRecvOperationCanceled; |
| }; |
| |
| #if(ENABLE_SOCKET_NODE_STATS) |
| /* |
| ** SocketNodeStats and SocketNodePortStats are used for tracking performance |
| ** of socket node. |
| */ |
| |
| //SocketNodePortStats contains all data that is maintained on a per-port basis. |
| class SocketNodePortStats |
| { |
| public: |
| SocketNodePortStats() |
| { |
| oscl_memset(this, 0, sizeof(SocketNodePortStats)); |
| } |
| //port events. |
| uint32 iNumPortEventConnectedPortReady; |
| uint32 iNumPortEventConnect; |
| uint32 iNumPortEventIncomingMsg; |
| |
| //incoming messages |
| uint32 iNumDequeueIncomingConnectMsg; |
| uint32 iNumDequeueIncomingDisconnectMsg; |
| uint32 iNumDequeueIncomingDataMsg; |
| |
| //outgoing messages |
| uint32 iNumQueueOutgoingUDPMsg; |
| uint32 iNumQueueOutgoingTCPMsg; |
| uint32 iNumQueueOutgoingEOSMsg; |
| |
| //socket receive results that had to be queued while |
| //waiting on connected port |
| uint32 iNumQueueSocketRecv; |
| |
| //number of times wait states were entered. |
| uint32 iNumWaitOnMemory; |
| uint32 iNumWaitOnConnectedPort; |
| uint32 iNumWaitOnSendRecvIdle; |
| |
| //memory pool callbacks. |
| uint32 iNumFreeChunkCallback; |
| |
| //Oscl socket & OScl DNS callbacks |
| uint32 iNumSocketCallback; |
| uint32 iNumDNSCallback; |
| |
| //number of Oscl socket and Oscl DNS calls. |
| uint32 iNumSend; |
| uint32 iNumSendTo; |
| uint32 iNumRecv; |
| uint32 iNumRecvFrom; |
| uint32 iNumRecvFromPackets; |
| uint32 iMaxRecvFromPackets; |
| uint32 iNumGetHostByName; |
| uint32 iNumConnect; |
| uint32 iNumShutdown; |
| |
| //Latency times through this node. |
| uint32 iMaxConnectOperationTime[EPVSocketPortConnectOperation_Last]; |
| uint32 iMaxSendOperationTime[EPVSocketPortSendOperation_Last]; |
| uint32 iMaxRecvOperationTime[EPVSocketPortRecvOperation_Last]; |
| |
| uint32 iConnectOperationTime[EPVSocketPortConnectOperation_Last]; |
| uint32 iSendOperationTime[EPVSocketPortSendOperation_Last]; |
| uint32 iRecvOperationTime[EPVSocketPortRecvOperation_Last]; |
| |
| void StartConnectTime(TPVSocketPortConnectOperation aOp) |
| { |
| iConnectOperationTime[aOp] = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()); |
| } |
| void EndConnectTime(TPVSocketPortConnectOperation aOp) |
| { |
| uint32 delta = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()) - iConnectOperationTime[aOp]; |
| if (delta > iMaxConnectOperationTime[aOp]) |
| iMaxConnectOperationTime[aOp] = delta; |
| } |
| void StartRecvTime(TPVSocketPortRecvOperation aOp) |
| { |
| iRecvOperationTime[aOp] = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()); |
| } |
| void EndRecvTime(TPVSocketPortRecvOperation aOp) |
| { |
| uint32 delta = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()) - iRecvOperationTime[aOp]; |
| if (delta > iMaxRecvOperationTime[aOp]) |
| iMaxRecvOperationTime[aOp] = delta; |
| } |
| void StartSendTime(TPVSocketPortSendOperation aOp) |
| { |
| iSendOperationTime[aOp] = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()); |
| } |
| void EndSendTime(TPVSocketPortSendOperation aOp) |
| { |
| uint32 delta = OsclTickCount::TicksToMsec(OsclTickCount::TickCount()) - iSendOperationTime[aOp]; |
| if (delta > iMaxSendOperationTime[aOp]) |
| iMaxSendOperationTime[aOp] = delta; |
| } |
| void Log(PVLogger* iLogger, OSCL_String& aMime) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats:PORT '%s'", aMime.get_cstr())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num PortEventConnectedPortReady", iNumPortEventConnectedPortReady)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num PortEventConnect", iNumPortEventConnect)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num PortEventIncomingMsg", iNumPortEventIncomingMsg)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num DequeueIncomingConnectMsg", iNumDequeueIncomingConnectMsg)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num DequeueIncomingDisconnectMsg", iNumDequeueIncomingDisconnectMsg)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num DequeueIncomingDataMsg", iNumDequeueIncomingDataMsg)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num QueueOutgoingUDPMsg", iNumQueueOutgoingUDPMsg)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num QueueOutgoingTCPMsg", iNumQueueOutgoingTCPMsg)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num QueueOutgoingEOSMsg", iNumQueueOutgoingEOSMsg)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num QueueSocketRecv", iNumQueueSocketRecv)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num WaitOnMemory", iNumWaitOnMemory)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num WaitOnConnectedPort", iNumWaitOnConnectedPort)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num WaitOnSendRecvIdle", iNumWaitOnSendRecvIdle)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num FreeChunkCallback", iNumFreeChunkCallback)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num SocketCallback", iNumSocketCallback)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num DNSCallback", iNumDNSCallback)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num Send", iNumSend)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num SendTo", iNumSendTo)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num Recv", iNumRecv)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num RecvFrom", iNumRecvFrom)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num RecvFrom Packets", iNumRecvFromPackets)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max RecvFrom Packets", iMaxRecvFromPackets)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num GetHostByName", iNumGetHostByName)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num Connect", iNumConnect)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Num Shutdown", iNumShutdown)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Connect GetHostByName Time (msec)", iMaxConnectOperationTime[EPVSocketPortConnectOperation_GetHostByName])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Connect Time (msec)", iMaxConnectOperationTime[EPVSocketPortConnectOperation_Connect])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Connect Shutdown Time (msec)", iMaxConnectOperationTime[EPVSocketPortConnectOperation_Shutdown])); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Send Time (msec)", iMaxSendOperationTime[EPVSocketPortSendOperation_Send])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max SendTo Time (msec)", iMaxSendOperationTime[EPVSocketPortSendOperation_SendTo])); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Recv Time (msec)", iMaxRecvOperationTime[EPVSocketPortRecvOperation_Recv])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max RecvFrom Time (msec)", iMaxRecvOperationTime[EPVSocketPortRecvOperation_RecvFrom])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Recv Wait On Connected Port Time (msec)", iMaxRecvOperationTime[EPVSocketPortRecvOperation_WaitOnConnectedPort])); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats: %8d Max Recv Wait On Memory Time (msec)", iMaxRecvOperationTime[EPVSocketPortRecvOperation_WaitOnMemory])); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, |
| (0, "SocketNodeStats:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")); |
| } |
| }; |
| |
| //SocketNodeStats contains all data that is maintained on a per-node basis. |
| class SocketNodeStats |
| { |
| public: |
| SocketNodeStats() |
| { |
| oscl_memset(this, 0, sizeof(SocketNodeStats)); |
| } |
| |
| PVLogger* iLogger; |
| bool iLogged; |
| void Init() |
| { |
| iLogged = false; |
| iLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.socketnode"); |
| } |
| void Logoff() |
| { |
| iLogger = NULL; |
| } |
| |
| //Run calls |
| uint32 iNumRun; |
| |
| //Node cmds. |
| uint32 iNumQueueNodeCmd; |
| |
| //Number of UDP bind operations. |
| uint32 iNumBind; |
| |
| void Log(PVMFPortVector<PVMFSocketPort, PVMFSocketNodeAllocator>& aPortVec); |
| }; |
| #endif |
| |
| /* |
| ** SocketPortConfig contains all the information associated with a port including |
| ** the Oscl socket, memory pool, and status. |
| */ |
| class SocketPortConfig : public OsclMemPoolFixedChunkAllocatorObserver |
| { |
| public: |
| SocketPortConfig() |
| { |
| iPVMFPort = NULL; |
| iSockId = 0; |
| iUDPSocket = NULL; |
| iTCPSocket = NULL; |
| iDNS = NULL; |
| iMemPool = NULL; |
| iContainer = NULL; |
| iTag = PVMF_SOCKET_NODE_PORT_TYPE_UNKNOWN; |
| iRTP = false; |
| }; |
| |
| void DoSetSocketPortMemAllocator(PVLogger*, OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc); |
| void CleanupMemPools(); |
| |
| void freechunkavailable(OsclAny* aContextData); |
| |
| SocketPortState iState; |
| |
| PVMFSocketPort *iPVMFPort; |
| SOCKET_ADDR iAddr; |
| uint32 iSockId; |
| OsclUDPSocket* iUDPSocket; |
| OsclTCPSocket* iTCPSocket; |
| OsclDNS *iDNS; |
| OsclNetworkAddress iSourceAddr;//arg for recv from calls. |
| Oscl_Vector<uint32, OsclMemAllocator> iRecvFromPacketLen;//arg for recv from calls. |
| |
| //socket pending request and state |
| PVMFSharedMediaDataPtr iPendingRecvMediaData, iPendingSendMediaData; |
| |
| //Fixed chunk memory pool for media messages |
| PVMFSocketNodeMemPool *iMemPool; |
| |
| PVMFSocketNode* iContainer; |
| int32 iTag; |
| |
| PVMFSocketActivity iSocketRecvActivity; |
| |
| OSCL_HeapString<OsclMemAllocator> iMime; |
| bool iRTP; |
| |
| #if(ENABLE_SOCKET_NODE_STATS) |
| SocketNodePortStats iPortStats; |
| #endif |
| }; |
| |
| /* |
| ** DnsCache is used to cache DNS lookup results to avoid unnecessary lookups of a previously |
| ** used host. |
| */ |
| class PVMFDnsCache |
| { |
| public: |
| PVMFDnsCache(uint32 aNumOfRecords = 4): iNumOfRecords(aNumOfRecords), iAddrIP(NULL), iAddrDNS(NULL) |
| { |
| }; |
| ~PVMFDnsCache() |
| { |
| for (uint32 i = 0; i < iNumOfRecords; i++) |
| { |
| if (iAddrDNS) |
| { |
| if (NULL != iAddrDNS[i]) |
| { |
| OSCL_ARRAY_DELETE(iAddrDNS[i]); |
| iAddrDNS[i] = NULL; |
| } |
| } |
| if (iAddrIP) |
| { |
| if (NULL != iAddrIP[i]) |
| { |
| OSCL_ARRAY_DELETE(iAddrIP[i]); |
| iAddrIP[i] = NULL; |
| } |
| } |
| } |
| OSCL_ARRAY_DELETE(iAddrIP); |
| OSCL_ARRAY_DELETE(iAddrDNS); |
| } |
| void NewL(void) |
| { |
| iAddrIP = OSCL_ARRAY_NEW(char*, iNumOfRecords); |
| iAddrDNS = OSCL_ARRAY_NEW(char*, iNumOfRecords); |
| if ((NULL == iAddrIP) || (NULL == iAddrIP)) |
| { |
| OSCL_ARRAY_DELETE(iAddrIP); |
| OSCL_ARRAY_DELETE(iAddrDNS); |
| OSCL_LEAVE(OsclErrNoMemory); |
| } |
| for (uint32 i = 0; i < iNumOfRecords; i++) |
| iAddrDNS[i] = iAddrIP[i] = NULL; |
| }; |
| |
| //if name is not in record, add one; if it does, update it |
| bool UpdateCacheRecord(char *name, char *ipAddr) |
| { |
| for (uint32 i = 0; i < iNumOfRecords; i++) |
| { |
| if (NULL == iAddrDNS[i]) |
| {//new record |
| int32 tmpLen = oscl_strlen(name); |
| iAddrDNS[i] = OSCL_ARRAY_NEW(char, tmpLen + 4); |
| oscl_strncpy(iAddrDNS[i], name, tmpLen + 2); |
| iAddrIP[i] = OSCL_ARRAY_NEW(char, 32); |
| oscl_strncpy(iAddrIP[i], ipAddr, 30); |
| return true; |
| } |
| if (0 == oscl_strcmp(iAddrDNS[i], name)) |
| {//update record |
| if (oscl_strlen(ipAddr) + 1 > 32) |
| { |
| return false; |
| } |
| oscl_strncpy(iAddrIP[i], ipAddr, 30); |
| return true; |
| } |
| } |
| return false; |
| } |
| //find the ip address corresponds to name. len is the size of ipAddr bufferr |
| bool QueryGetHostByName(const char *name, char *ipAddr, const uint32 len) |
| { |
| for (uint32 i = 0; i < iNumOfRecords; i++) |
| { |
| if (NULL == iAddrDNS[i]) |
| return false; |
| if (0 == oscl_strcmp(iAddrDNS[i], name)) |
| { |
| if (oscl_strlen(iAddrIP[i]) + 1 > len) |
| { |
| return false; |
| } |
| oscl_strncpy(ipAddr, iAddrIP[i], 30); |
| return true; |
| } |
| } |
| return false; |
| } |
| private: |
| uint32 iNumOfRecords; |
| char** iAddrIP; |
| char** iAddrDNS; |
| }; |
| |
| /* |
| ** Memory pool sizes. |
| */ |
| #define SIMPLE_MEDIA_BUF_CLASS_SIZE 128 /*oscl_mem_aligned_size(sizeof(PVMFSimpleMediaBuffer) + oscl_mem_aligned_size(sizeof(OsclRefCounterSA<SimpleMediaBufferCombinedCleanupSA>)*/ |
| #define MEDIA_DATA_CLASS_SIZE 128 /*oscl_mem_aligned_size(sizeof(PVMFMediaData)) + oscl_mem_aligned_size(sizeof(OsclRefCounterDA)) + oscl_mem_aligned_size(sizeof(MediaDataCleanupDA)) + sizeof(PVMFMediaMsgHeader))*/ |
| |
| /* |
| ** The Socket Node |
| */ |
| class PVMFSocketNode |
| : public PVMFNodeInterface |
| , public OsclActiveObject |
| , public OsclSocketObserver |
| , public OsclDNSObserver |
| , public PVMFSocketNodeExtensionInterface |
| { |
| public: |
| |
| OSCL_IMPORT_REF PVMFSocketNode(int32 aPriority); |
| OSCL_IMPORT_REF ~PVMFSocketNode(); |
| |
| |
| //**********begin PVMFSocketNodeExtensionInterface |
| OSCL_IMPORT_REF void addRef(); |
| OSCL_IMPORT_REF void removeRef(); |
| OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface); |
| OSCL_IMPORT_REF PVMFStatus AllocateConsecutivePorts(PvmfMimeString* aPortConfig, |
| uint32& aLowerPortNum, |
| uint32& aHigherPortNum, uint32& aStartPortNum); |
| OSCL_IMPORT_REF PVMFStatus SetMaxTCPRecvBufferSize(uint32 aBufferSize); |
| OSCL_IMPORT_REF PVMFStatus GetMaxTCPRecvBufferSize(uint32& aSize); |
| OSCL_IMPORT_REF PVMFStatus SetMaxTCPRecvBufferCount(uint32 aBufferSize); |
| OSCL_IMPORT_REF PVMFStatus GetMaxTCPRecvBufferCount(uint32& aSize); |
| |
| //**********end PVMFSocketNodeExtensionInterface |
| |
| //************ begin OsclSocketObserver |
| OSCL_IMPORT_REF void HandleSocketEvent(int32 aId, TPVSocketFxn aFxn, TPVSocketEvent aEvent, int32 aError); |
| //************ end OsclSocketObserver |
| |
| //************ begin OsclDNSObserver |
| OSCL_IMPORT_REF void HandleDNSEvent(int32 aId, TPVDNSFxn aFxn, TPVDNSEvent aEvent, int32 aError); |
| //************ end OsclDNSObserver |
| |
| //from PVMFNodeInterface |
| OSCL_IMPORT_REF PVMFStatus ThreadLogon(); |
| OSCL_IMPORT_REF PVMFStatus ThreadLogoff(); |
| OSCL_IMPORT_REF PVMFStatus GetCapability(PVMFNodeCapability& aNodeCapability); |
| OSCL_IMPORT_REF PVMFPortIter* GetPorts(const PVMFPortFilter* aFilter = NULL); |
| OSCL_IMPORT_REF PVMFCommandId QueryUUID(PVMFSessionId, const PvmfMimeString& aMimeType, |
| Oscl_Vector<PVUuid, PVMFSocketNodeAllocator>& aUuids, |
| bool aExactUuidsOnly = false, |
| const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId QueryInterface(PVMFSessionId, const PVUuid& aUuid, |
| PVInterface*& aInterfacePtr, |
| const OsclAny* aContext = NULL); |
| |
| OSCL_IMPORT_REF PVMFCommandId RequestPort(PVMFSessionId aSession |
| , int32 aPortTag |
| , const PvmfMimeString* aPortConfig = NULL |
| , const OsclAny* aContext = NULL); |
| |
| OSCL_IMPORT_REF PVMFCommandId ReleasePort(PVMFSessionId, PVMFPortInterface& aPort, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Init(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Prepare(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Start(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Stop(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Flush(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Pause(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId Reset(PVMFSessionId, const OsclAny* aContext = NULL); |
| OSCL_IMPORT_REF PVMFCommandId CancelAllCommands(PVMFSessionId, const OsclAny* aContextData = NULL); |
| OSCL_IMPORT_REF PVMFCommandId CancelCommand(PVMFSessionId, PVMFCommandId aCmdId, const OsclAny* aContextData = NULL); |
| |
| //from PVMFPortActivityHandler |
| void HandlePortActivity(const PVMFPortActivity& aActivity); |
| |
| //These are some extra APIs that are used by Streaming Manager and are unique to socket node. |
| OSCL_IMPORT_REF bool GetPortConfig(PVMFPortInterface &aPort, OsclNetworkAddress &aLocalAdd, OsclNetworkAddress &aRemoteAdd); |
| OSCL_IMPORT_REF bool SetPortConfig(PVMFPortInterface &aPort, OsclNetworkAddress aLocalAdd, OsclNetworkAddress aRemoteAdd); |
| |
| OSCL_IMPORT_REF bool setSocketPortMemAllocator(PVMFPortInterface* aPort, |
| OsclSharedPtr<PVMFSharedSocketDataBufferAlloc> aAlloc); |
| |
| |
| private: |
| friend class SocketPortConfig; |
| |
| //from OsclActiveObject |
| void Run(); |
| |
| /********************************************* |
| * Socket extension interface |
| **********************************************/ |
| |
| // Reference counter for extension |
| uint32 iExtensionRefCount; |
| |
| /********************************************* |
| * Command Processing and Event Notification |
| **********************************************/ |
| |
| //Command queue type |
| typedef PVMFNodeCommandQueue<PVMFSocketNodeCommand, PVMFSocketNodeAllocator> PVMFSocketNodeCmdQ; |
| |
| PVMFSocketNodeCmdQ iPendingCmdQueue; |
| PVMFSocketNodeCmdQ iCurrentCmdQueue; |
| PVMFSocketNodeCmdQ iCancelCmdQueue; |
| |
| void MoveCmdToCancelQueue(PVMFSocketNodeCommand& aCmd); |
| |
| void CommandComplete(PVMFSocketNodeCmdQ&, |
| PVMFSocketNodeCommand&, |
| PVMFStatus, |
| OsclAny* aData = NULL, |
| PVUuid* aEventUUID = NULL, |
| int32* aEventCode = NULL); |
| |
| void ReportErrorEvent(PVMFEventType aEventType, |
| OsclAny* aEventData = NULL, |
| PVUuid* aEventUUID = NULL, |
| int32* aEventCode = NULL); |
| |
| void ReportInfoEvent(PVMFEventType aEventType, |
| OsclAny* aEventData = NULL, |
| PVUuid* aEventUUID = NULL, |
| int32* aEventCode = NULL); |
| |
| PVMFCommandId QueueCommandL(PVMFSocketNodeCommand& aCmd); |
| |
| bool CanProcessCommand(); |
| void ProcessCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand&); |
| |
| //Command handlers. |
| PVMFStatus DoRequestPort(PVMFSocketNodeCommand& aCmd, PVMFSocketPort* &port); |
| PVMFStatus DoReset(PVMFSocketNodeCommand&); |
| PVMFStatus DoQueryUuid(PVMFSocketNodeCommand&); |
| PVMFStatus DoQueryInterface(PVMFSocketNodeCommand&); |
| PVMFStatus DoReleasePort(PVMFSocketNodeCommand&); |
| PVMFStatus DoInit(PVMFSocketNodeCommand&); |
| PVMFStatus DoPrepare(PVMFSocketNodeCommand&); |
| PVMFStatus DoStart(PVMFSocketNodeCommand&); |
| PVMFStatus DoStop(PVMFSocketNodeCommand&); |
| PVMFStatus DoFlush(PVMFSocketNodeCommand&); |
| PVMFStatus DoPause(PVMFSocketNodeCommand&); |
| PVMFStatus DoCancelAllCommands(PVMFSocketNodeCommand&); |
| PVMFStatus DoCancelCommand(PVMFSocketNodeCommand&); |
| |
| PVMFStatus DoCancelCurrentCommand(PVMFSocketNodeCmdQ& aCmdQ, PVMFSocketNodeCommand& aCmd); |
| PVMFStatus DoStopNodeActivity(); |
| PVMFSocketPort* iRequestedPort; |
| |
| //node state |
| void ChangeExternalState(TPVMFNodeInterfaceState aNewState) |
| { |
| iInterfaceState = aNewState; |
| } |
| |
| //node capability |
| PVMFNodeCapability iCapability; |
| |
| //for error messages. |
| int32 iCommandErrorCode; |
| int32 iErrorEventErrorCode; |
| void ReportSocketNodeError(PVMFStatus aStatus, PVMFSocketNodeErrorEventType aEvent) |
| { |
| PVUuid eventuuid = PVMFSocketNodeEventTypeUUID; |
| iErrorEventErrorCode = aEvent; |
| ReportErrorEvent(aStatus, NULL, &eventuuid, &iErrorEventErrorCode); |
| } |
| |
| //Used to stop all port activity, this var counts down from N to 0, or |
| //has a value of (-1) to indicate it's inactive |
| int32 iNumStopPortActivityPending; |
| |
| /********************************************* |
| * Oscl Socket Handling |
| **********************************************/ |
| |
| void HandleRecvComplete(SocketPortConfig& tmpSockConfig, PVMFStatus, PVMFSocketActivity*); |
| void HandleRecvFromComplete(SocketPortConfig& tmpSockConfig, PVMFStatus, PVMFSocketActivity*); |
| |
| OsclSocketServ *iSockServ; |
| |
| const int TIMEOUT_CONNECT; |
| const int TIMEOUT_SEND; |
| const int TIMEOUT_SENDTO; |
| const int TIMEOUT_RECV; |
| const int TIMEOUT_RECVFROM; |
| const int TIMEOUT_SHUTDOWN; |
| const int UDP_PORT_RANGE; |
| const int MAX_UDP_PACKET_SIZE; |
| |
| int32 iMaxTcpRecvBufferSize; |
| int32 iMaxTcpRecvBufferCount; |
| |
| /********************************************* |
| * Oscl DNS Handling |
| **********************************************/ |
| |
| PVMFDnsCache iDnsCache; |
| |
| /********************************************* |
| * Port Data Handling |
| **********************************************/ |
| |
| bool CanProcessIncomingMsg(SocketPortConfig& aSockConfig); |
| |
| void ProcessIncomingMsg(SocketPortConfig& aSockConfig); |
| |
| bool ParseTransportConfig(OSCL_String *aPortConfig, |
| SOCKET_ADDR &aSockConfig, |
| OSCL_String& aMime); |
| bool ParseTransportConfig(char *aPortConfig, |
| int32 aLen, |
| SOCKET_ADDR &aSockConfig, |
| OSCL_String& aMime); |
| |
| /********************************************* |
| * Port & Socket Creation |
| **********************************************/ |
| |
| PVMFStatus AllocatePortMemPool(int32 tag, PVMFSocketNodeMemPool* & aMemPool); |
| PVMFStatus AddPort(int32 tag, PVMFSocketPort* &port); |
| void CleanupTCP(SocketPortConfig& tmpSockConfig); |
| void CleanupUDP(SocketPortConfig& tmpSockConfig); |
| void CleanupDNS(SocketPortConfig& tmpSockConfig); |
| void CleanupPorts(); |
| |
| OsclAny* CreateOsclSocketAndBind(SOCKET_ADDR &, uint32); |
| |
| uint32 iSocketID; |
| bool iInSocketCallback; |
| |
| Oscl_Vector<OsclTCPSocket*, OsclMemAllocator> iClosedTCPSocketVector; |
| void CleanupClosedTCPSockets(); |
| Oscl_Vector<OsclUDPSocket*, OsclMemAllocator> iClosedUDPSocketVector; |
| void CleanupClosedUDPSockets(); |
| Oscl_Vector<OsclDNS*, OsclMemAllocator> iClosedDNSVector; |
| void CleanupClosedDNS(); |
| |
| /********************************************* |
| * Port Data |
| **********************************************/ |
| |
| PVMFPortVector<PVMFSocketPort, PVMFSocketNodeAllocator> iPortVector; |
| Oscl_Vector<SocketPortConfig*, PVMFSocketNodeAllocator> iAllocatedPortVector; |
| |
| SocketPortConfig* FindSocketPortConfig(SOCKET_ADDR& aSockConfig); |
| bool MatchSocketAddr(SOCKET_ADDR& aSockAddr, SocketPortConfig& aSockConfig); |
| SocketPortConfig* FindSocketPortConfig(uint32 aId); |
| |
| /********************************************* |
| * Operation and Sequence Handlers |
| **********************************************/ |
| |
| PVMFStatus StartSequence(SocketPortConfig&, TPVSocketPortSequence, OsclAny* param = NULL); |
| void SequenceComplete(SocketPortConfig& tmpSockConfig, PVMFStatus); |
| |
| bool CanReceive(SocketPortConfig& aConfig); |
| |
| PVMFStatus StartConnectOperation(SocketPortConfig& aSockConfig, TPVSocketPortConnectOperation aOperation); |
| PVMFStatus StartRecvOperation(SocketPortConfig& aSockConfig); |
| PVMFStatus StartSendOperation(SocketPortConfig& aSockConfig, PVMFSharedMediaMsgPtr& aMsg); |
| void StartRecvWaitOnMemory(SocketPortConfig& aSockConfig, int32 aSize = 0); |
| void StartRecvWaitOnConnectedPort(SocketPortConfig& aSockConfig, PVMFSocketActivity& aSocketActivity); |
| |
| PVMFStatus ConnectOperationComplete(SocketPortConfig& tmpSockConfig, PVMFStatus, PVMFSocketActivity*); |
| PVMFStatus SendOperationComplete(SocketPortConfig& tmpSockConfig, PVMFStatus, PVMFSocketActivity*); |
| PVMFStatus RecvOperationComplete(SocketPortConfig& tmpSockConfig, PVMFStatus, PVMFSocketActivity*); |
| |
| PVMFStatus CancelSendOperation(SocketPortConfig& tmpSockConfig); |
| PVMFStatus CancelRecvOperation(SocketPortConfig& tmpSockConfig); |
| PVMFStatus CancelConnectOperation(SocketPortConfig& tmpSockConfig); |
| |
| /********************************************* |
| * Loggers, Error Trap, Allocator |
| **********************************************/ |
| |
| PVLogger *iLogger; |
| PVLogger *iDataPathLogger; |
| |
| void LogRTPHeaderFields(SocketPortConfig& aSockConfig, |
| OsclRefCounterMemFrag& memFragIn); |
| |
| OsclErrorTrapImp* iOsclErrorTrapImp; |
| |
| PVMFSocketNodeAllocator iAlloc; |
| |
| #if(ENABLE_SOCKET_NODE_STATS) |
| SocketNodeStats iSocketNodeStats; |
| #endif |
| }; |
| |
| #endif //PVMF_SOCKET_NODE_H_INCLUDED |
| |