initial import of sharesystem (unfinished)

final revision of handle system (I hope!)
initial import of plugin handles

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40234
This commit is contained in:
David Anderson 2006-12-29 23:18:13 +00:00
parent 5b331ca858
commit f068587ecc
11 changed files with 644 additions and 102 deletions

View File

@ -7,6 +7,8 @@
#define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys"
#define SMINTERFACE_HANDLESYSTEM_VERSION 1
#define DEFAULT_IDENTITY NULL
namespace SourceMod
{
/**
@ -37,6 +39,7 @@ namespace SourceMod
HandleError_Index, /* generic internal indexing error */
HandleError_Access, /* No access permitted to free this handle */
HandleError_Limit, /* The limited number of handles has been reached */
HandleError_Identity, /* The identity token was not usable */
};
enum HandleAccessRight
@ -54,14 +57,14 @@ namespace SourceMod
{
HandleSecurity()
{
owner = 0;
owner = NULL;
access[HandleAccess_Create] = true;
access[HandleAccess_Read] = true;
access[HandleAccess_Delete] = true;
access[HandleAccess_Inherit] = true;
access[HandleAccess_Clone] = true;
}
IdentityToken_t owner; /* Owner of the handle */
IdentityToken_t *owner; /* Owner of the handle */
bool access[HandleAccess_TOTAL]; /* World access rights */
};
@ -112,12 +115,14 @@ namespace SourceMod
* @param parent Parent handle to inherit from, 0 for none.
* @param security Pointer to a temporary HandleSecurity object, NULL to use default
* or inherited permissions.
* @param ident Security token for any permissions.
* @return A new HandleType_t unique ID.
*/
virtual HandleType_t CreateTypeEx(const char *name,
IHandleTypeDispatch *dispatch,
HandleType_t parent,
const HandleSecurity *security) =0;
const HandleSecurity *security,
IdentityToken_t *ident) =0;
/**
@ -143,7 +148,7 @@ namespace SourceMod
* @param type Type chain to remove.
* @return True on success, false on failure.
*/
virtual bool RemoveType(HandleType_t type, IdentityToken_t ident) =0;
virtual bool RemoveType(HandleType_t type, IdentityToken_t *ident) =0;
/**
* @brief Finds a handle type by name.
@ -159,14 +164,14 @@ namespace SourceMod
*
* @param type Type to use on the handle.
* @param object Object to bind to the handle.
* @param source Identity token for object using this handle (for example, a script).
* @param owner Owner for the handle.
* @param ident Identity token if any security rights are needed.
* @return A new Handle_t, or 0 on failure.
*/
virtual Handle_t CreateHandle(HandleType_t type,
void *object,
IdentityToken_t source,
IdentityToken_t ident) =0;
IdentityToken_t *owner,
IdentityToken_t *ident) =0;
/**
* @brief Creates a new handle.
@ -181,7 +186,7 @@ namespace SourceMod
virtual Handle_t CreateScriptHandle(HandleType_t type,
void *object,
sp_context_t *ctx,
IdentityToken_t ident) =0;
IdentityToken_t *ident) =0;
/**
* @brief Frees the memory associated with a handle and calls any destructors.
@ -192,7 +197,7 @@ namespace SourceMod
* @param ident Identity token, for destroying secure handles (0 for none).
* @return A HandleError error code.
*/
virtual HandleError FreeHandle(Handle_t handle, IdentityToken_t ident) =0;
virtual HandleError FreeHandle(Handle_t handle, IdentityToken_t *ident) =0;
/**
* @brief Clones a handle by adding to its internal reference count. Its data,
@ -200,11 +205,11 @@ namespace SourceMod
*
* @param handle Handle to duplicate. Any non-free handle target is valid.
* @param newhandle If non-NULL, stores the duplicated handle in the pointer.
* @param source New source of cloned handle.
* @param owner New owner of cloned handle.
* @param ident Security token, if needed.
* @return A HandleError error code.
*/
virtual HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t source, IdentityToken_t ident) =0;
virtual HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *owner, IdentityToken_t *ident) =0;
/**
* @brief Retrieves the contents of a handle.
@ -215,7 +220,7 @@ namespace SourceMod
* @param object Address to store object in.
* @return HandleError error code.
*/
virtual HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t ident, void **object) =0;
virtual HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t *ident, void **object) =0;
};
};

View File

@ -147,7 +147,7 @@ namespace SourceMod
/**
* @brief Returns a plugin's identity token.
*/
virtual IdentityToken_t GetIdentity() =0;
virtual IdentityToken_t *GetIdentity() =0;
};

View File

@ -3,11 +3,13 @@
#include <sp_vm_types.h>
#define DEFAULT_IDENTITY 0
#define NO_IDENTITY 0
namespace SourceMod
{
typedef unsigned int IdentityToken_t;
struct IdentityToken_t;
typedef unsigned int HandleType_t;
typedef HandleType_t IdentityType_t;
/**
* @brief Defines the base functionality required by a shared interface.
*/
@ -49,12 +51,13 @@ namespace SourceMod
{
public:
/**
* @brief Adds an interface to the global interface system
* @brief Adds an interface to the global interface system.
*
* @param iface Interface pointer (must be unique).
* @param token Parent token of the module/interface.
* @return True on success, false otherwise.
*/
virtual bool AddInterface(SMInterface *iface, IdentityToken_t token) =0;
virtual bool AddInterface(SMInterface *iface, IdentityToken_t *token) =0;
/**
* @brief Requests an interface from the global interface system.
@ -67,8 +70,8 @@ namespace SourceMod
*/
virtual bool RequestInterface(const char *iface_name,
unsigned int iface_vers,
IdentityToken_t token,
void **pIface) =0;
IdentityToken_t *token,
SMInterface **pIface) =0;
/**
* @brief Adds a list of natives to the global native pool.
@ -76,7 +79,54 @@ namespace SourceMod
* @param token Identity token of parent object.
* @param natives Array of natives to add, NULL terminated.
*/
virtual void AddNatives(IdentityToken_t token, const sp_nativeinfo_t *natives[]) =0;
virtual void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]) =0;
/**
* @brief Creates a new identity type.
* NOTE: Module authors should never need to use this. Due to the current implementation,
* there is a hardcoded limit of 15 types. Core uses up a few, so think carefully!
*
* @param name String containing type name. Must not be empty or NULL.
* @return A new HandleType_t identifier, or 0 on failure.
*/
virtual IdentityType_t CreateIdentType(const char *name) =0;
/**
* @brief Finds an identity type by name.
* DEFAULT IDENTITY TYPES:
* "PLUGIN" - An IPlugin object.
* "MODULE" - An IModule object.
* "CORE" - An SMGlobalClass or other singleton.
*
* @param name String containing type name to search for.
* @return A HandleType_t identifier if found, 0 otherwise.
*/
virtual IdentityType_t FindIdentType(const char *name) =0;
/**
* @brief Creates a new identity token. This token is guaranteed to be unique
* amongst all other open identities.
*
* @param type Identity type.
* @return A new IdentityToken_t identifier.
*/
virtual IdentityToken_t *CreateIdentity(IdentityType_t type) =0;
/**
* @brief Destroys an identity type. Note that this will delete any identities
* that are under this type.
*
* @param type Identity type.
*/
virtual void DestroyIdentType(IdentityType_t type) =0;
/**
* @brief Destroys an identity token. Any handles being owned by this token, or
* any handles being
*
* @param identity Identity to remove.
*/
virtual void DestroyIdentity(IdentityToken_t *identity) =0;
};
};

View File

@ -13,6 +13,40 @@
using namespace SourcePawn;
using namespace SourceMod;
/**
* @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod
*/
class SMGlobalClass
{
friend class SourceModBase;
public:
SMGlobalClass();
public:
/**
* @brief Called when SourceMod is initially loading
*/
virtual void OnSourceModStartup(bool late)
{
}
/**
* @brief Called after all global classes have initialized
*/
virtual void OnSourceModAllInitialized()
{
}
/**
* @brief Called when SourceMod is shutting down
*/
virtual void OnSourceModShutdown()
{
}
private:
SMGlobalClass *m_pGlobalClassNext;
static SMGlobalClass *head;
};
extern ISourcePawnEngine *g_pSourcePawn;
extern IVirtualMachine *g_pVM;

View File

@ -52,40 +52,6 @@ private:
bool m_IsLateLoadInMap;
};
/**
* @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod
*/
class SMGlobalClass
{
friend class SourceModBase;
public:
SMGlobalClass();
public:
/**
* @brief Called when SourceMod is initially loading
*/
virtual void OnSourceModStartup(bool late)
{
}
/**
* @brief Called after all global classes have initialized
*/
virtual void OnSourceModAllInitialized()
{
}
/**
* @brief Called when SourceMod is shutting down
*/
virtual void OnSourceModShutdown()
{
}
private:
SMGlobalClass *m_pGlobalClassNext;
static SMGlobalClass *head;
};
extern SourceModBase g_SourceMod;
#endif //_INCLUDE_SOURCEMOD_GLOBALHEADER_H_

View File

@ -1,9 +1,22 @@
#include "HandleSys.h"
#include "ShareSys.h"
#include "PluginSys.h"
#include <assert.h>
HandleSystem g_HandleSys;
QHandle *ignore_handle;
inline HandleType_t TypeParent(HandleType_t type)
{
return (type & ~HANDLESYS_SUBTYPE_MASK);
}
inline HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index)
{
return g_HandleSys.GetHandle(token->ident, g_ShareSys.GetIdentRoot(), &ignore_handle, index, HandleAccess_Read);
}
HandleSystem::HandleSystem()
{
m_Handles = new QHandle[HANDLESYS_MAX_HANDLES + 1];
@ -28,18 +41,19 @@ HandleSystem::~HandleSystem()
HandleType_t HandleSystem::CreateType(const char *name, IHandleTypeDispatch *dispatch)
{
return CreateTypeEx(name, dispatch, 0, NULL);
return CreateTypeEx(name, dispatch, 0, NULL, NULL);
}
HandleType_t HandleSystem::CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch)
{
return CreateTypeEx(name, dispatch, parent, NULL);
return CreateTypeEx(name, dispatch, parent, NULL, NULL);
}
HandleType_t HandleSystem::CreateTypeEx(const char *name,
IHandleTypeDispatch *dispatch,
HandleType_t parent,
const HandleSecurity *security)
const HandleSecurity *security,
IdentityToken_t *ident)
{
if (!dispatch)
{
@ -56,8 +70,9 @@ HandleType_t HandleSystem::CreateTypeEx(const char *name,
return 0;
}
if (parent >= HANDLESYS_TYPEARRAY_SIZE
|| m_Types[parent].dispatch != NULL
|| m_Types[parent].sec.access[HandleAccess_Inherit] == false)
|| m_Types[parent].dispatch == NULL
|| (m_Types[parent].sec.access[HandleAccess_Inherit] == false
&& m_Types[parent].sec.owner != ident))
{
return 0;
}
@ -163,8 +178,16 @@ bool HandleSystem::FindHandleType(const char *name, HandleType_t *type)
HandleError HandleSystem::MakePrimHandle(HandleType_t type,
QHandle **in_pHandle,
unsigned int *in_index,
Handle_t *in_handle)
Handle_t *in_handle,
IdentityToken_t *owner)
{
unsigned int owner_index = 0;
if (owner && (IdentityHandle(owner, &owner_index) != HandleError_None))
{
return HandleError_Identity;
}
unsigned int handle;
if (m_FreeHandles == 0)
{
@ -187,10 +210,12 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
}
/* Set essential information */
pHandle->set = true;
pHandle->set = HandleSet_Used;;
pHandle->refcount = 1;
pHandle->type = type;
pHandle->serial = m_HSerial;
pHandle->owner = owner;
pHandle->ch_next = 0;
/* Create the hash value */
Handle_t hash = pHandle->serial;
@ -205,10 +230,44 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
*in_index = handle;
*in_handle = hash;
/* Decode the identity token */
if (owner)
{
QHandle *pIdentity = &m_Handles[owner_index];
if (pIdentity->ch_prev == 0)
{
pIdentity->ch_prev = handle;
pIdentity->ch_next = handle;
pHandle->ch_prev = 0;
} else {
/* Link previous node to us (forward) */
m_Handles[pIdentity->ch_next].ch_next = handle;
/* Link us to previous node (backwards) */
pHandle->ch_prev = pIdentity->ch_next;
/* Set new tail */
pIdentity->ch_next = handle;
}
pIdentity->refcount++;
} else {
pHandle->ch_prev = 0;
}
return HandleError_None;
}
Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t source, IdentityToken_t ident)
void HandleSystem::SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken)
{
if (!type
|| type >= HANDLESYS_TYPEARRAY_SIZE
|| m_Types[type].dispatch == NULL)
{
return;
}
m_Types[type].sec.owner = pToken;
}
Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityToken_t *source, IdentityToken_t *ident)
{
if (!type
|| type >= HANDLESYS_TYPEARRAY_SIZE
@ -230,12 +289,11 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok
QHandle *pHandle;
HandleError err;
if ((err=MakePrimHandle(type, &pHandle, &index, &handle)) != HandleError_None)
if ((err=MakePrimHandle(type, &pHandle, &index, &handle, source)) != HandleError_None)
{
return 0;
}
pHandle->source = source;
pHandle->object = object;
pHandle->clone = 0;
@ -245,15 +303,35 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok
Handle_t HandleSystem::CreateScriptHandle(HandleType_t type,
void *object,
sp_context_t *ctx,
IdentityToken_t ident)
IdentityToken_t *ident)
{
IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx);
return CreateHandle(type, object, pPlugin->GetIdentity(), ident);
}
bool HandleSystem::TypeCheck(HandleType_t intype, HandleType_t outtype)
{
/* Check the type inheritance */
if (intype & HANDLESYS_SUBTYPE_MASK)
{
if (intype != outtype
&& (TypeParent(intype) != TypeParent(outtype)))
{
return false;
}
} else {
if (intype != outtype)
{
return false;
}
}
return true;
}
HandleError HandleSystem::GetHandle(Handle_t handle,
IdentityToken_t ident,
IdentityToken_t *ident,
QHandle **in_pHandle,
unsigned int *in_index,
HandleAccessRight access)
@ -277,6 +355,11 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
if (!pHandle->set)
{
return HandleError_Freed;
} else if (pHandle->set == HandleSet_Identity
&& ident != g_ShareSys.GetIdentRoot())
{
/* Only IdentityHandle() can read this! */
return HandleError_Identity;
}
if (pHandle->serial != serial)
{
@ -289,7 +372,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
return HandleError_None;
}
HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t source, IdentityToken_t ident)
HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle, IdentityToken_t *source, IdentityToken_t *ident)
{
HandleError err;
QHandle *pHandle;
@ -307,13 +390,12 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle,
QHandle *pNewHandle;
Handle_t new_handle;
if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle)) != HandleError_None)
if ((err=MakePrimHandle(pHandle->type, &pNewHandle, &new_index, &new_handle, source)) != HandleError_None)
{
return err;
}
pNewHandle->clone = index;
pNewHandle->source = source;
if (out_newhandle)
{
@ -323,7 +405,7 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *out_newhandle,
return HandleError_None;
}
HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t ident)
HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t *ident)
{
unsigned int index;
QHandle *pHandle;
@ -361,14 +443,9 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, IdentityToken_t ident)
return HandleError_None;
}
inline HandleType_t TypeParent(HandleType_t type)
{
return (type & ~HANDLESYS_SUBTYPE_MASK);
}
HandleError HandleSystem::ReadHandle(Handle_t handle,
HandleType_t type,
IdentityToken_t ident,
IdentityToken_t *ident,
void **object)
{
unsigned int index;
@ -412,12 +489,59 @@ void HandleSystem::ReleasePrimHandle(unsigned int index)
{
QHandle *pHandle = &m_Handles[index];
pHandle->set = false;
pHandle->set = HandleSet_None;
m_Types[pHandle->type].opened--;
m_Handles[++m_FreeHandles].freeID = index;
/* Unlink us if necessary */
if (pHandle->owner)
{
unsigned int ident_index;
if (IdentityHandle(pHandle->owner, &ident_index) != HandleError_None)
{
/* Uh-oh! */
assert(pHandle->owner == 0);
return;
}
/* Note that since 0 is an invalid handle, if any of these links are 0,
* the data can still be set.
*/
QHandle *pIdentity = &m_Handles[ident_index];
/* Unlink case: We're the head AND tail node */
if (index == pIdentity->ch_prev && index == pIdentity->ch_next)
{
pIdentity->ch_prev = 0;
pIdentity->ch_next = 0;
}
/* Unlink case: We're the head node */
else if (index == pIdentity->ch_prev) {
/* Link us to the next in the chain */
pIdentity->ch_prev = pHandle->ch_next;
/* Patch up the previous link */
m_Handles[pHandle->ch_next].ch_prev = 0;
}
/* Unlink case: We're the tail node */
else if (index == pIdentity->ch_next) {
/* Link us to the previous in the chain */
pIdentity->ch_next = pHandle->ch_prev;
/* Patch up the next link */
m_Handles[pHandle->ch_prev].ch_next = 0;
}
/* Unlink case: We're in the middle! */
else {
/* Patch the forward reference */
m_Handles[pHandle->ch_next].ch_prev = pHandle->ch_prev;
/* Patch the backward reference */
m_Handles[pHandle->ch_prev].ch_next = pHandle->ch_next;
}
/* Lastly, decrease the reference count */
pIdentity->refcount--;
}
}
bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t ident)
bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
{
if (type == 0 || type >= HANDLESYS_TYPEARRAY_SIZE)
{
@ -499,3 +623,16 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t ident)
return true;
}
void HandleSystem::MarkHandleAsIdentity(Handle_t handle)
{
QHandle *pHandle;
unsigned int index;
if (GetHandle(handle, g_ShareSys.GetIdentRoot(), &pHandle, &index, HandleAccess_Read) != HandleError_None)
{
return;
}
pHandle->set = HandleSet_Identity;
}

View File

@ -16,16 +16,46 @@
#define HANDLESYS_SERIAL_MASK 0xFFFF0000
#define HANDLESYS_HANDLE_MASK 0x0000FFFF
/**
* The QHandle is a nasty structure that compacts the handle system into a big vector.
* The members of the vector each encapsulate one Handle, however, they also act as nodes
* in an inlined linked list and an inlined vector.
*
* The first of these lists is the 'freeID' list. Each node from 1 to N (where N
* is the number of free nodes) has a 'freeID' that specifies a free Handle ID. This
* is a quick hack to get around allocating a second base vector.
*
* The second vector is the identity linked list. An identity has its own handle, so
* these handles are used as sentinel nodes for index linking. They point to the first and last
* index into the handle array. Each subsequent Handle who is owned by that indentity is mapped into
* that list. This lets owning identities be unloaded in O(n) time.
*
* Eventually, there may be a third list for type chains.
*/
enum HandleSet
{
HandleSet_None = 0,
HandleSet_Used,
HandleSet_Identity
};
struct QHandle
{
HandleType_t type; /* Handle type */
void *object; /* Unmaintained object pointer */
unsigned int freeID; /* ID of a free handle in the free handle chain */
IdentityToken_t source; /* Identity of object which owns this */
IdentityToken_t *owner; /* Identity of object which owns this */
unsigned int serial; /* Serial no. for sanity checking */
unsigned int refcount; /* Reference count for safe destruction */
Handle_t clone; /* If non-zero, this is our cloned parent */
bool set; /* Whether or not this handle is set */
HandleSet set; /* Information about the handle's state */
/* The following variables are unrelated to the Handle array, and used
* as an inlined chain of information */
unsigned int freeID; /* ID of a free handle in the free handle chain */
/* Indexes into the handle array for owner membership.
* For identity roots, these are treated as the head/tail. */
unsigned int ch_prev; /* chained previous handle or HEAD */
unsigned int ch_next; /* chained next handle or TAIL */
};
struct QHandleType
@ -41,6 +71,8 @@ struct QHandleType
class HandleSystem :
public IHandleSys
{
friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
friend class ShareSystem;
public:
HandleSystem();
~HandleSystem();
@ -49,24 +81,26 @@ public: //IHandleSystem
HandleType_t CreateTypeEx(const char *name,
IHandleTypeDispatch *dispatch,
HandleType_t parent,
const HandleSecurity *security);
const HandleSecurity *security,
IdentityToken_t *ident);
HandleType_t CreateChildType(const char *name, HandleType_t parent, IHandleTypeDispatch *dispatch);
bool RemoveType(HandleType_t type, IdentityToken_t ident);
bool RemoveType(HandleType_t type, IdentityToken_t *ident);
bool FindHandleType(const char *name, HandleType_t *type);
Handle_t CreateHandle(HandleType_t type,
void *object,
IdentityToken_t source,
IdentityToken_t ident);
Handle_t CreateScriptHandle(HandleType_t type, void *object, sp_context_t *ctx, IdentityToken_t ident);
HandleError FreeHandle(Handle_t handle, IdentityToken_t ident);
HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t source, IdentityToken_t ident);
HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t ident, void **object);
private:
IdentityToken_t *source,
IdentityToken_t *ident);
Handle_t CreateScriptHandle(HandleType_t type, void *object, sp_context_t *ctx, IdentityToken_t *ident);
HandleError FreeHandle(Handle_t handle, IdentityToken_t *ident);
HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *source, IdentityToken_t *ident);
HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t *ident, void **object);
bool TypeCheck(HandleType_t intype, HandleType_t outtype);
protected:
/**
* Decodes a handle with sanity and security checking.
*/
HandleError GetHandle(Handle_t handle,
IdentityToken_t ident,
IdentityToken_t *ident,
QHandle **pHandle,
unsigned int *index,
HandleAccessRight access);
@ -75,12 +109,28 @@ private:
* Creates a basic handle and sets its reference count to 1.
* Does not do any type or security checking.
*/
HandleError MakePrimHandle(HandleType_t type, QHandle **pHandle, unsigned int *index, HandleType_t *handle);
HandleError MakePrimHandle(HandleType_t type,
QHandle **pHandle,
unsigned int *index,
HandleType_t *handle,
IdentityToken_t *owner);
/**
* Frees a primitive handle. Does no object freeing, only reference count and bookkeepping.
* Frees a primitive handle. Does no object freeing, only reference count, bookkeepping,
* and linked list maintenance.
*/
void ReleasePrimHandle(unsigned int index);
/**
* Sets the security owner of a type
*/
void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
/**
* Marks a handle as an identity.
* This prevents it from being tampered with by outside stuff
*/
void MarkHandleAsIdentity(Handle_t handle);
private:
QHandle *m_Handles;
QHandleType *m_Types;

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include "PluginSys.h"
#include "ShareSys.h"
#include "LibrarySys.h"
#include "HandleSys.h"
#include "sourcemm_api.h"
@ -8,6 +9,7 @@
CPluginManager g_PluginSys;
HandleType_t g_PluginType = 0;
IdentityType_t g_PluginIdent = 0;
CPlugin::CPlugin(const char *file)
{
@ -22,8 +24,8 @@ CPlugin::CPlugin(const char *file)
m_pub_funcs = NULL;
m_errormsg[256] = '\0';
snprintf(m_filename, sizeof(m_filename), "%s", file);
/* :TODO: ShareSys token */
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, DEFAULT_IDENTITY, 1);
m_handle = 0;
m_ident = NULL;
}
CPlugin::~CPlugin()
@ -70,7 +72,20 @@ CPlugin::~CPlugin()
m_plugin = NULL;
}
g_HandleSys.FreeHandle(m_handle, g_PluginType);
if (m_handle)
{
g_HandleSys.FreeHandle(m_handle, g_PluginSys.GetIdentity());
g_ShareSys.DestroyIdentity(m_ident);
}
}
void CPlugin::InitIdentity()
{
if (!m_handle)
{
m_ident = g_ShareSys.CreateIdentity(g_PluginIdent);
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity());
}
}
CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
@ -447,9 +462,9 @@ bool CPlugin::SetPauseState(bool paused)
return true;
}
IdentityToken_t CPlugin::GetIdentity()
IdentityToken_t *CPlugin::GetIdentity()
{
return 0;
return m_ident;
}
/*******************
@ -499,6 +514,7 @@ CPluginManager::CPluginManager()
{
m_LoadLookup = sm_trie_create();
m_AllPluginsLoaded = false;
m_MyIdent = NULL;
}
CPluginManager::~CPluginManager()
@ -661,6 +677,7 @@ void CPluginManager::LoadAutoPlugin(const char *file)
if (pPlugin->GetStatus() == Plugin_Created)
{
AddCoreNativesToPlugin(pPlugin);
pPlugin->InitIdentity();
pPlugin->Call_AskPluginLoad(NULL, 0);
}
@ -712,6 +729,8 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
AddCoreNativesToPlugin(pPlugin);
pPlugin->InitIdentity();
/* Finally, ask the plugin if it wants to be loaded */
if (!pPlugin->Call_AskPluginLoad(error, err_max))
{
@ -1092,20 +1111,25 @@ bool CPluginManager::IsLateLoadTime()
void CPluginManager::OnSourceModAllInitialized()
{
m_MyIdent = g_ShareSys.CreateCoreIdentity();
HandleSecurity sec;
sec.owner = 1; /* :TODO: implement ShareSys */
sec.owner = m_MyIdent; /* :TODO: implement ShareSys */
sec.access[HandleAccess_Create] = false;
sec.access[HandleAccess_Delete] = false;
sec.access[HandleAccess_Inherit] = false;
sec.access[HandleAccess_Clone] = false;
g_PluginType = g_HandleSys.CreateTypeEx("IPlugin", this, 0, &sec);
g_PluginType = g_HandleSys.CreateTypeEx("IPlugin", this, 0, &sec, NULL);
g_PluginIdent = g_ShareSys.CreateIdentType("PLUGIN");
}
void CPluginManager::OnSourceModShutdown()
{
g_HandleSys.RemoveType(g_PluginType, 1);
g_HandleSys.RemoveType(g_PluginType, m_MyIdent);
g_ShareSys.DestroyIdentType(g_PluginIdent);
g_ShareSys.DestroyIdentity(m_MyIdent);
}
void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)

View File

@ -93,7 +93,7 @@ public:
virtual const sp_plugin_t *GetPluginStructure() const;
virtual IPluginFunction *GetFunctionByName(const char *public_name);
virtual IPluginFunction *GetFunctionById(funcid_t func_id);
virtual IdentityToken_t GetIdentity();
virtual IdentityToken_t *GetIdentity();
public:
/**
* Creates a plugin object with default values.
@ -114,11 +114,17 @@ public:
*/
bool FinishMyCompile(char *error, size_t maxlength);
void CancelMyCompile();
/**
* Sets an error state on the plugin
*/
void SetErrorState(PluginStatus status, const char *error_fmt, ...);
/**
* Initializes the plugin's identity information
*/
void InitIdentity();
/**
* Calls the OnPluginLoad function, and sets any failed states if necessary.
* NOTE: Valid pre-states are: Plugin_Created
@ -151,6 +157,7 @@ private:
CFunction **m_pub_funcs;
char m_errormsg[256];
time_t m_LastAccess;
IdentityToken_t *m_ident;
Handle_t m_handle;
};
@ -262,6 +269,10 @@ protected:
void ReleaseIterator(CPluginIterator *iter);
CFunction *GetFunctionFromPool(funcid_t f, CPlugin *plugin);
void ReleaseFunctionToPool(CFunction *func);
inline IdentityToken_t *GetIdentity()
{
return m_MyIdent;
}
private:
List<IPluginsListener *> m_listeners;
List<CPlugin *> m_plugins;
@ -271,6 +282,7 @@ private:
CPluginInfoDatabase m_PluginInfo;
Trie *m_LoadLookup;
bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent;
};
extern CPluginManager g_PluginSys;

195
core/systems/ShareSys.cpp Normal file
View File

@ -0,0 +1,195 @@
#include "ShareSys.h"
#include "HandleSys.h"
ShareSystem g_ShareSys;
ShareSystem::ShareSystem()
{
m_IdentRoot.ident = 0;
m_TypeRoot = 0;
m_IfaceType = 0;
m_CoreType = 0;
}
IdentityToken_t *ShareSystem::CreateCoreIdentity()
{
if (!m_CoreType)
{
m_CoreType = CreateIdentType("CORE");
}
return CreateIdentity(m_CoreType);
}
void ShareSystem::OnSourceModStartup(bool late)
{
HandleSecurity sec;
sec.owner = GetIdentRoot();
sec.access[HandleAccess_Inherit] = false;
sec.access[HandleAccess_Delete] = false;
m_TypeRoot = g_HandleSys.CreateTypeEx("Identity", this, 0, &sec, NULL);
m_IfaceType = g_HandleSys.CreateTypeEx("Interface", this, 0, &sec, NULL);
/* Initialize our static identity handle */
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, NULL);
}
void ShareSystem::OnSourceModShutdown()
{
if (m_CoreType)
{
g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
}
g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
}
IdentityType_t ShareSystem::FindIdentType(const char *name)
{
HandleType_t type;
if (g_HandleSys.FindHandleType(name, &type))
{
if (g_HandleSys.TypeCheck(type, m_TypeRoot))
{
return type;
}
}
return 0;
}
IdentityType_t ShareSystem::CreateIdentType(const char *name)
{
if (!m_TypeRoot)
{
return 0;
}
return g_HandleSys.CreateTypeEx(name, this, m_TypeRoot, NULL, GetIdentRoot());
}
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
{
/* We don't care here */
}
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type)
{
if (!m_TypeRoot)
{
return 0;
}
/* :TODO: Cache? */
IdentityToken_t *pToken = new IdentityToken_t;
pToken->ident = g_HandleSys.CreateHandle(type, NULL, NULL, GetIdentRoot());
return pToken;
}
bool ShareSystem::AddInterface(SMInterface *iface, IdentityToken_t *token)
{
if (!iface)
{
return false;
}
IfaceInfo info;
info.iface = iface;
info.token = token;
if (token)
{
/* If we're an external object, we have to do this */
info.handle = g_HandleSys.CreateHandle(m_IfaceType, iface, token, GetIdentRoot());
} else {
info.handle = 0;
}
m_Interfaces.push_back(info);
return true;
}
bool ShareSystem::RequestInterface(const char *iface_name,
unsigned int iface_vers,
IdentityToken_t *token,
SMInterface **pIface)
{
/* If Some yahoo.... SOME HOOLIGAN... some NO GOOD DIRTY
* HORRIBLE PERSON passed in a token that we don't recognize....
* <b>Punish them.</b>
*/
if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, GetIdentRoot(), NULL))
{
return false;
}
/* See if the interface exists */
List<IfaceInfo>::iterator iter;
SMInterface *iface;
IdentityToken_t *iface_owner;
Handle_t iface_handle;
bool found = false;
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
{
IfaceInfo &info = (*iter);
iface = info.iface;
if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
{
if (iface->GetInterfaceVersion() == iface_vers
|| iface->IsVersionCompatible(iface_vers))
{
iface_owner = info.token;
iface_handle = info.handle;
found = true;
break;
}
}
}
if (!found)
{
return false;
}
/* If something external owns this, we need to track it. */
if (iface_owner)
{
Handle_t newhandle;
if (g_HandleSys.CloneHandle(iface_handle, &newhandle, token, GetIdentRoot())
!= HandleError_None)
{
return false;
}
/**
* Now we can deny module loads based on dependencies.
*/
}
/* :TODO: finish */
return NULL;
}
void ShareSystem::AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[])
{
/* :TODO: implement */
}
void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
{
g_HandleSys.FreeHandle(identity->ident, GetIdentRoot());
delete identity;
}
void ShareSystem::DestroyIdentType(IdentityType_t type)
{
g_HandleSys.RemoveType(type, GetIdentRoot());
}

69
core/systems/ShareSys.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef _INCLUDE_SOURCEMOD_SHARESYSTEM_H_
#define _INCLUDE_SOURCEMOD_SHARESYSTEM_H_
#include <IShareSys.h>
#include <IHandleSys.h>
#include <sh_list.h>
#include "sm_globals.h"
#include "sourcemod.h"
using namespace SourceHook;
namespace SourceMod
{
struct IdentityToken_t
{
Handle_t ident;
};
};
struct IfaceInfo
{
SMInterface *iface;
IdentityToken_t *token;
Handle_t handle;
};
class ShareSystem :
public IShareSys,
public SMGlobalClass,
public IHandleTypeDispatch
{
public:
ShareSystem();
public: //IShareSys
bool AddInterface(SMInterface *iface, IdentityToken_t *token);
bool RequestInterface(const char *iface_name,
unsigned int iface_vers,
IdentityToken_t *token,
SMInterface **pIface);
void AddNatives(IdentityToken_t *token, const sp_nativeinfo_t *natives[]);
IdentityType_t CreateIdentType(const char *name);
IdentityType_t FindIdentType(const char *name);
IdentityToken_t *CreateIdentity(IdentityType_t type);
void DestroyIdentType(IdentityType_t type);
void DestroyIdentity(IdentityToken_t *identity);
public: //SMGlobalClass
/* Pre-empt in case anything tries to register idents early */
void OnSourceModStartup(bool late);
void OnSourceModShutdown();
public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
public:
IdentityToken_t *CreateCoreIdentity();
public:
inline IdentityToken_t *GetIdentRoot()
{
return &m_IdentRoot;
}
private:
List<IfaceInfo> m_Interfaces;
HandleType_t m_TypeRoot;
IdentityToken_t m_IdentRoot;
HandleType_t m_IfaceType;
IdentityType_t m_CoreType;
};
extern ShareSystem g_ShareSys;
#endif //_INCLUDE_SOURCEMOD_SHARESYSTEM_H_