]> git.saurik.com Git - apple/securityd.git/blob - src/notifications.cpp
2224dd96564b0f93e2200b73d7c39cfe6de81760
[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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // EntropyManager - manage entropy on the system.
29 //
30 #include "notifications.h"
31 #include "server.h"
32 #include <securityd_client/ucspNotify.h>
33
34
35 Listener::ListenerMap Listener::listeners;
36 Mutex Listener::setLock;
37
38
39 Listener::Listener(Port port, NotificationDomain dom, NotificationMask evs)
40 : domain(dom), events(evs), mPort(port)
41 { setup(); }
42
43 Listener::Listener(NotificationDomain dom, NotificationMask evs)
44 : domain(dom), events(evs)
45 { setup(); }
46
47 void Listener::setup()
48 {
49 assert(events); // what's the point?
50
51 // register in listener set
52 StLock<Mutex> _(setLock);
53 listeners.insert(ListenerMap::value_type(mPort, this));
54 }
55
56 Listener::~Listener()
57 {
58 secdebug("notify", "%p destroyed", this);
59 }
60
61
62 //
63 // Send a notification to all registered listeners
64 //
65 void Listener::notify(NotificationDomain domain,
66 NotificationEvent event, const CssmData &data)
67 {
68 for (ListenerMap::const_iterator it = listeners.begin();
69 it != listeners.end(); it++) {
70 Listener *listener = it->second;
71 if (listener->domain == domain && listener->wants(event))
72 listener->notifyMe(domain, event, data);
73 }
74 }
75
76
77 //
78 // Handle a port death or deallocation by removing all Listeners using that port.
79 // Returns true iff we had one.
80 //
81 bool Listener::remove(Port port)
82 {
83 assert(port); // Listeners with null ports are eternal
84 typedef ListenerMap::iterator Iterator;
85 StLock<Mutex> _(setLock);
86 pair<Iterator, Iterator> range = listeners.equal_range(port);
87 if (range.first == range.second)
88 return false; // not one of ours
89
90 for (Iterator it = range.first; it != range.second; it++)
91 delete it->second;
92 listeners.erase(range.first, range.second);
93 port.destroy();
94 return true; // got it
95 }
96
97
98 //
99 // Construct a new Listener and hook it up
100 //
101 ProcessListener::ProcessListener(Process &proc, Port receiver,
102 NotificationDomain dom, NotificationMask evs)
103 : Listener(receiver, dom, evs), process(proc)
104 {
105 // let's get told when the receiver port dies
106 Server::active().notifyIfDead(mPort);
107
108 secdebug("notify", "%p created domain %ld events 0x%lx port %d",
109 this, domain, events, mPort.port());
110 }
111
112
113 //
114 // Send a single notification for this listener
115 //
116 void ProcessListener::notifyMe(NotificationDomain domain,
117 NotificationEvent event, const CssmData &data)
118 {
119 secdebug("notify", "%p sending domain %ld event 0x%lx to port %d process %d",
120 this, domain, event, mPort.port(), process.pid());
121
122 // send mach message (via MIG simpleroutine)
123 if (IFDEBUG(kern_return_t rc =) ucsp_notify_sender_notify(mPort,
124 MACH_SEND_TIMEOUT, 0,
125 domain, event, data.data(), data.length(),
126 0 /*@@@ placeholder for sender ID */))
127 secdebug("notify", "%p send failed (error=%d)", this, rc);
128 }