xref: /haiku/src/add-ons/kernel/network/notifications/notifications.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
1 /*
2  * Copyright 2008-2013, 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 <kernel.h>
11 #include <generic_syscall.h>
12 #include <Notifications.h>
13 #include <util/KMessage.h>
14 
15 //#define TRACE_NOTIFICATIONS
16 #ifdef TRACE_NOTIFICATIONS
17 #	define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x)
18 #else
19 #	define TRACE(x...) ;
20 #endif
21 
22 
23 class NetNotificationService : public DefaultUserNotificationService {
24 public:
25 								NetNotificationService();
26 	virtual						~NetNotificationService();
27 
28 			void				Notify(const KMessage& event);
29 
30 protected:
31 	virtual	void				LastReferenceReleased();
32 	virtual	void				FirstAdded();
33 	virtual	void				LastRemoved();
34 };
35 
36 
37 static NetNotificationService sNotificationService;
38 
39 
40 //	#pragma mark - NetNotificationService
41 
42 
43 NetNotificationService::NetNotificationService()
44 	:
45 	DefaultUserNotificationService("network")
46 {
47 }
48 
49 
50 NetNotificationService::~NetNotificationService()
51 {
52 }
53 
54 
55 void
56 NetNotificationService::Notify(const KMessage& event)
57 {
58 	uint32 opcode = event.GetInt32("opcode", 0);
59 	if (opcode == 0)
60 		return;
61 
62 	TRACE("notify for %lx\n", opcode);
63 
64 	DefaultUserNotificationService::Notify(event, opcode);
65 }
66 
67 
68 void
69 NetNotificationService::LastReferenceReleased()
70 {
71 	// don't delete us here
72 }
73 
74 
75 void
76 NetNotificationService::FirstAdded()
77 {
78 	// The reference counting doesn't work for us, as we'll have to
79 	// ensure our module stays loaded.
80 	module_info* dummy;
81 	get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
82 }
83 
84 
85 void
86 NetNotificationService::LastRemoved()
87 {
88 	// Give up the reference _AddListener()
89 	put_module(NET_NOTIFICATIONS_MODULE_NAME);
90 }
91 
92 
93 //	#pragma mark - User generic syscall
94 
95 
96 static status_t
97 net_notifications_control(const char *subsystem, uint32 function, void *buffer,
98 	size_t bufferSize)
99 {
100 	struct net_notifications_control control;
101 	if (bufferSize != sizeof(struct net_notifications_control)
102 		|| function != NET_NOTIFICATIONS_CONTROL_WATCHING)
103 		return B_BAD_VALUE;
104 	if (!IS_USER_ADDRESS(buffer) || user_memcpy(&control, buffer,
105 			sizeof(struct net_notifications_control)) < B_OK)
106 		return B_BAD_ADDRESS;
107 
108 	if (control.flags != 0) {
109 		return sNotificationService.UpdateUserListener(control.flags,
110 			control.port, control.token);
111 	}
112 
113 	return sNotificationService.RemoveUserListeners(control.port,
114 		control.token);
115 }
116 
117 
118 //	#pragma mark - exported module API
119 
120 
121 static status_t
122 send_notification(const KMessage* event)
123 {
124 	sNotificationService.Notify(*event);
125 	return B_OK;
126 }
127 
128 
129 static status_t
130 notifications_std_ops(int32 op, ...)
131 {
132 	switch (op) {
133 		case B_MODULE_INIT:
134 		{
135 			TRACE("init\n");
136 
137 			new(&sNotificationService) NetNotificationService();
138 			status_t result = sNotificationService.Register();
139 			if (result != B_OK)
140 				return result;
141 
142 			register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
143 				net_notifications_control, 1, 0);
144 			return B_OK;
145 		}
146 		case B_MODULE_UNINIT:
147 			TRACE("uninit\n");
148 
149 			unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
150 
151 			// TODO: due to the way the locking in the notification
152 			// manager works, there's a potential race condition here
153 			// where someone attempts to add a listener right as
154 			// we're uninitializing. Needs to be looked at/resolved.
155 			sNotificationService.Unregister();
156 
157 			// we need to release the reference that was acquired
158 			// on our behalf by the NotificationManager.
159 			sNotificationService.ReleaseReference();
160 			sNotificationService.~NetNotificationService();
161 			return B_OK;
162 
163 		default:
164 			return B_ERROR;
165 	}
166 }
167 
168 
169 net_notifications_module_info sNotificationsModule = {
170 	{
171 		NET_NOTIFICATIONS_MODULE_NAME,
172 		0,
173 		notifications_std_ops
174 	},
175 
176 	send_notification
177 };
178 
179 module_info* modules[] = {
180 	(module_info*)&sNotificationsModule,
181 	NULL
182 };
183