Counter Strike : Global Offensive Source Code
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.

258 lines
6.0 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #ifdef _GAMECONSOLE
  7. #define SUPPORT_NET_CONSOLE 0
  8. #else
  9. #define SUPPORT_NET_CONSOLE 1
  10. #endif
  11. #if SUPPORT_NET_CONSOLE
  12. #if defined(_WIN32)
  13. #if !defined(_X360)
  14. #include "winlite.h"
  15. #include <winsock2.h>
  16. #endif
  17. #undef SetPort // winsock screws with the SetPort string... *sigh*
  18. #define MSG_NOSIGNAL 0
  19. #elif POSIX
  20. #ifdef OSX
  21. #define MSG_NOSIGNAL 0 // doesn't exist on OSX, use SO_NOSIGPIPE socket option instead
  22. #endif
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <netinet/tcp.h>
  27. #include <errno.h>
  28. #include <sys/ioctl.h>
  29. #define closesocket close
  30. #define WSAGetLastError() errno
  31. #define ioctlsocket ioctl
  32. #endif // SUPPORT_NET_CONSOLE
  33. #include "mathlib/expressioncalculator.h"
  34. #include "client_pch.h"
  35. #include <time.h>
  36. #include "console.h"
  37. #include "netconsole.h"
  38. // memdbgon must be the last include file in a .cpp file!!!
  39. #include "tier0/memdbgon.h"
  40. extern IVEngineClient *engineClient;
  41. #if SUPPORT_NET_CONSOLE
  42. void InitNetConsole( void )
  43. {
  44. if ( !g_pNetConsoleMgr )
  45. g_pNetConsoleMgr = new CNetConsoleMgr;
  46. }
  47. #endif
  48. CNetConsoleMgr::CNetConsoleMgr( void ) : m_Socket( this )
  49. {
  50. m_bActive = false;
  51. m_bPasswordProtected = false;
  52. int nPassword = CommandLine()->FindParm( "-netconpassword" );
  53. if ( nPassword )
  54. {
  55. char const *pPassword = CommandLine()->GetParm( nPassword + 1 );
  56. V_strncpy( m_pPassword, pPassword, sizeof( m_pPassword ) );
  57. m_bPasswordProtected = true;
  58. }
  59. int nPort = CommandLine()->FindParm( "-netconport" );
  60. if ( nPort )
  61. {
  62. char const *pPortNum = CommandLine()->GetParm( nPort + 1 );
  63. m_Address = net_local_adr;
  64. int nPortNumber = EvaluateExpression( pPortNum, -1 );
  65. if ( nPortNumber > 0 )
  66. {
  67. m_Address.SetPort( nPortNumber );
  68. m_bActive = true;
  69. m_Socket.CreateListenSocket( m_Address, true );
  70. }
  71. }
  72. // now, handle cmds from parent process
  73. if ( g_nForkID > 0 )
  74. {
  75. int opt = 1;
  76. // set this socket to non-blocking
  77. ioctlsocket( g_nSocketToParentProcess, FIONBIO, (unsigned long*)&opt ); // non-blocking
  78. m_ParentConnection.m_hSocket = g_nSocketToParentProcess;
  79. m_ParentConnection.m_bAuthorized = true; // no password needed from parent
  80. m_ParentConnection.m_bInputOnly = true; // we don't want to spew to here
  81. }
  82. }
  83. CNetConsoleMgr::CNetConsoleMgr( int nPort ) : m_Socket( this )
  84. {
  85. m_bPasswordProtected = false;
  86. m_Address.SetPort( nPort );
  87. m_bActive = true;
  88. m_Socket.CreateListenSocket( m_Address, true );
  89. }
  90. static char const s_pszPasswordMessage[]="This server is password protected for console access. Must send PASS command\n\r";
  91. void CNetConsoleMgr::Execute( CConnectedNetConsoleData *pData )
  92. {
  93. if ( memcmp( pData->m_pszInputCommandBuffer, "PASS ", 5 ) == 0 )
  94. {
  95. if ( V_strcmp( pData->m_pszInputCommandBuffer + 5, m_pPassword ) == 0 )
  96. pData->m_bAuthorized = true;
  97. else
  98. {
  99. // bad password
  100. Warning( "Bad password attempt from net console\n" );
  101. pData->m_bAuthorized = false;
  102. }
  103. }
  104. else
  105. {
  106. if ( pData->m_bAuthorized )
  107. {
  108. #ifdef DEDICATED
  109. Cbuf_AddText(CBUF_SERVER, pData->m_pszInputCommandBuffer, kCommandSrcUserInput );
  110. Cbuf_Execute();
  111. #else
  112. engineClient->ClientCmd_Unrestricted( pData->m_pszInputCommandBuffer, true );
  113. #endif
  114. }
  115. else
  116. {
  117. SocketHandle_t hSocket = pData->m_hSocket;
  118. #ifdef OSX
  119. int val = 1;
  120. setsockopt( hSocket, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
  121. #endif
  122. send( hSocket, s_pszPasswordMessage, strlen( s_pszPasswordMessage ), MSG_NOSIGNAL );
  123. }
  124. }
  125. }
  126. void CNetConsoleMgr::SendStringToNetConsoles( char const *pString )
  127. {
  128. m_Socket.RunFrame();
  129. int nCount = NumConnectedSockets();
  130. if ( nCount )
  131. {
  132. // lets add the lf to any cr's
  133. char *pTmp = (char * ) stackalloc( strlen( pString ) * 2 + 1 );
  134. char *oString = pTmp;
  135. char const *pIn = pString;
  136. while ( *pIn )
  137. {
  138. if ( *pIn == '\n' )
  139. *( oString++ ) = '\r';
  140. *( oString++ ) = *( pIn++ );
  141. }
  142. *( oString++ ) = 0;
  143. for ( int i = 0; i < nCount; i++ )
  144. {
  145. CConnectedNetConsoleData *pData = GetConnection( i );
  146. if ( pData->m_bAuthorized && ( ! pData->m_bInputOnly ) ) // no output to un-authed net consoles
  147. {
  148. #ifdef OSX
  149. int val = 1;
  150. setsockopt( pData->m_hSocket, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val));
  151. #endif
  152. send( pData->m_hSocket, pTmp, oString - pTmp - 1, MSG_NOSIGNAL );
  153. }
  154. }
  155. }
  156. }
  157. void CNetConsoleMgr::RunFrame( void )
  158. {
  159. // check for incoming data
  160. m_Socket.RunFrame();
  161. int nCount = NumConnectedSockets();
  162. for ( int i = nCount - 1; i >= 0; i-- )
  163. {
  164. CConnectedNetConsoleData *pData = GetConnection( i );
  165. SocketHandle_t hSocket = pData->m_hSocket;
  166. char ch;
  167. int pendingLen = recv( hSocket, &ch, sizeof(ch), MSG_PEEK );
  168. if ( pendingLen == -1 && SocketWouldBlock() )
  169. continue;
  170. if ( pendingLen <= 0 ) // eof or error
  171. {
  172. CloseConnection( i );
  173. continue;
  174. }
  175. // find out how much we have to read
  176. unsigned long readLen;
  177. ioctlsocket( hSocket, FIONREAD, &readLen );
  178. while( readLen > 0 )
  179. {
  180. char recvBuf[256];
  181. int recvLen = recv( hSocket, recvBuf , MIN( sizeof( recvBuf ) , readLen ), 0 );
  182. if ( recvLen == 0 ) // socket was closed
  183. {
  184. CloseConnection( i );
  185. break;
  186. }
  187. if ( recvLen < 0 && !SocketWouldBlock() )
  188. {
  189. break;
  190. }
  191. readLen -= recvLen;
  192. // now, lets write what we've got into the command buffer
  193. HandleInputChars( recvBuf, recvLen, pData );
  194. }
  195. }
  196. }
  197. void CNetConsoleMgr::HandleInputChars( char const *pIn, int recvLen, CConnectedNetConsoleData *pData )
  198. {
  199. while( recvLen )
  200. {
  201. switch( *pIn )
  202. {
  203. case '\r':
  204. case '\n':
  205. {
  206. if ( pData->m_nCharsInCommandBuffer )
  207. {
  208. pData->m_pszInputCommandBuffer[pData->m_nCharsInCommandBuffer] = 0;
  209. Execute( pData );
  210. }
  211. pData->m_nCharsInCommandBuffer = 0;
  212. break;
  213. }
  214. default:
  215. {
  216. if ( pData->m_nCharsInCommandBuffer < MAX_NETCONSOLE_INPUT_LEN - 1 )
  217. pData->m_pszInputCommandBuffer[pData->m_nCharsInCommandBuffer++] = *pIn;
  218. break;
  219. }
  220. }
  221. pIn++;
  222. recvLen--;
  223. }
  224. }
  225. CNetConsoleMgr *g_pNetConsoleMgr;
  226. #endif // support_netconsole