summaryrefslogtreecommitdiff
path: root/networksystem/networksystem.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /networksystem/networksystem.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'networksystem/networksystem.cpp')
-rw-r--r--networksystem/networksystem.cpp491
1 files changed, 491 insertions, 0 deletions
diff --git a/networksystem/networksystem.cpp b/networksystem/networksystem.cpp
new file mode 100644
index 0000000..b8650ec
--- /dev/null
+++ b/networksystem/networksystem.cpp
@@ -0,0 +1,491 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#include "networksystem.h"
+#include "filesystem.h"
+#include "UDP_Socket.h"
+#include "sm_protocol.h"
+#include "NetChannel.h"
+#include "UDP_Process.h"
+#include <winsock.h>
+#include "networkclient.h"
+#include "networkserver.h"
+#include "networksystem/inetworkmessage.h"
+#include "mathlib/mathlib.h"
+#include "tier2/tier2.h"
+
+
+//-----------------------------------------------------------------------------
+// Singleton instance
+//-----------------------------------------------------------------------------
+static CNetworkSystem g_NetworkSystem;
+CNetworkSystem *g_pNetworkSystemImp = &g_NetworkSystem;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CNetworkSystem, INetworkSystem,
+ NETWORKSYSTEM_INTERFACE_VERSION, g_NetworkSystem );
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CNetworkSystem::CNetworkSystem()
+{
+ m_bWinsockInitialized = false;
+ m_bNetworkEventCreated = false;
+ m_bInMidPacket = false;
+ m_pServer = NULL;
+ m_pClient = NULL;
+ m_nGroupBits = 1;
+ m_nTypeBits = LargestPowerOfTwoLessThanOrEqual( net_num_messages );
+}
+
+CNetworkSystem::~CNetworkSystem()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Initialization, shutdown
+//-----------------------------------------------------------------------------
+InitReturnVal_t CNetworkSystem::Init()
+{
+ InitReturnVal_t nRetVal = BaseClass::Init();
+ if ( nRetVal != INIT_OK )
+ return nRetVal;
+
+ // initialize winsock 2.0
+ WSAData wsaData;
+
+ if ( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
+ {
+ Warning( "Error! Failed to load network socket library.\n");
+ return INIT_OK;
+ }
+ else
+ {
+ m_bWinsockInitialized = true;
+ }
+
+ LPHOSTENT lp = gethostbyname("localhost");
+ if ( !lp )
+ {
+ Warning( "Error! Failed to query local host info\n");
+ return INIT_OK;
+ }
+ m_LocalHostName = lp->h_name;
+
+ lp = gethostbyname( m_LocalHostName );
+ if ( !lp )
+ {
+ Warning( "Error! Failed to query local host info\n");
+ return INIT_OK;
+ }
+
+ sockaddr ip;
+ m_LocalAddressString = inet_ntoa( *((in_addr*)(lp->h_addr_list[0])) );
+ StringToSockaddr( m_LocalAddressString, &ip );
+ m_LocalAddress.SetFromSockadr( &ip );
+ return INIT_OK;
+}
+
+void CNetworkSystem::Shutdown()
+{
+ if ( m_bWinsockInitialized )
+ {
+ WSACleanup();
+ }
+ CleanupNetworkMessages();
+ BaseClass::Shutdown();
+}
+
+
+//-----------------------------------------------------------------------------
+// Connect, disconnect
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::Connect( CreateInterfaceFn factory )
+{
+ if ( !BaseClass::Connect( factory ) )
+ return false;
+
+ if ( !g_pFullFileSystem )
+ {
+ Warning( "The network system requires the filesystem to run!\n" );
+ return false;
+ }
+
+ return INIT_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the current time
+//-----------------------------------------------------------------------------
+float CNetworkSystem::GetTime( void )
+{
+ return Plat_FloatTime();
+}
+
+
+//-----------------------------------------------------------------------------
+// Installs network message factories to be used with all connections
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::RegisterMessage( INetworkMessage *pMessage )
+{
+ if ( m_pServer || m_pClient )
+ {
+ Warning( "Cannot register messages after connection has started.\n" );
+ return false;
+ }
+
+ if ( pMessage->GetGroup() == 0 )
+ {
+ Warning( "Network message group 0 is reserved by the network system.\n" );
+ return false;
+ }
+
+ // Look for already registered message
+ if ( m_NetworkMessages.Find( pMessage ) >= 0 )
+ return false;
+
+ // Allocate more space in messages
+ int nGroupBits = LargestPowerOfTwoLessThanOrEqual( pMessage->GetGroup() );
+ int nTypeBits = LargestPowerOfTwoLessThanOrEqual( pMessage->GetType() );
+ m_nGroupBits = max( nGroupBits, m_nGroupBits );
+ m_nTypeBits = max( nTypeBits, m_nTypeBits );
+
+ m_NetworkMessages.AddToTail( pMessage );
+ return true;
+}
+
+void CNetworkSystem::CleanupNetworkMessages( )
+{
+ int nCount = m_NetworkMessages.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ m_NetworkMessages[i]->Release();
+ }
+
+ m_NetworkMessages.RemoveAll();
+}
+
+
+//-----------------------------------------------------------------------------
+// Finds a network message given a particular message type
+//-----------------------------------------------------------------------------
+INetworkMessage* CNetworkSystem::FindNetworkMessage( int group, int type )
+{
+ int nCount = m_NetworkMessages.Count();
+ for (int i=0; i < nCount; i++ )
+ {
+ if ( ( m_NetworkMessages[i]->GetGroup() == group ) && ( m_NetworkMessages[i]->GetType() == type ) )
+ return m_NetworkMessages[i];
+ }
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::StringToSockaddr( const char *s, struct sockaddr *sadr )
+{
+ struct hostent *h;
+ char *colon;
+ char copy[128];
+
+ Q_memset (sadr, 0, sizeof(*sadr));
+ ((struct sockaddr_in *)sadr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)sadr)->sin_port = 0;
+
+ Q_strncpy (copy, s, sizeof( copy ) );
+ // strip off a trailing :port if present
+ for (colon = copy ; *colon ; colon++)
+ if (*colon == ':')
+ {
+ *colon = 0;
+ ((struct sockaddr_in *)sadr)->sin_port = htons((short)atoi(colon+1));
+ }
+
+ if (copy[0] >= '0' && copy[0] <= '9' && Q_strstr( copy, "." ) )
+ {
+ *(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
+ }
+ else
+ {
+// if ( net_nodns )
+// return false; // DNS names disabled
+
+ if ( (h = gethostbyname(copy)) == NULL )
+ return false;
+
+ *(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the local address
+//-----------------------------------------------------------------------------
+const char* CNetworkSystem::GetLocalHostName( void ) const
+{
+ return m_LocalHostName;
+}
+
+const char* CNetworkSystem::GetLocalAddress( void ) const
+{
+ return m_LocalAddressString;
+}
+
+
+//-----------------------------------------------------------------------------
+// Start, shutdown a server
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::StartServer( unsigned short nServerListenPort )
+{
+ if ( !m_bWinsockInitialized )
+ return false;
+
+ Assert( !m_pServer );
+ m_pServer = new CNetworkServer;
+ return m_pServer->Init( nServerListenPort );
+}
+
+void CNetworkSystem::ShutdownServer( )
+{
+ if ( m_pServer )
+ {
+ m_pServer->Shutdown();
+ delete m_pServer;
+ m_pServer = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Server update
+//-----------------------------------------------------------------------------
+void CNetworkSystem::ServerReceiveMessages()
+{
+ if ( m_pServer )
+ {
+ m_pServer->ReadPackets();
+ }
+}
+
+void CNetworkSystem::ServerSendMessages()
+{
+ if ( m_pServer )
+ {
+ m_pServer->SendUpdates();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Start, shutdown a client
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::StartClient( unsigned short nClientListenPort )
+{
+ if ( !m_bWinsockInitialized )
+ return false;
+
+ Assert( !m_pClient );
+ m_pClient = new CNetworkClient;
+ return m_pClient->Init( nClientListenPort );
+}
+
+void CNetworkSystem::ShutdownClient( )
+{
+ if ( m_pClient )
+ {
+ m_pClient->Shutdown();
+ delete m_pClient;
+ m_pClient = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Server update
+//-----------------------------------------------------------------------------
+void CNetworkSystem::ClientReceiveMessages()
+{
+ if ( m_pClient )
+ {
+ m_pClient->ReadPackets();
+ }
+}
+
+void CNetworkSystem::ClientSendMessages()
+{
+ if ( m_pClient )
+ {
+ m_pClient->SendUpdate();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Server update
+//-----------------------------------------------------------------------------
+INetChannel* CNetworkSystem::ConnectClientToServer( const char *pServer, int nServerListenPort )
+{
+ if ( m_pClient )
+ {
+ if ( m_pClient->Connect( pServer, nServerListenPort ) )
+ return m_pClient->GetNetChannel();
+ }
+ return NULL;
+}
+
+void CNetworkSystem::DisconnectClientFromServer( INetChannel* pChannel )
+{
+ if ( m_pClient && ( m_pClient->GetNetChannel() == pChannel ) )
+ {
+ m_pClient->Disconnect();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Queues up a network packet
+//-----------------------------------------------------------------------------
+void CNetworkSystem::EnqueueConnectionlessNetworkPacket( CNetPacket *pPacket, IConnectionlessPacketHandler *pHandler )
+{
+ int i = m_PacketQueue.AddToTail( );
+
+ PacketInfo_t& info = m_PacketQueue[i];
+ info.m_pPacket = pPacket;
+ info.m_pHandler = pHandler;
+ info.m_pNetChannel = NULL;
+}
+
+void CNetworkSystem::EnqueueNetworkPacket( CNetPacket *pPacket, CNetChannel *pNetChannel )
+{
+ int i = m_PacketQueue.AddToTail( );
+
+ PacketInfo_t& info = m_PacketQueue[i];
+ info.m_pPacket = pPacket;
+ info.m_pHandler = NULL;
+ info.m_pNetChannel = pNetChannel;
+}
+
+
+//-----------------------------------------------------------------------------
+// Network event iteration helpers
+//-----------------------------------------------------------------------------
+bool CNetworkSystem::StartProcessingNewPacket()
+{
+ PacketInfo_t& info = m_PacketQueue[ m_nProcessingPacket ];
+ if ( info.m_pHandler )
+ {
+ UDP_ProcessConnectionlessPacket( info.m_pPacket, info.m_pHandler );
+ return false;
+ }
+
+ if ( !info.m_pNetChannel )
+ {
+ // Not an error that may happen during connect or disconnect
+ Warning( "Sequenced packet without connection from %s\n" , info.m_pPacket->m_From.ToString() );
+ return false;
+ }
+
+ return info.m_pNetChannel->StartProcessingPacket( info.m_pPacket );
+}
+
+bool CNetworkSystem::AdvanceProcessingNetworkPacket( )
+{
+ m_PacketQueue[ m_nProcessingPacket ].m_pPacket->Release();
+ m_PacketQueue[ m_nProcessingPacket ].m_pPacket = NULL;
+
+ ++m_nProcessingPacket;
+ bool bOverflowed = ( m_nProcessingPacket >= m_PacketQueue.Count() );
+ if ( bOverflowed )
+ {
+ m_PacketQueue.RemoveAll();
+ m_nProcessingPacket = 0;
+ }
+ return !bOverflowed;
+}
+
+
+//-----------------------------------------------------------------------------
+// Network event iteration
+//-----------------------------------------------------------------------------
+NetworkEvent_t *CNetworkSystem::FirstNetworkEvent( )
+{
+ Assert( !m_bInMidPacket && !m_nProcessingPacket );
+ m_nProcessingPacket = 0;
+ m_bInMidPacket = false;
+ return NextNetworkEvent();
+}
+
+NetworkEvent_t *CNetworkSystem::NextNetworkEvent( )
+{
+ int nPacketCount = m_PacketQueue.Count();
+ if ( m_nProcessingPacket >= nPacketCount )
+ return NULL;
+
+ while( true )
+ {
+ // Continue processing the packet we're currently on
+ if ( m_bInMidPacket )
+ {
+ PacketInfo_t& info = m_PacketQueue[ m_nProcessingPacket ];
+ while( info.m_pNetChannel->ProcessPacket( info.m_pPacket ) )
+ {
+ Assert( m_bNetworkEventCreated );
+ m_bNetworkEventCreated = false;
+ return (NetworkEvent_t*)m_EventMessageBuffer;
+ }
+ info.m_pNetChannel->EndProcessingPacket( info.m_pPacket );
+ m_bInMidPacket = false;
+
+ if ( !AdvanceProcessingNetworkPacket() )
+ return NULL;
+ }
+
+ // Keep reading packets until we find one that either generates an event,
+ // one that encounters a packet we need to process, or we exhaust the event queue
+ while( !StartProcessingNewPacket() )
+ {
+ bool bOverflowed = !AdvanceProcessingNetworkPacket();
+
+ if ( m_bNetworkEventCreated )
+ {
+ m_bNetworkEventCreated = false;
+ return (NetworkEvent_t*)m_EventMessageBuffer;
+ }
+
+ if ( bOverflowed )
+ return NULL;
+ }
+
+ m_bInMidPacket = true;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Network event creation
+//-----------------------------------------------------------------------------
+NetworkEvent_t* CNetworkSystem::CreateNetworkEvent( int nSizeInBytes )
+{
+ Assert( nSizeInBytes <= sizeof( m_EventMessageBuffer ) );
+
+ // If this assertion fails, it means two or more network events were created
+ // before the main network event loop had a chance to inform external code
+ Assert( !m_bNetworkEventCreated );
+ m_bNetworkEventCreated = true;
+ return ( NetworkEvent_t* )m_EventMessageBuffer;
+}
+
+bool CNetworkSystem::IsNetworkEventCreated()
+{
+ return m_bNetworkEventCreated;
+}
+