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