2014-07-09 19:05:07 -04:00
# include "stdafx.h"
2018-06-16 14:02:12 -04:00
# include <random>
2015-07-01 23:17:14 -04:00
# include "MessageManager.h"
2014-07-09 19:05:07 -04:00
# include "GameServerConnection.h"
# include "HandShakeMessage.h"
# include "InputDataMessage.h"
# include "MovieDataMessage.h"
# include "GameInformationMessage.h"
# include "SaveStateMessage.h"
# include "Console.h"
# include "ControlManager.h"
2015-07-01 23:17:14 -04:00
# include "ClientConnectionData.h"
2015-07-17 20:58:57 -04:00
# include "EmulationSettings.h"
2016-02-05 23:14:27 -05:00
# include "StandardController.h"
2016-02-06 15:33:45 -05:00
# include "SelectControllerMessage.h"
# include "PlayerListMessage.h"
# include "GameServer.h"
2016-02-10 23:07:42 -05:00
# include "ForceDisconnectMessage.h"
2017-11-19 23:08:23 -05:00
# include "BaseControlDevice.h"
2018-06-16 14:02:12 -04:00
# include "ServerInformationMessage.h"
2014-07-09 19:05:07 -04:00
2017-11-19 23:08:23 -05:00
GameServerConnection * GameServerConnection : : _netPlayDevices [ BaseControlDevice : : PortCount ] = { } ;
2016-02-05 23:14:27 -05:00
2018-07-01 15:21:05 -04:00
GameServerConnection : : GameServerConnection ( shared_ptr < Console > console , shared_ptr < Socket > socket , string serverPassword ) : GameConnection ( console , socket )
2014-07-09 19:05:07 -04:00
{
//Server-side connection
2018-06-16 14:02:12 -04:00
_serverPassword = serverPassword ;
2016-02-06 15:33:45 -05:00
_controllerPort = GameConnection : : SpectatorPort ;
2018-06-16 14:02:12 -04:00
SendServerInformation ( ) ;
2014-07-09 19:05:07 -04:00
}
GameServerConnection : : ~ GameServerConnection ( )
{
2018-06-16 14:02:12 -04:00
if ( ! _playerName . empty ( ) ) {
MessageManager : : DisplayMessage ( " NetPlay " , _playerName + " (Player " + std : : to_string ( _controllerPort + 1 ) + " ) disconnected. " ) ;
2015-07-01 23:17:14 -04:00
}
2014-07-09 19:05:07 -04:00
2016-02-05 23:14:27 -05:00
UnregisterNetPlayDevice ( this ) ;
2014-07-09 19:05:07 -04:00
}
2018-06-16 14:02:12 -04:00
void GameServerConnection : : SendServerInformation ( )
{
std : : random_device rd ;
std : : mt19937 engine ( rd ( ) ) ;
std : : uniform_int_distribution < > dist ( ( int ) ' ' , ( int ) ' ~ ' ) ;
string hash ( 50 , ' ' ) ;
for ( int i = 0 ; i < 50 ; i + + ) {
int random = dist ( engine ) ;
hash [ i ] = ( char ) random ;
}
_connectionHash = hash ;
ServerInformationMessage message ( hash ) ;
SendNetMessage ( message ) ;
}
2014-07-09 19:05:07 -04:00
void GameServerConnection : : SendGameInformation ( )
{
2018-07-01 15:21:05 -04:00
_console - > Pause ( ) ;
2018-07-07 14:52:51 -04:00
RomInfo romInfo = _console - > GetRomInfo ( ) ;
2018-07-13 22:19:26 -04:00
GameInformationMessage gameInfo ( romInfo . RomName , romInfo . Hash . Crc32 , _controllerPort , _console - > GetSettings ( ) - > CheckFlag ( EmulationFlags : : Paused ) ) ;
2016-01-23 00:52:06 -05:00
SendNetMessage ( gameInfo ) ;
2018-07-01 15:21:05 -04:00
SaveStateMessage saveState ( _console ) ;
2016-01-23 00:52:06 -05:00
SendNetMessage ( saveState ) ;
2018-07-01 15:21:05 -04:00
_console - > Resume ( ) ;
2014-07-09 19:05:07 -04:00
}
2017-11-19 23:08:23 -05:00
void GameServerConnection : : SendMovieData ( uint8_t port , ControlDeviceState state )
2014-07-09 19:05:07 -04:00
{
if ( _handshakeCompleted ) {
2015-08-28 21:01:18 -04:00
MovieDataMessage message ( state , port ) ;
SendNetMessage ( message ) ;
2014-07-09 19:05:07 -04:00
}
}
2016-02-10 23:07:42 -05:00
void GameServerConnection : : SendForceDisconnectMessage ( string disconnectMessage )
{
ForceDisconnectMessage message ( disconnectMessage ) ;
SendNetMessage ( message ) ;
Disconnect ( ) ;
}
2017-11-19 23:08:23 -05:00
void GameServerConnection : : PushState ( ControlDeviceState state )
2016-02-05 23:14:27 -05:00
{
if ( _inputData . size ( ) = = 0 | | state ! = _inputData . back ( ) ) {
2017-11-19 23:08:23 -05:00
_inputData . clear ( ) ;
2016-02-05 23:14:27 -05:00
_inputData . push_back ( state ) ;
}
}
2017-11-19 23:08:23 -05:00
ControlDeviceState GameServerConnection : : GetState ( )
2014-07-09 19:05:07 -04:00
{
2015-07-06 21:31:32 -04:00
size_t inputBufferSize = _inputData . size ( ) ;
2017-11-19 23:08:23 -05:00
ControlDeviceState stateData ;
2014-07-09 19:05:07 -04:00
if ( inputBufferSize > 0 ) {
stateData = _inputData . front ( ) ;
if ( inputBufferSize > 1 ) {
//Always keep the last one the client sent, it will be used until a new one is received
_inputData . pop_front ( ) ;
}
}
2016-02-05 23:14:27 -05:00
return stateData ;
2014-07-09 19:05:07 -04:00
}
2014-07-09 21:48:54 -04:00
2016-02-06 15:33:45 -05:00
void GameServerConnection : : ProcessHandshakeResponse ( HandShakeMessage * message )
{
//Send the game's current state to the client and register the controller
if ( message - > IsValid ( ) ) {
2018-06-16 14:02:12 -04:00
if ( message - > CheckPassword ( _serverPassword , _connectionHash ) ) {
2018-07-01 15:21:05 -04:00
_console - > Pause ( ) ;
2016-02-06 15:33:45 -05:00
2018-06-16 14:02:12 -04:00
_controllerPort = message - > IsSpectator ( ) ? GameConnection : : SpectatorPort : GetFirstFreeControllerPort ( ) ;
_playerName = message - > GetPlayerName ( ) ;
2016-02-06 15:33:45 -05:00
2018-06-16 14:02:12 -04:00
string playerPortMessage = _controllerPort = = GameConnection : : SpectatorPort ? " Spectator " : " Player " + std : : to_string ( _controllerPort + 1 ) ;
2016-02-06 15:33:45 -05:00
2018-06-16 14:02:12 -04:00
MessageManager : : DisplayMessage ( " NetPlay " , _playerName + " ( " + playerPortMessage + " ) connected. " ) ;
2016-02-06 15:33:45 -05:00
2018-07-07 14:52:51 -04:00
if ( _console - > GetRomInfo ( ) . RomName . size ( ) > 0 ) {
2018-06-16 14:02:12 -04:00
SendGameInformation ( ) ;
}
2016-02-06 15:33:45 -05:00
2018-06-16 14:02:12 -04:00
_handshakeCompleted = true ;
RegisterNetPlayDevice ( this , _controllerPort ) ;
GameServer : : SendPlayerList ( ) ;
2018-07-01 15:21:05 -04:00
_console - > Resume ( ) ;
2018-06-16 14:02:12 -04:00
} else {
SendForceDisconnectMessage ( " The password you provided did not match - you have been disconnected. " ) ;
}
2016-02-10 23:07:42 -05:00
} else {
SendForceDisconnectMessage ( " Server is using a different version of Mesen ( " + EmulationSettings : : GetMesenVersionString ( ) + " ) - you have been disconnected. " ) ;
2016-02-19 13:05:04 -05:00
MessageManager : : DisplayMessage ( " NetPlay " , + " NetplayVersionMismatch " , message - > GetPlayerName ( ) ) ;
2016-02-06 15:33:45 -05:00
}
}
2015-07-01 23:17:14 -04:00
void GameServerConnection : : ProcessMessage ( NetMessage * message )
{
switch ( message - > GetType ( ) ) {
case MessageType : : HandShake :
2016-02-06 15:33:45 -05:00
ProcessHandshakeResponse ( ( HandShakeMessage * ) message ) ;
2015-07-01 23:17:14 -04:00
break ;
2016-02-06 15:33:45 -05:00
2015-07-01 23:17:14 -04:00
case MessageType : : InputData :
2018-06-29 00:08:48 -04:00
if ( ! _handshakeCompleted ) {
SendForceDisconnectMessage ( " Handshake has not been completed - invalid packet " ) ;
return ;
2018-06-16 14:02:12 -04:00
}
2016-02-05 23:14:27 -05:00
PushState ( ( ( InputDataMessage * ) message ) - > GetInputState ( ) ) ;
2015-07-01 23:17:14 -04:00
break ;
2016-02-06 15:33:45 -05:00
case MessageType : : SelectController :
2018-06-29 00:08:48 -04:00
if ( ! _handshakeCompleted ) {
SendForceDisconnectMessage ( " Handshake has not been completed - invalid packet " ) ;
return ;
2018-06-16 14:02:12 -04:00
}
2016-02-06 15:33:45 -05:00
SelectControllerPort ( ( ( SelectControllerMessage * ) message ) - > GetPortNumber ( ) ) ;
break ;
2015-08-28 21:01:18 -04:00
default :
break ;
2015-07-01 23:17:14 -04:00
}
}
2016-02-06 15:33:45 -05:00
void GameServerConnection : : SelectControllerPort ( uint8_t port )
{
2018-07-01 15:21:05 -04:00
_console - > Pause ( ) ;
2016-02-06 15:33:45 -05:00
if ( port = = GameConnection : : SpectatorPort ) {
//Client wants to be a spectator, make sure we are not using any controller
UnregisterNetPlayDevice ( this ) ;
_controllerPort = port ;
} else {
GameServerConnection * netPlayDevice = GetNetPlayDevice ( port ) ;
if ( netPlayDevice = = this ) {
//Nothing to do, we're already this player
} else if ( netPlayDevice = = nullptr ) {
//This port is free, we can switch
UnregisterNetPlayDevice ( this ) ;
RegisterNetPlayDevice ( this , port ) ;
_controllerPort = port ;
} else {
//Another player is using this port, we can't use it
}
}
SendGameInformation ( ) ;
GameServer : : SendPlayerList ( ) ;
2018-07-01 15:21:05 -04:00
_console - > Resume ( ) ;
2016-02-06 15:33:45 -05:00
}
2015-12-26 17:11:00 -05:00
void GameServerConnection : : ProcessNotification ( ConsoleNotificationType type , void * parameter )
2014-07-09 21:48:54 -04:00
{
switch ( type ) {
case ConsoleNotificationType : : GamePaused :
case ConsoleNotificationType : : GameResumed :
2015-07-01 23:17:14 -04:00
case ConsoleNotificationType : : GameReset :
2016-01-21 17:57:18 -05:00
case ConsoleNotificationType : : StateLoaded :
2016-01-23 00:52:06 -05:00
case ConsoleNotificationType : : CheatAdded :
2016-02-05 23:14:27 -05:00
case ConsoleNotificationType : : ConfigChanged :
2020-04-22 22:30:54 -04:00
case ConsoleNotificationType : : GameInitCompleted :
2014-07-09 21:48:54 -04:00
SendGameInformation ( ) ;
break ;
2015-08-28 21:01:18 -04:00
default :
break ;
2014-07-09 21:48:54 -04:00
}
2016-02-05 23:14:27 -05:00
}
void GameServerConnection : : RegisterNetPlayDevice ( GameServerConnection * device , uint8_t port )
{
GameServerConnection : : _netPlayDevices [ port ] = device ;
}
void GameServerConnection : : UnregisterNetPlayDevice ( GameServerConnection * device )
{
if ( device ! = nullptr ) {
2017-11-19 23:08:23 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2016-02-05 23:14:27 -05:00
if ( GameServerConnection : : _netPlayDevices [ i ] = = device ) {
GameServerConnection : : _netPlayDevices [ i ] = nullptr ;
break ;
}
}
}
}
GameServerConnection * GameServerConnection : : GetNetPlayDevice ( uint8_t port )
{
return GameServerConnection : : _netPlayDevices [ port ] ;
2016-02-06 15:33:45 -05:00
}
uint8_t GameServerConnection : : GetFirstFreeControllerPort ( )
{
uint8_t hostPost = GameServer : : GetHostControllerPort ( ) ;
2017-11-19 23:08:23 -05:00
for ( int i = 0 ; i < BaseControlDevice : : PortCount ; i + + ) {
2016-02-06 15:33:45 -05:00
if ( hostPost ! = i & & GameServerConnection : : _netPlayDevices [ i ] = = nullptr ) {
return i ;
}
}
return GameConnection : : SpectatorPort ;
}
string GameServerConnection : : GetPlayerName ( )
{
2018-06-16 14:02:12 -04:00
return _playerName ;
2016-02-06 15:33:45 -05:00
}
uint8_t GameServerConnection : : GetControllerPort ( )
{
return _controllerPort ;
2014-07-09 21:48:54 -04:00
}