232 lines
6.3 KiB
C
232 lines
6.3 KiB
C
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// $NoKeywords: $
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
#ifndef PURE_SERVER_H
|
|||
|
#define PURE_SERVER_H
|
|||
|
#ifdef _WIN32
|
|||
|
#pragma once
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
#include "ifilelist.h"
|
|||
|
#include "tier1/utldict.h"
|
|||
|
#include "tier1/utlbuffer.h"
|
|||
|
#include "filesystem.h"
|
|||
|
|
|||
|
|
|||
|
class KeyValues;
|
|||
|
|
|||
|
|
|||
|
class CPureServerWhitelist
|
|||
|
{
|
|||
|
public:
|
|||
|
friend class CAllowFromDiskList;
|
|||
|
friend class CForceMatchList;
|
|||
|
friend class CPureFileTracker;
|
|||
|
|
|||
|
// Call this to free it.
|
|||
|
static CPureServerWhitelist* Create( IFileSystem *pFileSystem );
|
|||
|
void Release();
|
|||
|
|
|||
|
// Get the file lists.
|
|||
|
IFileList* GetAllowFromDiskList(); // This is the list of files that can be loaded off disk. Make sure to Release() it when finished!
|
|||
|
IFileList* GetForceMatchList(); // This is the list of files that must match CRCs. Make sure to Release() it when finished!
|
|||
|
|
|||
|
// Load up any entries in the KV file.
|
|||
|
bool LoadFromKeyValues( KeyValues *kv );
|
|||
|
|
|||
|
// Encode for networking.
|
|||
|
void Encode( CUtlBuffer &buf );
|
|||
|
void Decode( CUtlBuffer &buf );
|
|||
|
|
|||
|
// Calls IFileSystem::CacheFileCRCs for all files and directories marked check_crc.
|
|||
|
void CacheFileCRCs();
|
|||
|
|
|||
|
// Instead of loading keyvalues, you can call this to make it force all files to come from Steam.
|
|||
|
// This is used with sv_pure 2.
|
|||
|
void EnableFullyPureMode();
|
|||
|
bool IsInFullyPureMode() const;
|
|||
|
|
|||
|
// Used by sv_pure command when you're connected to a server.
|
|||
|
void PrintWhitelistContents();
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
CPureServerWhitelist();
|
|||
|
~CPureServerWhitelist();
|
|||
|
|
|||
|
void Init( IFileSystem *pFileSystem );
|
|||
|
void Term();
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
class CAllowFromDiskList : public IFileList
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual bool IsFileInList( const char *pFilename );
|
|||
|
virtual void Release();
|
|||
|
|
|||
|
CPureServerWhitelist *m_pWhitelist;
|
|||
|
};
|
|||
|
class CForceMatchList : public IFileList
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual bool IsFileInList( const char *pFilename );
|
|||
|
virtual void Release();
|
|||
|
|
|||
|
CPureServerWhitelist *m_pWhitelist;
|
|||
|
};
|
|||
|
|
|||
|
class CCommand
|
|||
|
{
|
|||
|
public:
|
|||
|
CCommand();
|
|||
|
~CCommand();
|
|||
|
|
|||
|
public:
|
|||
|
bool m_bAllowFromDisk;
|
|||
|
bool m_bCheckCRC;
|
|||
|
unsigned short m_LoadOrder; // What order this thing was specified in the whitelist file.
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
void UpdateCommandStats( CUtlDict<CPureServerWhitelist::CCommand*,int> &commands, int *pHighest, int *pLongestPathName );
|
|||
|
void PrintCommand( const char *pFileSpec, const char *pExt, int maxPathnameLen, CPureServerWhitelist::CCommand *pCommand );
|
|||
|
int FindCommandByLoadOrder( CUtlDict<CPureServerWhitelist::CCommand*,int> &commands, int iLoadOrder );
|
|||
|
|
|||
|
void InternalCacheFileCRCs( CUtlDict<CCommand*,int> &theList, ECacheCRCType eType );
|
|||
|
|
|||
|
CCommand* GetBestEntry( const char *pFilename );
|
|||
|
|
|||
|
void EncodeCommandList( CUtlDict<CPureServerWhitelist::CCommand*,int> &theList, CUtlBuffer &buf );
|
|||
|
void DecodeCommandList( CUtlDict<CPureServerWhitelist::CCommand*,int> &theList, CUtlBuffer &buf );
|
|||
|
|
|||
|
CPureServerWhitelist::CCommand* CheckEntry(
|
|||
|
CUtlDict<CPureServerWhitelist::CCommand*,int> &dict,
|
|||
|
const char *pEntryName,
|
|||
|
CPureServerWhitelist::CCommand *pBestEntry );
|
|||
|
|
|||
|
private:
|
|||
|
unsigned short m_LoadCounter; // Incremented as we load things so their m_LoadOrder increases.
|
|||
|
int m_RefCount;
|
|||
|
|
|||
|
// Commands are applied to files in order.
|
|||
|
CUtlDict<CCommand*,int> m_FileCommands; // file commands
|
|||
|
CUtlDict<CCommand*,int> m_RecursiveDirCommands; // ... commands
|
|||
|
CUtlDict<CCommand*,int> m_NonRecursiveDirCommands; // *.* commands
|
|||
|
IFileSystem *m_pFileSystem;
|
|||
|
|
|||
|
CAllowFromDiskList m_AllowFromDiskList;
|
|||
|
CForceMatchList m_ForceMatchList;
|
|||
|
|
|||
|
// In this mode, all files must come from Steam.
|
|||
|
bool m_bFullyPureMode;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
CPureServerWhitelist* CreatePureServerWhitelist( IFileSystem *pFileSystem );
|
|||
|
|
|||
|
struct UserReportedFileHash_t
|
|||
|
{
|
|||
|
int m_idxFile;
|
|||
|
USERID_t m_userID;
|
|||
|
FileHash_t m_FileHash;
|
|||
|
|
|||
|
static bool Less( const UserReportedFileHash_t& lhs, const UserReportedFileHash_t& rhs )
|
|||
|
{
|
|||
|
if ( lhs.m_idxFile < rhs.m_idxFile )
|
|||
|
return true;
|
|||
|
if ( lhs.m_idxFile > rhs.m_idxFile )
|
|||
|
return false;
|
|||
|
if ( lhs.m_userID.uid.steamid.m_SteamLocalUserID.As64bits < rhs.m_userID.uid.steamid.m_SteamLocalUserID.As64bits )
|
|||
|
return true;
|
|||
|
return false;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
struct UserReportedFile_t
|
|||
|
{
|
|||
|
CRC32_t m_crcIdentifier;
|
|||
|
CUtlString m_filename;
|
|||
|
CUtlString m_path;
|
|||
|
int m_nFileFraction;
|
|||
|
|
|||
|
static bool Less( const UserReportedFile_t& lhs, const UserReportedFile_t& rhs )
|
|||
|
{
|
|||
|
if ( lhs.m_crcIdentifier < rhs.m_crcIdentifier )
|
|||
|
return true;
|
|||
|
if ( lhs.m_crcIdentifier > rhs.m_crcIdentifier )
|
|||
|
return false;
|
|||
|
if ( lhs.m_nFileFraction < rhs.m_nFileFraction )
|
|||
|
return true;
|
|||
|
if ( lhs.m_nFileFraction > rhs.m_nFileFraction )
|
|||
|
return false;
|
|||
|
int nCmp = Q_strcmp( lhs.m_filename.String(), rhs.m_filename.String() );
|
|||
|
if ( nCmp < 0 )
|
|||
|
return true;
|
|||
|
if ( nCmp > 0 )
|
|||
|
return false;
|
|||
|
nCmp = Q_strcmp( lhs.m_path.String(), rhs.m_path.String() );
|
|||
|
if ( nCmp < 0 )
|
|||
|
return true;
|
|||
|
return false;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
struct MasterFileHash_t
|
|||
|
{
|
|||
|
int m_idxFile;
|
|||
|
int m_cMatches;
|
|||
|
FileHash_t m_FileHash;
|
|||
|
|
|||
|
static bool Less( const MasterFileHash_t& lhs, const MasterFileHash_t& rhs )
|
|||
|
{
|
|||
|
return lhs.m_idxFile < rhs.m_idxFile;
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
class CPureFileTracker
|
|||
|
{
|
|||
|
public:
|
|||
|
CPureFileTracker():
|
|||
|
m_treeAllReportedFiles( UserReportedFile_t::Less ),
|
|||
|
m_treeMasterFileHashes( MasterFileHash_t::Less ),
|
|||
|
m_treeUserReportedFileHash( UserReportedFileHash_t::Less )
|
|||
|
{
|
|||
|
m_flLastFileReceivedTime = 0.f;
|
|||
|
m_cMatchedFile = 0;
|
|||
|
m_cMatchedMasterFile = 0;
|
|||
|
m_cMatchedMasterFileHash = 0;
|
|||
|
m_cMatchedFileFullHash = 0;
|
|||
|
}
|
|||
|
|
|||
|
void AddUserReportedFileHash( int idxFile, FileHash_t *pFileHash, USERID_t userID, bool bAddMasterRecord );
|
|||
|
bool DoesFileMatch( const char *pPathID, const char *pRelativeFilename, int nFileFraction, FileHash_t *pFileHash, USERID_t userID );
|
|||
|
int ListUserFiles( bool bListAll, const char *pchFilenameFind );
|
|||
|
int ListAllTrackedFiles( bool bListAll, const char *pchFilenameFind, int nFileFractionMin, int nFileFractionMax );
|
|||
|
|
|||
|
CUtlRBTree< UserReportedFile_t, int > m_treeAllReportedFiles;
|
|||
|
CUtlRBTree< MasterFileHash_t, int > m_treeMasterFileHashes;
|
|||
|
CUtlRBTree< UserReportedFileHash_t, int > m_treeUserReportedFileHash;
|
|||
|
|
|||
|
float m_flLastFileReceivedTime;
|
|||
|
int m_cMatchedFile;
|
|||
|
int m_cMatchedMasterFile;
|
|||
|
int m_cMatchedMasterFileHash;
|
|||
|
int m_cMatchedFileFullHash;
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
extern CPureFileTracker g_PureFileTracker;
|
|||
|
|
|||
|
|
|||
|
#endif // PURE_SERVER_H
|
|||
|
|