Add workaround for missing addrlen in PRNetAddr & BONE failing getsockopt.
authorseawood%netscape.com
Sun, 10 Feb 2002 21:35:59 +0000
changeset 2244 b06bc2369074710e0bb648ece4a2f02ea9cdfe76
parent 2242 85877fd6dba8da0a49b7cc904d162f271ffdfe45
child 2252 1897928aa0846e5e1145c83a8e15e276242ea251
push idunknown
push userunknown
push dateunknown
bugs122364
Add workaround for missing addrlen in PRNetAddr & BONE failing getsockopt. Thanks to Paul Ashford <arougthopher@lizardland.net> for the patch. Bug #122364 r=wtc
pr/include/md/_beos.h
pr/src/io/prsocket.c
pr/src/md/beos/bnet.c
--- a/pr/include/md/_beos.h
+++ b/pr/include/md/_beos.h
@@ -46,16 +46,20 @@
 #include <support/SupportDefs.h>
 #include <kernel/OS.h>
 #include <dirent.h>
 
 /*
  * Internal configuration macros
  */
 
+#ifdef BONE_VERSION
+#define _PR_HAVE_SOCKADDR_LEN
+#endif
+
 #define PR_LINKER_ARCH	"beos"
 #define _PR_SI_SYSNAME  "BEOS"
 #ifdef __powerpc__
 #define _PR_SI_ARCHITECTURE "ppc"
 #else
 #define _PR_SI_ARCHITECTURE "x86"
 #endif
 #define PR_DLL_SUFFIX		".so"
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -350,23 +350,33 @@ static PRStatus PR_CALLBACK SocketConnec
     err = _MD_mac_get_nonblocking_connect_error(osfd);
     if (err == -1)
         return PR_FAILURE;
 	else     
 		return PR_SUCCESS;
 
 #elif defined(XP_BEOS)
 
+#ifdef BONE_VERSION  /* bug 122364 */
+    /* temporary workaround until getsockopt(SO_ERROR) works in BONE */
+    if (out_flags & PR_POLL_EXCEPT) {
+        PR_SetError(PR_CONNECT_REFUSED_ERROR, 0);
+        return PR_FAILURE;
+    }
+    PR_ASSERT(out_flags & PR_POLL_WRITE);
+    return PR_SUCCESS;
+#else
     err = _MD_beos_get_nonblocking_connect_error(fd);
     if( err != 0 ) {
-	_PR_MD_MAP_CONNECT_ERROR(err);
-	return PR_FAILURE;
+        _PR_MD_MAP_CONNECT_ERROR(err);
+        return PR_FAILURE;
     }
     else
-	return PR_SUCCESS;
+        return PR_SUCCESS;
+#endif /* BONE_VERSION */
 
 #else
     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
     return PR_FAILURE;
 #endif
 }
 
 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
--- a/pr/src/md/beos/bnet.c
+++ b/pr/src/md/beos/bnet.c
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; c-basic-offset: 4 -*- */
-/* 
+/*
  * The contents of this file are subject to the Mozilla Public
  * License Version 1.1 (the "License"); you may not use this file
  * except in compliance with the License. You may obtain a copy of
  * the License at http://www.mozilla.org/MPL/
  * 
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
@@ -52,338 +52,355 @@
 
 /*
 ** Global lock variable used to bracket calls into rusty libraries that
 ** aren't thread safe (like libc, libX, etc).
 */
 static PRLock *_pr_rename_lock = NULL;
 static PRMonitor *_pr_Xfe_mon = NULL;
 
-#define READ_FD		1
-#define WRITE_FD	2
+#define READ_FD     1
+#define WRITE_FD    2
 
-/* 
+/*
 ** This is a support routine to handle "deferred" i/o on sockets. 
 ** It uses "select", so it is subject to all of the BeOS limitations
 ** (only READ notification, only sockets)
 */
 
 /*
  * socket_io_wait --
  *
  * wait for socket i/o, periodically checking for interrupt
  *
  */
 
 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
-    PRIntervalTime timeout)
+                              PRIntervalTime timeout)
 {
     PRInt32 rv = -1;
     struct timeval tv;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime epoch, now, elapsed, remaining;
     PRInt32 syserror;
     fd_set rd_wr;
 
     switch (timeout) {
-	case PR_INTERVAL_NO_WAIT:
-	    PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
-	    break;
-	case PR_INTERVAL_NO_TIMEOUT:
-	    /*
-	     * This is a special case of the 'default' case below.
-	     * Please see the comments there.
-	     */
-	    tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
-	    tv.tv_usec = 0;
-	    FD_ZERO(&rd_wr);
-	    do {
-		FD_SET(osfd, &rd_wr);
-		if (fd_type == READ_FD)
-		    rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
-		else
-		    rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
-		if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+    case PR_INTERVAL_NO_WAIT:
+        PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+        break;
+    case PR_INTERVAL_NO_TIMEOUT:
+        /*
+         * This is a special case of the 'default' case below.
+         * Please see the comments there.
+         */
+        tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+        tv.tv_usec = 0;
+        FD_ZERO(&rd_wr);
+        do {
+            FD_SET(osfd, &rd_wr);
+            if (fd_type == READ_FD)
+                rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+            else
+                rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+            if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
 #ifdef BONE_VERSION
-		    _PR_MD_MAP_SELECT_ERROR(syserror);
+                _PR_MD_MAP_SELECT_ERROR(syserror);
 #else
-		    if (syserror == EBADF) {
-			PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
-		    } else {
-			PR_SetError(PR_UNKNOWN_ERROR, syserror);
-		    }
+                if (syserror == EBADF) {
+                    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+                } else {
+                    PR_SetError(PR_UNKNOWN_ERROR, syserror);
+                }
 #endif
-		    break;
-		}
-		if (_PR_PENDING_INTERRUPT(me)) {
-		    me->flags &= ~_PR_INTERRUPT;
-		    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
-		    rv = -1;
-		    break;
-		}
-	    } while (rv == 0 || (rv == -1 && syserror == EINTR));
-	    break;
-	default:
-	    now = epoch = PR_IntervalNow();
-	    remaining = timeout;
-	    FD_ZERO(&rd_wr);
-	    do {
-		/*
-		 * We block in _MD_SELECT for at most
-		 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
-		 * so that there is an upper limit on the delay
-		 * before the interrupt bit is checked.
-		 */
-		tv.tv_sec = PR_IntervalToSeconds(remaining);
-		if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
-		    tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
-		    tv.tv_usec = 0;
-		} else {
-		    tv.tv_usec = PR_IntervalToMicroseconds(
-			remaining -
-			PR_SecondsToInterval(tv.tv_sec));
-		}  
-		FD_SET(osfd, &rd_wr);
-		if (fd_type == READ_FD)
-		    rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
-		else
-		    rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
-		/*
-		 * we don't consider EINTR a real error
-		 */
-		if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+                break;
+            }
+            if (_PR_PENDING_INTERRUPT(me)) {
+                me->flags &= ~_PR_INTERRUPT;
+                PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+                rv = -1;
+                break;
+            }
+        } while (rv == 0 || (rv == -1 && syserror == EINTR));
+        break;
+    default:
+        now = epoch = PR_IntervalNow();
+        remaining = timeout;
+        FD_ZERO(&rd_wr);
+        do {
+            /*
+             * We block in _MD_SELECT for at most
+             * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+             * so that there is an upper limit on the delay
+             * before the interrupt bit is checked.
+             */
+            tv.tv_sec = PR_IntervalToSeconds(remaining);
+            if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+                tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+                tv.tv_usec = 0;
+            } else {
+                tv.tv_usec = PR_IntervalToMicroseconds(
+                                 remaining -
+                                 PR_SecondsToInterval(tv.tv_sec));
+            }
+            FD_SET(osfd, &rd_wr);
+            if (fd_type == READ_FD)
+                rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+            else
+                rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+            /*
+             * we don't consider EINTR a real error
+             */
+            if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
 #ifdef BONE_VERSION
-		    _PR_MD_MAP_SELECT_ERROR(syserror);
+                _PR_MD_MAP_SELECT_ERROR(syserror);
 #else
-		    if (syserror == EBADF) {
-			PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
-		    } else {
-			PR_SetError(PR_UNKNOWN_ERROR, syserror);
-		    }
+                if (syserror == EBADF) {
+                    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+                } else {
+                    PR_SetError(PR_UNKNOWN_ERROR, syserror);
+                }
 #endif
-		    break;
-		}
-		if (_PR_PENDING_INTERRUPT(me)) {
-		    me->flags &= ~_PR_INTERRUPT;
-		    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
-		    rv = -1;
-		    break;
-		}
-		/*
-		 * We loop again if _MD_SELECT timed out or got interrupted
-		 * by a signal, and the timeout deadline has not passed yet.
-		 */
-		if (rv == 0 || (rv == -1 && syserror == EINTR)) { 
-		    /*
-		     * If _MD_SELECT timed out, we know how much time
-		     * we spent in blocking, so we can avoid a
-		     * PR_IntervalNow() call.
-		     */
-		    if (rv == 0) {
-			now += PR_SecondsToInterval(tv.tv_sec)
-			    + PR_MicrosecondsToInterval(tv.tv_usec);
-		    } else {
-			now = PR_IntervalNow();
-		    }
-		    elapsed = (PRIntervalTime) (now - epoch);
-		    if (elapsed >= timeout) {
-			PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
-			rv = -1;
-			break;
-		    } else {
-			remaining = timeout - elapsed;
-		    }
-		}
-	    } while (rv == 0 || (rv == -1 && syserror == EINTR));
-	    break;
+                break;
+            }
+            if (_PR_PENDING_INTERRUPT(me)) {
+                me->flags &= ~_PR_INTERRUPT;
+                PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+                rv = -1;
+                break;
+            }
+            /*
+             * We loop again if _MD_SELECT timed out or got interrupted
+             * by a signal, and the timeout deadline has not passed yet.
+             */
+            if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+                /*
+                 * If _MD_SELECT timed out, we know how much time
+                 * we spent in blocking, so we can avoid a
+                 * PR_IntervalNow() call.
+                 */
+                if (rv == 0) {
+                    now += PR_SecondsToInterval(tv.tv_sec)
+                           + PR_MicrosecondsToInterval(tv.tv_usec);
+                } else {
+                    now = PR_IntervalNow();
+                }
+                elapsed = (PRIntervalTime) (now - epoch);
+                if (elapsed >= timeout) {
+                    PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+                    rv = -1;
+                    break;
+                } else {
+                    remaining = timeout - elapsed;
+                }
+            }
+        } while (rv == 0 || (rv == -1 && syserror == EINTR));
+        break;
     }
     return(rv);
-}  
+}
 
 PRInt32
 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
           PRIntervalTime timeout)
 {
     PRInt32 osfd = fd->secret->md.osfd;
     PRInt32 rv, err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
 #ifndef BONE_VERSION
     if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
-	_PR_MD_MAP_RECV_ERROR(EPIPE);
-	return -1;
+        _PR_MD_MAP_RECV_ERROR(EPIPE);
+        return -1;
     }
 #endif
 
 #ifdef BONE_VERSION
     /*
     ** Gah, stupid hack.  If reading a zero amount, instantly return success.
     ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
     ** mozilla use to check for socket availability.
     */
 
     if( 0 == amount ) return(0);
 #endif
 
     while ((rv = recv(osfd, buf, amount, flags)) == -1) {
-	err = _MD_ERRNO();
+        err = _MD_ERRNO();
 
-	if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
-	    if (fd->secret->nonblocking) {
-		break;
-	    }
-	    /* If socket was supposed to be blocking, 
-		wait a while for the condition to be
-		satisfied. */
-	    if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
-		goto done;
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
-	    continue;
+        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+            if (fd->secret->nonblocking) {
+                break;
+            }
+            /* If socket was supposed to be blocking,
+            wait a while for the condition to be
+            satisfied. */
+            if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+                goto done;
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+            continue;
 
-	} else 
-	    break;
+        } else
+            break;
     }
 
     if (rv < 0) {
-	_PR_MD_MAP_RECV_ERROR(err);
+        _PR_MD_MAP_RECV_ERROR(err);
     }
 
 done:
     return(rv);
 }
 
 PRInt32
 _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;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
     while ((*addrlen = PR_NETADDR_SIZE(addr)),
-	   ((rv = recvfrom(osfd, buf, amount, flags,
-			   (struct sockaddr *) addr,
-                           (_PRSockLen_t *)addrlen)) == -1)) {
-	err = _MD_ERRNO();
+            ((rv = recvfrom(osfd, buf, amount, flags,
+                            (struct sockaddr *) addr,
+                            (_PRSockLen_t *)addrlen)) == -1)) {
+        err = _MD_ERRNO();
 
-	if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
-	    if (fd->secret->nonblocking) {
-		break;
-	    }
+        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+            if (fd->secret->nonblocking) {
+                break;
+            }
             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
                 goto done;
 
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
-	    continue;
-
-	} else {
-	    break;
-	}
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+            continue;
+        } else {
+            break;
+        }
     }
 
     if (rv < 0) {
-	_PR_MD_MAP_RECVFROM_ERROR(err);
+        _PR_MD_MAP_RECVFROM_ERROR(err);
     }
 
 done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    if (rv != -1) {
+        /* ignore the sa_len field of struct sockaddr */
+        if (addr) {
+            addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+        }
+    }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
     return(rv);
 }
 
 PRInt32
 _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
           PRIntervalTime timeout)
 {
     PRInt32 osfd = fd->secret->md.osfd;
     PRInt32 rv, err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
 #ifndef BONE_VERSION
     if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
     {
-	_PR_MD_MAP_SEND_ERROR(EPIPE);
-	return -1;
+        _PR_MD_MAP_SEND_ERROR(EPIPE);
+        return -1;
     }
 #endif
 
     while ((rv = send(osfd, buf, amount, flags)) == -1) {
-	err = _MD_ERRNO();
+        err = _MD_ERRNO();
 
-	if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
-	    if (fd->secret->nonblocking) {
-		break;
-	    }
+        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+            if (fd->secret->nonblocking) {
+                break;
+            }
 
 #ifndef BONE_VERSION
-	    if( _PR_PENDING_INTERRUPT(me)) {
+            if( _PR_PENDING_INTERRUPT(me)) {
 
                 me->flags &= ~_PR_INTERRUPT;
                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
                 return -1;
             }
 
-	    /* in UNIX implementations, you could do a socket_io_wait here.
-	     * but since BeOS doesn't yet support WRITE notification in select,
-	     * you're spanked.
-	     */
-	     snooze( 10000L );
-	     continue;
+            /* in UNIX implementations, you could do a socket_io_wait here.
+             * but since BeOS doesn't yet support WRITE notification in select,
+             * you're spanked.
+             */
+            snooze( 10000L );
+            continue;
 #else /* BONE_VERSION */
-	    if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
-		goto done; 
+            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+                goto done;
 #endif
-	
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
-	    continue;
+
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+            continue;
 
-	} else {
-	    break;
-	}
+        } else {
+            break;
+        }
     }
 
     if (rv < 0) {
-	_PR_MD_MAP_SEND_ERROR(err);
+        _PR_MD_MAP_SEND_ERROR(err);
     }
 
 #ifdef BONE_VERSION
 done:
 #endif
     return(rv);
 }
 
 PRInt32
 _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;
     PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    PRNetAddr addrCopy;
+
+    addrCopy = *addr;
+    ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+    ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
 
     while ((rv = sendto(osfd, buf, amount, flags,
-			(struct sockaddr *) addr, addrlen)) == -1) {
-	err = _MD_ERRNO();
+                        (struct sockaddr *) &addrCopy, addrlen)) == -1) {
+#else
+    while ((rv = sendto(osfd, buf, amount, flags,
+                        (struct sockaddr *) addr, addrlen)) == -1) {
+#endif
+        err = _MD_ERRNO();
 
-	if ((err == EAGAIN) || (err == EWOULDBLOCK))	{
-	    if (fd->secret->nonblocking) {
-		break;
-	    }
+        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+            if (fd->secret->nonblocking) {
+                break;
+            }
 
 #ifdef BONE_VERSION
-	    if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
-		goto done;  
+            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+                goto done;
 #endif
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
-	    continue;
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+            continue;
 
-	} else {
-	    break;
-	}
+        } else {
+            break;
+        }
     }
 
     if (rv < 0) {
-	_PR_MD_MAP_SENDTO_ERROR(err);
+        _PR_MD_MAP_SENDTO_ERROR(err);
     }
 
 #ifdef BONE_VERSION
 done:
 #endif
     return(rv);
 }
 
@@ -401,202 +418,223 @@ PRInt32 _MD_writev(
     /*
      * Calculate the total number of bytes to be sent; needed for
      * optimization later.
      * We could avoid this if this number was passed in; but it is
      * probably not a big deal because iov_size is usually small (less than
      * 3)
      */
     if (!fd->secret->nonblocking) {
-	for (index=0; index<iov_size; index++) {
-	    amount += iov[index].iov_len;
-	}
+        for (index=0; index<iov_size; index++) {
+            amount += iov[index].iov_len;
+        }
     }
 
     while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
-	err = _MD_ERRNO();
-	if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
-	    if (fd->secret->nonblocking) {
-		break;
-	    }
-	    if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
-		goto done;
+        err = _MD_ERRNO();
+        if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
+            if (fd->secret->nonblocking) {
+                break;
+            }
+            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+                goto done;
 
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
-	    continue;
-	} else {
-	    break;
-	}
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+            continue;
+        } else {
+            break;
+        }
     }
 
     if (rv < 0) {
-	_PR_MD_MAP_WRITEV_ERROR(err);
+        _PR_MD_MAP_WRITEV_ERROR(err);
     }
 done:
     return(rv);
-} 
+}
 
 #endif /* BONE_VERSION */
 
 PRInt32
 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
             PRIntervalTime timeout)
 {
     PRInt32 osfd = fd->secret->md.osfd;
     PRInt32 rv, err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
     while ((rv = accept(osfd, (struct sockaddr *) addr,
-		    (_PRSockLen_t *)addrlen)) == -1) {
-	err = _MD_ERRNO();
+                        (_PRSockLen_t *)addrlen)) == -1) {
+        err = _MD_ERRNO();
 
-	if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
-	    if (fd->secret->nonblocking) {
-		    break;
-	    }
-#ifndef BONE_VERSION
-	    /* If it's SUPPOSED to be a blocking thread, wait
-	     * a while to see if the triggering condition gets
-	     * satisfied.
-	     */
-	    /* Assume that we're always using a native thread */
-#endif
-	    if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
-		goto done;
-	} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
-	    continue;
-	} else {
-	    break;
-	}
+        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+            if (fd->secret->nonblocking) {
+                break;
+            }
+            /* If it's SUPPOSED to be a blocking thread, wait
+             * a while to see if the triggering condition gets
+             * satisfied.
+             */
+            /* Assume that we're always using a native thread */
+            if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+                goto done;
+        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+            continue;
+        } else {
+            break;
+        }
     }
-
-#ifndef BONE_VERSION
-    if (addr) addr->raw.family = AF_INET;
-#endif
-
     if (rv < 0) {
-		_PR_MD_MAP_ACCEPT_ERROR(err);
+        _PR_MD_MAP_ACCEPT_ERROR(err);
     }
 done:
-#ifndef BONE_VERSION
 #ifdef _PR_HAVE_SOCKADDR_LEN
     if (rv != -1) {
-	/* Mask off the first byte of struct sockaddr (the length field) */
-	if (addr) {
-	    *((unsigned char *) addr) = 0;
+        /* Mask off the first byte of struct sockaddr (the length field) */
+        if (addr) {
+            addr->raw.family = ((struct sockaddr *) addr)->sa_family;
 #ifdef IS_LITTLE_ENDIAN
-	    addr->raw.family = ntohs(addr->raw.family);
+            addr->raw.family = ntohs(addr->raw.family);
 #endif
-	}
+        }
     }
 #endif /* _PR_HAVE_SOCKADDR_LEN */
-#endif /* !BONE_VERSION */
     return(rv);
 }
 
 PRInt32
 _MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
              PRIntervalTime timeout)
 {
-    PRInt32 osfd = fd->secret->md.osfd;
     PRInt32 rv, err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
+    PRInt32 osfd = fd->secret->md.osfd;
 
 #ifndef BONE_VERSION
     fd->secret->md.connectValueValid = PR_FALSE;
 #endif
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    PRNetAddr addrCopy;
+
+    addrCopy = *addr;
+    ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+    ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+#endif
+
+    /* (Copied from unix.c)
+     * We initiate the connection setup by making a nonblocking connect()
+     * call.  If the connect() call fails, there are two cases we handle
+     * specially:
+     * 1. The connect() call was interrupted by a signal.  In this case
+     *    we simply retry connect().
+     * 2. The NSPR socket is nonblocking and connect() fails with
+     *    EINPROGRESS.  We first wait until the socket becomes writable.
+     *    Then we try to find out whether the connection setup succeeded
+     *    or failed.
+     */
 
 retry:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
+#else
     if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+#endif
         err = _MD_ERRNO();
 #ifndef BONE_VERSION
-	fd->secret->md.connectReturnValue = rv;
-	fd->secret->md.connectReturnError = err;
-	fd->secret->md.connectValueValid = PR_TRUE;
+        fd->secret->md.connectReturnValue = rv;
+        fd->secret->md.connectReturnError = err;
+        fd->secret->md.connectValueValid = PR_TRUE;
 #endif
-	if( err == EINTR ) {
+        if( err == EINTR ) {
 
-	    if( _PR_PENDING_INTERRUPT(me)) {
+            if( _PR_PENDING_INTERRUPT(me)) {
 
-		me->flags &= ~_PR_INTERRUPT;
+                me->flags &= ~_PR_INTERRUPT;
                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
                 return -1;
             }
 #ifndef BONE_VERSION
-	    snooze( 100000L );
+            snooze( 100000L );
 #endif
             goto retry;
         }
 
 #ifndef BONE_VERSION
         if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
 
-	    /*
-	    ** There's no timeout on this connect, but that's not
-	    ** a big deal, since the connect times out anyways
-	    ** after 30 seconds.   Just sleep for 1/10th of a second
-	    ** and retry until we go through or die.
-	    */
+            /*
+            ** There's no timeout on this connect, but that's not
+            ** a big deal, since the connect times out anyways
+            ** after 30 seconds.   Just sleep for 1/10th of a second
+            ** and retry until we go through or die.
+            */
 
-	    if( _PR_PENDING_INTERRUPT(me)) {
+            if( _PR_PENDING_INTERRUPT(me)) {
                 me->flags &= ~_PR_INTERRUPT;
                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
                 return -1;
-            } 
+            }
 
-	    goto retry;
-	}
+            goto retry;
+        }
 
-	if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
-	    PR_Lock(_connectLock);
-	    connectList[connectCount].osfd = osfd;
-	    memcpy(&connectList[connectCount].addr, addr, addrlen);
-	    connectList[connectCount].addrlen = addrlen;
-	    connectList[connectCount].timeout = timeout;
-	    connectCount++;
-	    PR_Unlock(_connectLock);
-	    _PR_MD_MAP_CONNECT_ERROR(err);
-	    return rv;
-	}
+        if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
+            PR_Lock(_connectLock);
+            connectList[connectCount].osfd = osfd;
+            memcpy(&connectList[connectCount].addr, addr, addrlen);
+            connectList[connectCount].addrlen = addrlen;
+            connectList[connectCount].timeout = timeout;
+            connectCount++;
+            PR_Unlock(_connectLock);
+            _PR_MD_MAP_CONNECT_ERROR(err);
+            return rv;
+        }
 #else /* BONE_VERSION */
-	if(!fd->secret->nonblocking && (err == EINPROGRESS)) {
+        if(!fd->secret->nonblocking && (err == EINPROGRESS)) {
 
-	    rv = socket_io_wait(osfd, WRITE_FD, timeout);
-	    if (rv == -1) {
-		return -1;
-	    }
+            rv = socket_io_wait(osfd, WRITE_FD, timeout);
+            if (rv == -1) {
+                return -1;
+            }
 
-	    PR_ASSERT(rv == 1);
-	    if (_PR_PENDING_INTERRUPT(me)) {
-		me->flags &= ~_PR_INTERRUPT;
-		PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
-		return -1;
-	    }
-	    err = _MD_beos_get_nonblocking_connect_error(osfd);
-	    if (err != 0) {
-		_PR_MD_MAP_CONNECT_ERROR(err);
-		return -1;
-	    }
-	    return 0;
-	} 
+            PR_ASSERT(rv == 1);
+            if (_PR_PENDING_INTERRUPT(me)) {
+                me->flags &= ~_PR_INTERRUPT;
+                PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+                return -1;
+            }
+            err = _MD_beos_get_nonblocking_connect_error(osfd);
+            if (err != 0) {
+                _PR_MD_MAP_CONNECT_ERROR(err);
+                return -1;
+            }
+            return 0;
+        }
 #endif
 
-	_PR_MD_MAP_CONNECT_ERROR(err);
+        _PR_MD_MAP_CONNECT_ERROR(err);
     }
 
     return rv;
 }
 
 PRInt32
 _MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
 {
     PRInt32 rv, err;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    PRNetAddr addrCopy;
 
+    addrCopy = *addr;
+    ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+    ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+    rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
+#else
     rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
-
+#endif
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_BIND_ERROR(err);
     }
 
     return(rv);
 }
 
@@ -607,48 +645,48 @@ PRInt32
 
 #ifndef BONE_VERSION
     /* Bug workaround!  Setting listen to 0 on Be accepts no connections.
     ** On most UN*Xes this sets the default.
     */
 
     if( backlog == 0 ) backlog = 5;
 #endif
- 
+
     rv = listen(fd->secret->md.osfd, backlog);
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_LISTEN_ERROR(err);
     }
 
     return(rv);
 }
 
 PRInt32
 _MD_shutdown (PRFileDesc *fd, PRIntn how)
 {
     PRInt32 rv, err;
 
 #ifndef BONE_VERSION
     if (how == PR_SHUTDOWN_SEND)
-	fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
+        fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
     else if (how == PR_SHUTDOWN_RCV)
-	fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
+        fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
     else if (how == PR_SHUTDOWN_BOTH) {
-	fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
+        fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
     }
 
     return 0;
 #else /* BONE_VERSION */
     rv = shutdown(fd->secret->md.osfd, how);
     if (rv < 0) {
-	err = _MD_ERRNO();
-	_PR_MD_MAP_SHUTDOWN_ERROR(err);
+        err = _MD_ERRNO();
+        _PR_MD_MAP_SHUTDOWN_ERROR(err);
     }
-    return(rv); 
+    return(rv);
 #endif
 }
 
 PRInt32
 _MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
 {
     return PR_NOT_IMPLEMENTED_ERROR;
 }
@@ -665,17 +703,24 @@ PRInt32
 
 PRStatus
 _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
 {
     PRInt32 rv, err;
 
     rv = getsockname(fd->secret->md.osfd,
                      (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
-
+#ifdef _PR_HAVE_SOCKADDR_LEN
+    if (rv == 0) {
+        /* ignore the sa_len field of struct sockaddr */
+        if (addr) {
+            addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+        }
+    }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
     }
 
     return rv==0?PR_SUCCESS:PR_FAILURE;
 }
 
@@ -693,30 +738,26 @@ PRStatus
     }
     return rv==0?PR_SUCCESS:PR_FAILURE;
 }
 
 PRStatus
 _MD_getsockopt (PRFileDesc *fd, PRInt32 level,
                 PRInt32 optname, char* optval, PRInt32* optlen)
 {
-#ifndef BONE_VERSON
-    return PR_NOT_IMPLEMENTED_ERROR;
-#else
     PRInt32 rv, err;
 
     rv = getsockopt(fd->secret->md.osfd, level, optname,
                     optval, (_PRSockLen_t *)optlen);
     if (rv < 0) {
         err = _MD_ERRNO();
         _PR_MD_MAP_GETSOCKOPT_ERROR(err);
     }
 
     return rv==0?PR_SUCCESS:PR_FAILURE;
-#endif
 }
 
 PRStatus
 _MD_setsockopt (PRFileDesc *fd, PRInt32 level,
                 PRInt32 optname, const char* optval, PRInt32 optlen)
 {
     PRInt32 rv, err;
 
@@ -740,72 +781,72 @@ PRInt32
 _MD_socket (int af, int type, int flags)
 {
     PRInt32 osfd, err;
 
     osfd = socket( af, type, 0 );
 
     if( -1 == osfd ) {
 
-	err = _MD_ERRNO();
-	_PR_MD_MAP_SOCKET_ERROR( err );
+        err = _MD_ERRNO();
+        _PR_MD_MAP_SOCKET_ERROR( err );
     }
 
     return( osfd );
 }
 #else
 PRInt32
 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
 {
     PRInt32 osfd, err;
 
     osfd = socket(domain, type, proto);
 
     if (osfd == -1) {
-	err = _MD_ERRNO();
-	_PR_MD_MAP_SOCKET_ERROR(err);
+        err = _MD_ERRNO();
+        _PR_MD_MAP_SOCKET_ERROR(err);
     }
 
     return(osfd);
-} 
+}
 #endif
 
 PRInt32
 _MD_socketavailable (PRFileDesc *fd)
 {
 #ifdef BONE_VERSION
     PRInt32 result;
 
     if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
-	_PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
-	return -1;
+        _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
+        return -1;
     }
     return result;
 #else
     return PR_NOT_IMPLEMENTED_ERROR;
 #endif
 }
 
 PRInt32
 _MD_get_socket_error (void)
 {
     return PR_NOT_IMPLEMENTED_ERROR;
 }
 
 PRStatus
 _MD_gethostname (char *name, PRUint32 namelen)
 {
-PRInt32 rv, err;
+    PRInt32 rv, err;
 
     rv = gethostname(name, namelen);
     if (rv == 0)
     {
-	err = _MD_ERRNO();
-	_PR_MD_MAP_GETHOSTNAME_ERROR(err);
-	return PR_FAILURE;
+        err = _MD_ERRNO();
+        _PR_MD_MAP_GETHOSTNAME_ERROR(err);
+        return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
 #ifndef BONE_VERSION
 PRInt32
 _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
 {
@@ -818,17 +859,18 @@ PRInt32
         return errno;
     }
     return 0;  /* no error */
 }
 #else
 PRInt32
 _MD_beos_get_nonblocking_connect_error(int osfd)
 {
-    int err;
-    _PRSockLen_t optlen = sizeof(err);
-    if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
-	return errno;
-    } else {
-	return err;
-    }
-} 
+    return PR_NOT_IMPLEMENTED_ERROR;
+    //    int err;
+    //    _PRSockLen_t optlen = sizeof(err);
+    //    if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
+    //        return errno;
+    //    } else {
+    //        return err;
+    //    }
+}
 #endif /* BONE_VERSION */