summaryrefslogtreecommitdiff
path: root/replay/sv_sessioninfopublisher.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/sv_sessioninfopublisher.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'replay/sv_sessioninfopublisher.cpp')
-rw-r--r--replay/sv_sessioninfopublisher.cpp182
1 files changed, 182 insertions, 0 deletions
diff --git a/replay/sv_sessioninfopublisher.cpp b/replay/sv_sessioninfopublisher.cpp
new file mode 100644
index 0000000..dda091c
--- /dev/null
+++ b/replay/sv_sessioninfopublisher.cpp
@@ -0,0 +1,182 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=======================================================================================//
+
+#include "sv_sessioninfopublisher.h"
+#include "sv_replaycontext.h"
+#include "sv_recordingsessionblock.h"
+#include "sv_recordingsession.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//----------------------------------------------------------------------------------------
+
+CSessionInfoPublisher::CSessionInfoPublisher( CServerRecordingSession *pSession )
+: m_pSession( pSession ),
+ m_flSessionInfoPublishTime( 0.0f ),
+ m_itLastCompletedBlockWrittenToBuffer( ~0 ),
+ m_pFilePublisher( NULL ),
+ m_bShouldPublish( false )
+{
+}
+
+CSessionInfoPublisher::~CSessionInfoPublisher()
+{
+}
+
+void CSessionInfoPublisher::Publish()
+{
+ m_bShouldPublish = true;
+}
+
+bool CSessionInfoPublisher::IsDone() const
+{
+ return !m_bShouldPublish && m_pFilePublisher == NULL;
+}
+
+void CSessionInfoPublisher::OnStopRecord( bool bAborting )
+{
+}
+
+void CSessionInfoPublisher::AbortPublish()
+{
+ m_bShouldPublish = false;
+
+ if ( m_pFilePublisher && !m_pFilePublisher->IsDone() )
+ {
+ m_pFilePublisher->AbortAndCleanup();
+ }
+}
+
+void CSessionInfoPublisher::RefreshSessionInfoBlockData( CUtlBuffer &buf )
+{
+ const CBaseRecordingSession::BlockContainer_t &vecBlocks = m_pSession->GetBlocks();
+
+ // Start from head if this is the first time we're writing, otherwise start
+ // from block after the last one written.
+ const int itStart = m_itLastCompletedBlockWrittenToBuffer == vecBlocks.InvalidIndex() ?
+ 0 : m_itLastCompletedBlockWrittenToBuffer + 1;
+
+ for( int i = itStart; i < vecBlocks.Count(); ++i )
+ {
+ const CServerRecordingSessionBlock *pBlock = SV_CastBlock( vecBlocks[ i ] );
+
+ // NOTE: This will SeekPut() on buf, based on the block's reconstruction index.
+ pBlock->WriteSessionInfoDataToBuffer( buf );
+
+ // Cache the last block written whose state isn't going to change
+ if ( pBlock->m_nRemoteStatus == CBaseRecordingSessionBlock::STATUS_READYFORDOWNLOAD &&
+ i > m_itLastCompletedBlockWrittenToBuffer )
+ {
+ m_itLastCompletedBlockWrittenToBuffer = i;
+ }
+
+ IF_REPLAY_DBG( Warning( "Writing block w/ recon index %i to session info buffer\n", pBlock->m_iReconstruction ) );
+ }
+}
+
+void CSessionInfoPublisher::Think()
+{
+ // Existing publisher?
+ if ( m_pFilePublisher )
+ {
+ // Finished?
+ if ( m_pFilePublisher->IsDone() )
+ {
+ // Free/clear
+ delete m_pFilePublisher;
+ m_pFilePublisher = NULL;
+ }
+ else
+ {
+ // Let the publisher think
+ m_pFilePublisher->Think();
+ }
+ }
+
+ // Publish needed?
+ if ( !m_bShouldPublish )
+ return;
+
+ // Already publishing?
+ if ( m_pFilePublisher )
+ return;
+
+ DBG( "Publishing session info...\n" );
+
+ // Write outstanding blocks to the buffer
+ RefreshSessionInfoBlockData( m_bufSessionInfo );
+
+ // We now know the uncompressed payload size
+ const int nPayloadSize = m_bufSessionInfo.TellPut();
+
+ // Create as much of the header as possible now - the rest will be written in AdjustHeader()
+ // once the publisher knows the md5 digest and the compression result.
+ Assert( m_pSession->m_strName.Length() < MAX_SESSIONNAME_LENGTH ); // The only way this name is going to get very long is if
+ V_strcpy_safe( m_SessionInfoHeader.m_szSessionName, m_pSession->m_strName.Get() );
+ m_SessionInfoHeader.m_nNumBlocks = m_pSession->GetNumBlocks();
+ m_SessionInfoHeader.m_bRecording = m_pSession->m_bRecording;
+ m_SessionInfoHeader.m_uPayloadSizeUC = nPayloadSize;
+
+ // Format a path & filename that points to the tmp dir, with <session name>.dmx on the end
+ CFmtStr fmtTmpSessionInfoFile( "%s%s.%s", SV_GetTmpDir(), m_pSession->m_strName.Get(), GENERIC_FILE_EXTENSION );
+
+ // Publish the file now (asynchronous)
+ PublishFileParams_t params;
+ params.m_pOutFilename = fmtTmpSessionInfoFile.Access(),
+ params.m_pSrcData = (uint8 *)m_bufSessionInfo.Base();
+ params.m_nSrcSize = nPayloadSize;
+ params.m_pCallbackHandler = this;
+ params.m_nCompressorType = COMPRESSORTYPE_LZSS;
+ params.m_bHash = true;
+ params.m_bFreeSrcData = false;
+ params.m_bDeleteFile = false;
+ params.m_pHeaderData = &m_SessionInfoHeader;
+ params.m_nHeaderSize = sizeof( SessionInfoHeader_t );
+ params.m_pUserData = NULL;
+ m_pFilePublisher = SV_PublishFile( params );
+
+ // Reset flag
+ m_bShouldPublish = false;
+}
+
+void CSessionInfoPublisher::OnPublishComplete( const IFilePublisher *pPublisher, void *pUserData )
+{
+ Assert( !pUserData );
+
+ // Handle publish failure
+ if ( pPublisher->GetStatus() != IFilePublisher::PUBLISHSTATUS_OK )
+ {
+ g_pServerReplayContext->OnPublishFailed();
+ }
+}
+
+void CSessionInfoPublisher::OnPublishAborted( const IFilePublisher *pPublisher )
+{
+ Assert( pPublisher == m_pFilePublisher );
+
+ g_pServerReplayContext->OnPublishFailed();
+}
+
+void CSessionInfoPublisher::AdjustHeader( const IFilePublisher *pPublisher, void *pHeaderData )
+{
+ SessionInfoHeader_t *pHeader = static_cast< SessionInfoHeader_t * >( pHeaderData );
+
+ // Set compressor type - will return COMPRESSORTYPE_INVALID if compression failed.
+ pHeader->m_nCompressorType = pPublisher->GetCompressorType();
+ pHeader->m_uPayloadSize = pPublisher->GetCompressedSize();
+
+ // Get MD5 digest
+ pPublisher->GetHash( pHeader->m_aHash );
+}
+
+void CSessionInfoPublisher::PublishAllSynchronous()
+{
+ while ( !IsDone() )
+ {
+ Think();
+ }
+}
+
+//----------------------------------------------------------------------------------------