* 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:
@@ -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
|
||||
|
||||
@@ -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 == ¬ificationListener) {
|
||||
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*>(¬ificationListener) != NULL
|
||||
? "user " : "", listener, flags);
|
||||
|
||||
listener->flags = flags;
|
||||
listener->listener = ¬ificationListener;
|
||||
|
||||
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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user