Checked in our version of libsocket.so. When building for BONE use this command:

BONE_VERSION=1 jam
This will remove the select() function from libsocket.so.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7202 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2004-04-15 15:57:49 +00:00
parent fde2fe1c1c
commit eda72d2688
3 changed files with 538 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
SubDir OBOS_TOP src kits network libsocket ;
UsePrivateHeaders net ;
{
local defines ;
if $(BONE_VERSION) {
defines += BONE_VERSION ;
}
defines = [ FDefines $(defines) ] ;
SubDirCcFlags $(defines) ;
SubDirC++Flags $(defines) ;
}
SharedLibrary socket :
socket.c
select.c
;
# Installation -- in the test directory for the time being
OBOSInstallRelSymLink install-networking
: [ FDirName $(OBOS_TEST_DIR) kits net lib ]
: libsocket.so
: installed-networking-test ;
Package openbeos-networkingkit-cvs :
libsocket.so :
# boot home config lib ;
boot home Desktop openbeos-networkingkit lib ;
+179
View File
@@ -0,0 +1,179 @@
#include <unistd.h>
#include <image.h>
#include <OS.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <errno.h>
#include "net_stack_driver.h"
#ifndef BONE_VERSION
static int fd_set_count(fd_set * bits, int nbits)
{
int count;
int fd;
count = 0;
for (fd = 0; fd < nbits; fd++)
if (FD_ISSET(fd, bits))
count++;
return count;
}
_EXPORT int select(int nbits, struct fd_set * rbits,
struct fd_set * wbits,
struct fd_set * ebits,
struct timeval * tv)
{
int fd;
int n;
struct stack_driver_args args;
status_t status;
area_id area;
struct r5_selectsync * rss;
#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
// We share a area with the fd_set on it with the network stack code.
// The r5_notify_select_event in the net_stack_driver code will fill it and wakeup us
// when a event raise.
area = create_area("r5_selectsync", (void **) &rss,
B_ANY_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(*rss)), B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA);
if (area < B_OK) {
errno = area;
return -1;
};
// The area is multi-thread protected by a semaphore locker
rss->lock = create_sem(1, "r5_selectsync_lock");
if (rss->lock < B_OK) {
errno = rss->lock;
rss->wakeup = 0;
n = -1;
goto error;
};
// Create the wakeup call semaphore
rss->wakeup = create_sem(0, "r5_selectsync_wakeup");
if (rss->wakeup < B_OK) {
errno = rss->wakeup;
n = -1;
goto error;
};
FD_ZERO(&rss->rbits);
FD_ZERO(&rss->wbits);
FD_ZERO(&rss->ebits);
/* Beware, ugly hacky hack: we pass the area_id of our shared r5_selectsync,
that net_stack_driver should udate directly
*/
args.u.select.sync = (struct selectsync *) area;
/* call, indirectly, net_stack_select() for each event to monitor
* as we are not the vfs, we can't call this device hook ourself, but
* our NET_STACK_SELECT opcode would do it for us...
*/
n = 0;
for (fd = 0; fd < nbits; fd++) {
if (rbits && FD_ISSET(fd, rbits)) {
args.u.select.ref = (fd << 8) | 1;
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
n++;
};
if (wbits && FD_ISSET(fd, wbits)) {
args.u.select.ref = (fd << 8) | 2;
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
n++;
};
if (ebits && FD_ISSET(fd, ebits)) {
args.u.select.ref = (fd << 8) | 3;
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
n++;
};
}
if (n < 1) {
// TODO: maybe we could hack a workaround for select() on file/dev here:
// If no fd handle the NET_STACK_SELECT, assume they're files, so always
// readable and writable?
errno = B_BAD_VALUE;
n = -1;
goto error;
};
// Okay, now wait for our wakeup call.
// Maybe his's already there, even... (when the select event is already raised)
if (tv) {
bigtime_t timeout;
timeout = tv->tv_sec * 1000000LL + tv->tv_usec;
status = acquire_sem_etc(rss->wakeup, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, timeout);
} else
status = acquire_sem(rss->wakeup);
// we don't need it anymore, and we say "select() party is over" that way, too :-)
delete_sem(rss->lock);
delete_sem(rss->wakeup);
rss->lock = rss->wakeup = -1;
// unregister socket event notification
for(fd = 0; fd < nbits; fd++) {
if (rbits && FD_ISSET(fd, rbits)) {
args.u.select.ref = (fd << 8) | 1;
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
};
if (wbits && FD_ISSET(fd, wbits)) {
args.u.select.ref = (fd << 8) | 2;
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
};
if (ebits && FD_ISSET(fd, ebits)) {
args.u.select.ref = (fd << 8) | 3;
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
};
};
// Okay, what the final result?
switch (status) {
case B_OK:
case B_WOULD_BLOCK:
case B_TIMED_OUT: // logicly, 'n' should stay to 0 in this case...
n = 0;
if (rbits) {
memcpy(rbits, &rss->rbits, sizeof(*rbits));
n += fd_set_count(rbits, nbits);
};
if (wbits) {
memcpy(wbits, &rss->wbits, sizeof(*wbits));
n += fd_set_count(wbits, nbits);
};
if (ebits) {
memcpy(ebits, &rss->ebits, sizeof(*ebits));
n += fd_set_count(ebits, nbits);
};
break;
default:
errno = status;
n = -1;
break;
};
error:
if (rss->lock >= 0)
delete_sem(rss->lock);
if (rss->wakeup >= 0)
delete_sem(rss->wakeup);
delete_area(area);
return n;
}
#endif
+330
View File
@@ -0,0 +1,330 @@
/* socket.c */
/* This is a very simple little shared library that acts as a wrapper
* for our device/kernel stack!
*/
#include <fcntl.h>
#include <unistd.h>
#include <kernel/OS.h>
#include <iovec.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <netinet/in.h>
#include "net_stack_driver.h"
// Forward declaration of sysctl.h, because it's currently declared under headers/private/kernel/sysctl.h
int sysctl(int *, uint, void *, size_t *, void *, size_t);
static char * get_stack_driver_path(void);
_EXPORT int socket(int family, int type, int protocol)
{
int sock;
int rv;
struct stack_driver_args args;
sock = open(get_stack_driver_path(), O_RDWR);
if (sock < 0)
return sock;
args.u.socket.family = family;
args.u.socket.type = type;
args.u.socket.proto = protocol;
rv = ioctl(sock, NET_STACK_SOCKET, &args, sizeof(args));
if (rv < 0) {
close(sock);
return rv;
}
return sock;
}
_EXPORT int bind(int sock, const struct sockaddr *addr, int addrlen)
{
struct stack_driver_args args;
args.u.sockaddr.addr = (struct sockaddr *) addr;
args.u.sockaddr.addrlen = addrlen;
return ioctl(sock, NET_STACK_BIND, &args, sizeof(args));
}
_EXPORT int shutdown(int sock, int how)
{
struct stack_driver_args args;
args.u.integer = how;
return ioctl(sock, NET_STACK_SHUTDOWN, &args, sizeof(args));
}
_EXPORT int connect(int sock, const struct sockaddr *addr, int addrlen)
{
struct stack_driver_args args;
args.u.sockaddr.addr = (struct sockaddr *) addr;
args.u.sockaddr.addrlen = addrlen;
return ioctl(sock, NET_STACK_CONNECT, &args, sizeof(args));
}
_EXPORT int listen(int sock, int backlog)
{
struct stack_driver_args args;
args.u.integer = backlog;
return ioctl(sock, NET_STACK_LISTEN, &args, sizeof(args));
}
_EXPORT int accept(int sock, struct sockaddr *addr, int *addrlen)
{
struct stack_driver_args args;
int rv;
int new_sock;
void *cookie;
new_sock = open(get_stack_driver_path(), O_RDWR);
if (new_sock < 0)
return new_sock;
// The network stack driver will need to know to which net_stack_cookie to
// *bind* with the new accepted socket. He can't know himself find out
// the net_stack_cookie of our new_sock file descriptor, the just open() one...
// So, here, we ask him the net_stack_cookie value for our fd... :-)
rv = ioctl(new_sock, NET_STACK_GET_COOKIE, &cookie);
if (rv < 0) {
close(new_sock);
return rv;
}
args.u.accept.cookie = cookie; // this way driver can use the right fd/cookie for the new_sock!
args.u.accept.addr = addr;
args.u.accept.addrlen = *addrlen;
rv = ioctl(sock, NET_STACK_ACCEPT, &args, sizeof(args));
if (rv < 0) {
close(new_sock);
return rv;
}
*addrlen = args.u.accept.addrlen;
return new_sock;
}
_EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
struct sockaddr *addr, size_t *addrlen)
{
struct msghdr mh;
struct iovec iov;
int rv;
/* XXX - would this be better done as scatter gather? */
mh.msg_name = (caddr_t)addr;
mh.msg_namelen = addrlen ? *addrlen : 0;
mh.msg_flags = flags;
mh.msg_control = NULL;
mh.msg_controllen = 0;
iov.iov_base = buffer;
iov.iov_len = buflen;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
rv = ioctl(sock, NET_STACK_RECVFROM, &mh, sizeof(mh));
if (rv < 0)
return rv;
if (addrlen)
*addrlen = mh.msg_namelen;
return rv;
}
_EXPORT ssize_t sendto(int sock, const void *buffer, size_t buflen, int flags,
const struct sockaddr *addr, size_t addrlen)
{
struct msghdr mh;
struct iovec iov;
/* XXX - would this be better done as scatter gather? */
mh.msg_name = (caddr_t)addr;
mh.msg_namelen = addrlen;
mh.msg_flags = flags;
mh.msg_control = NULL;
mh.msg_controllen = 0;
iov.iov_base = (caddr_t)buffer;
iov.iov_len = buflen;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
return ioctl(sock, NET_STACK_SENDTO, &mh, sizeof(mh));
}
/* These need to be adjusted to take account of the MSG_PEEK
* flag, but old R5 doesn't use it...
*/
_EXPORT ssize_t recv(int sock, void *data, size_t datalen, int flags)
{
struct stack_driver_args args;
int rv;
args.u.transfer.data = data;
args.u.transfer.datalen = datalen;
args.u.transfer.flags = flags;
args.u.transfer.addr = NULL;
args.u.transfer.addrlen = 0;
rv = ioctl(sock, NET_STACK_RECV, &args, sizeof(args));
if (rv < 0)
return rv;
return args.u.transfer.datalen;
}
_EXPORT ssize_t send(int sock, const void *data, size_t datalen, int flags)
{
struct stack_driver_args args;
int rv;
args.u.transfer.data = (void *) data;
args.u.transfer.datalen = datalen;
args.u.transfer.flags = flags;
args.u.transfer.addr = NULL;
args.u.transfer.addrlen = 0;
rv = ioctl(sock, NET_STACK_SEND, &args, sizeof(args));
if (rv < 0)
return rv;
return args.u.transfer.datalen;
}
_EXPORT int getsockopt(int sock, int level, int option, void *optval, size_t *optlen)
{
struct stack_driver_args args;
int rv;
args.u.sockopt.level = level;
args.u.sockopt.option = option;
args.u.sockopt.optval = optval;
args.u.sockopt.optlen = *optlen;
rv = ioctl(sock, NET_STACK_GETSOCKOPT, &args, sizeof(args));
if (rv ==0)
*optlen = args.u.sockopt.optlen;
return rv;
}
_EXPORT int setsockopt(int sock, int level, int option, const void *optval, size_t optlen)
{
struct stack_driver_args args;
args.u.sockopt.level = level;
args.u.sockopt.option = option;
args.u.sockopt.optval = (void *) optval;
args.u.sockopt.optlen = optlen;
return ioctl(sock, NET_STACK_SETSOCKOPT, &args, sizeof(args));
}
_EXPORT int getpeername(int sock, struct sockaddr *addr, int *addrlen)
{
struct stack_driver_args args;
int rv;
args.u.sockaddr.addr = addr;
args.u.sockaddr.addrlen = *addrlen;
rv = ioctl(sock, NET_STACK_GETPEERNAME, &args, sizeof(args));
if (rv < 0)
return rv;
*addrlen = args.u.sockaddr.addrlen;
return rv;
}
_EXPORT int getsockname(int sock, struct sockaddr *addr, int *addrlen)
{
struct stack_driver_args args;
int rv;
args.u.sockaddr.addr = addr;
args.u.sockaddr.addrlen = *addrlen;
rv = ioctl(sock, NET_STACK_GETSOCKNAME, &args, sizeof(args));
if (rv < 0)
return rv;
*addrlen = args.u.sockaddr.addrlen;
return rv;
}
// #pragma mark -
_EXPORT int sysctl (int *name, uint namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
int s;
struct sysctl_args sa;
int rv;
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0)
return s;
sa.name = name;
sa.namelen = namelen;
sa.oldp = oldp;
sa.oldlenp = oldlenp;
sa.newp = newp;
sa.newlen = newlen;
rv = ioctl(s, NET_STACK_SYSCTL, &sa, sizeof(sa));
close(s);
return rv;
}
// #pragma mark -
/*
* Private routines
* ----------------
*/
static char * get_stack_driver_path(void) {
char * path;
// user-defined stack driver path?
path = getenv("NET_STACK_DRIVER_PATH");
if (path)
return path;
// use the default stack driver path
return NET_STACK_DRIVER_PATH;
}