diff options
Diffstat (limited to 'utils/vmpi/IThreadedTCPSocket.h')
| -rw-r--r-- | utils/vmpi/IThreadedTCPSocket.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/utils/vmpi/IThreadedTCPSocket.h b/utils/vmpi/IThreadedTCPSocket.h new file mode 100644 index 0000000..904dc7f --- /dev/null +++ b/utils/vmpi/IThreadedTCPSocket.h @@ -0,0 +1,173 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef ITHREADEDTCPSOCKET_H +#define ITHREADEDTCPSOCKET_H +#ifdef _WIN32 +#pragma once +#endif + + +#include "iphelpers.h" + + +class IThreadedTCPSocket; + + +class CTCPPacket +{ +public: + // Access the contents of the packet. + const char* GetData() const; + int GetLen() const; + + // You can attach some user data to the packet. + int GetUserData() const; + void SetUserData( int userData ); + + // Free resources associated with the packet. + void Release(); + +public: + friend class CThreadedTCPSocket; + ~CTCPPacket(); // Use Release(), not delete. + + int m_UserData; + int m_Len; + char m_Data[1]; +}; + + +inline const char* CTCPPacket::GetData() const +{ + return m_Data; +} + + +inline int CTCPPacket::GetLen() const +{ + return m_Len; +} + + +// The application implements this to handle packets that are received. +// Note that the implementation must be thread-safe because these functions can be called +// from various threads. +class ITCPSocketHandler +{ +public: + + enum + { + SocketError=0, + ConnectionTimedOut + }; + + // This is called right when the socket becomes ready to have data sent through it and + // before OnPacketReceive is ever called. + virtual void Init( IThreadedTCPSocket *pSocket ) = 0; + + // This is called when a packet arrives. NOTE: you are responsible for freeing the packet + // by calling CTCPPacket::Release() on it. + virtual void OnPacketReceived( CTCPPacket *pPacket ) = 0; + + // Handle errors inside the socket. After this is called, the socket is no longer alive. + // Note: this might be called from ANY thread (the main thread, the send thread, or the receive thread). + // + // errorCode is one of the enums above (SocketError, ConnectionTimedOut, etc). + virtual void OnError( int errorCode, const char *pErrorString ) = 0; +}; + + +// +// This is the main threaded TCP socket class. +// The way these work is that they have a thread for sending and a thread for receiving data. +// +// The send thread is continually pushing your data out the door. +// +// The receive thread is continually receiving data. When it receives data, it calls your HandlePacketFn +// to allow the user to handle it. Be very careful in your HandlePacketFn, since it is in another thread. +// Anything it accesses should be protected by mutexes and the like. +// +class IThreadedTCPSocket +{ +public: + // Cleanup everything and exit. + // Note: if the receive thread is inside your HandlePacketFn returns, this function blocks until that function returns. + virtual void Release() = 0; + + // Returns the address of whoever you are connected to. + virtual CIPAddr GetRemoteAddr() const = 0; + + // Returns true if the socket is connected and ready to go. If this returns false, then the socket won't + // send or receive data any more. It also means that your ITCPSocketHandler's OnError function has been called. + virtual bool IsValid() = 0; + + // Send data. Any thread can call these functions, and they don't block. They make a copy of the data, then + // enqueue it for sending. + virtual bool Send( const void *pData, int len ) = 0; + virtual bool SendChunks( void const * const *pChunks, const int *pChunkLengths, int nChunks ) = 0; +}; + + + +// Use these to get incoming connections. +class ITCPConnectSocket +{ +public: + // Call this to stop listening for connections and delete the object. + virtual void Release() = 0; + + // Keep calling this as long as you want to wait for connections. + // + // If it returns true and pSocket is NULL, it means it hasn't connected yet. + // If it returns true and pSocket is non-NULL, then it has connected. + // If it returns false, then the connection attempt failed and all further Update() calls will return false. + virtual bool Update( IThreadedTCPSocket **pSocket, unsigned long milliseconds=0 ) = 0; +}; + + +// This class is implemented by the app and passed into CreateListener. When the listener makes +// a new connection, it calls CreateNewHandler() to have the app create something that will handle +// the received packets and errors for the new socket. +class IHandlerCreator +{ +public: + // This function must return a valid value. + virtual ITCPSocketHandler* CreateNewHandler() = 0; +}; + + +// Use this to listen for TCP connections. The ITCPConnectSocket will keep returning connections +// until you call Release(). +ITCPConnectSocket* ThreadedTCP_CreateListener( + IHandlerCreator *pHandlerCreator, // This handles messages from the socket. + const unsigned short port, // Listen on this port. + int nQueueLength = 5 // How many connections + ); + + +// Use this to connect to a remote process. After Update() returns a non-NULL value, you should +// call Release() on the ITCPConnectSocket because it won't ever return another connection. +ITCPConnectSocket* ThreadedTCP_CreateConnector( + const CIPAddr &addr, // Who to connect to. + const CIPAddr &localAddr, // Local address to bind to. Leave uninitialized (pass in CIPAddr()) and it will + // an interface and a port for you. You can also just fill in the port, and it will + // use that port and choose an interface for you. + IHandlerCreator *pHandlerCreator// If it connects, it asks this thing to make a handler for the connection. + ); + + +// Enable or disable timeouts. +void ThreadedTCP_EnableTimeouts( bool bEnable ); + +// This should be called at init time. If set to true, it'll set the send and recv threads to low priority. +// (Default is true). +void ThreadedTCP_SetTCPSocketThreadPriorities( bool bSetTCPSocketThreadPriorities ); + + +#endif // ITHREADEDTCPSOCKET_H |