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// notifications - handling of securityd-gated notification messages
27//
28#ifndef _H_NOTIFICATIONS
29#define _H_NOTIFICATIONS
30
31#include <security_utilities/mach++.h>
32#include <security_utilities/machserver.h>
33#include <security_utilities/globalizer.h>
34#include <securityd_client/ssclient.h>
35#include <map>
36#include <queue>
37
38#include "SharedMemoryServer.h"
39
40using MachPlusPlus::Port;
41using MachPlusPlus::MachServer;
42using SecurityServer::NotificationDomain;
43using SecurityServer::NotificationEvent;
44using SecurityServer::NotificationMask;
45
46class SharedMemoryListener;
47
48//
49// A registered receiver of notifications.
50// This is an abstract class; you must subclass to define notifyMe().
51//
52// All Listeners in existence are collected in an internal map of ports to
53// Listener*s, which makes them eligible to have events delivered to them via
54// their notifyMe() method. There are (only) two viable lifetime management
55// strategies for your Listener subclass:
56// (1) Eternal: don't ever destroy your Listener. All is well. By convention,
57// such Listeners use the null port.
58// (2) Port-based: To get rid of your Listeners, call Listener::remove(port),
59// which will delete(!) all Listeners constructed with that port.
60// Except for the remove() functionality, Listener does not interpret the port.
61//
62// If you need another Listener lifetime management strategy, you will probably
63// have to change things around here.
64//
65class Listener: public RefCount {
66public:
67	Listener(NotificationDomain domain, NotificationMask events,
68		mach_port_t port = MACH_PORT_NULL);
69	virtual ~Listener();
70
71	// inject an event into the notification system
72    static void notify(NotificationDomain domain,
73		NotificationEvent event, const CssmData &data);
74    static void notify(NotificationDomain domain,
75		NotificationEvent event, uint32 sequence, const CssmData &data);
76    static bool remove(Port port);
77
78    const NotificationDomain domain;
79    const NotificationMask events;
80
81	bool wants(NotificationEvent event)
82	{ return (1 << event) & events; }
83
84protected:
85	class Notification : public RefCount {
86	public:
87		Notification(NotificationDomain domain, NotificationEvent event,
88			uint32 seq, const CssmData &data);
89		virtual ~Notification();
90
91		const NotificationDomain domain;
92		const NotificationEvent event;
93		const uint32 sequence;
94		const CssmAutoData data;
95
96		size_t size() const
97		{ return data.length(); }	//@@@ add "slop" here for heuristic?
98	};
99
100	virtual void notifyMe(Notification *message) = 0;
101
102public:
103	class JitterBuffer {
104	public:
105		JitterBuffer() : mNotifyLast(0) { }
106
107		bool inSequence(Notification *message);
108		RefPointer<Notification> popNotification();
109
110	private:
111		uint32 mNotifyLast;		// last notification seq processed
112		typedef std::map<uint32, RefPointer<Notification> > JBuffer;
113		JBuffer mBuffer;		// early messages buffer
114	};
115
116private:
117	static void sendNotification(Notification *message);
118
119private:
120    typedef multimap<mach_port_t, RefPointer<Listener> > ListenerMap;
121    static ListenerMap& listeners;
122    static Mutex setLock;
123};
124
125
126
127class SharedMemoryListener : public Listener, public SharedMemoryServer, public Security::MachPlusPlus::MachServer::Timer
128{
129protected:
130	virtual void action ();
131	virtual void notifyMe(Notification *message);
132
133	bool mActive;
134
135public:
136	SharedMemoryListener (const char* serverName, u_int32_t serverSize);
137	virtual ~SharedMemoryListener ();
138};
139
140#endif
141