Added a simple ping message to Qt netplay in an effort to measure round trip message delay.

This commit is contained in:
harry 2024-02-26 06:05:01 -05:00
parent 015f6a0acd
commit 145fc1614f
3 changed files with 150 additions and 1 deletions

View File

@ -26,6 +26,7 @@
#include "../../movie.h"
#include "../../debug.h"
#include "utils/crc32.h"
#include "utils/timeStamp.h"
#include "utils/StringUtils.h"
#include "Qt/main.h"
#include "Qt/dface.h"
@ -482,6 +483,22 @@ void NetPlayServer::serverProcessMessage( NetPlayClient *client, void *msgBuf, s
}
}
break;
case NETPLAY_PING_RESP:
{
netPlayPingResp *ping = static_cast<netPlayPingResp*>(msgBuf);
ping->toHostByteOrder();
FCEU::timeStampRecord ts;
ts.readNew();
uint64_t diff = ts.toMilliSeconds() - ping->hostTimeStamp;
client->recordPingResult( diff );
//printf("Ping Latency ms: %llu Avg:%f\n", static_cast<unsigned long long>(diff), client->getAvgPingDelay());
}
break;
default:
printf("Unknown Msg: %08X\n", msgId);
break;
@ -494,7 +511,7 @@ void NetPlayServer::update(void)
bool shouldRunFrame = false;
unsigned int clientMinFrame = 0xFFFFFFFF;
unsigned int clientMaxFrame = 0;
const uint32_t maxLead = 5u;
const uint32_t maxLead = maxLeadFrames;
const uint32_t currFrame = static_cast<uint32_t>(currFrameCounter);
const uint32_t leadFrame = currFrame + maxLead;
const uint32_t lastFrame = inputFrameBack();
@ -606,7 +623,40 @@ void NetPlayServer::update(void)
}
}
}
bool shouldRunPing = (cycleCounter % 120) == 0;
if (shouldRunPing)
{
FCEU::timeStampRecord ts;
ts.readNew();
netPlayPingReq ping;
ping.hostTimeStamp = ts.toMilliSeconds();
ping.toNetworkByteOrder();
for (auto it = clientList.begin(); it != clientList.end(); it++)
{
NetPlayClient *client = *it;
if (client->state > 0)
{
sendMsg( client, &ping, sizeof(ping) );
}
}
}
bool shouldFlushOutput = true;
if (shouldFlushOutput)
{
for (auto it = clientList.begin(); it != clientList.end(); it++)
{
NetPlayClient *client = *it;
client->flushData();
}
}
cycleCounter++;
}
//-----------------------------------------------------------------------------
//--- NetPlayClient
@ -784,6 +834,30 @@ void NetPlayClient::onSocketError(QAbstractSocket::SocketError error)
emit errorOccurred(errorMsg);
}
//-----------------------------------------------------------------------------
void NetPlayClient::recordPingResult( uint64_t delay_ms )
{
pingNumSamples++;
pingDelayLast = delay_ms;
pingDelaySum += delay_ms;
}
//-----------------------------------------------------------------------------
void NetPlayClient::resetPingData()
{
pingNumSamples = 0;
pingDelayLast = 0;
pingDelaySum = 0;
}
//-----------------------------------------------------------------------------
double NetPlayClient::getAvgPingDelay()
{
double ms = 0.0;
if (pingNumSamples > 0)
{
ms = static_cast<double>(pingDelaySum) / static_cast<double>(pingNumSamples);
}
return ms;
}
//-----------------------------------------------------------------------------
static void clientMessageCallback( void *userData, void *msgBuf, size_t msgSize )
{
NetPlayClient *client = static_cast<NetPlayClient*>(userData);
@ -821,6 +895,8 @@ void NetPlayClient::update(void)
statusMsg.toNetworkByteOrder();
sock->write( reinterpret_cast<const char*>(&statusMsg), sizeof(statusMsg) );
flushData();
}
}
//-----------------------------------------------------------------------------
@ -995,6 +1071,17 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
}
}
break;
case NETPLAY_PING_REQ:
{
netPlayPingResp pong;
netPlayPingReq *ping = static_cast<netPlayPingReq*>(msgBuf);
ping->toHostByteOrder();
pong.hostTimeStamp = ping->hostTimeStamp;
pong.toNetworkByteOrder();
sock->write( (const char*)&pong, sizeof(netPlayPingResp) );
}
break;
default:
printf("Unknown Msg: %08X\n", msgId);
break;

View File

@ -119,6 +119,9 @@ class NetPlayServer : public QTcpServer
void setRole(int _role);
bool claimRole(NetPlayClient* client, int _role);
uint32_t getMaxLeadFrames(){ return maxLeadFrames; }
void setMaxLeadFrames(uint32_t value){ maxLeadFrames = value; }
void serverProcessMessage( NetPlayClient *client, void *msgBuf, size_t msgSize );
QString sessionName;
@ -135,6 +138,8 @@ class NetPlayServer : public QTcpServer
int roleMask = 0;
NetPlayClient* clientPlayer[4] = { nullptr };
int forceResyncCount = 10;
uint32_t cycleCounter = 0;
uint32_t maxLeadFrames = 10u;
public slots:
void newConnectionRdy(void);
@ -209,6 +214,9 @@ class NetPlayClient : public QObject
bool shouldDestroy(){ return needsDestroy; }
bool isPaused(){ return paused; }
void setPaused(bool value){ paused = value; }
void recordPingResult( uint64_t delay_ms );
void resetPingData(void);
double getAvgPingDelay();
QString userName;
QString password;
@ -234,6 +242,10 @@ class NetPlayClient : public QObject
bool _connected = false;
bool paused = false;
uint64_t pingDelaySum = 0;
uint64_t pingDelayLast = 0;
uint64_t pingNumSamples = 0;
std::list <NetPlayFrameInput> input;
FCEU::mutex inputMtx;

View File

@ -22,6 +22,8 @@ enum netPlayMsgType
NETPLAY_RUN_FRAME_REQ,
NETPLAY_CLIENT_STATE,
NETPLAY_ERROR_MSG,
NETPLAY_PING_REQ,
NETPLAY_PING_RESP,
};
enum netPlayerId
@ -269,5 +271,53 @@ struct netPlayClientState
}
};
struct netPlayPingReq
{
netPlayMsgHdr hdr;
uint64_t hostTimeStamp;
netPlayPingReq(void)
: hdr(NETPLAY_PING_REQ, sizeof(netPlayPingReq)), hostTimeStamp(0)
{
}
void toHostByteOrder()
{
hdr.toHostByteOrder();
hostTimeStamp = netPlayByteSwap(hostTimeStamp);
}
void toNetworkByteOrder()
{
hdr.toNetworkByteOrder();
hostTimeStamp = netPlayByteSwap(hostTimeStamp);
}
};
struct netPlayPingResp
{
netPlayMsgHdr hdr;
uint64_t hostTimeStamp;
netPlayPingResp(void)
: hdr(NETPLAY_PING_RESP, sizeof(netPlayPingResp)), hostTimeStamp(0)
{
}
void toHostByteOrder()
{
hdr.toHostByteOrder();
hostTimeStamp = netPlayByteSwap(hostTimeStamp);
}
void toNetworkByteOrder()
{
hdr.toNetworkByteOrder();
hostTimeStamp = netPlayByteSwap(hostTimeStamp);
}
};
#pragma pack(pop)