int CLuaDefs::CanUseFunction ( lua_CFunction f, lua_State* luaVM ) { // Grab the function name we're calling. If it's one of our functions, see if we can use it. std::string strFunction; CLuaCFunction* pFunction = CLuaCFunctions::GetFunction ( f ); if ( pFunction ) { return static_cast < bool > ( CLuaDefs::CanUseFunction ( pFunction->GetName ().c_str (), luaVM, pFunction->IsRestricted () ) ); } // It's one of lua's functions, allow this return true; }
int CLuaDefs::CanUseFunction ( lua_CFunction f, lua_State* luaVM ) { // Quick cull of unknown pointer range if ( CLuaCFunctions::IsNotFunction( f ) ) return true; // Get associated resource CResource* pResource = m_pResourceManager->GetResourceFromLuaState( luaVM ); if ( !pResource ) return true; // Update execution time check pResource->GetVirtualMachine()->CheckExecutionTime(); // Check function right cache in resource bool bAllowed; if ( pResource->CheckFunctionRightCache( f, &bAllowed ) ) { // If in cache, and not allowed, do warning here if ( !bAllowed ) m_pScriptDebugging->LogBadAccess ( luaVM ); } else { // If not in cache, do full check bAllowed = true; // Grab the function name we're calling. If it's one of our functions, see if we can use it. CLuaCFunction* pFunction = CLuaCFunctions::GetFunction ( f ); dassert( pFunction ); if ( pFunction ) { // If it's not one of lua's functions, see if we allow it bAllowed = CLuaDefs::CanUseFunction ( pFunction->GetName ().c_str (), luaVM/*, pResource*/, pFunction->IsRestricted () ); } // Update cache in resource pResource->UpdateFunctionRightCache( f, bAllowed ); } g_pGame->GetDebugHookManager()->OnPreFunction( f, luaVM, bAllowed ); // If not allowed, do no more if ( !bAllowed ) return false; // Check if function timing is active if ( g_pStats->bFunctionTimingActive || g_pGame->GetDebugHookManager()->HasPostFunctionHooks() ) { // Check if hook needs applying if ( !ms_bRegisterdPostCallHook ) { OutputDebugLine ( "[Lua] Registering PostCallHook" ); ms_bRegisterdPostCallHook = true; lua_registerPostCallHook ( CLuaDefs::DidUseFunction ); } // Start to time the function ms_TimingFunctionStack.push_back ( STimingFunction( luaVM, f, GetTimeUs(), g_uiNetSentByteCounter ) ); } return true; }
// // Called after a Lua function if post call hook has been installed // void CLuaDefs::DidUseFunction ( lua_CFunction f, lua_State* luaVM ) { // Quick cull of unknown pointer range - Deals with calls from client dll (when the server has been loaded into the same process) if ( CLuaCFunctions::IsNotFunction( f ) ) return; if ( !ms_TimingFunctionStack.empty () ) { // Check if the function used was being timed const STimingFunction& info = ms_TimingFunctionStack.back (); if ( info.f == f ) { // Finish the timing TIMEUS elapsedTime = GetTimeUs() - info.startTime; uint uiDeltaBytes = g_uiNetSentByteCounter - info.uiStartByteCount; // Record timing over a threshold if ( elapsedTime >= CPerfStatFunctionTiming::ms_PeakUsThresh || uiDeltaBytes > 1000 ) { CLuaCFunction* pFunction = CLuaCFunctions::GetFunction ( info.f ); if ( pFunction ) { CResource* pResource = g_pGame->GetResourceManager ()->GetResourceFromLuaState ( info.luaVM ); SString strResourceName = pResource ? pResource->GetName() : "unknown"; CPerfStatFunctionTiming::GetSingleton ()->UpdateTiming ( strResourceName, pFunction->GetName ().c_str (), elapsedTime, uiDeltaBytes ); } } ms_TimingFunctionStack.pop_back (); } } // Check if we should remove the hook if ( !g_pStats->bFunctionTimingActive && !g_pGame->GetDebugHookManager()->HasPostFunctionHooks() ) { ms_TimingFunctionStack.clear (); OutputDebugLine ( "[Lua] Removing PostCallHook" ); assert ( ms_bRegisterdPostCallHook ); ms_bRegisterdPostCallHook = false; lua_registerPostCallHook ( NULL ); } g_pGame->GetDebugHookManager()->OnPostFunction( f, luaVM ); }
int CLuaDefs::CanUseFunction ( lua_CFunction f, lua_State* luaVM ) { // Quick cull of unknown pointer range if ( CLuaCFunctions::IsNotFunction( f ) ) return true; // these are for OOP and establish the function to call, at which point the function is called normally so we get this called like so: // Call 1: f = CLuaClassDefs::NewIndex // Call 2: f = setElementHealth // ignore new index as it isn't registered as an LuaCFunction and just throws an assert in debug/causes issues. if ( f == (lua_CFunction)&CLuaClassDefs::NewIndex || f == (lua_CFunction)&CLuaClassDefs::StaticNewIndex || f == (lua_CFunction)&CLuaClassDefs::Index || f == (lua_CFunction)&CLuaClassDefs::Call || f == (lua_CFunction)&CLuaClassDefs::ToString || f == (lua_CFunction)&CLuaClassDefs::ReadOnly || f == (lua_CFunction)&CLuaClassDefs::WriteOnly ) { return true; } // Get associated resource CResource* pResource = m_pResourceManager->GetResourceFromLuaState( luaVM ); if ( !pResource ) return true; // Update execution time check pResource->GetVirtualMachine()->CheckExecutionTime(); // Check function right cache in resource bool bAllowed; // Check cached ACL rights if ( pResource->CheckFunctionRightCache( f, &bAllowed ) ) { // If in cache, and not allowed, do warning here if ( !bAllowed ) m_pScriptDebugging->LogBadAccess ( luaVM ); } // Not cached yet else { // If not in cache, do full check bAllowed = true; // Grab the function name we're calling. If it's one of our functions, see if we can use it. CLuaCFunction* pFunction = CLuaCFunctions::GetFunction ( f ); // works for anything registered for Lua VM // e.g. setElementHealth, setElementFrozen if ( pFunction ) { // If it's not one of lua's functions, see if we allow it bAllowed = CLuaDefs::CanUseFunction ( pFunction->GetName ().c_str (), luaVM, pFunction->IsRestricted () ); } // works for custom ACL functions e.g. // Element.position and other custom oop definitions not registered by string. else { // get the 2nd upvalue (ACL Name) const char* szName = lua_tostring ( luaVM, lua_upvalueindex ( 2 ) ); // if it has no name do nothing if ( szName != NULL && strcmp ( szName , "" ) != 0 ) { // get the function by name CLuaCFunction* pFunction = CLuaCFunctions::GetFunction ( szName ); if ( pFunction ) { // check the resource cache for the Lua name we looked up bAllowed = CLuaDefs::CanUseFunction ( szName, luaVM, pFunction->IsRestricted () ); } } } // Update cache in resource pResource->UpdateFunctionRightCache( f, bAllowed ); } g_pGame->GetDebugHookManager()->OnPreFunction( f, luaVM, bAllowed ); // If not allowed, do no more if ( !bAllowed ) return false; // Check if function timing is active if ( g_pStats->bFunctionTimingActive || g_pGame->GetDebugHookManager()->HasPostFunctionHooks() ) { // Check if hook needs applying if ( !ms_bRegisterdPostCallHook ) { OutputDebugLine ( "[Lua] Registering PostCallHook" ); ms_bRegisterdPostCallHook = true; lua_registerPostCallHook ( CLuaDefs::DidUseFunction ); } // Start to time the function ms_TimingFunctionStack.push_back ( STimingFunction( luaVM, f, GetTimeUs(), g_uiNetSentByteCounter ) ); } return true; }