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