#ifndef _H_CDSA_CLIENT_CSSMCLIENT
#define _H_CDSA_CLIENT_CSSMCLIENT 1
#include <Security/utilities.h>
#include <Security/threading.h>
#include <Security/globalizer.h>
#include <Security/cssmalloc.h>
#include <Security/refcount.h>
#include <map>
#include <stdio.h> // debug
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(int err) : CssmError(err) { }
CSSM_RETURN cssmError() const;
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 CssmAllocator &allocator() const;
virtual void allocator(CssmAllocator &alloc);
virtual bool operator <(const ObjectImpl &other) const;
virtual bool operator ==(const ObjectImpl &other) const;
static void check(CSSM_RETURN status);
protected:
bool mActive; mutable CssmAllocator *mAllocator;
template <class Obj> Obj parent() const
{ assert(mParent); return Obj(static_cast<typename Obj::Impl *>(&(*mParent))); }
void addChild();
void removeChild();
bool isIdle() const { return mChildCount == 0; }
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(); }
CssmAllocator &allocator() const { return mImpl->allocator(); }
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; }
private:
RefPointer<Impl> mImpl;
};
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;
protected:
void activate();
void deactivate();
};
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);
CssmImpl *get();
private:
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