/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ // // structure - structural framework for securityd objects // #ifndef _H_STRUCTURE #define _H_STRUCTURE #include "securityserver.h" #include #include // // Track a per-process real world object // template class Node; class PerConnection; class PerProcess; class PerSession; class PerGlobal; // // A generic core node of the object mesh. // Repeat after me: "Everything that matters is a Node." // // This contains the mesh links (as smart pointers to NodeCores). // The 'parent' is the next-more-global related object in the mesh, if any; // nodes with the same parent "belong together" at the more global layer. // For example, processes have their sessions as parents. // The 'referent' is an object at the *same* globality layer that controls // the lifetime of this node. For example, a Database has its Process as // its referent. // Both parent and referent are optional (can be NULL). // The references set is a partial referent back-link. All NodeCores listed // in a node's References have this node as a referent, but the set is // selective (not necessarily complete). The References set propagates the // 'kill' operation up the referents chain; thus being included in a node's // References means that a kill() on the referent will (recursively) kill // all references, too. // // Do not inherit directly from NodeCore; use Node<> (below). // class NodeCore : public RefCount, public Mutex { template friend class Node; public: #if !defined(DEBUGDUMP) // (see below if DEBUGDUMP) NodeCore() : Mutex(Mutex::recursive) { } #endif virtual ~NodeCore(); bool hasParent() const { return mParent; } bool hasReferent() const { return mReferent; } // reference set operations template void allReferences(void (Sub::*func)()); template Sub *findFirst(Value (Sub::*func)() const, Value compare); void clearReferences(); virtual void kill(); // always invoke NodeCore's in your override // for STL ordering (so we can have sets of RefPointers of NodeCores) bool operator < (const NodeCore &other) const { return this < &other; } private: RefPointer mParent; RefPointer mReferent; typedef set > ReferenceSet; ReferenceSet mReferences; #if defined(DEBUGDUMP) public: // dump support NodeCore(); // dump-only constructor (registers node) virtual void dumpNode(); // node description (partial line) virtual void dump(); // dumpNode() + references + NL static void dumpAll(); // dump all nodes static Mutex mCoreLock; // lock for mCoreNodes static set mCoreNodes; // (debug) set of all known nodes #endif //DEBUGDUMP }; template void NodeCore::allReferences(void (Sub::*func)()) { StLock _(*this); for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) if (Sub *sub = dynamic_cast(it->get())) (sub->*func)(); } template Sub *NodeCore::findFirst(Value (Sub::*func)() const, Value compare) { StLock _(*this); for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) if (Sub *sub = dynamic_cast(it->get())) if ((sub->*func)() == compare) return sub; return NULL; } // // A typed node of the object mesh. // This adds type-safe accessors and modifiers to NodeCore. // template class Node : public NodeCore { protected: void parent(Glob &p) { StLock _(*this); mParent = &p; } virtual void referent(Base &r) { StLock _(*this); mReferent = &r; } void clearReferent() { StLock _(*this); mReferent = NULL; } public: template T& parent() const { assert(mParent); return safer_cast(*mParent); } template T& referent() const { assert(mReferent); return safer_cast(*mReferent); } public: void addReference(Base &p) { StLock _(*this); assert(p.mReferent == this); mReferences.insert(&p); } void removeReference(Base &p) { StLock _(*this); mReferences.erase(&p); } }; // // Connection (client thread) layer nodes // class PerConnection : public Node { public: }; // // Process (client process) layer nodes // class PerProcess : public HandleObject, public Node { public: }; // // Session (client-side session) layer nodes // class PerSession : public Node { public: }; // // Global (per-system) layer nodes // class PerGlobal : public Node { public: }; // // A map from mach port names to (refcounted) pointers-to-somethings // template class PortMap : public Mutex, public std::map > { typedef std::map > _Map; public: bool contains(mach_port_t port) const { return find(port) != end(); } Node *getOpt(mach_port_t port) const { typename _Map::const_iterator it = find(port); return (it == end()) ? NULL : it->second; } Node *get(mach_port_t port) const { typename _Map::const_iterator it = find(port); assert(it != end()); return it->second; } Node *get(mach_port_t port, OSStatus error) const { typename _Map::const_iterator it = find(port); if (it == end()) MacOSError::throwMe(error); return it->second; } void dump(); }; template void PortMap::dump() { for (typename _Map::const_iterator it = begin(); it != end(); it++) it->second->dump(); } #endif //_H_STRUCTURE