1.1 --- a/core/systems/PluginSys.h Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,458 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
1.36 -#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
1.37 -
1.38 -#include <time.h>
1.39 -#include <errno.h>
1.40 -#include <sys/stat.h>
1.41 -#include <IPluginSys.h>
1.42 -#include <IHandleSys.h>
1.43 -#include <IForwardSys.h>
1.44 -#include <sh_list.h>
1.45 -#include <sh_stack.h>
1.46 -#include <sh_vector.h>
1.47 -#include <sh_string.h>
1.48 -#include "sm_globals.h"
1.49 -#include "PluginInfoDatabase.h"
1.50 -#include "sm_trie.h"
1.51 -#include "sourcemod.h"
1.52 -#include <IRootConsoleMenu.h>
1.53 -#if defined ORANGEBOX_BUILD
1.54 -#include "convar_sm_ob.h"
1.55 -#else
1.56 -#include "convar_sm.h"
1.57 -#endif
1.58 -#include "ITranslator.h"
1.59 -#include "NativeOwner.h"
1.60 -#include "ShareSys.h"
1.61 -
1.62 -using namespace SourceHook;
1.63 -
1.64 -/**
1.65 - * NOTES:
1.66 - *
1.67 - * UPDATE 2008-03-11: These comments are horribly out of date. They paint a good overall
1.68 - * picture of how PluginSys works, but things like dependencies and fake natives have
1.69 - * complicated things quite a bit.
1.70 - *
1.71 - * Currently this system needs a lot of work but it's good skeletally. Plugin creation
1.72 - * is done without actually compiling anything. This is done by Load functions in the
1.73 - * manager. This will need a rewrite when we add context switching.
1.74 - *
1.75 - * The plugin object itself has a few things to note. The most important is that it stores
1.76 - * a table of function objects. The manager marshals allocation and freeing of these objects.
1.77 - * The plugin object can be in erroneous states, they are:
1.78 - * Plugin_Error --> Some error occurred any time during or after compilation.
1.79 - * This error can be cleared since the plugin itself is valid.
1.80 - * However, the state itself being set prevents any runtime action.
1.81 - * Plugin_BadLoad --> The plugin failed to load entirely and nothing can be done to save it.
1.82 - *
1.83 - * If a plugin fails to load externally, it is never added to the internal tracker. However,
1.84 - * plugins that failed to load from the internal loading mechanism are always tracked. This
1.85 - * allows users to see which automatically loaded plugins failed, and makes the interface a bit
1.86 - * more flexible.
1.87 - *
1.88 - * Once a plugin is compiled, it sets its own state to Plugin_Created. This state is still invalid
1.89 - * for execution. SourceMod is a two pass system, and even though the second pass is not implemented
1.90 - * yet, it is structured so Plugin_Created must be switched to Plugin_Running in the second pass. When
1.91 - * implemented, a Created plugin will be switched to Error in the second pass if it not loadable.
1.92 - *
1.93 - * The two pass loading mechanism is described below. Modules/natives are not implemented yet.
1.94 - * PASS ONE: All loadable plugins are found and have the following steps performed:
1.95 - * 1. Loading and compilation is attempted.
1.96 - * 2. If successful, all natives from Core are added.
1.97 - * 3. OnPluginLoad() is called.
1.98 - * 4. If failed, any user natives are scrapped and the process halts here.
1.99 - * 5. If successful, the plugin is ready for Pass 2.
1.100 - * INTERMEDIATE:
1.101 - * 1. All forced modules are loaded.
1.102 - * PASS TWO: All loaded plugins are found and have these steps performed:
1.103 - * 1. Any modules referenced in the plugin that are not already loaded, are loaded.
1.104 - * 2. If any module fails to load and the plugin requires it, load fails and jump to step 6.
1.105 - * 3. If any natives are unresolved, check if they are found in the user-natives pool.
1.106 - * 4. If yes, load succeeds. If not, natives are passed through a native acceptance filter.
1.107 - * 5. If the filter fails, the plugin is marked as failed.
1.108 - * 6. If the plugin has failed to load at this point, any dynamic natives it has added are scrapped.
1.109 - * Furthermore, any plugin that referenced these natives must now have pass 2 re-ran.
1.110 - * PASS THREE (not a real pass):
1.111 - * 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
1.112 - */
1.113 -
1.114 -enum LoadRes
1.115 -{
1.116 - LoadRes_Successful,
1.117 - LoadRes_AlreadyLoaded,
1.118 - LoadRes_Failure,
1.119 - LoadRes_NeverLoad
1.120 -};
1.121 -
1.122 -struct AutoConfig
1.123 -{
1.124 - String autocfg;
1.125 - String folder;
1.126 - bool create;
1.127 -};
1.128 -
1.129 -class CPlugin;
1.130 -
1.131 -class CPlugin :
1.132 - public IPlugin,
1.133 - public CNativeOwner
1.134 -{
1.135 - friend class CPluginManager;
1.136 - friend class CFunction;
1.137 -public:
1.138 - CPlugin(const char *file);
1.139 - ~CPlugin();
1.140 -public:
1.141 - PluginType GetType();
1.142 - SourcePawn::IPluginContext *GetBaseContext();
1.143 - sp_context_t *GetContext();
1.144 - void *GetPluginStructure();
1.145 - const char *GetFilename();
1.146 - bool IsDebugging();
1.147 - PluginStatus GetStatus();
1.148 - const sm_plugininfo_t *GetPublicInfo();
1.149 - bool SetPauseState(bool paused);
1.150 - unsigned int GetSerial();
1.151 - IdentityToken_t *GetIdentity();
1.152 - unsigned int CalcMemUsage();
1.153 - bool SetProperty(const char *prop, void *ptr);
1.154 - bool GetProperty(const char *prop, void **ptr, bool remove=false);
1.155 - void DropEverything();
1.156 - SourcePawn::IPluginRuntime *GetRuntime();
1.157 -public:
1.158 - /**
1.159 - * Creates a plugin object with default values.
1.160 - * If an error buffer is specified, and an error occurs, the error will be copied to the buffer
1.161 - * and NULL will be returned.
1.162 - * If an error buffer is not specified, the error will be copied to an internal buffer and
1.163 - * a valid (but error-stated) CPlugin will be returned.
1.164 - */
1.165 - static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
1.166 -public:
1.167 -
1.168 - /**
1.169 - * Sets an error state on the plugin
1.170 - */
1.171 - void SetErrorState(PluginStatus status, const char *error_fmt, ...);
1.172 -
1.173 - /**
1.174 - * Initializes the plugin's identity information
1.175 - */
1.176 - void InitIdentity();
1.177 -
1.178 - /**
1.179 - * Calls the OnPluginLoad function, and sets any failed states if necessary.
1.180 - * NOTE: Valid pre-states are: Plugin_Created
1.181 - * NOTE: If validated, plugin state is changed to Plugin_Loaded
1.182 - *
1.183 - * If the error buffer is NULL, the error message is cached locally.
1.184 - */
1.185 - bool Call_AskPluginLoad(char *error, size_t maxlength);
1.186 -
1.187 - /**
1.188 - * Calls the OnPluginStart function.
1.189 - * NOTE: Valid pre-states are: Plugin_Created
1.190 - * NOTE: Post-state will be Plugin_Running
1.191 - */
1.192 - void Call_OnPluginStart();
1.193 -
1.194 - /**
1.195 - * Calls the OnPluginEnd function.
1.196 - */
1.197 - void Call_OnPluginEnd();
1.198 -
1.199 - /**
1.200 - * Calls the OnAllPluginsLoaded function.
1.201 - */
1.202 - void Call_OnAllPluginsLoaded();
1.203 -
1.204 - /**
1.205 - * Toggles debug mode in the plugin
1.206 - */
1.207 - bool ToggleDebugMode(bool debug, char *error, size_t maxlength);
1.208 -
1.209 - /**
1.210 - * Returns true if a plugin is usable.
1.211 - */
1.212 - bool IsRunnable();
1.213 -
1.214 - /**
1.215 - * Get languages info.
1.216 - */
1.217 - IPhraseCollection *GetPhrases();
1.218 -public:
1.219 - /**
1.220 - * Returns the modification time during last plugin load.
1.221 - */
1.222 - time_t GetTimeStamp();
1.223 -
1.224 - /**
1.225 - * Returns the current modification time of the plugin file.
1.226 - */
1.227 - time_t GetFileTimeStamp();
1.228 -
1.229 - /**
1.230 - * Returns true if the plugin was running, but is now invalid.
1.231 - */
1.232 - bool WasRunning();
1.233 -
1.234 - Handle_t GetMyHandle();
1.235 -
1.236 - bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
1.237 - void AddConfig(bool autoCreate, const char *cfg, const char *folder);
1.238 - unsigned int GetConfigCount();
1.239 - AutoConfig *GetConfig(unsigned int i);
1.240 - inline void AddLibrary(const char *name)
1.241 - {
1.242 - m_Libraries.push_back(name);
1.243 - }
1.244 - void LibraryActions(bool dropping);
1.245 -protected:
1.246 - void UpdateInfo();
1.247 - void SetTimeStamp(time_t t);
1.248 - void DependencyDropped(CPlugin *pOwner);
1.249 -private:
1.250 - PluginType m_type;
1.251 - char m_filename[PLATFORM_MAX_PATH];
1.252 - PluginStatus m_status;
1.253 - unsigned int m_serial;
1.254 - sm_plugininfo_t m_info;
1.255 - char m_errormsg[256];
1.256 - time_t m_LastAccess;
1.257 - IdentityToken_t *m_ident;
1.258 - Handle_t m_handle;
1.259 - bool m_WasRunning;
1.260 - IPhraseCollection *m_pPhrases;
1.261 - List<String> m_RequiredLibs;
1.262 - List<String> m_Libraries;
1.263 - Trie *m_pProps;
1.264 - bool m_FakeNativesMissing;
1.265 - bool m_LibraryMissing;
1.266 - CVector<AutoConfig *> m_configs;
1.267 - bool m_bGotAllLoaded;
1.268 - int m_FileVersion;
1.269 - char m_DateTime[256];
1.270 - IPluginRuntime *m_pRuntime;
1.271 - IPluginContext *m_pContext;
1.272 -};
1.273 -
1.274 -class CPluginManager :
1.275 - public IPluginManager,
1.276 - public SMGlobalClass,
1.277 - public IHandleTypeDispatch,
1.278 - public IRootConsoleCommand
1.279 -{
1.280 - friend class CPlugin;
1.281 -public:
1.282 - CPluginManager();
1.283 - ~CPluginManager();
1.284 -public:
1.285 - /* Implements iterator class */
1.286 - class CPluginIterator : public IPluginIterator
1.287 - {
1.288 - public:
1.289 - CPluginIterator(List<CPlugin *> *mylist);
1.290 - virtual ~CPluginIterator();
1.291 - virtual bool MorePlugins();
1.292 - virtual IPlugin *GetPlugin();
1.293 - virtual void NextPlugin();
1.294 - void Release();
1.295 - public:
1.296 - void Reset();
1.297 - private:
1.298 - List<CPlugin *> *mylist;
1.299 - List<CPlugin *>::iterator current;
1.300 - };
1.301 - friend class CPluginManager::CPluginIterator;
1.302 -public: //IPluginManager
1.303 - IPlugin *LoadPlugin(const char *path,
1.304 - bool debug,
1.305 - PluginType type,
1.306 - char error[],
1.307 - size_t maxlength,
1.308 - bool *wasloaded);
1.309 - bool UnloadPlugin(IPlugin *plugin);
1.310 - IPlugin *FindPluginByContext(const sp_context_t *ctx);
1.311 - unsigned int GetPluginCount();
1.312 - IPluginIterator *GetPluginIterator();
1.313 - void AddPluginsListener(IPluginsListener *listener);
1.314 - void RemovePluginsListener(IPluginsListener *listener);
1.315 -public: //SMGlobalClass
1.316 - void OnSourceModAllInitialized();
1.317 - void OnSourceModShutdown();
1.318 -public: //IHandleTypeDispatch
1.319 - void OnHandleDestroy(HandleType_t type, void *object);
1.320 - bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
1.321 -public: //IRootConsoleCommand
1.322 - void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
1.323 -public:
1.324 - /**
1.325 - * Loads all plugins not yet loaded
1.326 - */
1.327 - void LoadAll_FirstPass(const char *config, const char *basedir);
1.328 -
1.329 - /**
1.330 - * Runs the second loading pass for all plugins
1.331 - */
1.332 - void LoadAll_SecondPass();
1.333 -
1.334 - /**
1.335 - * Tests a plugin file mask against a local folder.
1.336 - * The alias is searched backwards from localdir - i.e., given this input:
1.337 - * csdm/ban csdm/ban
1.338 - * ban csdm/ban
1.339 - * csdm/ban optional/csdm/ban
1.340 - * All of these will return true for an alias match.
1.341 - * Wildcards are allowed in the filename.
1.342 - */
1.343 - bool TestAliasMatch(const char *alias, const char *localdir);
1.344 -
1.345 - /**
1.346 - * Returns whether anything loaded will be a late load.
1.347 - */
1.348 - bool IsLateLoadTime() const;
1.349 -
1.350 - /**
1.351 - * Converts a Handle to an IPlugin if possible.
1.352 - */
1.353 - IPlugin *PluginFromHandle(Handle_t handle, HandleError *err);
1.354 -
1.355 - /**
1.356 - * Finds a plugin based on its index. (starts on index 1)
1.357 - */
1.358 - CPlugin *GetPluginByOrder(int num);
1.359 -
1.360 - int GetOrderOfPlugin(IPlugin *pl);
1.361 -
1.362 - /**
1.363 - * Internal version of FindPluginByContext()
1.364 - */
1.365 - CPlugin *GetPluginByCtx(const sp_context_t *ctx);
1.366 -
1.367 - /**
1.368 - * Gets status text for a status code
1.369 - */
1.370 - const char *GetStatusText(PluginStatus status);
1.371 -
1.372 - /**
1.373 - * Reload or update plugins on level shutdown.
1.374 - */
1.375 - void ReloadOrUnloadPlugins();
1.376 -
1.377 - /**
1.378 - * Add public functions from all running or paused
1.379 - * plugins to the specified forward if the names match.
1.380 - */
1.381 - void AddFunctionsToForward(const char *name, IChangeableForward *pForward);
1.382 -
1.383 - /**
1.384 - * Iterates through plugins to call OnAllPluginsLoaded.
1.385 - */
1.386 - void AllPluginsLoaded();
1.387 -
1.388 - CPlugin *GetPluginFromIdentity(IdentityToken_t *pToken);
1.389 -
1.390 - void Shutdown();
1.391 -
1.392 - void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop);
1.393 -
1.394 - bool LibraryExists(const char *lib);
1.395 -
1.396 - bool ReloadPlugin(CPlugin *pl);
1.397 -
1.398 - void UnloadAll();
1.399 -
1.400 - CPlugin *FindPluginByConsoleArg(const char *arg);
1.401 -private:
1.402 - LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength);
1.403 -
1.404 - void LoadAutoPlugin(const char *plugin);
1.405 -
1.406 - /**
1.407 - * Recursively loads all plugins in the given directory.
1.408 - */
1.409 - void LoadPluginsFromDir(const char *basedir, const char *localdir);
1.410 -
1.411 - /**
1.412 - * Adds a plugin object. This is wrapped by LoadPlugin functions.
1.413 - */
1.414 - void AddPlugin(CPlugin *pPlugin);
1.415 -
1.416 - /**
1.417 - * Runs the second loading pass on a plugin.
1.418 - */
1.419 - bool RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength);
1.420 -
1.421 - /**
1.422 - * Runs an extension pass on a plugin.
1.423 - */
1.424 - bool LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength);
1.425 -
1.426 - /**
1.427 - * Manages required natives.
1.428 - */
1.429 - bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength);
1.430 -
1.431 - void _SetPauseState(CPlugin *pPlugin, bool pause);
1.432 -protected:
1.433 - /**
1.434 - * Caching internal objects
1.435 - */
1.436 - void ReleaseIterator(CPluginIterator *iter);
1.437 -public:
1.438 - inline IdentityToken_t *GetIdentity()
1.439 - {
1.440 - return m_MyIdent;
1.441 - }
1.442 -private:
1.443 - void TryRefreshDependencies(CPlugin *pOther);
1.444 -private:
1.445 - List<IPluginsListener *> m_listeners;
1.446 - List<CPlugin *> m_plugins;
1.447 - CStack<CPluginManager::CPluginIterator *> m_iters;
1.448 - CPluginInfoDatabase m_PluginInfo;
1.449 - Trie *m_LoadLookup;
1.450 - bool m_AllPluginsLoaded;
1.451 - IdentityToken_t *m_MyIdent;
1.452 -
1.453 - /* Dynamic native stuff */
1.454 - List<FakeNative *> m_Natives;
1.455 -
1.456 - bool m_LoadingLocked;
1.457 -};
1.458 -
1.459 -extern CPluginManager g_PluginSys;
1.460 -
1.461 -#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_