1/*
2 * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6/*! Provides the networking stack notification service. */
7
8#include <net_notifications.h>
9
10#include <generic_syscall.h>
11#include <Notifications.h>
12#include <util/KMessage.h>
13
14//#define TRACE_NOTIFICATIONS
15#ifdef TRACE_NOTIFICATIONS
16#	define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x)
17#else
18#	define TRACE(x...) ;
19#endif
20
21
22class NetNotificationService : public DefaultUserNotificationService {
23public:
24							NetNotificationService();
25	virtual					~NetNotificationService();
26
27			void			Notify(const KMessage& event);
28
29protected:
30	virtual	void			FirstAdded();
31	virtual	void			LastRemoved();
32};
33
34static NetNotificationService sNotificationService;
35
36
37//	#pragma mark - NetNotificationService
38
39
40NetNotificationService::NetNotificationService()
41	: DefaultUserNotificationService("network")
42{
43}
44
45
46NetNotificationService::~NetNotificationService()
47{
48}
49
50
51void
52NetNotificationService::Notify(const KMessage& event)
53{
54	uint32 opcode = event.GetInt32("opcode", 0);
55	if (opcode == 0)
56		return;
57
58	TRACE("notify for %lx\n", opcode);
59
60	DefaultUserNotificationService::Notify(event, opcode);
61}
62
63
64void
65NetNotificationService::FirstAdded()
66{
67	// The reference counting doesn't work for us, as we'll have to
68	// ensure our module stays loaded.
69	module_info* dummy;
70	get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
71}
72
73
74void
75NetNotificationService::LastRemoved()
76{
77	// Give up the reference _AddListener()
78	put_module(NET_NOTIFICATIONS_MODULE_NAME);
79}
80
81
82//	#pragma mark - User generic syscall
83
84
85static status_t
86net_notifications_control(const char *subsystem, uint32 function, void *buffer,
87	size_t bufferSize)
88{
89	struct net_notifications_control control;
90	if (bufferSize != sizeof(struct net_notifications_control)
91		|| function != NET_NOTIFICATIONS_CONTROL_WATCHING)
92		return B_BAD_VALUE;
93	if (user_memcpy(&control, buffer,
94			sizeof(struct net_notifications_control)) < B_OK)
95		return B_BAD_ADDRESS;
96
97	if (control.flags != 0) {
98		return sNotificationService.UpdateUserListener(control.flags,
99			control.port, control.token);
100	}
101
102	return sNotificationService.RemoveUserListeners(control.port,
103		control.token);
104}
105
106
107//	#pragma mark - exported module API
108
109
110static status_t
111send_notification(const KMessage* event)
112{
113	sNotificationService.Notify(*event);
114	return B_OK;
115}
116
117
118static status_t
119notifications_std_ops(int32 op, ...)
120{
121	switch (op) {
122		case B_MODULE_INIT:
123			TRACE("init\n");
124
125			new(&sNotificationService) NetNotificationService();
126
127			register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
128				net_notifications_control, 1, 0);
129			return B_OK;
130
131		case B_MODULE_UNINIT:
132			TRACE("uninit\n");
133
134			unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
135
136			sNotificationService.~NetNotificationService();
137			return B_OK;
138
139		default:
140			return B_ERROR;
141	}
142}
143
144
145net_notifications_module_info sNotificationsModule = {
146	{
147		NET_NOTIFICATIONS_MODULE_NAME,
148		0,
149		notifications_std_ops
150	},
151
152	send_notification
153};
154
155module_info* modules[] = {
156	(module_info*)&sNotificationsModule,
157	NULL
158};
159