* More or less completed the network notification module - it does not remove

old invalid user listeners yet, though (ie. if a team dies).
* Implemented userland network monitor functions.
* Added a few notifications to the network stack, even though this part isn't
  complete yet (especially notify_interface_changed()).
* Added optional debug output to the notifications module.
* Added the module to the image, it basically works now (tested).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28825 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-12-27 20:48:28 +00:00
parent 2e71ef292f
commit d68ffdedc0
10 changed files with 179 additions and 44 deletions
+4 -3
View File
@@ -138,12 +138,12 @@ BEOS_ADD_ONS_DRIVERS_GRAPHICS = $(X86_ONLY)radeon $(X86_ONLY)nvidia
$(X86_ONLY)s3 $(X86_ONLY)vesa #$(X86_ONLY)via #$(X86_ONLY)vmware
;
BEOS_ADD_ONS_DRIVERS_MIDI = emuxki ;
BEOS_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)broadcom440x
BEOS_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com $(X86_ONLY)broadcom440x
$(X86_ONLY)broadcom570x etherpci $(X86_ONLY)ipro1000
pegasus $(X86_ONLY)rtl8139 rtl8169 $(X86_ONLY)rtl81xx sis900
$(X86_ONLY)via_rhine wb840 $(X86_ONLY)ipro100 $(X86_ONLY)nforce
#vlance
$(X86_ONLY)marvell_yukon $(X86_ONLY)syskonnect
$(X86_ONLY)marvell_yukon $(X86_ONLY)syskonnect
$(X86_ONLY)attansic_l2 $(X86_ONLY)ar81xx usb_ecm
;
#BEOS_ADD_ONS_DRIVERS_ACPI = $(X86_ONLY)acpi_button ;
@@ -420,7 +420,8 @@ AddSymlinkToHaikuImage beos system add-ons Tracker
AddFilesToHaikuImage beos system add-ons input_server devices
: <input>keyboard <input>mouse <input>wacom ;
AddFilesToHaikuImage beos system add-ons input_server filters : screen_saver ;
AddFilesToHaikuImage beos system add-ons kernel network : stack ;
AddFilesToHaikuImage beos system add-ons kernel network
: <net>notifications stack ;
AddFilesToHaikuImage beos system add-ons kernel network devices
: $(BEOS_NETWORK_DEVICES) ;
AddFilesToHaikuImage beos system add-ons kernel network datalink_protocols
+7 -8
View File
@@ -24,8 +24,7 @@ struct net_notifications_module_info {
// generic syscall interface
#define NET_NOTIFICATIONS_SYSCALLS "network/notifications"
#define NET_NOTIFICATIONS_START_WATCHING 1
#define NET_NOTIFICATIONS_STOP_WATCHING 2
#define NET_NOTIFICATIONS_CONTROL_WATCHING 1
struct net_notifications_control {
uint32 flags;
@@ -36,15 +35,15 @@ struct net_notifications_control {
// TODO: the following part of this header should end up in a public header
// some day!
#define B_NETWORK_INTERFACE_ADDED 1
#define B_NETWORK_INTERFACE_REMOVED 2
#define B_NETWORK_INTERFACE_CHANGED 3
#define B_NETWORK_DEVICE_LINK_CHANGED 4
#define B_NETWORK_INTERFACE_ADDED 0x01
#define B_NETWORK_INTERFACE_REMOVED 0x02
#define B_NETWORK_INTERFACE_CHANGED 0x03
#define B_NETWORK_DEVICE_LINK_CHANGED 0x10
// TODO: add routes, stack unloaded/loaded, ... events
enum {
B_WATCH_NETWORK_INTERFACE_CHANGES = 0x0001,
B_WATCH_NETWORK_LINK_CHANGES = 0x0002
B_WATCH_NETWORK_INTERFACE_CHANGES = 0x000f,
B_WATCH_NETWORK_LINK_CHANGES = 0x00f0
};
#define B_NETWORK_MONITOR '_NTN'
@@ -7,12 +7,18 @@
#include <net_notifications.h>
//#include <messaging.h>
#include <generic_syscall.h>
#include <Notifications.h>
#include <util/KMessage.h>
//#define TRACE_NOTIFICATIONS
#ifdef TRACE_NOTIFICATIONS
# define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x)
#else
# define TRACE(x...) ;
#endif
// TODO: add generic syscall interface
// TODO: add possibility to remove teams/ports that are gone
static UserMessagingMessageSender sNotificationSender;
@@ -75,8 +81,11 @@ static NetNotificationService sNotificationService;
net_listener::~net_listener()
{
if (dynamic_cast<UserNetListener*>(listener) != NULL)
// Only delete the listener if it's one of ours
if (dynamic_cast<UserNetListener*>(listener) != NULL) {
TRACE("delete user listener %p\n", listener);
delete listener;
}
}
@@ -101,21 +110,25 @@ NetNotificationService::~NetNotificationService()
void
NetNotificationService::Notify(const KMessage& event)
{
uint32 flags = event.GetInt32("flags", 0);
if (flags == 0)
uint32 opcode = event.GetInt32("opcode", 0);
if (opcode == 0)
return;
TRACE("notify for %lx\n", opcode);
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if ((listener->flags & flags) != 0)
if ((listener->flags & opcode) != 0) {
TRACE(" notify listener %p for %lx\n", listener, opcode);
listener->listener->EventOccured(*this, &event);
}
}
iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if ((listener->flags & flags) != 0)
if ((listener->flags & opcode) != 0)
listener->listener->AllListenersNotified(*this);
}
}
@@ -170,8 +183,14 @@ NetNotificationService::RemoveListener(const KMessage* eventSpecifier,
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (listener->listener == &notificationListener) {
TRACE("remove listener %p\n", listener);
iterator.Remove();
delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK;
}
}
@@ -180,7 +199,7 @@ NetNotificationService::RemoveListener(const KMessage* eventSpecifier,
}
inline status_t
status_t
NetNotificationService::RemoveUserListeners(port_id port, uint32 token)
{
UserNetListener userListener(port, token);
@@ -190,8 +209,14 @@ NetNotificationService::RemoveUserListeners(port_id port, uint32 token)
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) {
TRACE("remove user listener %p\n", listener);
iterator.Remove();
delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK;
}
}
@@ -237,11 +262,22 @@ NetNotificationService::_AddListener(uint32 flags,
if (listener == NULL)
return B_NO_MEMORY;
TRACE("add %slistener %p for %lx\n",
dynamic_cast<UserNetListener*>(&notificationListener) != NULL
? "user " : "", listener, flags);
listener->flags = flags;
listener->listener = &notificationListener;
RecursiveLocker _(fRecursiveLock);
if (fListeners.IsEmpty()) {
// The reference counting doesn't work for us, as we'll have to
// ensure our module stays loaded.
module_info* dummy;
get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
}
fListeners.Add(listener);
return B_OK;
}
@@ -250,27 +286,36 @@ NetNotificationService::_AddListener(uint32 flags,
// #pragma mark - User generic syscall
status_t
_user_start_watching_network(uint32 flags, port_id port, uint32 token)
static status_t
net_notifications_control(const char *subsystem, uint32 function, void *buffer,
size_t bufferSize)
{
return sNotificationService.UpdateUserListener(flags, port, token);
}
struct net_notifications_control control;
if (bufferSize != sizeof(struct net_notifications_control)
|| function != NET_NOTIFICATIONS_CONTROL_WATCHING)
return B_BAD_VALUE;
if (user_memcpy(&control, buffer,
sizeof(struct net_notifications_control)) < B_OK)
return B_BAD_ADDRESS;
if (control.flags != 0) {
return sNotificationService.UpdateUserListener(control.flags,
control.port, control.token);
}
status_t
_user_stop_watching_network(port_id port, uint32 token)
{
return sNotificationService.RemoveUserListeners(port, token);
return sNotificationService.RemoveUserListeners(control.port,
control.token);
}
// #pragma mark - exported module API
static void
static status_t
send_notification(const KMessage* event)
{
sNotificationService.Notify(*event);
return B_OK;
}
@@ -279,10 +324,20 @@ notifications_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
TRACE("init\n");
new(&sNotificationSender) UserMessagingMessageSender();
new(&sNotificationService) NetNotificationService();
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
net_notifications_control, 1, 0);
return B_OK;
case B_MODULE_UNINIT:
TRACE("uninit\n");
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
sNotificationSender.~UserMessagingMessageSender();
sNotificationService.~NetNotificationService();
return B_OK;
@@ -518,7 +518,8 @@ datalink_std_ops(int32 op, ...)
status_t
interface_protocol_init(struct net_interface *_interface, net_datalink_protocol **_protocol)
interface_protocol_init(struct net_interface *_interface,
net_datalink_protocol **_protocol)
{
net_interface_private *interface = (net_interface_private *)_interface;
@@ -547,7 +548,8 @@ interface_protocol_send_data(net_datalink_protocol *_protocol,
net_buffer *buffer)
{
interface_protocol *protocol = (interface_protocol *)_protocol;
net_interface_private *interface = (net_interface_private *)protocol->interface;
net_interface_private *interface
= (net_interface_private *)protocol->interface;
// TODO: Need to think about this locking. We can't obtain the
// RX Lock here (nor would it make sense) as the ARP
+4 -1
View File
@@ -186,8 +186,10 @@ add_interface_to_domain(net_domain *_domain,
put_device_interface(deviceInterface);
if (status == B_OK)
if (status == B_OK) {
list_add_item(&domain->interfaces, interface);
notify_interface_added(interface);
}
return status;
}
@@ -203,6 +205,7 @@ remove_interface_from_domain(net_interface *interface)
net_domain_private *domain = (net_domain_private *)interface->domain;
list_remove_item(&domain->interfaces, interface);
notify_interface_removed(interface);
delete_interface((net_interface_private *)interface);
return B_OK;
}
@@ -764,6 +764,7 @@ unregister_device_monitor(net_device *device, net_device_monitor *monitor)
status_t
device_link_changed(net_device *device)
{
notify_link_changed(device);
return B_OK;
}
@@ -9,6 +9,7 @@
notification listeners independent from the stack status.
*/
#include <net_device.h>
#include <net_notifications.h>
#include <util/KMessage.h>
@@ -20,7 +21,7 @@ static net_notifications_module_info* sNotificationModule;
status_t
notify_interface_added(const char* interface)
notify_interface_added(net_interface* interface)
{
if (sNotificationModule == NULL)
return B_NOT_SUPPORTED;
@@ -29,14 +30,14 @@ notify_interface_added(const char* interface)
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_ADDED);
message.AddString("interface", interface);
message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message);
}
status_t
notify_interface_removed(const char* interface)
notify_interface_removed(net_interface* interface)
{
if (sNotificationModule == NULL)
return B_NOT_SUPPORTED;
@@ -45,14 +46,14 @@ notify_interface_removed(const char* interface)
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_REMOVED);
message.AddString("interface", interface);
message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message);
}
status_t
notify_interface_changed(const char* interface)
notify_interface_changed(net_interface* interface)
{
if (sNotificationModule == NULL)
return B_NOT_SUPPORTED;
@@ -61,14 +62,14 @@ notify_interface_changed(const char* interface)
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_INTERFACE_CHANGED);
message.AddString("interface", interface);
message.AddString("interface", interface->name);
return sNotificationModule->send_notification(&message);
}
status_t
notify_link_changed(const char* interface)
notify_link_changed(net_device* device)
{
if (sNotificationModule == NULL)
return B_NOT_SUPPORTED;
@@ -77,7 +78,10 @@ notify_link_changed(const char* interface)
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_DEVICE_LINK_CHANGED);
message.AddString("interface", interface);
message.AddString("device", device->name);
message.AddInt32("media", device->media);
message.AddInt64("link speed", device->link_speed);
message.AddInt32("link quality", device->link_quality);
return sNotificationModule->send_notification(&message);
}
@@ -34,10 +34,10 @@ status_t get_domain_datalink_protocols(net_interface *interface);
status_t put_domain_datalink_protocols(net_interface *interface);
// notifications.cpp
status_t notify_interface_added(const char* interface);
status_t notify_interface_removed(const char* interface);
status_t notify_interface_changed(const char* interface);
status_t notify_link_changed(const char* interface);
status_t notify_interface_added(net_interface* interface);
status_t notify_interface_removed(net_interface* interface);
status_t notify_interface_changed(net_interface* interface);
status_t notify_link_changed(net_device* device);
status_t init_notifications();
void uninit_notifications();
+3 -1
View File
@@ -1,14 +1,16 @@
SubDir HAIKU_TOP src kits network ;
UsePrivateHeaders libroot net shared ;
UsePrivateHeaders app libroot net shared ;
UsePrivateSystemHeaders ;
SharedLibrary libnetwork.so :
init.cpp
interfaces.cpp
notifications.cpp
socket.cpp
r5_compatibility.cpp
:
be
<libnetwork_dns>dns_dst.o
<libnetwork_dns>dns_inet.o
<libnetwork_dns>dns_irs.o
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
/*! The notifications API uses the generic syscall interface of the
network's stack notification module.
*/
#include <net_notifications.h>
#include <MessengerPrivate.h>
#include <generic_syscall_defs.h>
#include <syscalls.h>
static status_t
check_for_notifications_syscall(void)
{
uint32 version = 0;
return _kern_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, B_SYSCALL_INFO,
&version, sizeof(version));
}
// #pragma mark -
status_t
start_watching_network(uint32 flags, const BMessenger& target)
{
if (check_for_notifications_syscall() != B_OK)
return B_NOT_SUPPORTED;
BMessenger::Private targetPrivate(const_cast<BMessenger&>(target));
net_notifications_control control;
control.flags = flags;
control.port = targetPrivate.Port();
control.token = targetPrivate.Token();
return _kern_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
NET_NOTIFICATIONS_CONTROL_WATCHING, &control,
sizeof(net_notifications_control));
}
status_t
start_watching_network(uint32 flags, const BHandler* handler,
const BLooper* looper)
{
const BMessenger target(handler, looper);
return start_watching_network(flags, target);
}
status_t
stop_watching_network(const BMessenger& target)
{
return start_watching_network(0, target);
// start_watching_network() without flags just stops everything
}
status_t
stop_watching_network(const BHandler* handler, const BLooper* looper)
{
const BMessenger target(handler, looper);
return stop_watching_network(target);
}