2019-10-20 20:05:39 -04:00
# include "stdafx.h"
# include <random>
# include "MessageManager.h"
# include "GameServerConnection.h"
# include "HandShakeMessage.h"
# include "InputDataMessage.h"
# include "MovieDataMessage.h"
# include "GameInformationMessage.h"
# include "SaveStateMessage.h"
# include "Console.h"
# include "BaseCartridge.h"
# include "ControlManager.h"
# include "ClientConnectionData.h"
# include "EmuSettings.h"
# include "SelectControllerMessage.h"
# include "PlayerListMessage.h"
# include "GameServer.h"
# include "ForceDisconnectMessage.h"
# include "BaseControlDevice.h"
# include "ServerInformationMessage.h"
2021-03-10 11:13:28 -05:00
GameServerConnection * GameServerConnection : : _netPlayDevices [ BaseControlDevice : : PortCount ] = { } ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
GameServerConnection : : GameServerConnection ( shared_ptr < Console > console , shared_ptr < Socket > socket , string serverPassword ) : GameConnection ( console , socket )
2019-10-20 20:05:39 -04:00
{
//Server-side connection
_serverPassword = serverPassword ;
_controllerPort = GameConnection : : SpectatorPort ;
SendServerInformation ( ) ;
}
GameServerConnection : : ~ GameServerConnection ( )
{
2021-03-10 11:13:28 -05:00
if ( ! _playerName . empty ( ) ) {
MessageManager : : DisplayMessage ( " NetPlay " , _playerName + " (Player " + std : : to_string ( _controllerPort + 1 ) + " ) disconnected. " ) ;
2019-10-20 20:05:39 -04:00
}
UnregisterNetPlayDevice ( this ) ;
}
void GameServerConnection : : SendServerInformation ( )
{
std : : random_device rd ;
std : : mt19937 engine ( rd ( ) ) ;
std : : uniform_int_distribution < > dist ( ( int ) ' ' , ( int ) ' ~ ' ) ;
string hash ( 50 , ' ' ) ;
2021-03-10 11:13:28 -05:00
for ( int i = 0 ; i < 50 ; i + + ) {
2019-10-20 20:05:39 -04:00
int random = dist ( engine ) ;
hash [ i ] = ( char ) random ;
}
_connectionHash = hash ;
ServerInformationMessage message ( hash ) ;
SendNetMessage ( message ) ;
}
void GameServerConnection : : SendGameInformation ( )
{
_console - > Lock ( ) ;
RomInfo romInfo = _console - > GetRomInfo ( ) ;
2021-03-10 11:13:28 -05:00
GameInformationMessage gameInfo ( romInfo . RomFile . GetFileName ( ) , _console - > GetCartridge ( ) - > GetSha1Hash ( ) , _controllerPort , _console - > IsPaused ( ) ) ;
2019-10-20 20:05:39 -04:00
SendNetMessage ( gameInfo ) ;
SaveStateMessage saveState ( _console ) ;
SendNetMessage ( saveState ) ;
_console - > Unlock ( ) ;
}
void GameServerConnection : : SendMovieData ( uint8_t port , ControlDeviceState state )
{
2021-03-10 11:13:28 -05:00
if ( _handshakeCompleted ) {
2019-10-20 20:05:39 -04:00
MovieDataMessage message ( state , port ) ;
SendNetMessage ( message ) ;
}
}
void GameServerConnection : : SendForceDisconnectMessage ( string disconnectMessage )
{
ForceDisconnectMessage message ( disconnectMessage ) ;
SendNetMessage ( message ) ;
Disconnect ( ) ;
}
void GameServerConnection : : PushState ( ControlDeviceState state )
{
2021-03-10 11:13:28 -05:00
if ( _inputData . size ( ) = = 0 | | state ! = _inputData . back ( ) ) {
2019-10-20 20:05:39 -04:00
_inputData . clear ( ) ;
_inputData . push_back ( state ) ;
}
}
ControlDeviceState GameServerConnection : : GetState ( )
{
size_t inputBufferSize = _inputData . size ( ) ;
ControlDeviceState stateData ;
2021-03-10 11:13:28 -05:00
if ( inputBufferSize > 0 ) {
2019-10-20 20:05:39 -04:00
stateData = _inputData . front ( ) ;
2021-03-10 11:13:28 -05:00
if ( inputBufferSize > 1 ) {
2019-10-20 20:05:39 -04:00
//Always keep the last one the client sent, it will be used until a new one is received
_inputData . pop_front ( ) ;
}
}
return stateData ;
}
void GameServerConnection : : ProcessHandshakeResponse ( HandShakeMessage * message )
{
//Send the game's current state to the client and register the controller
2021-03-10 11:13:28 -05:00
if ( message - > IsValid ( _console - > GetSettings ( ) - > GetVersion ( ) ) ) {
if ( message - > CheckPassword ( _serverPassword , _connectionHash ) ) {
2019-10-20 20:05:39 -04:00
_console - > Lock ( ) ;
_controllerPort = message - > IsSpectator ( ) ? GameConnection : : SpectatorPort : GetFirstFreeControllerPort ( ) ;
_playerName = message - > GetPlayerName ( ) ;
2021-03-10 11:13:28 -05:00
string playerPortMessage = _controllerPort = = GameConnection : : SpectatorPort ? " Spectator " : " Player " + std : : to_string ( _controllerPort + 1 ) ;
2019-10-20 20:05:39 -04:00
MessageManager : : DisplayMessage ( " NetPlay " , _playerName + " ( " + playerPortMessage + " ) connected. " ) ;
2021-03-10 11:13:28 -05:00
if ( _console - > GetCartridge ( ) ) {
2019-10-20 20:05:39 -04:00
SendGameInformation ( ) ;
}
_handshakeCompleted = true ;
RegisterNetPlayDevice ( this , _controllerPort ) ;
GameServer : : SendPlayerList ( ) ;
_console - > Unlock ( ) ;
2021-03-10 11:13:28 -05:00
} else {
2019-10-20 20:05:39 -04:00
SendForceDisconnectMessage ( " The password you provided did not match - you have been disconnected. " ) ;
}
2021-03-10 11:13:28 -05:00
} else {
SendForceDisconnectMessage ( " Server is using a different version of Mesen-S ( " + _console - > GetSettings ( ) - > GetVersionString ( ) + " ) - you have been disconnected. " ) ;
2019-10-20 20:05:39 -04:00
MessageManager : : DisplayMessage ( " NetPlay " , + " NetplayVersionMismatch " , message - > GetPlayerName ( ) ) ;
}
}
void GameServerConnection : : ProcessMessage ( NetMessage * message )
{
2021-03-10 11:13:28 -05:00
switch ( message - > GetType ( ) ) {
case MessageType : : HandShake :
ProcessHandshakeResponse ( ( HandShakeMessage * ) message ) ;
break ;
2019-10-20 20:05:39 -04:00
2021-03-10 11:13:28 -05:00
case MessageType : : InputData :
if ( ! _handshakeCompleted ) {
SendForceDisconnectMessage ( " Handshake has not been completed - invalid packet " ) ;
return ;
}
PushState ( ( ( InputDataMessage * ) message ) - > GetInputState ( ) ) ;
break ;
case MessageType : : SelectController :
if ( ! _handshakeCompleted ) {
SendForceDisconnectMessage ( " Handshake has not been completed - invalid packet " ) ;
return ;
}
SelectControllerPort ( ( ( SelectControllerMessage * ) message ) - > GetPortNumber ( ) ) ;
break ;
default :
break ;
2019-10-20 20:05:39 -04:00
}
}
void GameServerConnection : : SelectControllerPort ( uint8_t port )
{
_console - > Lock ( ) ;
2021-03-10 11:13:28 -05:00
if ( port = = GameConnection : : SpectatorPort ) {
2019-10-20 20:05:39 -04:00
//Client wants to be a spectator, make sure we are not using any controller
UnregisterNetPlayDevice ( this ) ;
_controllerPort = port ;
2021-03-10 11:13:28 -05:00
} else {
2019-10-20 20:05:39 -04:00
GameServerConnection * netPlayDevice = GetNetPlayDevice ( port ) ;
2021-03-10 11:13:28 -05:00
if ( netPlayDevice = = this ) {
2019-10-20 20:05:39 -04:00
//Nothing to do, we're already this player
2021-03-10 11:13:28 -05:00
} else if ( netPlayDevice = = nullptr ) {
2019-10-20 20:05:39 -04:00
//This port is free, we can switch
UnregisterNetPlayDevice ( this ) ;
RegisterNetPlayDevice ( this , port ) ;
_controllerPort = port ;
2021-03-10 11:13:28 -05:00
} else {
2019-10-20 20:05:39 -04:00
//Another player is using this port, we can't use it
}
}
SendGameInformation ( ) ;
GameServer : : SendPlayerList ( ) ;
_console - > Unlock ( ) ;
}
void GameServerConnection : : ProcessNotification ( ConsoleNotificationType type , void * parameter )
{
2021-03-10 11:13:28 -05:00
switch ( type ) {
case ConsoleNotificationType : : GamePaused :
case ConsoleNotificationType : : GameLoaded :
case ConsoleNotificationType : : GameResumed :
case ConsoleNotificationType : : GameReset :
case ConsoleNotificationType : : StateLoaded :
case ConsoleNotificationType : : CheatsChanged :
case ConsoleNotificationType : : ConfigChanged :
SendGameInformation ( ) ;
break ;
case ConsoleNotificationType : : BeforeEmulationStop : {
2019-10-20 20:05:39 -04:00
//Make clients unload the current game
GameInformationMessage gameInfo ( " " , " 0000000000000000000000000000000000000000 " , _controllerPort , true ) ;
SendNetMessage ( gameInfo ) ;
break ;
}
2021-03-10 11:13:28 -05:00
default :
break ;
2019-10-20 20:05:39 -04:00
}
}
void GameServerConnection : : RegisterNetPlayDevice ( GameServerConnection * device , uint8_t port )
{
GameServerConnection : : _netPlayDevices [ port ] = device ;
}
void GameServerConnection : : UnregisterNetPlayDevice ( GameServerConnection * device )
{
2021-03-10 11:13:28 -05:00
if ( device ! = nullptr ) {
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
if ( GameServerConnection : : _netPlayDevices [ i ] = = device ) {
2019-10-20 20:05:39 -04:00
GameServerConnection : : _netPlayDevices [ i ] = nullptr ;
break ;
}
}
}
}
GameServerConnection * GameServerConnection : : GetNetPlayDevice ( uint8_t port )
{
return GameServerConnection : : _netPlayDevices [ port ] ;
}
uint8_t GameServerConnection : : GetFirstFreeControllerPort ( )
{
uint8_t hostPost = GameServer : : GetHostControllerPort ( ) ;
2021-03-10 11:13:28 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
if ( hostPost ! = i & & GameServerConnection : : _netPlayDevices [ i ] = = nullptr ) {
2019-10-20 20:05:39 -04:00
return i ;
}
}
return GameConnection : : SpectatorPort ;
}
string GameServerConnection : : GetPlayerName ( )
{
return _playerName ;
}
uint8_t GameServerConnection : : GetControllerPort ( )
{
return _controllerPort ;
2021-03-10 11:13:28 -05:00
}