]>
git.saurik.com Git - apple/securityd.git/blob - src/structure.h
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // structure - structural framework for securityd objects
31 #include <security_utilities/refcount.h>
32 #include <security_utilities/mach++.h>
33 #include <security_cdsa_utilities/handleobject.h>
36 using MachPlusPlus::Port
;
40 // Track a per-process real world object
42 template <class Base
, class Glob
> class Node
;
50 // A generic core node of the object mesh.
51 // Repeat after me: "Everything that matters is a Node."
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
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.
68 // Do not inherit directly from NodeCore; use Node<> (below).
70 class NodeCore
: public RefCount
, public Mutex
{
71 template <class Base
, class Glob
> friend class Node
;
73 #if !defined(DEBUGDUMP) // (see below if DEBUGDUMP)
74 NodeCore() : Mutex(Mutex::recursive
) { }
78 void addReference(NodeCore
&p
);
79 void removeReference(NodeCore
&p
);
81 // reference set operations
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();
88 virtual void kill(); // kill all references and self
89 virtual void kill(NodeCore
&ref
); // kill ref from my references()
91 // for STL ordering (so we can have sets of RefPointers of NodeCores)
92 bool operator < (const NodeCore
&other
) const
93 { return this < &other
; }
96 void parent(NodeCore
&p
); // set parent
97 void referent(NodeCore
&r
); // set referent
98 void clearReferent(); // clear referent
100 bool hasParent() const { return mParent
; }
101 bool hasReferent() const { return mReferent
; }
104 RefPointer
<NodeCore
> mParent
;
105 RefPointer
<NodeCore
> mReferent
;
106 typedef set
<RefPointer
<NodeCore
> > ReferenceSet
;
107 ReferenceSet mReferences
;
109 IFDEBUG(bool hasReference(NodeCore
&p
));
111 #if defined(DEBUGDUMP)
112 public: // dump support
113 NodeCore(); // dump-only constructor (registers node)
115 virtual void dumpNode(); // node description (partial line)
116 virtual void dump(); // dumpNode() + references + NL
117 static void dumpAll(); // dump all nodes
119 static Mutex mCoreLock
; // lock for mCoreNodes
120 static set
<NodeCore
*> mCoreNodes
; // (debug) set of all known nodes
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.
132 void NodeCore::allReferences(void (Sub::*func
)())
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()))
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.
148 template <class Sub
, class Value
>
149 RefPointer
<Sub
> NodeCore::findFirst(Value (Sub::*func
)() const, Value compare
)
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
)
161 // A typed node of the object mesh.
162 // This adds type-safe accessors and modifiers to NodeCore.
164 template <class Base
, class Glob
>
165 class Node
: public NodeCore
{
167 // type-safer versions of node mesh setters
168 void parent(Glob
&p
) { NodeCore::parent(p
); }
169 void referent(Base
&r
) { NodeCore::referent(r
); }
174 { assert(mParent
); return safer_cast
<T
&>(*mParent
); }
178 { assert(mReferent
); return safer_cast
<T
&>(*mReferent
); }
181 void addReference(Base
&p
) { NodeCore::addReference(p
); }
182 void removeReference(Base
&p
) { NodeCore::removeReference(p
); }
187 // Connection (client thread) layer nodes
189 class PerConnection
: public Node
<PerConnection
, PerProcess
> {
195 // Process (client process) layer nodes
197 class PerProcess
: public HandleObject
, public Node
<PerProcess
, PerSession
> {
203 // Session (client-side session) layer nodes
205 class PerSession
: public Node
<PerSession
, PerGlobal
> {
211 // Global (per-system) layer nodes
213 class PerGlobal
: public Node
<PerGlobal
, PerGlobal
> {
219 // A map from mach port names to (refcounted) pointers-to-somethings
221 template <class Node
>
222 class PortMap
: public Mutex
, public std::map
<Port
, RefPointer
<Node
> > {
223 typedef std::map
<Port
, RefPointer
<Node
> > _Map
;
225 bool contains(mach_port_t port
) const { return this->find(port
) != this->end(); }
226 Node
*getOpt(mach_port_t port
) const
228 typename
_Map::const_iterator it
= this->find(port
);
229 return (it
== this->end()) ? NULL
: it
->second
;
232 Node
*get(mach_port_t port
) const
234 typename
_Map::const_iterator it
= this->find(port
);
235 assert(it
!= this->end());
239 Node
*get(mach_port_t port
, OSStatus error
) const
241 typename
_Map::const_iterator it
= this->find(port
);
242 if (it
== this->end())
243 MacOSError::throwMe(error
);
250 template <class Node
>
251 void PortMap
<Node
>::dump()
253 for (typename
_Map::const_iterator it
= this->begin(); it
!= this->end(); it
++)
258 #endif //_H_STRUCTURE