Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: master header file for socketlib.lib
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #ifndef SOCKETLIB_H
  9. #define SOCKETLIB_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "tier0/basetypes.h"
  14. #include "utlbuffer.h"
  15. typedef int64 SocketHandle_t;
  16. //===========================================================================
  17. // Error Codes used by socketlib
  18. //===========================================================================
  19. enum SocketErrorCode_t
  20. {
  21. SOCKET_SUCCESS = 0,
  22. SOCKET_ERR_OPERATION_NOT_SUPPORTED,
  23. SOCKET_ERR_CREATE_FAILED,
  24. SOCKET_ERR_READ_OPERATION_FAILED,
  25. SOCKET_ERR_WRITE_OPERATION_FAILED,
  26. SOCKET_ERR_CONNECT_FAILED,
  27. SOCKET_ERR_LISTEN_FAILED,
  28. SOCKET_ERR_ACCEPT_FAILED,
  29. SOCKET_ERR_POLLING_OPERATION_FAILED,
  30. SOCKET_ERR_BIND_OPERATION_FAILED,
  31. SOCKET_ERR_ENABLE_NON_BLOCKING_MODE_FAILED,
  32. SOCKET_ERR_HOST_NOT_FOUND,
  33. SOCKET_ERR_GENERAL_SOCKET_ERROR,
  34. SOCKET_ERR_READ_OPERATION_WOULD_BLOCK,
  35. SOCKET_ERR_WRITE_OPERATION_WOULD_BLOCK,
  36. SOCKET_ERR_CONNECTION_CLOSED,
  37. SOCKET_ERR_CONNECTION_RESET,
  38. SOCKET_ERR_NO_INCOMING_CONNECTIONS,
  39. SOCKET_ERR_NO_AVAILABLE_ENDPOINTS,
  40. SOCKET_ERR_BAD_USER_DATA,
  41. SOCKET_ERR_INVALID_CONNECTION,
  42. SOCKET_ERR_CANT_WRITE,
  43. SOCKET_ERR_MIXING_PACKET_SENDS,
  44. SOCKET_ERR_PARTIAL_PACKET_OVERFLOW,
  45. };
  46. const int MAX_SERVER_CONNECTIONS = 4; // Maximum number of concurrent connections allowed to a server.
  47. // In the future, this can be set higher and class CSocketConnection should use a growable array of Sockets.
  48. const int MAX_SERVER_CONNECTION_BACKLOG = 16; // Maximum number of connections allowed in the listening backlog.
  49. const int INVALID_ENDPOINT_INDEX = -1; // Represents an invalid endpoint index.
  50. enum ConnectionType_t // Type of connection: client or server.
  51. {
  52. CT_INDETERMINATE = 0,
  53. CT_CLIENT,
  54. CT_SERVER,
  55. };
  56. enum SocketProtocol_t // Protocol to use for the socket.
  57. {
  58. SP_INDETERMINATE = 0,
  59. SP_UDP,
  60. SP_VDP,
  61. SP_TCP,
  62. };
  63. enum SocketState_t // State of a given socket.
  64. {
  65. SSTATE_UNINITIALIZED = 0, // Socket is in completely uninitialized state.
  66. SSTATE_LISTENING, // Server socket is listening for connections.
  67. SSTATE_CONNECTION_IN_PROGRESS, // Socket is initialized and in the process of connecting to a client/server.
  68. SSTATE_CONNECTED, // Socket is initialized and connected to a client/server.
  69. };
  70. //-----------------------------------------------------------------------
  71. // Platform and build specific defines, change these as needed
  72. //-----------------------------------------------------------------------
  73. #if defined( PLATFORM_X360 )
  74. #define VDP_SUPPORT_ENABLED 1
  75. #else
  76. #define VDP_SUPPORT_ENABLED 0
  77. #endif
  78. #if defined( _DEBUG )
  79. #define UNSECURE_SOCKETS_ENABLED 1
  80. #else
  81. #define UNSECURE_SOCKETS_ENABLED 0
  82. #endif
  83. // ----------------------------------------------------------------------------
  84. // Basic platform-specific socket definitions go here to avoid
  85. // polluting other source files with common #defines.
  86. // ----------------------------------------------------------------------------
  87. #if defined( PLATFORM_X360 )
  88. #include <xtl.h>
  89. #include <winsockx.h>
  90. #elif defined( PLATFORM_WINDOWS_PC )
  91. #include <winsock2.h>
  92. #else
  93. #error No build platform macro (PLATFORM_*) defined
  94. #endif
  95. inline SocketHandle_t GetSocketHandle( SOCKET socket )
  96. {
  97. return static_cast<SocketHandle_t>( socket );
  98. }
  99. inline SOCKET GetPlatformSocket( SocketHandle_t handle )
  100. {
  101. return static_cast<SOCKET>( handle );
  102. }
  103. static const SocketHandle_t InvalidSocketHandle = static_cast<SocketHandle_t>( INVALID_SOCKET );
  104. // ----------------------------------------------------------------------------
  105. // CSocketConnection
  106. // Represents a client or server network connection.
  107. //
  108. // todo: Rework connection class to treat endpoints as standalone objects and unify
  109. // interface with named pipes.
  110. // ----------------------------------------------------------------------------
  111. class CSocketConnection
  112. {
  113. public:
  114. CSocketConnection();
  115. ~CSocketConnection();
  116. SocketErrorCode_t Init( ConnectionType_t connectionType, SocketProtocol_t socketProtocol ); // Initializes the connection class as either client or server with specified protocol.
  117. // Does not acquire any system resources.
  118. void Cleanup(); // Cleans up the class and restores it to the default uninitialized state.
  119. SocketErrorCode_t Listen( uint16 localPort, int numAllowedConnections ); // (Server-only) Listens for active client connections.
  120. SocketErrorCode_t TryAcceptIncomingConnection( int *newEndpointIndex ); // (Server-only) Attempts to accept an incoming connection, if one is available.
  121. int GetFirstAvailableListeningEndpoint(); // (Server-only) Gets the index of the first endpoint which is listening for connections.
  122. SocketState_t GetListeningSocketState(); // (Server-only) Gets the status of the listening socket on a server.
  123. SocketErrorCode_t ConnectToServer( const char *hostName, uint16 hostPort ); // (Client-only) Connects to a remote host using endpoint 0.
  124. // In most cases, the status of endpoint 0 will be SSTATE_CONNECTION_IN_PROGRESS.
  125. // The caller must periodically call PollClientConnectionState until the socket is connected before it is usable.
  126. SocketErrorCode_t PollClientConnectionState( bool *isConnected ); // (Client-only) Checks the status of endpoint 0 to see if it is connected successfully to a server.
  127. SocketState_t GetEndpointSocketState( int endpointIndex ); // Gets the status of the specified endpoint. (Clients only use endpoint 0.)
  128. SocketErrorCode_t CanReadFromEndpoint( int endpointIndex, bool *canRead ); // Gets a value indicating whether the endpoint can be successfully read from.
  129. SocketErrorCode_t CanWriteToEndpoint( int endpointIndex, bool *canWrite ); // Gets a value indicating whether the endpoint can be successfully written to.
  130. SocketErrorCode_t ReadFromEndpoint( int endpointIndex, byte *destinationBuffer, int bufferSize, int *bytesRead ); // Reads data from the specified endpoint.
  131. SocketErrorCode_t WriteToEndpoint( int endpointIndex, byte *sourceBuffer, int bufferSize, int *bytesWritten ); // Writes data to the specified endpoint.
  132. const char* GetLastSystemErrorString() const; // Gets a string containing the last underlying system error reported.
  133. // Only valid immediately after a function returns an unsuccessful error code.
  134. const char* GetLastErrorString() const; // Gets a string containing the last underlying system error reported.
  135. SocketHandle_t GetListeningSocket() const;
  136. SocketHandle_t GetEndpointSocket( int nEndpointIndex ) const;
  137. void ResetEndpoint( int endpointIndex );
  138. SocketErrorCode_t SetSocketOpt( int endpointIndex, int level, int optname, const void *optval, int optlen );
  139. private:
  140. SocketHandle_t CreateNewSocket();
  141. SocketHandle_t m_ListeningSocket;
  142. SocketHandle_t m_EndpointSockets[ MAX_SERVER_CONNECTIONS ];
  143. SocketState_t m_ListeningSocketState;
  144. SocketState_t m_EndpointStates[ MAX_SERVER_CONNECTIONS ];
  145. ConnectionType_t m_ConnectionType;
  146. SocketProtocol_t m_SocketProtocol;
  147. SocketErrorCode_t m_LastError;
  148. int m_LastSystemError;
  149. };
  150. //-----------------------------------------------------------------------------
  151. // Inline functions from CSocketConnection
  152. //-----------------------------------------------------------------------------
  153. //-----------------------------------------------------------------------------
  154. //
  155. //-----------------------------------------------------------------------------
  156. inline SocketHandle_t CSocketConnection::GetListeningSocket() const
  157. {
  158. return m_ListeningSocket;
  159. }
  160. //-----------------------------------------------------------------------------
  161. //
  162. //-----------------------------------------------------------------------------
  163. inline SocketHandle_t CSocketConnection::GetEndpointSocket( int nEndpointIndex ) const
  164. {
  165. AssertMsg( nEndpointIndex >= 0 && nEndpointIndex < MAX_SERVER_CONNECTIONS, "Endpoint index out of range" );
  166. return m_EndpointSockets[ nEndpointIndex ];
  167. }
  168. // ----------------------------------------------------------------------------
  169. // Start up and shutdown functions
  170. // Calls to these functions have to bracket any usage of this socket code
  171. // ----------------------------------------------------------------------------
  172. void SocketLibInit();
  173. void SocketLibShutdown();
  174. // Handy conversion to text of those nasty HRESULT codes
  175. const char* ConvertWinsockErrorToString( int errorCode );
  176. const char* ConvertSocketLibErrorToString( SocketErrorCode_t errorCode );
  177. // Bitwise representation of a network message header.
  178. struct MessageHeader_t
  179. {
  180. uint32 m_nLength;
  181. };
  182. // Byte swaps (in-place) a message header between system byte-order and network byte-order.
  183. void ByteSwapInPlaceMessageHeader( MessageHeader_t* messageHeader );
  184. // ----------------------------------------------------------------------------
  185. // Signature of a callback invoked once per message parsed by the CSocketMessageBuilder::FeedData function.
  186. // header = Header of the message read.
  187. // message = Message payload (m_nLength is given by the header)
  188. // userContext = Context provided by caller to FeedData
  189. // ----------------------------------------------------------------------------
  190. typedef void ( *NetworkMessageHandler )( const MessageHeader_t& header, const byte* message, void* userContext );
  191. // ----------------------------------------------------------------------------
  192. // Helper class to parse messages from a stream source.
  193. // This class maintains state between successive calls to FeedData so that partial messages
  194. // can be stored until fully parsed and dispatched.
  195. // ----------------------------------------------------------------------------
  196. class CSocketMessageBuilder
  197. {
  198. public:
  199. CSocketMessageBuilder( int initialSize = 0, int growSize = 0 );
  200. ~CSocketMessageBuilder();
  201. void SetMaxExpectedMsgSize( int expectedSize );
  202. // Parses the given stream data and fires a callback for each full message parsed.
  203. // This function has the side-effect of updating the CSocketMessageBuilder's internal parsing state
  204. // so that partial messages can be glued together.
  205. void FeedData( const void *data, int dataLength, NetworkMessageHandler networkMessageHandlerFunc, void *userContext );
  206. void AssignConnection( CSocketConnection* pConnection, int endpoint );
  207. SocketErrorCode_t SendDataPacket( const void* RESTRICT data, int dataLength );
  208. SocketErrorCode_t SendDataPacket( CSocketConnection* pConnection, int endpoint, const void* RESTRICT data, int dataLength );
  209. SocketErrorCode_t BeginSendPartialDataPacket( uint32 totalSize, const void* RESTRICT data, int dataLength );
  210. SocketErrorCode_t BeginSendPartialDataPacket( CSocketConnection* pConnection, int endpoint, uint32 totalSize, const void* RESTRICT data, int dataLength );
  211. bool WaitForIncomingMessage( DWORD timeOutValue );
  212. void* GetIncomingMessageData();
  213. uint32 GetIncomingMessageLen();
  214. void FeedDataManual( const void* RESTRICT data, int dataLength );
  215. bool HasCompleteMessageManual( );
  216. bool GetCurrentMessageManual( void*& msgData, uint32& msgSize );
  217. bool DiscardCurrentMessageManual();
  218. bool IsSendingPartialMessage() { return m_bSendingPartialMessage; }
  219. int32 PartialMessageBytesRemaining() { return m_bSendingPartialMessage ? m_PartialMessageBytesTotal - m_PartialMessageBytesSent : 0; }
  220. private:
  221. MessageHeader_t m_MessageHeader;
  222. uint32 m_nHeaderBytesRead;
  223. uint32 m_nMessageBytesRead;
  224. CSocketConnection* m_pConnection;
  225. int m_nConnectionEndpoint;
  226. CUtlBuffer m_MessageData;
  227. uint32 m_PartialMessageBytesSent; // used to combine multiple calls to SendDataPacket/BeginSendPartialDataPacket into one message packet
  228. uint32 m_PartialMessageBytesTotal;
  229. bool m_bSendingPartialMessage;
  230. int m_nRecvBufSize;
  231. byte* m_pRecvBuf;
  232. bool m_bSwappedHeader;
  233. };
  234. #endif // SOCKETLIB_H