Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

225 lines
4.8 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "networkserver.h"
#include "networksystem.h"
#include "icvar.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"
//-----------------------------------------------------------------------------
//
// Implementation of CPlayer
//
//-----------------------------------------------------------------------------
CNetworkServer::CNetworkServer( )
{
m_pSocket = new CUDPSocket;
}
CNetworkServer::~CNetworkServer()
{
delete m_pSocket;
}
bool CNetworkServer::Init( int nServerPort )
{
if ( !m_pSocket->Init( nServerPort ) )
{
Warning( "CNetworkServer: Unable to create socket!!!\n" );
return false;
}
return true;
}
void CNetworkServer::Shutdown()
{
m_pSocket->Shutdown();
}
CNetChannel *CNetworkServer::FindNetChannel( const netadr_t& from )
{
CPlayer *pl = FindPlayerByAddress( from );
if ( pl )
return &pl->m_NetChan;
return NULL;
}
CPlayer *CNetworkServer::FindPlayerByAddress( const netadr_t& adr )
{
int c = m_Players.Count();
for ( int i = 0; i < c; ++i )
{
CPlayer *player = m_Players[ i ];
if ( player->GetRemoteAddress().CompareAdr( adr ) )
return player;
}
return NULL;
}
CPlayer *CNetworkServer::FindPlayerByNetChannel( INetChannel *chan )
{
int c = m_Players.Count();
for ( int i = 0; i < c; ++i )
{
CPlayer *player = m_Players[ i ];
if ( &player->m_NetChan == chan )
return player;
}
return NULL;
}
#define SPEW_MESSAGES
#if defined( SPEW_MESSAGES )
#define SM_SPEW_MESSAGE( code, remote ) \
Warning( "Message: %s from '%s'\n", #code, remote );
#else
#define SM_SPEW_MESSAGE( code, remote )
#endif
// process a connectionless packet
bool CNetworkServer::ProcessConnectionlessPacket( CNetPacket *packet )
{
int code = packet->m_Message.ReadByte();
switch ( code )
{
case c2s_connect:
{
SM_SPEW_MESSAGE( c2s_connect, packet->m_From.ToString() );
CPlayer *pl = FindPlayerByAddress( packet->m_From );
if ( pl )
{
Warning( "Player already exists for %s\n", packet->m_From.ToString() );
}
else
{
// Creates the connection
pl = new CPlayer( this, packet->m_From );
m_Players.AddToTail( pl );
// Now send the conn accepted message
AcceptConnection( packet->m_From );
}
}
break;
default:
{
Warning( "CNetworkServer::ProcessConnectionlessPacket: Unknown code '%i' from '%s'\n",
code, packet->m_From.ToString() );
}
break;
}
return true;
}
void CNetworkServer::AcceptConnection( const netadr_t& remote )
{
byte data[ 512 ];
bf_write buf( "CNetworkServer::AcceptConnection", data, sizeof( data ) );
buf.WriteLong( -1 );
buf.WriteByte( s2c_connect_accept );
m_pSocket->SendTo( remote, buf.GetData(), buf.GetNumBytesWritten() );
}
void CNetworkServer::ReadPackets( void )
{
UDP_ProcessSocket( m_pSocket, this, this );
int c = m_Players.Count();
for ( int i = c - 1; i >= 0 ; --i )
{
if ( m_Players[ i ]->m_bMarkedForDeletion )
{
CPlayer *pl = m_Players[ i ];
m_Players.Remove( i );
delete pl;
}
}
}
void CNetworkServer::SendUpdates()
{
int c = m_Players.Count();
for ( int i = 0; i < c; ++i )
{
m_Players[ i ]->SendUpdate();
}
}
void CNetworkServer::OnConnectionStarted( INetChannel *pChannel )
{
// Create a network event
NetworkConnectionEvent_t *pConnection = g_pNetworkSystemImp->CreateNetworkEvent< NetworkConnectionEvent_t >( );
pConnection->m_nType = NETWORK_EVENT_CONNECTED;
pConnection->m_pChannel = pChannel;
}
void CNetworkServer::OnConnectionClosing( INetChannel *pChannel, char const *reason )
{
Warning( "OnConnectionClosing '%s'\n", reason );
CPlayer *pPlayer = FindPlayerByNetChannel( pChannel );
if ( pPlayer )
{
pPlayer->Shutdown();
}
// Create a network event
NetworkDisconnectionEvent_t *pDisconnection = g_pNetworkSystemImp->CreateNetworkEvent< NetworkDisconnectionEvent_t >( );
pDisconnection->m_nType = NETWORK_EVENT_DISCONNECTED;
pDisconnection->m_pChannel = pChannel;
}
void CNetworkServer::OnPacketStarted( int inseq, int outseq )
{
}
void CNetworkServer::OnPacketFinished()
{
}
//-----------------------------------------------------------------------------
//
// Implementation of CPlayer
//
//-----------------------------------------------------------------------------
CPlayer::CPlayer( CNetworkServer *server, netadr_t& remote ) :
m_bMarkedForDeletion( false )
{
m_NetChan.Setup( true, &remote, server->m_pSocket, "player", server );
}
void CPlayer::Shutdown()
{
m_bMarkedForDeletion = true;
m_NetChan.Shutdown( "received disconnect\n" );
}
void CPlayer::SendUpdate()
{
if ( m_NetChan.CanSendPacket() )
{
m_NetChan.SendDatagram( NULL );
}
}