sourcemod/core/systems/ShareSys.cpp
David Anderson efd3a8ab5f Handle system can now unload identities safely. when an identity is removed, all handles owned by it are removed in a chain.
--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40288
2007-01-11 07:29:09 +00:00

205 lines
4.3 KiB
C++

#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)
{
TypeAccess sec;
g_HandleSys.InitAccessDefaults(&sec, NULL);
sec.ident = GetIdentRoot();
m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
/* Initialize our static identity handle */
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), 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.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
}
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
{
/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
}
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type)
{
if (!m_TypeRoot)
{
return 0;
}
/* :TODO: Cache? */
IdentityToken_t *pToken = new IdentityToken_t;
pToken->ident = g_HandleSys.CreateHandleEx(type, NULL, GetIdentRoot(), GetIdentRoot(), NULL, true);
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(), NULL);
} 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>
*/
HandleSecurity sec;
sec.pIdentity = GetIdentRoot();
sec.pOwner = NULL;
if (!g_HandleSys.ReadHandle(token->ident, m_TypeRoot, &sec, 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, &sec)
!= 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)
{
HandleSecurity sec;
sec.pOwner = GetIdentRoot();
sec.pIdentity = GetIdentRoot();
g_HandleSys.FreeHandle(identity->ident, &sec);
delete identity;
}
void ShareSystem::DestroyIdentType(IdentityType_t type)
{
g_HandleSys.RemoveType(type, GetIdentRoot());
}