mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-14 12:46:58 +00:00
1
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user