]> git.saurik.com Git - apple/securityd.git/blob - src/notifications.cpp
securityd-30557.tar.gz
[apple/securityd.git] / src / notifications.cpp
1 /*
2 * Copyright (c) 2000-2004 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 // EntropyManager - manage entropy on the system.
27 //
28 #include "notifications.h"
29 #include "server.h"
30 #include <securityd_client/ucspNotify.h>
31
32 Listener::ListenerMap Listener::listeners;
33 Mutex Listener::setLock;
34
35
36 Listener::Listener(Port port, NotificationDomain dom, NotificationMask evs)
37 : domain(dom), events(evs), mPort(port)
38 { setup(); }
39
40 Listener::Listener(NotificationDomain dom, NotificationMask evs)
41 : domain(dom), events(evs)
42 { setup(); }
43
44 void Listener::setup()
45 {
46 assert(events); // what's the point?
47
48 // register in listener set
49 StLock<Mutex> _(setLock);
50 listeners.insert(ListenerMap::value_type(mPort, this));
51 }
52
53 Listener::~Listener()
54 {
55 secdebug("notify", "%p destroyed", this);
56 }
57
58
59 //
60 // Send a notification to all registered listeners
61 //
62 void Listener::notify(NotificationDomain domain,
63 NotificationEvent event, const CssmData &data)
64 {
65 for (ListenerMap::const_iterator it = listeners.begin();
66 it != listeners.end(); it++) {
67 Listener *listener = it->second;
68 if (listener->domain == domain && listener->wants(event))
69 listener->notifyMe(domain, event, data);
70 }
71 }
72
73
74 //
75 // Handle a port death or deallocation by removing all Listeners using that port.
76 // Returns true iff we had one.
77 //
78 bool Listener::remove(Port port)
79 {
80 assert(port); // Listeners with null ports are eternal
81 typedef ListenerMap::iterator Iterator;
82 StLock<Mutex> _(setLock);
83 pair<Iterator, Iterator> range = listeners.equal_range(port);
84 if (range.first == range.second)
85 return false; // not one of ours
86
87 for (Iterator it = range.first; it != range.second; it++)
88 delete it->second;
89 listeners.erase(range.first, range.second);
90 port.destroy();
91 return true; // got it
92 }
93
94
95 //
96 // Construct a new Listener and hook it up
97 //
98 ProcessListener::ProcessListener(Process &proc, Port receiver,
99 NotificationDomain dom, NotificationMask evs)
100 : Listener(receiver, dom, evs), process(proc)
101 {
102 // let's get told when the receiver port dies
103 Server::active().notifyIfDead(mPort);
104
105 secdebug("notify", "%p created domain %ld events 0x%lx port %d",
106 this, domain, events, mPort.port());
107 }
108
109
110 //
111 // Send a single notification for this listener
112 //
113 void ProcessListener::notifyMe(NotificationDomain domain,
114 NotificationEvent event, const CssmData &data)
115 {
116 secdebug("notify", "%p sending domain %ld event 0x%lx to port %d process %d",
117 this, domain, event, mPort.port(), process.pid());
118
119 // send mach message (via MIG simpleroutine)
120 if (IFDEBUG(kern_return_t rc =) ucsp_notify_sender_notify(mPort,
121 domain, event, data.data(), data.length(),
122 0 /*@@@ placeholder for sender ID */))
123 secdebug("notify", "%p send failed (error=%d)", this, rc);
124 }