]> git.saurik.com Git - apple/securityd.git/blob - src/structure.h
securityd-27887.tar.gz
[apple/securityd.git] / src / structure.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // structure - structural framework for securityd objects
27 //
28 #ifndef _H_STRUCTURE
29 #define _H_STRUCTURE
30
31 #include <security_utilities/refcount.h>
32 #include <security_utilities/mach++.h>
33 #include <security_cdsa_utilities/handleobject.h>
34 #include <map>
35
36 using MachPlusPlus::Port;
37
38
39 //
40 // Track a per-process real world object
41 //
42 template <class Base, class Glob> class Node;
43 class PerConnection;
44 class PerProcess;
45 class PerSession;
46 class PerGlobal;
47
48
49 //
50 // A generic core node of the object mesh.
51 // Repeat after me: "Everything that matters is a Node."
52 //
53 // This contains the mesh links (as smart pointers to NodeCores).
54 // The 'parent' is the next-more-global related object in the mesh, if any;
55 // nodes with the same parent "belong together" at the more global layer.
56 // For example, processes have their sessions as parents.
57 // The 'referent' is an object at the *same* globality layer that controls
58 // the lifetime of this node. For example, a Database has its Process as
59 // its referent.
60 // Both parent and referent are optional (can be NULL).
61 // The references set is a partial referent back-link. All NodeCores listed
62 // in a node's References have this node as a referent, but the set is
63 // selective (not necessarily complete). The References set propagates the
64 // 'kill' operation up the referents chain; thus being included in a node's
65 // References means that a kill() on the referent will (recursively) kill
66 // all references, too.
67 //
68 // Do not inherit directly from NodeCore; use Node<> (below).
69 //
70 class NodeCore : public RefCount, public Mutex {
71 template <class Base, class Glob> friend class Node;
72 public:
73 #if !defined(DEBUGDUMP) // (see below if DEBUGDUMP)
74 NodeCore() : Mutex(Mutex::recursive) { }
75 #endif
76 virtual ~NodeCore();
77
78 void addReference(NodeCore &p);
79 void removeReference(NodeCore &p);
80
81 // reference set operations
82 template <class Sub>
83 void allReferences(void (Sub::*func)());
84 template <class Sub, class Value>
85 RefPointer<Sub> findFirst(Value (Sub::*func)() const, Value compare);
86 void clearReferences();
87
88 virtual void kill(); // kill all references and self
89 virtual void kill(NodeCore &ref); // kill ref from my references()
90
91 // for STL ordering (so we can have sets of RefPointers of NodeCores)
92 bool operator < (const NodeCore &other) const
93 { return this < &other; }
94
95 protected:
96 void parent(NodeCore &p); // set parent
97 void referent(NodeCore &r); // set referent
98 void clearReferent(); // clear referent
99
100 bool hasParent() const { return mParent; }
101 bool hasReferent() const { return mReferent; }
102
103 private:
104 RefPointer<NodeCore> mParent;
105 RefPointer<NodeCore> mReferent;
106 typedef set<RefPointer<NodeCore> > ReferenceSet;
107 ReferenceSet mReferences;
108
109 IFDEBUG(bool hasReference(NodeCore &p));
110
111 #if defined(DEBUGDUMP)
112 public: // dump support
113 NodeCore(); // dump-only constructor (registers node)
114
115 virtual void dumpNode(); // node description (partial line)
116 virtual void dump(); // dumpNode() + references + NL
117 static void dumpAll(); // dump all nodes
118
119 static Mutex mCoreLock; // lock for mCoreNodes
120 static set<NodeCore *> mCoreNodes; // (debug) set of all known nodes
121 #endif //DEBUGDUMP
122 };
123
124
125 //
126 // Call a member on each reference of a Node<> object.
127 // The object lock is held throughout, and we keep a RefPointer to each object
128 // as it's being processed. Thus it's safe for a reference to self-unlink in
129 // the object mesh; it'll get destroyed after its method returns.
130 //
131 template <class Sub>
132 void NodeCore::allReferences(void (Sub::*func)())
133 {
134 StLock<Mutex> _(*this);
135 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end();)
136 if (RefPointer<Sub> sub = dynamic_cast<Sub *>((it++)->get()))
137 (sub->*func)();
138 }
139
140
141 //
142 // Find a reference of a Node<> object that satisfies a simple "method returns value"
143 // condition. There is no defined order of the scan, so if the condition is not unique,
144 // any one reference may be returned. If none are found, we return NULL.
145 // This returns a RefPointer: lifetime of the returned instance (if any) is ensured even
146 // if it is asynchronously removed from the references set.
147 //
148 template <class Sub, class Value>
149 RefPointer<Sub> NodeCore::findFirst(Value (Sub::*func)() const, Value compare)
150 {
151 StLock<Mutex> _(*this);
152 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++)
153 if (Sub *sub = dynamic_cast<Sub *>(it->get()))
154 if ((sub->*func)() == compare)
155 return sub;
156 return NULL;
157 }
158
159
160 //
161 // A typed node of the object mesh.
162 // This adds type-safe accessors and modifiers to NodeCore.
163 //
164 template <class Base, class Glob>
165 class Node : public NodeCore {
166 protected:
167 // type-safer versions of node mesh setters
168 void parent(Glob &p) { NodeCore::parent(p); }
169 void referent(Base &r) { NodeCore::referent(r); }
170
171 public:
172 template <class T>
173 T& parent() const
174 { assert(mParent); return safer_cast<T &>(*mParent); }
175
176 template <class T>
177 T& referent() const
178 { assert(mReferent); return safer_cast<T &>(*mReferent); }
179
180 public:
181 void addReference(Base &p) { NodeCore::addReference(p); }
182 void removeReference(Base &p) { NodeCore::removeReference(p); }
183 };
184
185
186 //
187 // Connection (client thread) layer nodes
188 //
189 class PerConnection : public Node<PerConnection, PerProcess> {
190 public:
191 };
192
193
194 //
195 // Process (client process) layer nodes
196 //
197 class PerProcess : public HandleObject, public Node<PerProcess, PerSession> {
198 public:
199 };
200
201
202 //
203 // Session (client-side session) layer nodes
204 //
205 class PerSession : public Node<PerSession, PerGlobal> {
206 public:
207 };
208
209
210 //
211 // Global (per-system) layer nodes
212 //
213 class PerGlobal : public Node<PerGlobal, PerGlobal> {
214 public:
215 };
216
217
218 //
219 // A map from mach port names to (refcounted) pointers-to-somethings
220 //
221 template <class Node>
222 class PortMap : public Mutex, public std::map<Port, RefPointer<Node> > {
223 typedef std::map<Port, RefPointer<Node> > _Map;
224 public:
225 bool contains(mach_port_t port) const { return find(port) != end(); }
226 Node *getOpt(mach_port_t port) const
227 {
228 typename _Map::const_iterator it = find(port);
229 return (it == end()) ? NULL : it->second;
230 }
231
232 Node *get(mach_port_t port) const
233 {
234 typename _Map::const_iterator it = find(port);
235 assert(it != end());
236 return it->second;
237 }
238
239 Node *get(mach_port_t port, OSStatus error) const
240 {
241 typename _Map::const_iterator it = find(port);
242 if (it == end())
243 MacOSError::throwMe(error);
244 return it->second;
245 }
246
247 void dump();
248 };
249
250 template <class Node>
251 void PortMap<Node>::dump()
252 {
253 for (typename _Map::const_iterator it = begin(); it != end(); it++)
254 it->second->dump();
255 }
256
257
258 #endif //_H_STRUCTURE