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