SI/DeviceGBA: Ensure data socket isn't backed up
When reading a reply from a message sent to the data socket there is the possibility that the other side gets sent multiple messages before replying to any of them, which can lead to multiple replies sent in a row. Though this only happens when things time out, it's quite possible for these timeouts to happen or build up over time, especially when initiating the connection. This change makes sure to flush any pending bytes that have not been read yet out of the socket after a successful POLL reply is received, since that is the most common time when backups occur, and as well as using the exact number of bytes in an expected reply, to ensure the received data and the message it's replying to do not get out of sync.
This commit is contained in:
parent
7712f0831f
commit
f6e9003ddc
|
@ -253,7 +253,7 @@ void GBASockServer::Send(const u8* si_buffer)
|
||||||
Disconnect();
|
Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GBASockServer::Receive(u8* si_buffer)
|
int GBASockServer::Receive(u8* si_buffer, u8 bytes)
|
||||||
{
|
{
|
||||||
if (!m_client)
|
if (!m_client)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -267,8 +267,7 @@ int GBASockServer::Receive(u8* si_buffer)
|
||||||
|
|
||||||
size_t num_received = 0;
|
size_t num_received = 0;
|
||||||
std::array<u8, RECV_MAX_SIZE> recv_data;
|
std::array<u8, RECV_MAX_SIZE> recv_data;
|
||||||
sf::Socket::Status recv_stat =
|
sf::Socket::Status recv_stat = m_client->receive(recv_data.data(), bytes, num_received);
|
||||||
m_client->receive(recv_data.data(), recv_data.size(), num_received);
|
|
||||||
if (recv_stat == sf::Socket::Disconnected)
|
if (recv_stat == sf::Socket::Disconnected)
|
||||||
{
|
{
|
||||||
Disconnect();
|
Disconnect();
|
||||||
|
@ -286,6 +285,21 @@ int GBASockServer::Receive(u8* si_buffer)
|
||||||
return static_cast<int>(std::min(num_received, recv_data.size()));
|
return static_cast<int>(std::min(num_received, recv_data.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBASockServer::Flush()
|
||||||
|
{
|
||||||
|
if (!m_client || !m_booted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t num_received = 1;
|
||||||
|
u8 byte;
|
||||||
|
while (num_received)
|
||||||
|
{
|
||||||
|
sf::Socket::Status recv_stat = m_client->receive(&byte, 1, num_received);
|
||||||
|
if (recv_stat == sf::Socket::Disconnected)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CSIDevice_GBA::CSIDevice_GBA(SIDevices device, int device_number) : ISIDevice(device, device_number)
|
CSIDevice_GBA::CSIDevice_GBA(SIDevices device, int device_number) : ISIDevice(device, device_number)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -329,7 +343,23 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int request_length)
|
||||||
|
|
||||||
case NextAction::ReceiveResponse:
|
case NextAction::ReceiveResponse:
|
||||||
{
|
{
|
||||||
int num_data_received = m_sock_server.Receive(buffer);
|
u8 bytes = 1;
|
||||||
|
switch (m_last_cmd)
|
||||||
|
{
|
||||||
|
case CMD_RESET:
|
||||||
|
case CMD_STATUS:
|
||||||
|
bytes = 3;
|
||||||
|
break;
|
||||||
|
case CMD_READ:
|
||||||
|
bytes = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int num_data_received = m_sock_server.Receive(buffer, bytes);
|
||||||
|
if (m_last_cmd == CMD_STATUS && num_data_received == 3)
|
||||||
|
m_sock_server.Flush();
|
||||||
|
|
||||||
m_next_action = NextAction::SendCommand;
|
m_next_action = NextAction::SendCommand;
|
||||||
if (num_data_received == 0)
|
if (num_data_received == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,8 @@ public:
|
||||||
bool IsConnected();
|
bool IsConnected();
|
||||||
void ClockSync();
|
void ClockSync();
|
||||||
void Send(const u8* si_buffer);
|
void Send(const u8* si_buffer);
|
||||||
int Receive(u8* si_buffer);
|
int Receive(u8* si_buffer, u8 bytes);
|
||||||
|
void Flush();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
Loading…
Reference in New Issue