#ifndef _H_CDSA_CLIENT_CSSMCLIENT
#define _H_CDSA_CLIENT_CSSMCLIENT 1
#include <security_utilities/threading.h>
#include <security_utilities/globalizer.h>
#include <security_utilities/refcount.h>
#include <security_cdsa_utilities/cssmalloc.h>
#include <security_cdsa_utilities/cssmpods.h>
#include <map>
namespace Security {
namespace CssmClient {
class Cssm;
class Module;
class Attachment;
class HasGuid {
public:
HasGuid(const Guid &guid) { mGuid = guid; }
HasGuid() { }
const Guid &guid() const { return mGuid; }
protected:
void setGuid(const Guid &guid) { mGuid = guid; }
private:
Guid mGuid;
};
class Error : public CssmError {
public:
Error(CSSM_RETURN err) : CssmError(err) { }
virtual const char *what () const throw();
enum {
objectBusy = -1,
};
};
class Object;
class ObjectImpl : virtual public RefCount
{
public:
explicit ObjectImpl(); explicit ObjectImpl(const Object &parent);
virtual ~ObjectImpl();
bool isActive() const { return mActive; }
virtual Allocator &allocator() const;
virtual void allocator(Allocator &alloc);
virtual bool operator <(const ObjectImpl &other) const;
virtual bool operator ==(const ObjectImpl &other) const;
static void check(CSSM_RETURN status);
bool isIdle() const { return mChildCount == 0; }
protected:
bool mActive; RecursiveMutex mActivateMutex;
mutable Allocator *mAllocator;
template <class Obj> Obj parent() const
{ assert(mParent); return Obj(static_cast<typename Obj::Impl *>(&(*mParent))); }
void addChild();
void removeChild();
virtual void activate() = 0;
virtual void deactivate() = 0;
private:
RefPointer<ObjectImpl> mParent; AtomicCounter<uint32> mChildCount;
};
class Object
{
friend class ObjectImpl;
public:
typedef ObjectImpl Impl;
explicit Object(Impl *impl) : mImpl(impl) {}
protected:
template <class _Impl> _Impl &impl() const
{ return dynamic_cast<_Impl &>(*mImpl); }
public:
Impl *operator ->() const { return &(*mImpl); }
Impl &operator *() const { return *mImpl; }
template <class _Impl> _Impl &checkedImpl() const
{ return dynamic_cast<_Impl &>(*mImpl); }
bool operator !() const { return !mImpl; }
operator bool() const { return mImpl; }
bool isActive() const { return mImpl && mImpl->isActive(); }
Allocator &allocator() const { return mImpl->allocator(); }
void release() { mImpl = NULL; }
bool operator <(const Object &other) const
{ return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl < other.mImpl; }
bool operator ==(const Object &other) const
{ return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl == other.mImpl; }
Impl* get() {return mImpl;}
private:
RefPointer<Impl> mImpl;
};
class ModuleImpl;
class RawModuleEvents {
friend class ModuleImpl;
public:
virtual ~RawModuleEvents();
virtual void notify(uint32 subService,
CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event) = 0;
private:
static CSSM_RETURN sendNotify(const CSSM_GUID *, void *context, uint32 subService,
CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event);
};
class ModuleEvents : public RawModuleEvents {
public:
virtual void insertion(uint32 subService, CSSM_SERVICE_TYPE type);
virtual void removal(uint32 subService, CSSM_SERVICE_TYPE type);
virtual void fault(uint32 subService, CSSM_SERVICE_TYPE type);
protected:
void notify(uint32 subService, CSSM_SERVICE_TYPE type, CSSM_MODULE_EVENT event);
};
class ModuleImpl : public ObjectImpl, public HasGuid
{
public:
ModuleImpl(const Guid &guid);
ModuleImpl(const Guid &guid, const Cssm &session);
virtual ~ModuleImpl();
void load() { activate(); }
void unload() { deactivate(); }
bool isLoaded() const { return isActive(); }
Cssm session() const;
void appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx);
void appNotifyCallback(RawModuleEvents *handler);
protected:
void activate();
void deactivate();
CSSM_API_ModuleEventHandler mAppNotifyCallback;
void *mAppNotifyCallbackCtx;
};
class Module : public Object
{
public:
typedef ModuleImpl Impl;
explicit Module(Impl *impl) : Object(impl) {}
Module() : Object(NULL) {} Module(const Guid &guid) : Object(new Impl(guid)) {}
Module(const Guid &guid, const Cssm &session) : Object(new Impl(guid, session)) {}
Impl *operator ->() const { return &impl<Impl>(); }
Impl &operator *() const { return impl<Impl>(); }
};
class AttachmentImpl : public ObjectImpl
{
public:
AttachmentImpl(const Guid &guid, CSSM_SERVICE_TYPE subserviceType);
AttachmentImpl(const Module &module, CSSM_SERVICE_TYPE subserviceType);
virtual ~AttachmentImpl();
virtual CSSM_SERVICE_MASK subserviceMask() const;
CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; }
CSSM_VERSION version() const { return mVersion; }
void version(const CSSM_VERSION &v) { mVersion = v; }
uint32 subserviceId() const { return mSubserviceId; }
virtual void subserviceId(uint32 id);
CSSM_ATTACH_FLAGS flags() const { return mAttachFlags; }
void flags(CSSM_ATTACH_FLAGS f) { mAttachFlags = f; }
void attach() { activate(); }
void detach() { deactivate(); }
bool attached() const { return isActive(); }
Module module() const;
const Guid &guid() const { return module()->guid(); }
CSSM_MODULE_HANDLE handle() { attach(); return mHandle; }
CssmSubserviceUid subserviceUid() const;
protected:
void activate();
void deactivate();
private:
void make(CSSM_SERVICE_TYPE subserviceType);
CSSM_MODULE_HANDLE mHandle;
CSSM_SERVICE_TYPE mSubserviceType; CSSM_VERSION mVersion;
uint32 mSubserviceId;
CSSM_ATTACH_FLAGS mAttachFlags;
CssmAllocatorMemoryFunctions mMemoryFunctions; };
class Attachment : public Object
{
public:
typedef AttachmentImpl Impl;
explicit Attachment(Impl *impl) : Object(impl) {}
Attachment(const Guid &guid, CSSM_SERVICE_TYPE subserviceType)
: Object(new Impl(guid, subserviceType)) {}
Attachment(const Module &module, CSSM_SERVICE_TYPE subserviceType)
: Object(new Impl(module, subserviceType)) {}
Impl *operator ->() const { return &impl<Impl>(); }
Impl &operator *() const { return impl<Impl>(); }
};
class Cssm;
class CssmImpl : public ObjectImpl {
class StandardCssm; friend class StandardCssm;
public:
CssmImpl();
virtual ~CssmImpl();
void init() { activate(); }
void terminate() { deactivate(); }
CSSM_PRIVILEGE_SCOPE scope() const { return mScope; }
void scope(CSSM_PRIVILEGE_SCOPE sc) { mScope = sc; }
const Guid &callerGuid() const { return mCallerGuid; }
void callerGuid(const CSSM_GUID &guid) { mCallerGuid = Guid::overlay(guid); }
Module autoModule(const Guid &guid);
protected:
explicit CssmImpl(bool);
void setup();
void activate();
void deactivate();
private:
CSSM_VERSION mVersion;
CSSM_PRIVILEGE_SCOPE mScope;
Guid mCallerGuid;
typedef map<Guid, Module> ModuleMap;
ModuleMap moduleMap;
Mutex mapLock;
public:
static Cssm standard();
static void catchExit();
private:
static void atExitHandler();
class StandardCssm : public Mutex {
public:
StandardCssm() : mCssm(NULL) { }
~StandardCssm();
void setCssm(CssmImpl *cssm);
void unsetCssm(CssmImpl *cssm);
Cssm get();
private:
RefPointer<CssmImpl> mCssm; };
static ModuleNexus<StandardCssm> mStandard;
};
class Cssm : public Object
{
public:
typedef CssmImpl Impl;
explicit Cssm(Impl *impl) : Object(impl) {}
explicit Cssm() : Object(new Impl()) {}
Impl *operator ->() const { return &impl<Impl>(); }
Impl &operator *() const { return impl<Impl>(); }
static Cssm standard() { return CssmImpl::standard(); }
};
}
}
#endif // _H_CDSA_CLIENT_CSSMCLIENT