Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
7.1 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "datacache/iresourceaccesscontrol.h"
  7. #include "tier1/utlvector.h"
  8. #include "tier1/utlstring.h"
  9. #include "tier2/tier2.h"
  10. #include "tier1/convar.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. //-----------------------------------------------------------------------------
  14. // NOTE: Necessary until we have all our resources wrangled.
  15. //-----------------------------------------------------------------------------
  16. static ConVar res_restrict_access( "res_restrict_access", "0" );
  17. //-----------------------------------------------------------------------------
  18. // Implementation class
  19. //-----------------------------------------------------------------------------
  20. class CResourceAccessControl : public CTier1AppSystem< IResourceAccessControl >
  21. {
  22. typedef CTier1AppSystem< IResourceAccessControl > BaseClass;
  23. // Inherited from IAppSystem
  24. public:
  25. virtual void Shutdown();
  26. // Inherited from IResourceAccessControl
  27. public:
  28. virtual ResourceList_t CreateResourceList( const char *pDebugName );
  29. virtual void DestroyAllResourceLists( );
  30. virtual void AddResource( ResourceList_t hResourceList, ResourceTypeOld_t nType, const char *pResourceName );
  31. virtual void LimitAccess( ResourceList_t hResourceList );
  32. virtual bool IsAccessAllowed( ResourceTypeOld_t nType, const char *pResource );
  33. // Other public methods
  34. public:
  35. CResourceAccessControl();
  36. private:
  37. enum
  38. {
  39. MAX_THREADS = 16
  40. };
  41. struct ResourceInfo_t
  42. {
  43. CUtlString m_DebugName;
  44. CUtlVector< CUtlString > m_Resources[RESOURCE_TYPE_OLD_COUNT];
  45. };
  46. bool ContainsResource( ResourceList_t hResourceList, ResourceTypeOld_t nType, const char *pResourceName );
  47. int FindOrAddCurrentThreadID();
  48. void FixupResourceName( const char *pResourceName, char *pBuf, int nBufLen );
  49. CUtlVector< ResourceInfo_t > m_ResourceLists;
  50. int m_pLimitAccess[MAX_THREADS];
  51. unsigned long m_pThread[MAX_THREADS];
  52. int m_nThreadCount;
  53. CThreadMutex m_Mutex;
  54. };
  55. //-----------------------------------------------------------------------------
  56. // Singleton
  57. //-----------------------------------------------------------------------------
  58. CResourceAccessControl g_ResourceAccessControl;
  59. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CResourceAccessControl, IResourceAccessControl,
  60. RESOURCE_ACCESS_CONTROL_INTERFACE_VERSION, g_ResourceAccessControl );
  61. //-----------------------------------------------------------------------------
  62. // Resource type names
  63. //-----------------------------------------------------------------------------
  64. static const char *s_pResourceTypeName[] =
  65. {
  66. "vgui panel", // .res file
  67. "material", // .vmt file
  68. "model", // .mdl file
  69. "particle system", // particle system
  70. "game sound", // game sound
  71. };
  72. //-----------------------------------------------------------------------------
  73. // Constructor, destructor
  74. //-----------------------------------------------------------------------------
  75. CResourceAccessControl::CResourceAccessControl()
  76. {
  77. m_nThreadCount = 0;
  78. memset( m_pLimitAccess, 0xFF, sizeof(m_pLimitAccess) );
  79. memset( m_pThread, 0, sizeof(m_pThread) );
  80. }
  81. //-----------------------------------------------------------------------------
  82. // Shutdown
  83. //-----------------------------------------------------------------------------
  84. void CResourceAccessControl::Shutdown()
  85. {
  86. DestroyAllResourceLists();
  87. memset( m_pLimitAccess, 0xFF, sizeof(m_pLimitAccess) );
  88. BaseClass::Shutdown();
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Creates a resource list
  92. //-----------------------------------------------------------------------------
  93. int CResourceAccessControl::FindOrAddCurrentThreadID()
  94. {
  95. unsigned long nThreadId = ThreadGetCurrentId();
  96. for ( int i = 0; i < m_nThreadCount; ++i )
  97. {
  98. if ( m_pThread[i] == nThreadId )
  99. return i;
  100. }
  101. if ( m_nThreadCount >= MAX_THREADS )
  102. {
  103. Error( "Exceeded maximum number of unique threads (%d) attempting to access datacache.\n", MAX_THREADS );
  104. return -1;
  105. }
  106. m_Mutex.Lock();
  107. int nIndex = m_nThreadCount;
  108. m_pThread[m_nThreadCount++] = nThreadId;
  109. m_Mutex.Unlock();
  110. return nIndex;
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Fixes up the asset name
  114. //-----------------------------------------------------------------------------
  115. void CResourceAccessControl::FixupResourceName( const char *pResourceName, char *pBuf, int nBufLen )
  116. {
  117. Q_StripExtension( pResourceName, pBuf, nBufLen );
  118. Q_FixSlashes( pBuf, '/' );
  119. V_RemoveDotSlashes( pBuf, '/' );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Creates a resource list
  123. //-----------------------------------------------------------------------------
  124. ResourceList_t CResourceAccessControl::CreateResourceList( const char *pDebugName )
  125. {
  126. int nIndex = m_ResourceLists.AddToTail();
  127. m_ResourceLists[nIndex].m_DebugName.Set( pDebugName );
  128. return (ResourceList_t)(intp)nIndex;
  129. }
  130. void CResourceAccessControl::DestroyAllResourceLists( )
  131. {
  132. m_ResourceLists.Purge();
  133. memset( m_pLimitAccess, 0xFF, sizeof(m_pLimitAccess) );
  134. }
  135. bool CResourceAccessControl::ContainsResource( ResourceList_t hResourceList, ResourceTypeOld_t nType, const char *pResourceName )
  136. {
  137. char pBuf[MAX_PATH];
  138. FixupResourceName( pResourceName, pBuf, sizeof(pBuf) );
  139. int nIndex = size_cast< int >( (intp)hResourceList );
  140. CUtlVector< CUtlString > &list = m_ResourceLists[nIndex].m_Resources[nType];
  141. int nCount = list.Count();
  142. for ( int i = 0; i < nCount; ++i )
  143. {
  144. if ( !Q_stricmp( pBuf, list[i].Get() ) )
  145. return true;
  146. }
  147. return false;
  148. }
  149. void CResourceAccessControl::AddResource( ResourceList_t hResourceList, ResourceTypeOld_t nType, const char *pResourceName )
  150. {
  151. if ( ContainsResource( hResourceList, nType, pResourceName ) )
  152. return;
  153. int nIndex = size_cast< int >( (intp)hResourceList );
  154. int nSubIndex = m_ResourceLists[nIndex].m_Resources[nType].AddToTail();
  155. char pBuf[MAX_PATH];
  156. FixupResourceName( pResourceName, pBuf, sizeof(pBuf) );
  157. m_ResourceLists[nIndex].m_Resources[nType][nSubIndex].Set( pBuf );
  158. }
  159. void CResourceAccessControl::LimitAccess( ResourceList_t hResourceList )
  160. {
  161. if ( !res_restrict_access.GetInt() )
  162. return;
  163. int nIndex = FindOrAddCurrentThreadID();
  164. if ( ( m_pLimitAccess[nIndex] >= 0 ) && ( hResourceList != RESOURCE_LIST_INVALID ) )
  165. {
  166. Warning( "Attempted to limit access while already limiting access!\n" );
  167. return;
  168. }
  169. m_pLimitAccess[nIndex] = size_cast< int >( (intp)hResourceList );
  170. }
  171. bool CResourceAccessControl::IsAccessAllowed( ResourceTypeOld_t nType, const char *pResourceName )
  172. {
  173. int nIndex = FindOrAddCurrentThreadID();
  174. if ( m_pLimitAccess[nIndex] < 0 )
  175. return true;
  176. int hResourceList = m_pLimitAccess[nIndex];
  177. if ( ContainsResource( (ResourceList_t)( intp )hResourceList, nType, pResourceName ) )
  178. return true;
  179. COMPILE_TIME_ASSERT( ARRAYSIZE( s_pResourceTypeName ) == RESOURCE_TYPE_OLD_COUNT );
  180. Warning( "Access to %s resource \"%s\" denied. Missing precache in %s?\n",
  181. s_pResourceTypeName[nType], pResourceName, m_ResourceLists[hResourceList].m_DebugName.Get() );
  182. return false;
  183. }