mirror of
https://github.com/libretro/Mesen.git
synced 2024-12-13 11:57:09 +00:00
99 lines
3.0 KiB
C++
99 lines
3.0 KiB
C++
#include "stdafx.h"
|
|
#include "GameConnection.h"
|
|
#include "HandShakeMessage.h"
|
|
#include "InputDataMessage.h"
|
|
#include "MovieDataMessage.h"
|
|
#include "GameInformationMessage.h"
|
|
#include "SaveStateMessage.h"
|
|
#include "PlayerListMessage.h"
|
|
#include "SelectControllerMessage.h"
|
|
#include "ClientConnectionData.h"
|
|
#include "ForceDisconnectMessage.h"
|
|
|
|
const uint32_t PlayerListMessage::PlayerNameMaxLength;
|
|
|
|
GameConnection::GameConnection(shared_ptr<Socket> socket, shared_ptr<ClientConnectionData> connectionData)
|
|
{
|
|
_connectionData = connectionData;
|
|
_socket = socket;
|
|
}
|
|
|
|
void GameConnection::ReadSocket()
|
|
{
|
|
auto lock = _socketLock.AcquireSafe();
|
|
int bytesReceived = _socket->Recv((char*)_readBuffer + _readPosition, 0x40000 - _readPosition, 0);
|
|
if(bytesReceived > 0) {
|
|
_readPosition += bytesReceived;
|
|
}
|
|
}
|
|
|
|
bool GameConnection::ExtractMessage(void *buffer, uint32_t &messageLength)
|
|
{
|
|
messageLength = _readBuffer[0] | (_readBuffer[1] << 8) | (_readBuffer[2] << 16) | (_readBuffer[3] << 24);
|
|
|
|
if(messageLength > 1000000) {
|
|
MessageManager::Log("[Netplay] Invalid data received, closing connection.");
|
|
Disconnect();
|
|
return false;
|
|
}
|
|
|
|
int packetLength = messageLength + sizeof(messageLength);
|
|
|
|
if(_readPosition >= packetLength) {
|
|
memcpy(buffer, _readBuffer+sizeof(messageLength), messageLength);
|
|
memmove(_readBuffer, _readBuffer + packetLength, _readPosition - packetLength);
|
|
_readPosition -= packetLength;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
NetMessage* GameConnection::ReadMessage()
|
|
{
|
|
ReadSocket();
|
|
|
|
if(_readPosition > 4) {
|
|
uint32_t messageLength;
|
|
if(ExtractMessage(_messageBuffer, messageLength)) {
|
|
switch((MessageType)_messageBuffer[0]) {
|
|
case MessageType::HandShake: return new HandShakeMessage(_messageBuffer, messageLength);
|
|
case MessageType::SaveState: return new SaveStateMessage(_messageBuffer, messageLength);
|
|
case MessageType::InputData: return new InputDataMessage(_messageBuffer, messageLength);
|
|
case MessageType::MovieData: return new MovieDataMessage(_messageBuffer, messageLength);
|
|
case MessageType::GameInformation: return new GameInformationMessage(_messageBuffer, messageLength);
|
|
case MessageType::PlayerList: return new PlayerListMessage(_messageBuffer, messageLength);
|
|
case MessageType::SelectController: return new SelectControllerMessage(_messageBuffer, messageLength);
|
|
case MessageType::ForceDisconnect: return new ForceDisconnectMessage(_messageBuffer, messageLength);
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void GameConnection::SendNetMessage(NetMessage &message)
|
|
{
|
|
auto lock = _socketLock.AcquireSafe();
|
|
message.Send(*_socket.get());
|
|
}
|
|
|
|
void GameConnection::Disconnect()
|
|
{
|
|
auto lock = _socketLock.AcquireSafe();
|
|
_socket->Close();
|
|
}
|
|
|
|
bool GameConnection::ConnectionError()
|
|
{
|
|
return _socket->ConnectionError();
|
|
}
|
|
|
|
void GameConnection::ProcessMessages()
|
|
{
|
|
NetMessage* message;
|
|
while((message = ReadMessage()) != nullptr) {
|
|
//Loop until all messages have been processed
|
|
message->Initialize();
|
|
ProcessMessage(message);
|
|
delete message;
|
|
}
|
|
} |