Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Core/GameEngine/Include/GameNetwork/ConnectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include "GameNetwork/FrameMetrics.h"
#include "GameNetwork/NetworkDefs.h"
#include "GameNetwork/DisconnectManager.h"
#if defined(GENERALS_ONLINE)
#include "GameNetwork/NetworkSettings.h"
#endif

class GameInfo;
class NetCommandWrapperList;
Expand All @@ -56,6 +59,7 @@ class ConnectionManager
virtual void update(Bool isInGame); ///< Service the Connections being managed by this instance.

#if defined(GENERALS_ONLINE)
const NetworkSettings &getNetworkSettings() const { return m_networkSettings; }
void SeedLatencyData(int highestLatency)
{
for (int i = 0; i < MAX_SLOTS; ++i) {
Expand Down Expand Up @@ -165,6 +169,10 @@ class ConnectionManager
Int getPingsReceived();

private:
#if defined(GENERALS_ONLINE)
NetworkSettings m_networkSettings;
#endif

void doRelay();
void doKeepAlive();
void sendRemoteCommand(NetCommandRef *msg);
Expand Down
3 changes: 3 additions & 0 deletions Core/GameEngine/Include/GameNetwork/FrameMetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class FrameMetrics {
Real *m_fpsList; ///< A record of how many game logic frames per second there were for the last 60 seconds.
time_t m_lastFpsTimeThing; ///< The time when the last fps entry started being recorded.
Int m_fpsListIndex; ///< Index into the array of the current fps list entry being measured.
#if defined(GENERALS_ONLINE)
UnsignedInt m_fpsListLength; ///< Entries m_fpsList holds, the history length can change after construction.
#endif
Real m_averageFps; ///< The current average logic fps, computed just like m_averageLatency below but with the fps numbers.

// round trip time to packet router variables.
Expand Down
2 changes: 1 addition & 1 deletion Core/GameEngine/Include/GameNetwork/NetworkDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static constexpr const Int MIN_LOGIC_FRAMES = 5;
static constexpr const Int MAX_FRAMES_AHEAD = 128;

#if defined(GENERALS_ONLINE)
static Int MIN_RUNAHEAD = 6;
extern Int MIN_RUNAHEAD;
#else
static constexpr const Int MIN_RUNAHEAD = 4;
#endif
Expand Down
35 changes: 35 additions & 0 deletions Core/GameEngine/Include/GameNetwork/NetworkSettings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#if defined(GENERALS_ONLINE)

#include <string>

// Per-match game networking policy, independent of online-service lifetime.
struct NetworkSettings
{
struct Send
{
int frames_per_packet = 2; // send interval in frames
bool flush_every_frame = true; // flush GNS after each frame
int flags = -1; // GNS send flags tried after a failed reliable send, -1 = none
} send;
struct InputDelay
{
int min_frames = 4;
int decision_interval_ms = 5000;
int fps_history_samples = 30; // per-second FPS samples averaged
int slack_percent = 30; // percent added to the measured round trip, also sets the start run ahead and the rating

struct Formula
{
int latency_history_samples = 200; // in-band ping samples averaged
} formula;
} input_delay;

static NetworkSettings LocalDefaults()
{
return NetworkSettings();
}
};

#endif
2 changes: 1 addition & 1 deletion Core/GameEngine/Source/GameNetwork/Connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ UnsignedInt Connection::doSend() {

if ((curtime - m_lastTimeSent) < m_frameGrouping) {
// DEBUG_LOG(("not sending packet, time = %d, m_lastFrameSent = %d, m_frameGrouping = %d", curtime, m_lastTimeSent, m_frameGrouping));
NetworkLog(ELogVerbosity::LOG_DEBUG, "not sending packet, time = %d, m_lastFrameSent = %d, m_frameGrouping = %d", curtime, m_lastTimeSent, m_frameGrouping);
NetworkLog(ELogVerbosity::LOG_DEBUG, "not sending packet, time = %I64d, m_lastFrameSent = %I64d, m_frameGrouping = %I64d", (Int64)curtime, (Int64)m_lastTimeSent, (Int64)m_frameGrouping);
return 0;
}

Expand Down
29 changes: 25 additions & 4 deletions Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
#include "../NetworkMesh.h"
#include "../ngmp_interfaces.h"

#if defined(GENERALS_ONLINE)
Int MIN_RUNAHEAD = 4;
#endif

static Bool hasValidTransferFileExtension(const AsciiString& filePath)
{
static const char* const validExtensions[] = {
Expand Down Expand Up @@ -272,6 +276,23 @@ ConnectionManager::ConnectionManager()
*/
void ConnectionManager::init()
{
#if defined(GENERALS_ONLINE)
m_networkSettings = NetworkSettings::LocalDefaults();
NGMP_OnlineServicesManager *services = NGMP_OnlineServicesManager::GetInstance();
if (TheLAN == nullptr && TheNGMPGame != nullptr && services != nullptr) {
const ServiceConfig &overrides = services->GetServiceConfig();
m_networkSettings.send = overrides.send;
m_networkSettings.input_delay = overrides.input_delay;
}
const NetworkSettings::InputDelay &runAhead = m_networkSettings.input_delay;
TheWritableGlobalData->m_networkFPSHistoryLength = (std::max)(1, runAhead.fps_history_samples);
TheWritableGlobalData->m_networkLatencyHistoryLength = (std::max)(1, runAhead.formula.latency_history_samples);
TheWritableGlobalData->m_networkRunAheadSlack = runAhead.slack_percent;
TheWritableGlobalData->m_networkRunAheadMetricsTime = runAhead.decision_interval_ms;
MIN_RUNAHEAD = runAhead.min_frames;
FRAME_GROUPING_CAP = (int)(m_networkSettings.send.frames_per_packet * (float)(1000.f / GENERALS_ONLINE_HIGH_FPS_LIMIT));
#endif

// if (m_transport == nullptr) {
// m_transport = new Transport;
// }
Expand Down Expand Up @@ -389,10 +410,10 @@ void ConnectionManager::reset()
#endif
m_packetRouterSlot = -1;

for (i = 0; i < TheGlobalData->m_networkFPSHistoryLength; ++i) {
for (i = 0; i < (UnsignedInt)MAX_SLOTS; ++i) {
m_fpsAverages[i] = -1;
}
for (i = 0; i < TheGlobalData->m_networkLatencyHistoryLength; ++i) {
for (i = 0; i < (UnsignedInt)MAX_SLOTS; ++i) {
m_latencyAverages[i] = 0.0;
}

Expand Down Expand Up @@ -1995,7 +2016,7 @@ void ConnectionManager::setFrameGrouping(time_t frameGrouping) {
// This is probably ok since the packet router should have the fastest connection of all
// the players in the game.

NetworkLog(ELogVerbosity::LOG_DEBUG, "ConnectionManager::setFrameGrouping Frame grouping is %d, is packet router %d", frameGrouping, m_localSlot == m_packetRouterSlot);
NetworkLog(ELogVerbosity::LOG_DEBUG, "ConnectionManager::setFrameGrouping Frame grouping is %I64d, is packet router %d", (Int64)frameGrouping, m_localSlot == m_packetRouterSlot);

if (m_localSlot == m_packetRouterSlot) {
frameGrouping = frameGrouping / 2;
Expand Down Expand Up @@ -2785,7 +2806,7 @@ void ConnectionManager::sendFrameDataToPlayer(UnsignedInt playerID, UnsignedInt
}

void ConnectionManager::sendSingleFrameToPlayer(UnsignedInt playerID, UnsignedInt frame) {
if ((TheGameLogic->getFrame() - FRAMES_TO_KEEP) > frame) {
if (frame + FRAMES_TO_KEEP < TheGameLogic->getFrame()) {
DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendSingleFrameToPlayer - player %d requested frame %d when we are on frame %d, this is too far in the past.", playerID, frame, TheGameLogic->getFrame()));
return;
}
Expand Down
2 changes: 1 addition & 1 deletion Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void DisconnectManager::updateDisconnectStatus(ConnectionManager *conMgr) {
m_haveNotifiedOtherPlayersOfCurrentFrame = TRUE;
}

DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - curTime = %d, m_timeOfDisconnectScreenOn = %d, curTime - m_timeOfDisconnectScreenOn = %d", curTime, m_timeOfDisconnectScreenOn, curTime - m_timeOfDisconnectScreenOn));
DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - curTime = %I64d, m_timeOfDisconnectScreenOn = %I64d, curTime - m_timeOfDisconnectScreenOn = %I64d", (Int64)curTime, (Int64)m_timeOfDisconnectScreenOn, (Int64)(curTime - m_timeOfDisconnectScreenOn)));

if (m_timeOfDisconnectScreenOn != 0) {
if ((curTime - m_timeOfDisconnectScreenOn) > TheGlobalData->m_networkDisconnectScreenNotifyTime) {
Expand Down
30 changes: 27 additions & 3 deletions Core/GameEngine/Source/GameNetwork/FrameMetrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ FrameMetrics::FrameMetrics()


m_fpsList = NEW Real[TheGlobalData->m_networkFPSHistoryLength];
#if defined(GENERALS_ONLINE)
m_fpsListLength = TheGlobalData->m_networkFPSHistoryLength;
#endif
}

FrameMetrics::~FrameMetrics() {
delete m_fpsList;
delete[] m_fpsList;
m_fpsList = NULL;

#if !defined(USE_NEW_FRAMEMETRIC_LOGIC)
delete m_latencyList;
delete[] m_latencyList;
m_latencyList = NULL;

delete[] m_pendingLatencies;
Expand Down Expand Up @@ -115,6 +118,15 @@ void FrameMetrics::init() {
#endif
m_minimumCushion = -1;

#if defined(GENERALS_ONLINE)
// the game network settings can change the history length after construction
if (m_fpsListLength != TheGlobalData->m_networkFPSHistoryLength) {
delete[] m_fpsList;
m_fpsList = NEW Real[TheGlobalData->m_networkFPSHistoryLength];
m_fpsListLength = TheGlobalData->m_networkFPSHistoryLength;
}
#endif

UnsignedInt i = 0;
for (; i < TheGlobalData->m_networkFPSHistoryLength; ++i) {
#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
Expand Down Expand Up @@ -228,8 +240,8 @@ void FrameMetrics::processLatencyResponse(UnsignedInt frame)
{
m_averageLatency += kvPaAir.second;
}
NetworkLog(ELogVerbosity::LOG_DEBUG, "Avg latency is: %f / %d = %f", m_averageLatency, m_mapLatenciesLookup.size(), m_averageLatency /= m_mapLatenciesLookup.size());
m_averageLatency /= m_mapLatenciesLookup.size();
NetworkLog(ELogVerbosity::LOG_DEBUG, "Avg latency is: %f over %d samples", m_averageLatency, (int)m_mapLatenciesLookup.size());


if (timeDiff > 1000)
Expand Down Expand Up @@ -280,4 +292,16 @@ void FrameMetrics::SeedLatencyData(int latency)
{
m_averageFps = GENERALS_ONLINE_HIGH_FPS_LIMIT;
m_averageLatency = latency / 1000.f;

#if defined(USE_NEW_FRAMEMETRIC_LOGIC)
// the next response recomputes the average from these maps, so they must carry the seed too
for (std::unordered_map<UnsignedInt, Real>::iterator it = m_mapLatenciesLookup.begin(); it != m_mapLatenciesLookup.end(); ++it)
{
it->second = m_averageLatency;
}
for (std::map<UnsignedInt, Real>::iterator it = m_mapLatenciesSorted.begin(); it != m_mapLatenciesSorted.end(); ++it)
{
it->second = m_averageLatency;
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class HTTPManager
// NOTE: set bDisableServiceAuth for endpoints that must be called with something other than the session token (e.g. the refresh endpoint, which needs the refresh token), otherwise the session token overwrites any Authorization header passed in inHeaders
void SendPOSTRequest(const char* szURI, EIPProtocolVersion protover, std::map<std::string, std::string>& inHeaders, const char* szPostData, std::function<void(bool bSuccess, int statusCode, std::string strBody, HTTPRequest* pReq)> completionCallback, std::function<void(size_t bytesReceived)> progressCallback = nullptr, int timeoutMS = -1, bool bDisableServiceAuth = false);
void SendPUTRequest(const char* szURI, EIPProtocolVersion protover, std::map<std::string, std::string>& inHeaders, const char* szData, std::function<void(bool bSuccess, int statusCode, std::string strBody, HTTPRequest* pReq)> completionCallback, std::function<void(size_t bytesReceived)> progressCallback = nullptr, int timeoutMS = -1);
void SendS3PUTRequest(const char* szURI, EIPProtocolVersion protover, std::map<std::string, std::string>& inHeaders, std::vector<uint8_t> vecBuffer, std::function<void(bool bSuccess, int statusCode, std::string strBody, HTTPRequest* pReq)> completionCallback, std::function<void(size_t bytesReceived)> progressCallback = nullptr, int timeoutMS = -1);
void SendS3PUTRequest(const char* szURI, EIPProtocolVersion protover, std::map<std::string, std::string>& inHeaders, std::vector<uint8_t> vecBuffer, std::function<void(bool bSuccess, int statusCode, std::string strBody, HTTPRequest* pReq)> completionCallback, std::function<void(size_t bytesReceived)> progressCallback = nullptr, int timeoutMS = -1, int maxSendBytesPerSec = 0);
void SendDELETERequest(const char* szURI, EIPProtocolVersion protover, std::map<std::string, std::string>& inHeaders, const char* szData, std::function<void(bool bSuccess, int statusCode, std::string strBody, HTTPRequest* pReq)> completionCallback, std::function<void(size_t bytesReceived)> progressCallback = nullptr, int timeoutMS = -1);

void Shutdown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class HTTPRequest
m_bAppendAuthIfPresent = false;
}

void SetMaxSendSpeed(int bytesPerSec)
{
m_maxSendBytesPerSec = bytesPerSec;
}

void OnResponsePartialWrite(std::uint8_t* pBuffer, size_t numBytes);

bool HasStarted() const { return m_bIsStarted; }
Expand Down Expand Up @@ -77,6 +82,8 @@ class HTTPRequest

bool m_bAppendAuthIfPresent = true;

int m_maxSendBytesPerSec = 0; // 0 = unlimited

EIPProtocolVersion m_protover;

int m_timeoutMS = 5000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,7 @@ void showNotificationBox(AsciiString nick, UnicodeString message, bool bPlaySoun
#define GENERALS_ONLINE_HIGH_FPS_RENDER 1 // This is optional on 30fps, but will boost/unlock the framerate, similar to gentool
#endif

#if defined(GENERALS_ONLINE_HIGH_FPS_SERVER)
static int FRAME_GROUPING_CAP = 32;
#else
static int FRAME_GROUPING_CAP = 64;
#endif
extern int FRAME_GROUPING_CAP;

//#define GENERALS_ONLINE_ENABLE_CONTROVERSIAL_NON_RETAIL_CHANGES 1

Expand Down
Loading
Loading