]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/handleobject.h
Security-29.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / handleobject.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // handleobject - give an object a process-global unique handle
21 //
22 #ifndef _H_HANDLEOBJECT
23 #define _H_HANDLEOBJECT
24
25 #include <Security/cssm.h>
26 #include <Security/utilities.h>
27 #include <Security/threading.h>
28 #include <Security/globalizer.h>
29 #include <hash_map>
30
31
32 namespace Security
33 {
34
35 //
36 // A HandledObject is a trivial mixin class whose only feature is that
37 // it has a *handle*, in the form of (currently) a CSSM_HANDLE of some kind.
38 // Subclasses need to assign such a handle during creation.
39 //
40 class HandledObject {
41 public:
42 typedef CSSM_HANDLE Handle;
43 static const Handle invalidHandle = 0;
44
45 Handle handle() const { return mMyHandle; }
46 bool validHandle() const { return mValid; }
47
48 protected:
49 HandledObject(Handle h) : mMyHandle(h), mValid(true) { }
50 HandledObject() { /*IFDEBUG(*/ mMyHandle = invalidHandle/*)*/ ; mValid = false; }
51
52 void setHandle(Handle h)
53 {
54 assert(!mValid); // guard against redefinition
55 mMyHandle = h;
56 mValid = true;
57 }
58 void clearHandle()
59 { assert(mValid); mValid = false; }
60
61 private:
62 Handle mMyHandle; // our handle value
63 bool mValid; // is the handle (still) valid?
64 };
65
66
67 //
68 // Mapping CSSM_HANDLE values to object pointers and back.
69 // A HandleObject is a HandledObject (see above) that makes up its own handle
70 // based on some mechanism that you know nothing about.
71 //
72 // Please be very careful about the limits of the object contract here.
73 // We promise to invent a suitable, unique Handle for each HandleObject in
74 // existence within one address space. We promise that if you hand that handle
75 // to the various findHandle<>() variants, we will give you back the HandleObject
76 // that created it. This is the entire contract.
77 // We *will* make some efforts to diagnose invalid handles and throw exceptions on
78 // them, but the find() operation is supposed to be *fast*, so no heroic measures
79 // will be taken.
80 //
81 class HandleObject : public HandledObject {
82 NOCOPY(HandleObject)
83 class State; friend class State;
84 template <class Subtype> friend Subtype &findHandle(CSSM_HANDLE, CSSM_RETURN);
85 template <class Subtype> friend Subtype &findHandleAndLock(CSSM_HANDLE, CSSM_RETURN);
86 template <class Subtype> friend Subtype &killHandle(CSSM_HANDLE, CSSM_RETURN);
87 public:
88 HandleObject() { state().make(this); }
89 virtual ~HandleObject() { state().erase(this); }
90
91 protected:
92 virtual void lock();
93 virtual bool tryLock();
94
95 private:
96 enum LocateMode { lockTarget, findTarget, removeTarget };
97
98 private:
99 typedef hash_map<CSSM_HANDLE, HandleObject *> HandleMap;
100 class State {
101 public:
102 State();
103 void make(HandleObject *obj);
104 HandleObject *locate(Handle h, LocateMode mode, CSSM_RETURN error);
105 void erase(HandleObject *obj);
106
107 private:
108 HandleMap handleMap;
109 uint32 sequence;
110 Mutex mLock;
111 };
112
113 static ModuleNexus<State> state;
114 };
115
116
117 //
118 // Type-specific ways to access the HandleObject map in various ways
119 //
120 template <class Subclass>
121 Subclass &findHandle(CSSM_HANDLE handle,
122 CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
123 {
124 Subclass *sub;
125 if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::findTarget, error))))
126 CssmError::throwMe(error);
127 return *sub;
128 }
129
130 template <class Subclass>
131 Subclass &findHandleAndLock(CSSM_HANDLE handle,
132 CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
133 {
134 Subclass *sub;
135 if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::lockTarget, error))))
136 CssmError::throwMe(error);
137 return *sub;
138 }
139
140 template <class Subclass>
141 Subclass &killHandle(CSSM_HANDLE handle,
142 CSSM_RETURN error = CSSMERR_CSSM_INVALID_ADDIN_HANDLE)
143 {
144 Subclass *sub;
145 if (!(sub = dynamic_cast<Subclass *>(HandleObject::state().locate(handle, HandleObject::removeTarget, error))))
146 CssmError::throwMe(error);
147 return *sub;
148 }
149
150 } // end namespace Security
151
152 #endif //_H_HANDLEOBJECT