summaryrefslogtreecommitdiff
path: root/replay/errorsystem.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /replay/errorsystem.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'replay/errorsystem.cpp')
-rw-r--r--replay/errorsystem.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/replay/errorsystem.cpp b/replay/errorsystem.cpp
new file mode 100644
index 0000000..5f0ab96
--- /dev/null
+++ b/replay/errorsystem.cpp
@@ -0,0 +1,230 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=======================================================================================//
+
+#include "errorsystem.h"
+#include "replay/ienginereplay.h"
+#include "vgui/ILocalize.h"
+#include "shared_replaycontext.h"
+
+#if !defined( DEDICATED )
+
+#include "cl_downloader.h"
+#include "cl_sessionblockdownloader.h"
+#include "cl_recordingsessionblock.h"
+#include "replay/iclientreplay.h"
+
+extern IClientReplay *g_pClient;
+
+#endif // !defined( DEDICATED )
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//----------------------------------------------------------------------------------------
+
+extern IEngineReplay *g_pEngine;
+extern vgui::ILocalize *g_pVGuiLocalize;
+
+//----------------------------------------------------------------------------------------
+
+CErrorSystem::CErrorSystem( IErrorReporter *pErrorReporter )
+: m_pErrorReporter( pErrorReporter )
+{
+}
+
+CErrorSystem::~CErrorSystem()
+{
+ Clear();
+}
+
+void CErrorSystem::Clear()
+{
+ FOR_EACH_LL( m_lstErrors, i )
+ {
+ wchar_t *pText = m_lstErrors[ i ];
+ delete [] pText;
+ }
+
+ m_lstErrors.RemoveAll();
+}
+
+void CErrorSystem::AddError( const wchar_t *pError )
+{
+ if ( !pError || !pError[0] )
+ return;
+
+ // Cache a copied version of the string
+ const int nLen = wcslen( pError ) + 1;
+ wchar_t *pNewError = new wchar_t[ nLen ];
+ const int nSize = nLen * sizeof( wchar_t );
+ V_wcsncpy( pNewError, pError, nSize );
+
+ m_lstErrors.AddToTail( pNewError );
+}
+
+void CErrorSystem::AddError( const char *pError )
+{
+ if ( !pError || !pError[0] )
+ return;
+
+ wchar_t wszError[1024];
+ V_UTF8ToUnicode( pError, wszError, sizeof( wszError ) );
+
+ AddError( wszError );
+}
+
+void CErrorSystem::AddErrorFromTokenName( const char *pToken )
+{
+ if ( g_pVGuiLocalize )
+ {
+ AddError( g_pVGuiLocalize->Find( pToken ) );
+ }
+ else
+ {
+ AddError( pToken );
+ }
+}
+
+void CErrorSystem::AddFormattedErrorFromTokenName( const char *pFormatToken/*=NULL*/, KeyValues *pFormatArgs/*=NULL*/ )
+{
+ if ( !pFormatToken )
+ {
+ AssertMsg( 0, "Error token should always be valid." );
+ return;
+ }
+
+ wchar_t wszErrorStr[1024];
+ if ( g_pVGuiLocalize )
+ {
+ g_pVGuiLocalize->ConstructString( wszErrorStr, sizeof( wszErrorStr ), pFormatToken, pFormatArgs );
+ }
+ else
+ {
+ V_UTF8ToUnicode( pFormatToken, wszErrorStr, sizeof( wszErrorStr ) );
+ }
+
+
+ // Add the error
+ AddError( wszErrorStr );
+
+ // Delete args
+ pFormatArgs->deleteThis();
+}
+
+#if !defined( DEDICATED )
+
+int g_nGenericErrorCounter = 0;
+
+void CErrorSystem::OGS_ReportSessionBlockDownloadError( const CHttpDownloader *pDownloader, const CClientRecordingSessionBlock *pBlock,
+ int nLocalFileSize, int nMaxBlock, const bool *pSizesDiffer,
+ const bool *pHashFail, uint8 *pLocalHash )
+
+{
+ // Create a download error and queue for upload
+ KeyValues *pDownloadError = pDownloader->GetOgsRow( g_nGenericErrorCounter );
+ g_pClient->UploadOgsData( pDownloadError, false );
+
+ // Create block download error
+ KeyValues *pBlockDownloadError = new KeyValues( "TF2ReplayBlockDownloadErrors" );
+ pBlockDownloadError->SetInt( "ErrorCounter", g_nGenericErrorCounter );
+ pBlockDownloadError->SetInt( "NumCurrentDownloads", CSessionBlockDownloader::sm_nNumCurrentDownloads );
+ pBlockDownloadError->SetInt( "MaxBlock", nMaxBlock );
+ pBlockDownloadError->SetInt( "RemoteStatus", (int)pBlock->m_nRemoteStatus );
+ pBlockDownloadError->SetInt( "ReconstructionIndex", pBlock->m_iReconstruction );
+ pBlockDownloadError->SetInt( "RemoteFileSize", (int)pBlock->m_uFileSize );
+ pBlockDownloadError->SetInt( "LocalFileSize", nLocalFileSize );
+ pBlockDownloadError->SetInt( "NumDownloadAttempts", pBlock->GetNumDownloadAttempts() );
+
+ // Only include these if appropriate - otherwise, let them be NULL for the given row
+ if ( pSizesDiffer )
+ {
+ pBlockDownloadError->SetInt( "SizesDiffer", (int)*pSizesDiffer );
+ }
+
+ if ( pHashFail )
+ {
+ pBlockDownloadError->SetInt( "HashFail", (int)*pHashFail );
+
+ // Include hashes
+ char szRemoteHash[64], szLocalHash[64];
+ V_binarytohex( pBlock->m_aHash, sizeof( pBlock->m_aHash ), szRemoteHash, sizeof( szRemoteHash ) );
+ V_binarytohex( pLocalHash, sizeof( pBlock->m_aHash ), szLocalHash, sizeof( szLocalHash ) );
+ pBlockDownloadError->SetString( "RemoteHash", szRemoteHash );
+ pBlockDownloadError->SetString( "LocalHash", szLocalHash );
+ }
+
+ // Upload block download error
+ g_pClient->UploadOgsData( pBlockDownloadError, false );
+
+ // Upload generic error and link to this specific block error.
+ OGS_ReportGenericError( "Block download failed" );
+}
+
+void CErrorSystem::OGS_ReportSessioInfoDownloadError( const CHttpDownloader *pDownloader, const char *pErrorToken )
+{
+ // Create a download error and queue for upload
+ KeyValues *pDownloadError = pDownloader->GetOgsRow( g_nGenericErrorCounter );
+ g_pClient->UploadOgsData( pDownloadError, false );
+
+ // Create session info download error
+ KeyValues *pSessionInfoDownloadError = new KeyValues( "TF2ReplaySessionInfoDownloadErrors" );
+ pSessionInfoDownloadError->SetInt( "ErrorCounter", g_nGenericErrorCounter++ );
+ pSessionInfoDownloadError->SetString( "SessionInfoDownloadErrorID", pErrorToken );
+ g_pClient->UploadOgsData( pSessionInfoDownloadError, false );
+
+ // Upload generic error and link to this specific block error.
+ OGS_ReportGenericError( "Session info download failed" );
+}
+
+// Note: we use the ErrorCounter as part of the key and so it must be unique. This means that all
+// special error tables (ie., session info download errors) must call back into this base function
+// to write out the base error and increment the counter.
+void CErrorSystem::OGS_ReportGenericError( const char *pGenericErrorToken )
+{
+ KeyValues *pGenericError = new KeyValues( "TF2ReplayErrors" );
+ pGenericError->SetInt( "ErrorCounter", g_nGenericErrorCounter++ );
+ pGenericError->SetString( "ReplayErrorID", pGenericErrorToken );
+
+ // Upload the generic error row now
+ g_pClient->UploadOgsData( pGenericError, true );
+
+ // Next error!
+ ++g_nGenericErrorCounter;
+}
+
+#endif // !defined( DEDICATED )
+
+float CErrorSystem::GetNextThinkTime() const
+{
+ return g_pEngine->GetHostTime() + 5.0f;
+}
+
+void CErrorSystem::Think()
+{
+ CBaseThinker::Think();
+
+ if ( m_lstErrors.Count() == 0 )
+ return;
+
+ const int nMaxLen = 4096;
+ wchar_t wszErrorText[ nMaxLen ] = L"";
+ FOR_EACH_LL( m_lstErrors, i )
+ {
+ const wchar_t *pError = m_lstErrors[ i ];
+ if ( wcslen( wszErrorText ) + wcslen( pError ) + 1 >= nMaxLen )
+ break;
+
+ wcscat( wszErrorText, pError );
+ wcscat( wszErrorText, L"\n" );
+ }
+
+ // Report now
+ m_pErrorReporter->ReportErrorsToUser( wszErrorText );
+
+ // Clear
+ Clear();
+}
+
+//----------------------------------------------------------------------------------------
+