Milán Major

netscape-revival

1 branch
Code

sun-java/md/ionet_md.c

#ifdef __linux /* jwz */
# include <endian.h>
#endif

#include "fd_md.h"
#include "socket_md.h"
#include "sys_api.h"
#include "iomgr.h"

#ifdef XP_MAC
#include <Types.h>

#include "xp_sock.h"
#endif


/*
** XXX This entire file needs to be encapsualted into nspr so that the
** XXX extra subroutine layers disappear
*/
#if defined(XP_PC)
void sysSocketInitializeFD(Classjava_io_FileDescriptor *fdptr, int infd)
{
    fdptr->fd = infd+1;

    /* make the socket address immediatly available for reuse */
    setsockopt(infd, SOL_SOCKET, SO_REUSEADDR, "yes", 4);
}


long sysSocketAvailable(int fdnum, long *pbytes)
{
    int ret = 1;

    if (ioctlsocket(fdnum, FIONREAD, pbytes) < 0) {
	ret = 0;
    }
    return ret;
}
#endif

void sysSocketFD(Classjava_io_FileDescriptor *fd, long fdnum)
{
    if ((fdnum >= 0) || (fdnum <= 2)) {
	SignalError(0, JAVAPKG "SecurityException", 0);
	return;
    }
    fd->fd = fdnum+1;
}

int sysListenFD(Classjava_io_FileDescriptor *fd, long count)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysListen(fdnum, count);
}

int sysAcceptFD(Classjava_io_FileDescriptor *fd, struct sockaddr *him, int *len)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysAccept(fdnum, him, len);
}

int sysBindFD(Classjava_io_FileDescriptor *fd, void *him, int len)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysBind(fdnum, (struct sockaddr*)him, len);
}

int sysConnectFD(Classjava_io_FileDescriptor *fd, struct sockaddr *him, size_t len)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysConnect(fdnum, him, len);
}

int sysRecvFD(Classjava_io_FileDescriptor *fd, char *buf, int nbytes, int32_t flags)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysRecv(fdnum, buf, nbytes, flags);
}

int sysSendFD(Classjava_io_FileDescriptor *fd, char *buf, int nbytes, int32_t flags)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysSend(fdnum, buf, nbytes, flags);
}

int sysSendtoFD(Classjava_io_FileDescriptor *fd, char *buf, int nbytes,
		int flags, struct sockaddr *to, int tolen)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysSendTo(fdnum, buf, nbytes, flags, to, tolen);
}

int sysRecvfromFD(Classjava_io_FileDescriptor *fd, char *buf, int nbytes,
		  int flags, struct sockaddr *from, int *fromlen)
{
    int ret;
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    ret = sysRecvFrom(fdnum, buf, nbytes, flags, from, fromlen);

#ifdef XP_PC
    /*
    ** Unlike the Unix recvfrom(...) winsock will return an error
    ** if the input buffer is smaller than the datagram.  So, to emulate
    ** the expected behavior, ignore the error and return the buffer
    ** size.  
    ** Fortunately, winsock does fill the buffer before returning
    ** an error...
    */
    if( (ret == SOCKET_ERROR) && (WSAGetLastError() == WSAEMSGSIZE) ) {
        ret = nbytes;
    }
#endif

    return ret;
}

long sysSocketAvailableFD(Classjava_io_FileDescriptor *fd, long *pbytes)
{
    int fdnum = (int) fd->fd - 1;
    if (fdnum == -1) {
	return -1;
    }
    return sysSocketAvailable(fdnum, pbytes);
}

/************************************************************************/

#ifdef XP_UNIX
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>

int sysConnect(int fd, struct sockaddr* sa, int len)
{
#ifdef IRIX
    static int first_time = 1;
    static sigset_t timer_set;
    sigset_t oldset;
#endif
    int rv;

#ifdef IRIX
    if (first_time) {
	sigemptyset(&timer_set);
	sigaddset(&timer_set, SIGALRM);
	first_time = 0;
    }
    sigprocmask(SIG_BLOCK, &timer_set, &oldset);
#endif
    for (;;) {
	rv = connect(fd, sa, len);
	if (rv == 0) {
	    break;
	}
	if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
	    (errno == EAGAIN) || (errno == EINPROGRESS)) {
	    /* Call select here and wait for the connect to finish */
	    fd_set wr;
	    memset(&wr, 0, sizeof(wr));
	    FD_SET(fd, &wr);
	    rv = select(fd+1, 0, &wr, 0, 0);
	    continue;
	}
	if ((errno == EISCONN) || (errno == EALREADY)) {
	    /* Connection finished */
	    rv = 0;
	}
	/* Some other error */
	break;
    }
#ifdef IRIX
    sigprocmask(SIG_SETMASK, &oldset, 0);
#endif
    return rv;
}

int sysAccept(int fd, struct sockaddr* sa, int *lenp)
{
#ifdef IRIX
    static int first_time = 1;
    static sigset_t timer_set;
    sigset_t oldset;
#endif
    int rv;

#ifdef IRIX
    if (first_time) {
	sigemptyset(&timer_set);
	sigaddset(&timer_set, SIGALRM);
	first_time = 0;
    }
    sigprocmask(SIG_BLOCK, &timer_set, &oldset);
#endif
    for (;;) {
	rv = accept(fd, sa, lenp);
	if (rv >= 0) {
	    break;
	}
	if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
	    (errno == EAGAIN) || (errno == EINPROGRESS)) {
	    /* Call select here and wait for the accept to finish */
	    fd_set rd;
	    memset(&rd, 0, sizeof(rd));
	    FD_SET(fd, &rd);
	    rv = select(fd+1, &rd, 0, 0, 0);
	    continue;
	}
	/* Some other error */
	break;
    }
#ifdef IRIX
    sigprocmask(SIG_SETMASK, &oldset, 0);
#endif
    return rv;
}

int sysRecv(int fd, void *buf, int len, int flags)
{
    int rv;

    for (;;) {
	rv = recv(fd, buf, len, flags);
	if (rv < 0) {
	    if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
		(errno == EAGAIN)) {
		/* Wait in select */
		fd_set rd;
		memset(&rd, 0, sizeof(rd));
		FD_SET(fd, &rd);
		rv = select(fd+1, &rd, 0, 0, 0);
		continue;
	    }
	}
	break;
    }
    return rv;
}

int sysSend(int fd, const void *buf, int len, int flags)
{
    int rv;

    for (;;) {
	rv = send(fd, buf, len, flags);
	if (rv < 0) {
	    if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
		(errno == EAGAIN)) {
		/* Wait in select */
		fd_set wr;
		memset(&wr, 0, sizeof(wr));
		FD_SET(fd, &wr);
		rv = select(fd+1, 0, &wr, 0, 0);
		continue;
	    }
	}
	break;
    }
    return rv;
}

int sysRecvFrom(int fd, void *buf, int len, int flags,
		struct sockaddr *from, int *fromlen)
{
    int rv;

    for (;;) {
	rv = recvfrom(fd, buf, len, flags, from, fromlen);
	if (rv < 0) {
	    if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
		(errno == EAGAIN)) {
		/* Wait in select */
		fd_set rd;
		memset(&rd, 0, sizeof(rd));
		FD_SET(fd, &rd);
		rv = select(fd+1, &rd, 0, 0, 0);
		continue;
	    }
	}
	break;
    }
    return rv;
}

int sysSendTo(int fd, const void *buf, int len, int flags,
	      struct sockaddr *to, int tolen)
{
    int rv;

    for (;;) {
	rv = sendto(fd, buf, len, flags, to, tolen);
	if (rv < 0) {
	    if ((errno == EINTR) || (errno == EWOULDBLOCK) ||
		(errno == EAGAIN)) {
		/* Wait in select */
		fd_set wr;
		memset(&wr, 0, sizeof(wr));
		FD_SET(fd, &wr);
		rv = select(fd+1, 0, &wr, 0, 0);
		continue;
	    }
	}
	break;
    }
    return rv;
}

long sysSocketAvailable(int fdnum, long *pbytes)
{
    int ret = 1;

    if (ioctl(fdnum, FIONREAD, pbytes) < 0) {
	ret = 0;
    }
    return ret;
}

void sysSocketInitializeFD(Classjava_io_FileDescriptor *fdptr, int fdnum)
{
    int flags;

    fdptr->fd = fdnum+1;

    /* make the socket address immediatly available for reuse */
    setsockopt(fdnum, SOL_SOCKET, SO_REUSEADDR, "yes", 4);

    /* make the socket non-blocking with async-io */
    flags = fcntl(fdnum, F_GETFL, 0);
#if defined(FNDELAY)
    fcntl(fdnum, F_SETFL, flags | FNDELAY);/* XXX async i/o ! */
#elif defined(O_NONBLOCK)
    fcntl(fdnum, F_SETFL, flags | O_NONBLOCK);/* XXX async i/o ! */
#endif
}

#endif /* XP_UNIX */



#ifdef XP_MAC

long sysSocketAvailable(int fdnum, long *pbytes) 
{
	return macsock_socketavailable(fdnum, (size_t *)pbytes);
}


void sysSocketInitializeFD(Classjava_io_FileDescriptor *fdptr, int fdnum)
{
	Boolean		setBlocking = true;
	
    fdptr->fd = fdnum+1;
    
    /* make the socket address immediatly available for reuse */
    XP_SOCK_SETSOCKOPT(fdnum, SOL_SOCKET, SO_REUSEADDR, "yes", 4);
    sysIOCtl(fdnum, FIONBIO, &setBlocking);
    
    /* Make sure the socket is non-blocking. */
}
#endif /* XP_MAC */