home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /* OS/2 Sockets module
- *
- */
-
- /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */
- /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */
- /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
- /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */
- /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */
-
- #include "primpl.h"
-
- void
- _PR_MD_INIT_IO()
- {
- sock_init();
- }
-
- /* --- SOCKET IO --------------------------------------------------------- */
-
-
- PRInt32
- _PR_MD_SOCKET(int af, int type, int flags)
- {
- int sock;
- PRUint32 one = 1;
- PRInt32 rv;
- PRInt32 err;
-
- sock = socket(af, type, flags);
-
- if (sock == -1 )
- {
- int rv = sock_errno();
- soclose(sock);
- _PR_MD_MAP_SOCKET_ERROR(rv);
- return (PRInt32) -1;
- }
-
- /*
- ** Make the socket Non-Blocking
- */
- rv = ioctl( sock, FIONBIO, (char *) &one, sizeof(one));
- if ( rv != 0 )
- {
- err = sock_errno();
- return -1;
- }
-
- return (PRInt32)sock;
- }
-
- /*
- ** _MD_CloseSocket() -- Close a socket
- **
- */
- PRInt32
- _MD_CloseSocket(PRInt32 osfd)
- {
- PRInt32 rv = -1;
-
- rv = soclose((int) osfd );
- if (rv < 0)
- _PR_MD_MAP_SOCKET_ERROR(sock_errno());
-
- return rv;
- }
-
- PRInt32
- _MD_SocketAvailable(PRFileDesc *fd)
- {
- PRInt32 result;
-
- if (ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
- return -1;
- }
- return result;
- }
-
- PRInt32
- _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
- PRIntervalTime timeout )
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- #ifdef BSD_SELECT
- fd_set rd;
- struct timeval tv, *tvp;
-
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- #else
- int socks[1];
- socks[0] = osfd;
- #endif
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- while ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- if ((rv = select(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
- #else
- if ((rv = select(socks, 1, 0, 0, -1)) == -1) {
- #endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- }
- else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- break;
- }
- }
- return(rv);
- }
- else if (timeout == PR_INTERVAL_NO_WAIT)
- {
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- else
- {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
- }
- return(rv);
- }
- else
- {
- retry:
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- rv = select(osfd + 1, &rd, NULL, NULL, tvp);
- #else
- long lTimeout = PR_IntervalToMilliseconds(timeout);
- rv = select(socks, 1, 0, 0, lTimeout);
- #endif
- if (rv > 0) {
- goto retry;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- } else {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- }
- } else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
- }
- }
- return(rv);
- } /* end _MD_Accept() */
-
-
-
- PRInt32
- _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv;
- int err, len;
- #ifdef BSD_SELECT
- fd_set wd, ex;
- struct timeval tv, *tvp;
- #else
- int socks[1];
- long lTimeout = -1;
- #endif
-
- if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
- {
- err = sock_errno();
- if ((!fd->secret->nonblocking) && (err == EINPROGRESS) || (err == EWOULDBLOCK))
- {
- #ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- tvp = NULL;
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
-
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- FD_ZERO(&ex);
- FD_SET(osfd, &ex);
- rv = select(osfd + 1, NULL, &wd, &ex, tvp);
- #else
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- lTimeout = -1;
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
-
- socks[0] = osfd;
- rv = select(socks, 0, 1, 1, lTimeout);
- #endif
- if (rv > 0)
- {
- #ifdef BSD_SELECT
- if (FD_ISSET(osfd, &ex))
- {
- DosSleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- if (err != 0)
- _PR_MD_MAP_CONNECT_ERROR(err);
- else
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- if (FD_ISSET(osfd, &wd))
- {
- /* it's connected */
- return 0;
- }
- #else
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- else
- return 0; /* It's connected ! */
- #endif
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return(-1);
- } else if (rv < 0)
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return(-1);
- }
- }
- _PR_MD_MAP_CONNECT_ERROR(err);
- }
- return rv;
- }
-
-
- PRInt32
- _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
- {
- PRInt32 rv;
- int one = 1;
-
- rv = bind(fd->secret->md.osfd, (struct sockaddr*) &(addr->inet), addrlen);
-
- if (rv == -1) {
- _PR_MD_MAP_BIND_ERROR(sock_errno());
- return -1;
- }
-
- return 0;
- }
-
-
- PRInt32
- _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- #ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
- #else
- int socks[1];
- long lTimeout = -1;
- #endif
-
- while ((rv = recv( osfd, buf, amount, 0)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
- #else
- socks[0] = osfd;
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- if ((rv = select(socks, 1, 0, 0, lTimeout)) == -1)
- #endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- }
- }
- else
- {
- _PR_MD_MAP_RECV_ERROR(err);
- break;
- }
- } /* end while() */
- return(rv);
- }
-
- PRInt32
- _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
- PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- #ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
- #else
- int socks[1];
- long lTimeout = -1;
- #endif
- PRInt32 bytesSent = 0;
-
- while(bytesSent < amount )
- {
- while ((rv = send( osfd, (char *) buf, amount, 0 )) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = select( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
- #else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = select( socks, 0, 1, 0, lTimeout)) == -1) {
- #endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SEND_ERROR(err);
- return -1;
- }
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
- break;
- }
- if ((rv >= 0) && (bytesSent < amount ))
- {
- #ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
- #else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = select(socks, 0, 1, 0,lTimeout)) == -1) {
- #endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- }
- return bytesSent;
- }
-
- PRInt32
- _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
- const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRInt32 bytesSent = 0;
- #ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
- #else
- int socks[1];
- long lTimeout = -1;
- #endif
-
- while(bytesSent < amount)
- {
- while ((rv = sendto( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- addrlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = select(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
- #else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = select(socks, 0, 1, 0, lTimeout)) == -1) {
- #endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SENDTO_ERROR(err);
- return -1;
- }
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
- break;
- }
- if ((rv >= 0) && (bytesSent < amount ))
- {
- #ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = select( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
- #else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = select( socks, 0, 1, 0, lTimeout)) == -1) {
- #endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- }
- return bytesSent;
- }
-
- PRInt32
- _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
- PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
- {
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRUint32 addrlen_temp = *addrlen;
- #ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
- #else
- int socks[1];
- long lTimeout = -1;
- #endif
-
- while ((rv = recvfrom( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- (int *) addrlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- #ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
- #else
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = select(socks, 1, 0, 0, lTimeout)) == -1)
- #endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- } else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- }
-
- /* recvfrom blows this value away if it fails first time */
- *addrlen = addrlen_temp;
- }
- else
- {
- _PR_MD_MAP_RECVFROM_ERROR(err);
- break;
- }
- }
- return(rv);
- }
-
- PRInt32
- _PR_MD_WRITEV(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
- {
- int index;
- int sent = 0;
- int rv;
-
- for (index=0; index < iov_size; index++)
- {
- rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
- if (rv > 0)
- sent += rv;
- if ( rv != iov[index].iov_len )
- {
- if (rv < 0)
- {
- if (fd->secret->nonblocking
- && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
- && (sent > 0))
- {
- return sent;
- }
- else
- {
- return -1;
- }
- }
- /* Only a nonblocking socket can have partial sends */
- PR_ASSERT(fd->secret->nonblocking);
- return sent;
- }
- }
- return sent;
- }
-
- PRInt32
- _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
- {
- PRInt32 rv;
-
- rv = shutdown(fd->secret->md.osfd, how);
- if (rv < 0)
- _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
- return rv;
- }
-
- PRStatus
- _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
- {
- PRInt32 rv;
-
- rv = getsockname((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKNAME_ERROR(sock_errno());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
- {
- PRInt32 rv;
-
- rv = getpeername((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETPEERNAME_ERROR(sock_errno());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
- {
- PRInt32 rv;
-
- rv = getsockopt((int)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
- }
- }
-
- PRStatus
- _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
- {
- PRInt32 rv;
-
- rv = setsockopt((int)fd->secret->md.osfd, level, optname, (char *) optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_SETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
- }
- }
-
- void
- _MD_MakeNonblock(PRFileDesc *f)
- {
- return; /* do nothing! */
- }
-