From 459a49cb24277b50989d1b20b6ba6fa8d510c964 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 20 Aug 2019 20:47:17 +0100 Subject: [PATCH] Add flags for mismatch type to client desync log --- src/crashlog.cpp | 16 +++++++++++++--- src/crashlog.h | 20 +++++++++++++++++--- src/network/network_client.cpp | 10 +++++++++- src/network/network_server.cpp | 2 +- src/os/macosx/crashlog_osx.cpp | 4 ++-- src/os/unix/crashlog_unix.cpp | 4 ++-- src/os/windows/crashlog_win.cpp | 4 ++-- 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 1ade5a5d42..fc692a7a37 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -449,12 +449,22 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last) const * @param last The last position in the buffer to write to. * @return the position of the \c '\0' character after the buffer. */ -char *CrashLog::FillDesyncCrashLog(char *buffer, const char *last) const +char *CrashLog::FillDesyncCrashLog(char *buffer, const char *last, const DesyncExtraInfo &info) const { time_t cur_time = time(nullptr); buffer += seprintf(buffer, last, "*** OpenTTD Multiplayer %s Desync Report ***\n\n", _network_server ? "Server" : "Client"); buffer += seprintf(buffer, last, "Desync at: %s", asctime(gmtime(&cur_time))); + if (!_network_server && info.flags) { + auto flag_check = [&](DesyncExtraInfo::Flags flag, const char *str) { + return info.flags & flag ? str : ""; + }; + buffer += seprintf(buffer, last, "Flags: %s%s%s%s\n", + flag_check(DesyncExtraInfo::DEIF_RAND1, "R"), + flag_check(DesyncExtraInfo::DEIF_RAND2, "Z"), + flag_check(DesyncExtraInfo::DEIF_STATE, "S"), + flag_check(DesyncExtraInfo::DEIF_DBL_RAND, "D")); + } YearMonthDay ymd; ConvertDateToYMD(_date, &ymd); @@ -627,7 +637,7 @@ bool CrashLog::MakeCrashLog() const * information like paths to the console. * @return true when everything is made successfully. */ -bool CrashLog::MakeDesyncCrashLog(const std::string *log_in, std::string *log_out) const +bool CrashLog::MakeDesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info) const { char filename[MAX_PATH]; char buffer[65536 * 2]; @@ -641,7 +651,7 @@ bool CrashLog::MakeDesyncCrashLog(const std::string *log_in, std::string *log_ou strftime(name_buffer_date, lastof(name_buffer) - name_buffer_date, "%Y%m%dT%H%M%SZ", gmtime(&cur_time)); printf("Desync encountered (%s), generating desync log...\n", mode); - char *b = this->FillDesyncCrashLog(buffer, lastof(buffer)); + char *b = this->FillDesyncCrashLog(buffer, lastof(buffer), info); if (log_in && !log_in->empty()) { b = strecpy(b, "\n", lastof(buffer), true); diff --git a/src/crashlog.h b/src/crashlog.h index f44000baee..eb25607fad 100644 --- a/src/crashlog.h +++ b/src/crashlog.h @@ -12,8 +12,22 @@ #ifndef CRASHLOG_H #define CRASHLOG_H +#include "core/enum_type.hpp" #include +struct DesyncExtraInfo { + enum Flags { + DEIF_NONE = 0, ///< no flags + DEIF_RAND1 = 1 << 0, ///< random 1 mismatch + DEIF_RAND2 = 1 << 1, ///< random 2 mismatch + DEIF_STATE = 1 << 2, ///< state mismatch + DEIF_DBL_RAND = 1 << 3, ///< double-seed sent + }; + + Flags flags = DEIF_NONE; +}; +DECLARE_ENUM_AS_BIT_SET(DesyncExtraInfo::Flags) + /** * Helper class for creating crash logs. */ @@ -113,7 +127,7 @@ public: virtual ~CrashLog() {} char *FillCrashLog(char *buffer, const char *last) const; - char *FillDesyncCrashLog(char *buffer, const char *last) const; + char *FillDesyncCrashLog(char *buffer, const char *last, const DesyncExtraInfo &info) const; bool WriteCrashLog(const char *buffer, char *filename, const char *filename_last, const char *name = "crash") const; /** @@ -130,7 +144,7 @@ public: bool WriteScreenshot(char *filename, const char *filename_last, const char *name = "crash") const; bool MakeCrashLog() const; - bool MakeDesyncCrashLog(const std::string *log_in, std::string *log_out) const; + bool MakeDesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info) const; bool MakeCrashSavegameAndScreenshot() const; /** @@ -140,7 +154,7 @@ public: */ static void InitialiseCrashLog(); - static void DesyncCrashLog(const std::string *log_in, std::string *log_out); + static void DesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info); static void SetErrorMessage(const char *message); static void AfterCrashLogCleanup(); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index a031fb2f37..e9f2b71617 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -288,13 +288,21 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) #else if (_sync_seed_1 != _random.state[0] || _sync_state_checksum != _state_checksum.state) { #endif + DesyncExtraInfo info; + if (_sync_seed_1 != _random.state[0]) info.flags |= DesyncExtraInfo::DEIF_RAND1; +#ifdef NETWORK_SEND_DOUBLE_SEED + if (_sync_seed_2 != _random.state[1]) info.flags |= DesyncExtraInfo::DEIF_RAND2; + info.flags |= DesyncExtraInfo::DEIF_DBL_RAND; +#endif + if (_sync_state_checksum != _state_checksum.state) info.flags |= DesyncExtraInfo::DEIF_STATE; + NetworkError(STR_NETWORK_ERROR_DESYNC); DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x} {%x, " OTTD_PRINTFHEX64 "} != {%x, " OTTD_PRINTFHEX64 "}" , _date, _date_fract, _tick_skip_counter, _sync_seed_1, _sync_state_checksum, _random.state[0], _state_checksum.state); DEBUG(net, 0, "Sync error detected!"); std::string desync_log; - CrashLog::DesyncCrashLog(nullptr, &desync_log); + CrashLog::DesyncCrashLog(nullptr, &desync_log, info); my_client->SendDesyncLog(desync_log); my_client->ClientError(NETWORK_RECV_STATUS_DESYNC); return false; diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index e1e8cd750a..0a796ba33d 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1214,7 +1214,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p NetworkAdminClientError(this->client_id, errorno); if (errorno == NETWORK_ERROR_DESYNC) { - CrashLog::DesyncCrashLog(&(this->desync_log), nullptr); + CrashLog::DesyncCrashLog(&(this->desync_log), nullptr, DesyncExtraInfo{}); // decrease the sync frequency for this point onwards _settings_client.network.sync_freq = min(_settings_client.network.sync_freq, 16); diff --git a/src/os/macosx/crashlog_osx.cpp b/src/os/macosx/crashlog_osx.cpp index 329f7c50a1..9a420ad16e 100644 --- a/src/os/macosx/crashlog_osx.cpp +++ b/src/os/macosx/crashlog_osx.cpp @@ -516,8 +516,8 @@ void CDECL HandleCrash(int signum, siginfo_t *si, void *context) } } -/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out) +/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info) { CrashLogOSX log(CrashLogOSX::DesyncTag{}); - log.MakeDesyncCrashLog(log_in, log_out); + log.MakeDesyncCrashLog(log_in, log_out, info); } diff --git a/src/os/unix/crashlog_unix.cpp b/src/os/unix/crashlog_unix.cpp index 7883f74b29..ca1e5de7d0 100644 --- a/src/os/unix/crashlog_unix.cpp +++ b/src/os/unix/crashlog_unix.cpp @@ -620,8 +620,8 @@ static void CDECL HandleCrash(int signum) } } -/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out) +/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info) { CrashLogUnix log(CrashLogUnix::DesyncTag{}); - log.MakeDesyncCrashLog(log_in, log_out); + log.MakeDesyncCrashLog(log_in, log_out, info); } diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 8f82cb46d0..fcd31e7094 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -612,10 +612,10 @@ static void CDECL CustomAbort(int signal) SetUnhandledExceptionFilter(ExceptionHandler); } -/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out) +/* static */ void CrashLog::DesyncCrashLog(const std::string *log_in, std::string *log_out, const DesyncExtraInfo &info) { CrashLogWindows log(nullptr); - log.MakeDesyncCrashLog(log_in, log_out); + log.MakeDesyncCrashLog(log_in, log_out, info); } /* The crash log GUI */