#include "notifications.h"
#include "server.h"
#include <securityd_client/ucspNotify.h>
Listener::ListenerMap Listener::listeners;
Mutex Listener::setLock;
Listener::Listener(Port port, NotificationDomain dom, NotificationMask evs)
: domain(dom), events(evs), mPort(port)
{ setup(); }
Listener::Listener(NotificationDomain dom, NotificationMask evs)
: domain(dom), events(evs)
{ setup(); }
void Listener::setup()
{
assert(events);
StLock<Mutex> _(setLock);
listeners.insert(ListenerMap::value_type(mPort, this));
}
Listener::~Listener()
{
secdebug("notify", "%p destroyed", this);
}
void Listener::notify(NotificationDomain domain,
NotificationEvent event, const CssmData &data)
{
for (ListenerMap::const_iterator it = listeners.begin();
it != listeners.end(); it++) {
Listener *listener = it->second;
if (listener->domain == domain && listener->wants(event))
listener->notifyMe(domain, event, data);
}
}
bool Listener::remove(Port port)
{
assert(port); typedef ListenerMap::iterator Iterator;
StLock<Mutex> _(setLock);
pair<Iterator, Iterator> range = listeners.equal_range(port);
if (range.first == range.second)
return false;
for (Iterator it = range.first; it != range.second; it++)
delete it->second;
listeners.erase(range.first, range.second);
port.destroy();
return true; }
ProcessListener::ProcessListener(Process &proc, Port receiver,
NotificationDomain dom, NotificationMask evs)
: Listener(receiver, dom, evs), process(proc)
{
Server::active().notifyIfDead(mPort);
secdebug("notify", "%p created domain %ld events 0x%lx port %d",
this, domain, events, mPort.port());
}
void ProcessListener::notifyMe(NotificationDomain domain,
NotificationEvent event, const CssmData &data)
{
secdebug("notify", "%p sending domain %ld event 0x%lx to port %d process %d",
this, domain, event, mPort.port(), process.pid());
if (IFDEBUG(kern_return_t rc =) ucsp_notify_sender_notify(mPort,
domain, event, data.data(), data.length(),
0 ))
secdebug("notify", "%p send failed (error=%d)", this, rc);
}