* The select()/deselect() hooks now actually call the socket's request_notification()
and cancel_notification() functions. * Completey dropped the old select code, as well as any R5 compatibility stuff. If we ever need it again, it's still in SVN history. * The socket module was put in uninit_driver() for no reason. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19256 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -15,8 +15,8 @@
|
|||||||
// Forward declaration
|
// Forward declaration
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
|
|
||||||
#define NET_STACK_DRIVER_DEV "net/stack"
|
#define NET_STACK_DRIVER_DEVICE "net/stack"
|
||||||
#define NET_STACK_DRIVER_PATH "/dev/" NET_STACK_DRIVER_DEV
|
#define NET_STACK_DRIVER_PATH "/dev/" NET_STACK_DRIVER_DEVICE
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NET_STACK_IOCTL_BASE = 8800,
|
NET_STACK_IOCTL_BASE = 8800,
|
||||||
@@ -105,47 +105,4 @@ struct control_net_module_args { // used by NET_STACK_CONTROL_NET_MODULE
|
|||||||
size_t length;
|
size_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Userland stack driver on_socket_event() callback mecanism implementation:
|
|
||||||
the driver start a kernel thread waiting on a port for
|
|
||||||
a NET_STACK_SOCKET_EVENT_MSG message, which come with a socket_event_data block.
|
|
||||||
|
|
||||||
The on_socket_event() mechanism stay in driver (kernelland) because it's
|
|
||||||
only there we can call kernel's notify_select_event() on BONE systems.
|
|
||||||
For non-BONE systems, we use our own r5_notify_select_event()
|
|
||||||
implementation, that could be moved into the userland net_server code,
|
|
||||||
but it'll have split (again!) the /dev/net/stack driver code...
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct notify_socket_event_args { // used by NET_STACK_NOTIFY_SOCKET_EVENT
|
|
||||||
port_id notify_port; // port waiting for notification, -1 = stop notify
|
|
||||||
void *cookie; // this cookie value will be pass back in the socket_event_args
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NET_STACK_SOCKET_EVENT_NOTIFICATION 'sevn'
|
|
||||||
|
|
||||||
struct socket_event_data {
|
|
||||||
uint32 event; // B_SELECT_READ, B_SELECT_WRITE or B_SELECT_ERROR
|
|
||||||
void *cookie; // The cookie as set in notify_socket_event_args for this socket
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
R5.0.3 and before select() kernel support is too buggy to be used, so
|
|
||||||
here are the structures we used to support select() on sockets, and *only* on
|
|
||||||
sockets!
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct select_args { // used by NET_STACK_SELECT and NET_STACK_DESELECT
|
|
||||||
struct selectsync *sync; // in fact, it's the area_id of a r5_selectsync struct!!!
|
|
||||||
uint32 ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct r5_selectsync {
|
|
||||||
sem_id lock; // lock this r5_selectsync
|
|
||||||
sem_id wakeup; // sem to release to wakeup select()
|
|
||||||
struct fd_set rbits; // read event bits field
|
|
||||||
struct fd_set wbits; // write event bits field
|
|
||||||
struct fd_set ebits; // exception event bits field
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* NET_STACK_DRIVER_H */
|
#endif /* NET_STACK_DRIVER_H */
|
||||||
|
|||||||
@@ -32,43 +32,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Local definitions
|
|
||||||
|
|
||||||
// this struct will store one select() event to monitor per thread
|
|
||||||
typedef struct selecter {
|
|
||||||
struct selecter *next;
|
|
||||||
thread_id thread;
|
|
||||||
uint32 event;
|
|
||||||
selectsync *sync;
|
|
||||||
uint32 ref;
|
|
||||||
} selecter;
|
|
||||||
|
|
||||||
// the cookie we attach to each file descriptor opened on our driver entry
|
// the cookie we attach to each file descriptor opened on our driver entry
|
||||||
typedef struct net_stack_cookie {
|
struct net_stack_cookie {
|
||||||
net_socket *socket; // NULL before ioctl(fd, NET_STACK_SOCKET/_ACCEPT)
|
net_socket *socket;
|
||||||
sem_id selecters_lock; // protect the selecters linked-list
|
// is set using NET_STACK_SOCKET/_ACCEPT
|
||||||
selecter *selecters; // the select()'ers lists (thread-aware)
|
};
|
||||||
} net_stack_cookie;
|
|
||||||
|
|
||||||
// TODO: disabled
|
|
||||||
/* To unload this driver execute
|
|
||||||
* $ echo unload > /dev/net/stack
|
|
||||||
* As soon as the last app stops using sockets the netstack will be unloaded.
|
|
||||||
*/
|
|
||||||
//static const char *kUnloadCommand = "unload";
|
|
||||||
|
|
||||||
|
|
||||||
// prototypes of device hooks functions
|
|
||||||
static status_t net_stack_open(const char *name, uint32 flags, void **_cookie);
|
|
||||||
static status_t net_stack_close(void *cookie);
|
|
||||||
static status_t net_stack_free_cookie(void *cookie);
|
|
||||||
static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t length);
|
|
||||||
static status_t net_stack_read(void *cookie, off_t pos, void *data, size_t *_length);
|
|
||||||
static status_t net_stack_write(void *cookie, off_t pos, const void *data, size_t *_length);
|
|
||||||
static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsync *sync);
|
|
||||||
static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync);
|
|
||||||
static status_t net_stack_readv(void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_length);
|
|
||||||
static status_t net_stack_writev(void *cookie, off_t pos, const iovec *vecs, size_t count, size_t *_length);
|
|
||||||
|
|
||||||
|
|
||||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||||
@@ -128,48 +96,6 @@ check_args(ArgType &args, void *data, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void
|
|
||||||
on_socket_event(void * socket, uint32 event, void *_cookie)
|
|
||||||
{
|
|
||||||
net_stack_cookie *cookie = (net_stack_cookie *) _cookie;
|
|
||||||
selecter *s;
|
|
||||||
|
|
||||||
if (!cookie)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (cookie->socket != socket) {
|
|
||||||
ERROR("on_socket_event(%p, %ld, %p): socket is higly suspect! Aborting.\n",
|
|
||||||
socket, event, cookie);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("on_socket_event(%p, %ld, %p)\n", socket, event, cookie);
|
|
||||||
|
|
||||||
// lock the selecters list
|
|
||||||
if (acquire_sem(cookie->selecters_lock) != B_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
s = cookie->selecters;
|
|
||||||
while (s) {
|
|
||||||
if (s->event == event)
|
|
||||||
// notify this selecter (thread/event pair)
|
|
||||||
#ifdef COMPILE_FOR_R5
|
|
||||||
notify_select_event(s->sync, s->ref);
|
|
||||||
#else
|
|
||||||
notify_select_event(s->sync, s->ref, event);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s = s->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlock the selecters list
|
|
||||||
release_sem(cookie->selecters_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static const char*
|
static const char*
|
||||||
opcode_name(int op)
|
opcode_name(int op)
|
||||||
@@ -226,81 +152,6 @@ opcode_name(int op)
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - driver
|
|
||||||
|
|
||||||
|
|
||||||
/** Do we init ourselves? If we're in safe mode we'll decline so if things
|
|
||||||
* screw up we can boot and delete the broken driver!
|
|
||||||
* After my experiences earlier - a good idea!
|
|
||||||
*/
|
|
||||||
|
|
||||||
status_t
|
|
||||||
init_hardware(void)
|
|
||||||
{
|
|
||||||
void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
|
||||||
if (settings != NULL) {
|
|
||||||
// we got a pointer, now get settings...
|
|
||||||
bool safemode = get_driver_boolean_parameter(settings, B_SAFEMODE_SAFE_MODE, false, false);
|
|
||||||
// now get rid of settings
|
|
||||||
unload_driver_settings(settings);
|
|
||||||
|
|
||||||
if (safemode) {
|
|
||||||
WARN("init_hardware: declining offer to join the party.\n");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("init_hardware done.\n");
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
init_driver(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
uninit_driver(void)
|
|
||||||
{
|
|
||||||
TRACE("uninit_driver\n");
|
|
||||||
|
|
||||||
put_module(NET_SOCKET_MODULE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char **
|
|
||||||
publish_devices(void)
|
|
||||||
{
|
|
||||||
static const char *devices[] = { NET_STACK_DRIVER_DEV, NULL };
|
|
||||||
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
device_hooks*
|
|
||||||
find_device(const char* device_name)
|
|
||||||
{
|
|
||||||
static device_hooks hooks = {
|
|
||||||
net_stack_open,
|
|
||||||
net_stack_close,
|
|
||||||
net_stack_free_cookie,
|
|
||||||
net_stack_control,
|
|
||||||
net_stack_read,
|
|
||||||
net_stack_write,
|
|
||||||
net_stack_select,
|
|
||||||
net_stack_deselect,
|
|
||||||
net_stack_readv,
|
|
||||||
net_stack_writev,
|
|
||||||
};
|
|
||||||
|
|
||||||
return &hooks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - device
|
// #pragma mark - device
|
||||||
|
|
||||||
|
|
||||||
@@ -321,11 +172,7 @@ net_stack_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
memset(cookie, 0, sizeof(net_stack_cookie));
|
cookie->socket = NULL;
|
||||||
cookie->socket = NULL; // the socket will be allocated in NET_STACK_SOCKET ioctl
|
|
||||||
cookie->selecters_lock = create_sem(1, "socket_selecters_lock");
|
|
||||||
|
|
||||||
// attach this new net_socket_cookie to file descriptor
|
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
|
|
||||||
TRACE("net_stack_open(%s, %s%s) return this cookie: %p\n",
|
TRACE("net_stack_open(%s, %s%s) return this cookie: %p\n",
|
||||||
@@ -357,28 +204,18 @@ static status_t
|
|||||||
net_stack_free_cookie(void *_cookie)
|
net_stack_free_cookie(void *_cookie)
|
||||||
{
|
{
|
||||||
net_stack_cookie *cookie = (net_stack_cookie *)_cookie;
|
net_stack_cookie *cookie = (net_stack_cookie *)_cookie;
|
||||||
selecter *s;
|
|
||||||
|
|
||||||
TRACE("net_stack_free_cookie(%p)\n", cookie);
|
TRACE("net_stack_free_cookie(%p)\n", cookie);
|
||||||
|
|
||||||
// free the selecters list
|
|
||||||
delete_sem(cookie->selecters_lock);
|
|
||||||
s = cookie->selecters;
|
|
||||||
while (s) {
|
|
||||||
selecter *tmp = s;
|
|
||||||
s = s->next;
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cookie->socket != NULL)
|
if (cookie->socket != NULL)
|
||||||
sSocket->free(cookie->socket);
|
sSocket->free(cookie->socket);
|
||||||
|
|
||||||
// free the cookie
|
|
||||||
free(cookie);
|
free(cookie);
|
||||||
|
|
||||||
if (atomic_add(&sOpenCount, -1) == 1) {
|
if (atomic_add(&sOpenCount, -1) == 1) {
|
||||||
// the last reference to us has been removed, unload the networking
|
// the last reference to us has been removed, unload the networking
|
||||||
// stack again
|
// stack again (it will only be actually unloaded in case there is
|
||||||
|
// no interface defined)
|
||||||
put_module(NET_SOCKET_MODULE_NAME);
|
put_module(NET_SOCKET_MODULE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,40 +529,13 @@ static status_t
|
|||||||
net_stack_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
net_stack_select(void *_cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||||
{
|
{
|
||||||
net_stack_cookie *cookie = (net_stack_cookie *)_cookie;
|
net_stack_cookie *cookie = (net_stack_cookie *)_cookie;
|
||||||
status_t status;
|
|
||||||
|
|
||||||
TRACE("net_stack_select(%p, %d, %ld, %p)\n", cookie, event, ref, sync);
|
TRACE("net_stack_select(%p, %d, %ld, %p)\n", cookie, event, ref, sync);
|
||||||
|
|
||||||
if (cookie->socket == NULL)
|
if (cookie->socket == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
selecter *s = (selecter *)malloc(sizeof(selecter));
|
return sSocket->request_notification(cookie->socket, event, ref, sync);
|
||||||
if (s == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
s->thread = find_thread(NULL);
|
|
||||||
s->event = event;
|
|
||||||
s->sync = sync;
|
|
||||||
s->ref = ref;
|
|
||||||
|
|
||||||
// lock the selecters list
|
|
||||||
status = acquire_sem(cookie->selecters_lock);
|
|
||||||
if (status != B_OK) {
|
|
||||||
free(s);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add it to selecters list
|
|
||||||
s->next = cookie->selecters;
|
|
||||||
cookie->selecters = s;
|
|
||||||
|
|
||||||
// unlock the selecters list
|
|
||||||
release_sem(cookie->selecters_lock);
|
|
||||||
|
|
||||||
// start (or continue) to monitor for socket event
|
|
||||||
// TODO: enable select() notification
|
|
||||||
// return sSocket->socket_set_event_callback(cookie->socket, on_socket_event, cookie, event);
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -736,44 +546,81 @@ net_stack_deselect(void *_cookie, uint8 event, selectsync *sync)
|
|||||||
|
|
||||||
TRACE("net_stack_deselect(%p, %d, %p)\n", cookie, event, sync);
|
TRACE("net_stack_deselect(%p, %d, %p)\n", cookie, event, sync);
|
||||||
|
|
||||||
if (!cookie || !cookie->socket)
|
if (cookie->socket == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// lock the selecters list
|
return sSocket->cancel_notification(cookie->socket, event, sync);
|
||||||
status_t status = acquire_sem(cookie->selecters_lock);
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
thread_id currentThread = find_thread(NULL);;
|
|
||||||
selecter *previous = NULL;
|
|
||||||
selecter *s = cookie->selecters;
|
|
||||||
|
|
||||||
while (s) {
|
|
||||||
if (s->thread == currentThread
|
|
||||||
&& s->event == event && s->sync == sync) {
|
|
||||||
// selecter found!
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = s;
|
|
||||||
s = s->next;
|
// #pragma mark - driver
|
||||||
|
|
||||||
|
|
||||||
|
/** Do we init ourselves? If we're in safe mode we'll decline so if things
|
||||||
|
* screw up we can boot and delete the broken driver!
|
||||||
|
* After my experiences earlier - a good idea!
|
||||||
|
*/
|
||||||
|
|
||||||
|
status_t
|
||||||
|
init_hardware(void)
|
||||||
|
{
|
||||||
|
void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
||||||
|
if (settings != NULL) {
|
||||||
|
// we got a pointer, now get settings...
|
||||||
|
bool safemode = get_driver_boolean_parameter(settings, B_SAFEMODE_SAFE_MODE, false, false);
|
||||||
|
// now get rid of settings
|
||||||
|
unload_driver_settings(settings);
|
||||||
|
|
||||||
|
if (safemode) {
|
||||||
|
WARN("net_stack: Safemode! Declining offer to join the party.\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s != NULL) {
|
return B_OK;
|
||||||
// remove it from selecters list
|
|
||||||
if (previous)
|
|
||||||
previous->next = s->next;
|
|
||||||
else
|
|
||||||
cookie->selecters = s->next;
|
|
||||||
free(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: enable deselect()
|
|
||||||
if (cookie->selecters == NULL) {
|
status_t
|
||||||
// selecters list is empty: no need to monitor socket events anymore
|
init_driver(void)
|
||||||
//sSocket->socket_set_event_callback(cookie->socket, NULL, NULL, event);
|
{
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlock the selecters list
|
|
||||||
return release_sem(cookie->selecters_lock);
|
void
|
||||||
|
uninit_driver(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char **
|
||||||
|
publish_devices(void)
|
||||||
|
{
|
||||||
|
static const char *devices[] = {
|
||||||
|
NET_STACK_DRIVER_DEVICE,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
device_hooks*
|
||||||
|
find_device(const char* device_name)
|
||||||
|
{
|
||||||
|
static device_hooks hooks = {
|
||||||
|
net_stack_open,
|
||||||
|
net_stack_close,
|
||||||
|
net_stack_free_cookie,
|
||||||
|
net_stack_control,
|
||||||
|
net_stack_read,
|
||||||
|
net_stack_write,
|
||||||
|
net_stack_select,
|
||||||
|
net_stack_deselect,
|
||||||
|
net_stack_readv,
|
||||||
|
net_stack_writev,
|
||||||
|
};
|
||||||
|
|
||||||
|
return &hooks;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user