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