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.

491 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "networksystem.h"
  7. #include "filesystem.h"
  8. #include "UDP_Socket.h"
  9. #include "sm_protocol.h"
  10. #include "NetChannel.h"
  11. #include "UDP_Process.h"
  12. #include <winsock.h>
  13. #include "networkclient.h"
  14. #include "networkserver.h"
  15. #include "networksystem/inetworkmessage.h"
  16. #include "mathlib/mathlib.h"
  17. #include "tier2/tier2.h"
  18. //-----------------------------------------------------------------------------
  19. // Singleton instance
  20. //-----------------------------------------------------------------------------
  21. static CNetworkSystem g_NetworkSystem;
  22. CNetworkSystem *g_pNetworkSystemImp = &g_NetworkSystem;
  23. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CNetworkSystem, INetworkSystem,
  24. NETWORKSYSTEM_INTERFACE_VERSION, g_NetworkSystem );
  25. //-----------------------------------------------------------------------------
  26. // Constructor, destructor
  27. //-----------------------------------------------------------------------------
  28. CNetworkSystem::CNetworkSystem()
  29. {
  30. m_bWinsockInitialized = false;
  31. m_bNetworkEventCreated = false;
  32. m_bInMidPacket = false;
  33. m_pServer = NULL;
  34. m_pClient = NULL;
  35. m_nGroupBits = 1;
  36. m_nTypeBits = LargestPowerOfTwoLessThanOrEqual( net_num_messages );
  37. }
  38. CNetworkSystem::~CNetworkSystem()
  39. {
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Initialization, shutdown
  43. //-----------------------------------------------------------------------------
  44. InitReturnVal_t CNetworkSystem::Init()
  45. {
  46. InitReturnVal_t nRetVal = BaseClass::Init();
  47. if ( nRetVal != INIT_OK )
  48. return nRetVal;
  49. // initialize winsock 2.0
  50. WSAData wsaData;
  51. if ( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
  52. {
  53. Warning( "Error! Failed to load network socket library.\n");
  54. return INIT_OK;
  55. }
  56. else
  57. {
  58. m_bWinsockInitialized = true;
  59. }
  60. LPHOSTENT lp = gethostbyname("localhost");
  61. if ( !lp )
  62. {
  63. Warning( "Error! Failed to query local host info\n");
  64. return INIT_OK;
  65. }
  66. m_LocalHostName = lp->h_name;
  67. lp = gethostbyname( m_LocalHostName );
  68. if ( !lp )
  69. {
  70. Warning( "Error! Failed to query local host info\n");
  71. return INIT_OK;
  72. }
  73. sockaddr ip;
  74. m_LocalAddressString = inet_ntoa( *((in_addr*)(lp->h_addr_list[0])) );
  75. StringToSockaddr( m_LocalAddressString, &ip );
  76. m_LocalAddress.SetFromSockadr( &ip );
  77. return INIT_OK;
  78. }
  79. void CNetworkSystem::Shutdown()
  80. {
  81. if ( m_bWinsockInitialized )
  82. {
  83. WSACleanup();
  84. }
  85. CleanupNetworkMessages();
  86. BaseClass::Shutdown();
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Connect, disconnect
  90. //-----------------------------------------------------------------------------
  91. bool CNetworkSystem::Connect( CreateInterfaceFn factory )
  92. {
  93. if ( !BaseClass::Connect( factory ) )
  94. return false;
  95. if ( !g_pFullFileSystem )
  96. {
  97. Warning( "The network system requires the filesystem to run!\n" );
  98. return false;
  99. }
  100. return INIT_OK;
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Returns the current time
  104. //-----------------------------------------------------------------------------
  105. float CNetworkSystem::GetTime( void )
  106. {
  107. return Plat_FloatTime();
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Installs network message factories to be used with all connections
  111. //-----------------------------------------------------------------------------
  112. bool CNetworkSystem::RegisterMessage( INetworkMessage *pMessage )
  113. {
  114. if ( m_pServer || m_pClient )
  115. {
  116. Warning( "Cannot register messages after connection has started.\n" );
  117. return false;
  118. }
  119. if ( pMessage->GetGroup() == 0 )
  120. {
  121. Warning( "Network message group 0 is reserved by the network system.\n" );
  122. return false;
  123. }
  124. // Look for already registered message
  125. if ( m_NetworkMessages.Find( pMessage ) >= 0 )
  126. return false;
  127. // Allocate more space in messages
  128. int nGroupBits = LargestPowerOfTwoLessThanOrEqual( pMessage->GetGroup() );
  129. int nTypeBits = LargestPowerOfTwoLessThanOrEqual( pMessage->GetType() );
  130. m_nGroupBits = max( nGroupBits, m_nGroupBits );
  131. m_nTypeBits = max( nTypeBits, m_nTypeBits );
  132. m_NetworkMessages.AddToTail( pMessage );
  133. return true;
  134. }
  135. void CNetworkSystem::CleanupNetworkMessages( )
  136. {
  137. int nCount = m_NetworkMessages.Count();
  138. for ( int i = 0; i < nCount; ++i )
  139. {
  140. m_NetworkMessages[i]->Release();
  141. }
  142. m_NetworkMessages.RemoveAll();
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Finds a network message given a particular message type
  146. //-----------------------------------------------------------------------------
  147. INetworkMessage* CNetworkSystem::FindNetworkMessage( int group, int type )
  148. {
  149. int nCount = m_NetworkMessages.Count();
  150. for (int i=0; i < nCount; i++ )
  151. {
  152. if ( ( m_NetworkMessages[i]->GetGroup() == group ) && ( m_NetworkMessages[i]->GetType() == type ) )
  153. return m_NetworkMessages[i];
  154. }
  155. return NULL;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose:
  159. //-----------------------------------------------------------------------------
  160. bool CNetworkSystem::StringToSockaddr( const char *s, struct sockaddr *sadr )
  161. {
  162. struct hostent *h;
  163. char *colon;
  164. char copy[128];
  165. Q_memset (sadr, 0, sizeof(*sadr));
  166. ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
  167. ((struct sockaddr_in *)sadr)->sin_port = 0;
  168. Q_strncpy (copy, s, sizeof( copy ) );
  169. // strip off a trailing :port if present
  170. for (colon = copy ; *colon ; colon++)
  171. if (*colon == ':')
  172. {
  173. *colon = 0;
  174. ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
  175. }
  176. if (copy[0] >= '0' && copy[0] <= '9' && Q_strstr( copy, "." ) )
  177. {
  178. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
  179. }
  180. else
  181. {
  182. // if ( net_nodns )
  183. // return false; // DNS names disabled
  184. if ( (h = gethostbyname(copy)) == NULL )
  185. return false;
  186. *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
  187. }
  188. return true;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Returns the local address
  192. //-----------------------------------------------------------------------------
  193. const char* CNetworkSystem::GetLocalHostName( void ) const
  194. {
  195. return m_LocalHostName;
  196. }
  197. const char* CNetworkSystem::GetLocalAddress( void ) const
  198. {
  199. return m_LocalAddressString;
  200. }
  201. //-----------------------------------------------------------------------------
  202. // Start, shutdown a server
  203. //-----------------------------------------------------------------------------
  204. bool CNetworkSystem::StartServer( unsigned short nServerListenPort )
  205. {
  206. if ( !m_bWinsockInitialized )
  207. return false;
  208. Assert( !m_pServer );
  209. m_pServer = new CNetworkServer;
  210. return m_pServer->Init( nServerListenPort );
  211. }
  212. void CNetworkSystem::ShutdownServer( )
  213. {
  214. if ( m_pServer )
  215. {
  216. m_pServer->Shutdown();
  217. delete m_pServer;
  218. m_pServer = NULL;
  219. }
  220. }
  221. //-----------------------------------------------------------------------------
  222. // Server update
  223. //-----------------------------------------------------------------------------
  224. void CNetworkSystem::ServerReceiveMessages()
  225. {
  226. if ( m_pServer )
  227. {
  228. m_pServer->ReadPackets();
  229. }
  230. }
  231. void CNetworkSystem::ServerSendMessages()
  232. {
  233. if ( m_pServer )
  234. {
  235. m_pServer->SendUpdates();
  236. }
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Start, shutdown a client
  240. //-----------------------------------------------------------------------------
  241. bool CNetworkSystem::StartClient( unsigned short nClientListenPort )
  242. {
  243. if ( !m_bWinsockInitialized )
  244. return false;
  245. Assert( !m_pClient );
  246. m_pClient = new CNetworkClient;
  247. return m_pClient->Init( nClientListenPort );
  248. }
  249. void CNetworkSystem::ShutdownClient( )
  250. {
  251. if ( m_pClient )
  252. {
  253. m_pClient->Shutdown();
  254. delete m_pClient;
  255. m_pClient = NULL;
  256. }
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Server update
  260. //-----------------------------------------------------------------------------
  261. void CNetworkSystem::ClientReceiveMessages()
  262. {
  263. if ( m_pClient )
  264. {
  265. m_pClient->ReadPackets();
  266. }
  267. }
  268. void CNetworkSystem::ClientSendMessages()
  269. {
  270. if ( m_pClient )
  271. {
  272. m_pClient->SendUpdate();
  273. }
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Server update
  277. //-----------------------------------------------------------------------------
  278. INetChannel* CNetworkSystem::ConnectClientToServer( const char *pServer, int nServerListenPort )
  279. {
  280. if ( m_pClient )
  281. {
  282. if ( m_pClient->Connect( pServer, nServerListenPort ) )
  283. return m_pClient->GetNetChannel();
  284. }
  285. return NULL;
  286. }
  287. void CNetworkSystem::DisconnectClientFromServer( INetChannel* pChannel )
  288. {
  289. if ( m_pClient && ( m_pClient->GetNetChannel() == pChannel ) )
  290. {
  291. m_pClient->Disconnect();
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Queues up a network packet
  296. //-----------------------------------------------------------------------------
  297. void CNetworkSystem::EnqueueConnectionlessNetworkPacket( CNetPacket *pPacket, IConnectionlessPacketHandler *pHandler )
  298. {
  299. int i = m_PacketQueue.AddToTail( );
  300. PacketInfo_t& info = m_PacketQueue[i];
  301. info.m_pPacket = pPacket;
  302. info.m_pHandler = pHandler;
  303. info.m_pNetChannel = NULL;
  304. }
  305. void CNetworkSystem::EnqueueNetworkPacket( CNetPacket *pPacket, CNetChannel *pNetChannel )
  306. {
  307. int i = m_PacketQueue.AddToTail( );
  308. PacketInfo_t& info = m_PacketQueue[i];
  309. info.m_pPacket = pPacket;
  310. info.m_pHandler = NULL;
  311. info.m_pNetChannel = pNetChannel;
  312. }
  313. //-----------------------------------------------------------------------------
  314. // Network event iteration helpers
  315. //-----------------------------------------------------------------------------
  316. bool CNetworkSystem::StartProcessingNewPacket()
  317. {
  318. PacketInfo_t& info = m_PacketQueue[ m_nProcessingPacket ];
  319. if ( info.m_pHandler )
  320. {
  321. UDP_ProcessConnectionlessPacket( info.m_pPacket, info.m_pHandler );
  322. return false;
  323. }
  324. if ( !info.m_pNetChannel )
  325. {
  326. // Not an error that may happen during connect or disconnect
  327. Warning( "Sequenced packet without connection from %s\n" , info.m_pPacket->m_From.ToString() );
  328. return false;
  329. }
  330. return info.m_pNetChannel->StartProcessingPacket( info.m_pPacket );
  331. }
  332. bool CNetworkSystem::AdvanceProcessingNetworkPacket( )
  333. {
  334. m_PacketQueue[ m_nProcessingPacket ].m_pPacket->Release();
  335. m_PacketQueue[ m_nProcessingPacket ].m_pPacket = NULL;
  336. ++m_nProcessingPacket;
  337. bool bOverflowed = ( m_nProcessingPacket >= m_PacketQueue.Count() );
  338. if ( bOverflowed )
  339. {
  340. m_PacketQueue.RemoveAll();
  341. m_nProcessingPacket = 0;
  342. }
  343. return !bOverflowed;
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Network event iteration
  347. //-----------------------------------------------------------------------------
  348. NetworkEvent_t *CNetworkSystem::FirstNetworkEvent( )
  349. {
  350. Assert( !m_bInMidPacket && !m_nProcessingPacket );
  351. m_nProcessingPacket = 0;
  352. m_bInMidPacket = false;
  353. return NextNetworkEvent();
  354. }
  355. NetworkEvent_t *CNetworkSystem::NextNetworkEvent( )
  356. {
  357. int nPacketCount = m_PacketQueue.Count();
  358. if ( m_nProcessingPacket >= nPacketCount )
  359. return NULL;
  360. while( true )
  361. {
  362. // Continue processing the packet we're currently on
  363. if ( m_bInMidPacket )
  364. {
  365. PacketInfo_t& info = m_PacketQueue[ m_nProcessingPacket ];
  366. while( info.m_pNetChannel->ProcessPacket( info.m_pPacket ) )
  367. {
  368. Assert( m_bNetworkEventCreated );
  369. m_bNetworkEventCreated = false;
  370. return (NetworkEvent_t*)m_EventMessageBuffer;
  371. }
  372. info.m_pNetChannel->EndProcessingPacket( info.m_pPacket );
  373. m_bInMidPacket = false;
  374. if ( !AdvanceProcessingNetworkPacket() )
  375. return NULL;
  376. }
  377. // Keep reading packets until we find one that either generates an event,
  378. // one that encounters a packet we need to process, or we exhaust the event queue
  379. while( !StartProcessingNewPacket() )
  380. {
  381. bool bOverflowed = !AdvanceProcessingNetworkPacket();
  382. if ( m_bNetworkEventCreated )
  383. {
  384. m_bNetworkEventCreated = false;
  385. return (NetworkEvent_t*)m_EventMessageBuffer;
  386. }
  387. if ( bOverflowed )
  388. return NULL;
  389. }
  390. m_bInMidPacket = true;
  391. }
  392. }
  393. //-----------------------------------------------------------------------------
  394. // Network event creation
  395. //-----------------------------------------------------------------------------
  396. NetworkEvent_t* CNetworkSystem::CreateNetworkEvent( int nSizeInBytes )
  397. {
  398. Assert( nSizeInBytes <= sizeof( m_EventMessageBuffer ) );
  399. // If this assertion fails, it means two or more network events were created
  400. // before the main network event loop had a chance to inform external code
  401. Assert( !m_bNetworkEventCreated );
  402. m_bNetworkEventCreated = true;
  403. return ( NetworkEvent_t* )m_EventMessageBuffer;
  404. }
  405. bool CNetworkSystem::IsNetworkEventCreated()
  406. {
  407. return m_bNetworkEventCreated;
  408. }