nsprpub/pr/src/md/beos/bnet.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "primpl.h"
     8 #include <signal.h>
     9 #include <unistd.h>
    10 #include <memory.h>
    11 #include <fcntl.h>
    12 #include <sys/types.h>
    13 #include <sys/socket.h>
    14 #include <sys/time.h>
    15 #include <sys/ioctl.h>
    17 /*
    18  * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
    19  * PRInt32* pointer to a _PRSockLen_t* pointer.
    20  */
    21 #define _PRSockLen_t int
    24 /*
    25 ** Global lock variable used to bracket calls into rusty libraries that
    26 ** aren't thread safe (like libc, libX, etc).
    27 */
    28 static PRLock *_pr_rename_lock = NULL;
    29 static PRMonitor *_pr_Xfe_mon = NULL;
    31 #define READ_FD     1
    32 #define WRITE_FD    2
    34 /*
    35 ** This is a support routine to handle "deferred" i/o on sockets. 
    36 ** It uses "select", so it is subject to all of the BeOS limitations
    37 ** (only READ notification, only sockets)
    38 */
    40 /*
    41  * socket_io_wait --
    42  *
    43  * wait for socket i/o, periodically checking for interrupt
    44  *
    45  */
    47 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
    48                               PRIntervalTime timeout)
    49 {
    50     PRInt32 rv = -1;
    51     struct timeval tv;
    52     PRThread *me = _PR_MD_CURRENT_THREAD();
    53     PRIntervalTime epoch, now, elapsed, remaining;
    54     PRBool wait_for_remaining;
    55     PRInt32 syserror;
    56     fd_set rd_wr;
    58     switch (timeout) {
    59     case PR_INTERVAL_NO_WAIT:
    60         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
    61         break;
    62     case PR_INTERVAL_NO_TIMEOUT:
    63         /*
    64          * This is a special case of the 'default' case below.
    65          * Please see the comments there.
    66          */
    67         tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
    68         tv.tv_usec = 0;
    69         FD_ZERO(&rd_wr);
    70         do {
    71             FD_SET(osfd, &rd_wr);
    72             if (fd_type == READ_FD)
    73                 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
    74             else
    75                 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
    76             if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
    77 #ifdef BONE_VERSION
    78                 _PR_MD_MAP_SELECT_ERROR(syserror);
    79 #else
    80                 if (syserror == EBADF) {
    81                     PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
    82                 } else {
    83                     PR_SetError(PR_UNKNOWN_ERROR, syserror);
    84                 }
    85 #endif
    86                 break;
    87             }
    88             if (_PR_PENDING_INTERRUPT(me)) {
    89                 me->flags &= ~_PR_INTERRUPT;
    90                 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
    91                 rv = -1;
    92                 break;
    93             }
    94         } while (rv == 0 || (rv == -1 && syserror == EINTR));
    95         break;
    96     default:
    97         now = epoch = PR_IntervalNow();
    98         remaining = timeout;
    99         FD_ZERO(&rd_wr);
   100         do {
   101             /*
   102              * We block in _MD_SELECT for at most
   103              * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
   104              * so that there is an upper limit on the delay
   105              * before the interrupt bit is checked.
   106              */
   107             wait_for_remaining = PR_TRUE;
   108             tv.tv_sec = PR_IntervalToSeconds(remaining);
   109             if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
   110                 wait_for_remaining = PR_FALSE;
   111                 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
   112                 tv.tv_usec = 0;
   113             } else {
   114                 tv.tv_usec = PR_IntervalToMicroseconds(
   115                                  remaining -
   116                                  PR_SecondsToInterval(tv.tv_sec));
   117             }
   118             FD_SET(osfd, &rd_wr);
   119             if (fd_type == READ_FD)
   120                 rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
   121             else
   122                 rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
   123             /*
   124              * we don't consider EINTR a real error
   125              */
   126             if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
   127 #ifdef BONE_VERSION
   128                 _PR_MD_MAP_SELECT_ERROR(syserror);
   129 #else
   130                 if (syserror == EBADF) {
   131                     PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
   132                 } else {
   133                     PR_SetError(PR_UNKNOWN_ERROR, syserror);
   134                 }
   135 #endif
   136                 break;
   137             }
   138             if (_PR_PENDING_INTERRUPT(me)) {
   139                 me->flags &= ~_PR_INTERRUPT;
   140                 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   141                 rv = -1;
   142                 break;
   143             }
   144             /*
   145              * We loop again if _MD_SELECT timed out or got interrupted
   146              * by a signal, and the timeout deadline has not passed yet.
   147              */
   148             if (rv == 0 || (rv == -1 && syserror == EINTR)) {
   149                 /*
   150                  * If _MD_SELECT timed out, we know how much time
   151                  * we spent in blocking, so we can avoid a
   152                  * PR_IntervalNow() call.
   153                  */
   154                 if (rv == 0) {
   155                     if (wait_for_remaining) {
   156                         now += remaining;
   157                     } else {
   158                         now += PR_SecondsToInterval(tv.tv_sec)
   159                                + PR_MicrosecondsToInterval(tv.tv_usec);
   160                     }
   161                 } else {
   162                     now = PR_IntervalNow();
   163                 }
   164                 elapsed = (PRIntervalTime) (now - epoch);
   165                 if (elapsed >= timeout) {
   166                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
   167                     rv = -1;
   168                     break;
   169                 } else {
   170                     remaining = timeout - elapsed;
   171                 }
   172             }
   173         } while (rv == 0 || (rv == -1 && syserror == EINTR));
   174         break;
   175     }
   176     return(rv);
   177 }
   179 PRInt32
   180 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
   181           PRIntervalTime timeout)
   182 {
   183     PRInt32 osfd = fd->secret->md.osfd;
   184     PRInt32 rv, err;
   185     PRThread *me = _PR_MD_CURRENT_THREAD();
   187 #ifndef BONE_VERSION
   188     if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
   189         _PR_MD_MAP_RECV_ERROR(EPIPE);
   190         return -1;
   191     }
   192 #endif
   194 #ifdef BONE_VERSION
   195     /*
   196     ** Gah, stupid hack.  If reading a zero amount, instantly return success.
   197     ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
   198     ** mozilla use to check for socket availability.
   199     */
   201     if( 0 == amount ) return(0);
   202 #endif
   204     while ((rv = recv(osfd, buf, amount, flags)) == -1) {
   205         err = _MD_ERRNO();
   207         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
   208             if (fd->secret->nonblocking) {
   209                 break;
   210             }
   211             /* If socket was supposed to be blocking,
   212             wait a while for the condition to be
   213             satisfied. */
   214             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   215                 goto done;
   216         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   217             continue;
   219         } else
   220             break;
   221     }
   223     if (rv < 0) {
   224         _PR_MD_MAP_RECV_ERROR(err);
   225     }
   227 done:
   228     return(rv);
   229 }
   231 PRInt32
   232 _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
   233               PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
   234 {
   235     PRInt32 osfd = fd->secret->md.osfd;
   236     PRInt32 rv, err;
   237     PRThread *me = _PR_MD_CURRENT_THREAD();
   239     while ((*addrlen = PR_NETADDR_SIZE(addr)),
   240             ((rv = recvfrom(osfd, buf, amount, flags,
   241                             (struct sockaddr *) addr,
   242                             (_PRSockLen_t *)addrlen)) == -1)) {
   243         err = _MD_ERRNO();
   245         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
   246             if (fd->secret->nonblocking) {
   247                 break;
   248             }
   249             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   250                 goto done;
   252         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
   253             continue;
   254         } else {
   255             break;
   256         }
   257     }
   259     if (rv < 0) {
   260         _PR_MD_MAP_RECVFROM_ERROR(err);
   261     }
   263 done:
   264 #ifdef _PR_HAVE_SOCKADDR_LEN
   265     if (rv != -1) {
   266         /* ignore the sa_len field of struct sockaddr */
   267         if (addr) {
   268             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
   269         }
   270     }
   271 #endif /* _PR_HAVE_SOCKADDR_LEN */
   272     return(rv);
   273 }
   275 PRInt32
   276 _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
   277           PRIntervalTime timeout)
   278 {
   279     PRInt32 osfd = fd->secret->md.osfd;
   280     PRInt32 rv, err;
   281     PRThread *me = _PR_MD_CURRENT_THREAD();
   283 #ifndef BONE_VERSION
   284     if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
   285     {
   286         _PR_MD_MAP_SEND_ERROR(EPIPE);
   287         return -1;
   288     }
   289 #endif
   291     while ((rv = send(osfd, buf, amount, flags)) == -1) {
   292         err = _MD_ERRNO();
   294         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
   295             if (fd->secret->nonblocking) {
   296                 break;
   297             }
   299 #ifndef BONE_VERSION
   300             if( _PR_PENDING_INTERRUPT(me)) {
   302                 me->flags &= ~_PR_INTERRUPT;
   303                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   304                 return -1;
   305             }
   307             /* in UNIX implementations, you could do a socket_io_wait here.
   308              * but since BeOS doesn't yet support WRITE notification in select,
   309              * you're spanked.
   310              */
   311             snooze( 10000L );
   312             continue;
   313 #else /* BONE_VERSION */
   314             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
   315                 goto done;
   316 #endif
   318         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
   319             continue;
   321         } else {
   322             break;
   323         }
   324     }
   326 #ifdef BONE_VERSION
   327     /*
   328      * optimization; if bytes sent is less than "amount" call
   329      * select before returning. This is because it is likely that
   330      * the next writev() call will return EWOULDBLOCK.
   331      */
   332     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
   333         && (timeout != PR_INTERVAL_NO_WAIT)) {
   334         if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
   335             rv = -1;
   336             goto done;
   337         }
   338     }
   339 #endif /* BONE_VERSION */
   341     if (rv < 0) {
   342         _PR_MD_MAP_SEND_ERROR(err);
   343     }
   345 #ifdef BONE_VERSION
   346 done:
   347 #endif
   348     return(rv);
   349 }
   351 PRInt32
   352 _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
   353             const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
   354 {
   355     PRInt32 osfd = fd->secret->md.osfd;
   356     PRInt32 rv, err;
   357     PRThread *me = _PR_MD_CURRENT_THREAD();
   358 #ifdef _PR_HAVE_SOCKADDR_LEN
   359     PRNetAddr addrCopy;
   361     addrCopy = *addr;
   362     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
   363     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
   365     while ((rv = sendto(osfd, buf, amount, flags,
   366                         (struct sockaddr *) &addrCopy, addrlen)) == -1) {
   367 #else
   368     while ((rv = sendto(osfd, buf, amount, flags,
   369                         (struct sockaddr *) addr, addrlen)) == -1) {
   370 #endif
   371         err = _MD_ERRNO();
   373         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
   374             if (fd->secret->nonblocking) {
   375                 break;
   376             }
   378 #ifdef BONE_VERSION
   379             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
   380                 goto done;
   381 #endif
   382         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
   383             continue;
   385         } else {
   386             break;
   387         }
   388     }
   390     if (rv < 0) {
   391         _PR_MD_MAP_SENDTO_ERROR(err);
   392     }
   394 #ifdef BONE_VERSION
   395 done:
   396 #endif
   397     return(rv);
   398 }
   400 #ifdef BONE_VERSION
   402 PRInt32 _MD_writev(
   403     PRFileDesc *fd, const PRIOVec *iov,
   404     PRInt32 iov_size, PRIntervalTime timeout)
   405 {
   406     PRInt32 rv, err;
   407     PRThread *me = _PR_MD_CURRENT_THREAD();
   408     PRInt32 index, amount = 0;
   409     PRInt32 osfd = fd->secret->md.osfd;
   410     struct iovec osiov[PR_MAX_IOVECTOR_SIZE];
   412     /* Ensured by PR_Writev */
   413     PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE);
   415     /*
   416      * We can't pass iov to writev because PRIOVec and struct iovec
   417      * may not be binary compatible.  Make osiov a copy of iov and
   418      * pass osiov to writev.
   419      */
   420     for (index = 0; index < iov_size; index++) {
   421         osiov[index].iov_base = iov[index].iov_base;
   422         osiov[index].iov_len = iov[index].iov_len;
   423     }
   425     /*
   426      * Calculate the total number of bytes to be sent; needed for
   427      * optimization later.
   428      * We could avoid this if this number was passed in; but it is
   429      * probably not a big deal because iov_size is usually small (less than
   430      * 3)
   431      */
   432     if (!fd->secret->nonblocking) {
   433         for (index=0; index<iov_size; index++) {
   434             amount += iov[index].iov_len;
   435         }
   436     }
   438     while ((rv = writev(osfd, osiov, iov_size)) == -1) {
   439         err = _MD_ERRNO();
   440         if ((err == EAGAIN) || (err == EWOULDBLOCK))    {
   441             if (fd->secret->nonblocking) {
   442                 break;
   443             }
   444             if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
   445                 goto done;
   447         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   448             continue;
   449         } else {
   450             break;
   451         }
   452     }
   454     /*
   455      * optimization; if bytes sent is less than "amount" call
   456      * select before returning. This is because it is likely that
   457      * the next writev() call will return EWOULDBLOCK.
   458      */
   459     if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
   460         && (timeout != PR_INTERVAL_NO_WAIT)) {
   461         if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
   462             rv = -1;
   463             goto done;
   464         }
   465     }
   468     if (rv < 0) {
   469         _PR_MD_MAP_WRITEV_ERROR(err);
   470     }
   471 done:
   472     return(rv);
   473 }
   475 #endif /* BONE_VERSION */
   477 PRInt32
   478 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
   479             PRIntervalTime timeout)
   480 {
   481     PRInt32 osfd = fd->secret->md.osfd;
   482     PRInt32 rv, err;
   483     PRThread *me = _PR_MD_CURRENT_THREAD();
   485     while ((rv = accept(osfd, (struct sockaddr *) addr,
   486                         (_PRSockLen_t *)addrlen)) == -1) {
   487         err = _MD_ERRNO();
   489         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
   490             if (fd->secret->nonblocking) {
   491                 break;
   492             }
   493             /* If it's SUPPOSED to be a blocking thread, wait
   494              * a while to see if the triggering condition gets
   495              * satisfied.
   496              */
   497             /* Assume that we're always using a native thread */
   498             if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   499                 goto done;
   500         } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
   501             continue;
   502         } else {
   503             break;
   504         }
   505     }
   506     if (rv < 0) {
   507         _PR_MD_MAP_ACCEPT_ERROR(err);
   508     } else if (addr != NULL) {
   509         /* bug 134099 */
   510         err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
   511     }
   512 done:
   513 #ifdef _PR_HAVE_SOCKADDR_LEN
   514     if (rv != -1) {
   515         /* Mask off the first byte of struct sockaddr (the length field) */
   516         if (addr) {
   517             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
   518         }
   519     }
   520 #endif /* _PR_HAVE_SOCKADDR_LEN */
   521     return(rv);
   522 }
   524 PRInt32
   525 _MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
   526              PRIntervalTime timeout)
   527 {
   528     PRInt32 rv, err;
   529     PRThread *me = _PR_MD_CURRENT_THREAD();
   530     PRInt32 osfd = fd->secret->md.osfd;
   532 #ifndef BONE_VERSION
   533     fd->secret->md.connectValueValid = PR_FALSE;
   534 #endif
   535 #ifdef _PR_HAVE_SOCKADDR_LEN
   536     PRNetAddr addrCopy;
   538     addrCopy = *addr;
   539     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
   540     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
   541 #endif
   543     /* (Copied from unix.c)
   544      * We initiate the connection setup by making a nonblocking connect()
   545      * call.  If the connect() call fails, there are two cases we handle
   546      * specially:
   547      * 1. The connect() call was interrupted by a signal.  In this case
   548      *    we simply retry connect().
   549      * 2. The NSPR socket is nonblocking and connect() fails with
   550      *    EINPROGRESS.  We first wait until the socket becomes writable.
   551      *    Then we try to find out whether the connection setup succeeded
   552      *    or failed.
   553      */
   555 retry:
   556 #ifdef _PR_HAVE_SOCKADDR_LEN
   557     if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
   558 #else
   559     if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
   560 #endif
   561         err = _MD_ERRNO();
   562 #ifndef BONE_VERSION
   563         fd->secret->md.connectReturnValue = rv;
   564         fd->secret->md.connectReturnError = err;
   565         fd->secret->md.connectValueValid = PR_TRUE;
   566 #endif
   567         if( err == EINTR ) {
   569             if( _PR_PENDING_INTERRUPT(me)) {
   571                 me->flags &= ~_PR_INTERRUPT;
   572                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   573                 return -1;
   574             }
   575 #ifndef BONE_VERSION
   576             snooze( 100000L );
   577 #endif
   578             goto retry;
   579         }
   581 #ifndef BONE_VERSION
   582         if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
   584             /*
   585             ** There's no timeout on this connect, but that's not
   586             ** a big deal, since the connect times out anyways
   587             ** after 30 seconds.   Just sleep for 1/10th of a second
   588             ** and retry until we go through or die.
   589             */
   591             if( _PR_PENDING_INTERRUPT(me)) {
   592                 me->flags &= ~_PR_INTERRUPT;
   593                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   594                 return -1;
   595             }
   597             goto retry;
   598         }
   600         if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
   601             PR_Lock(_connectLock);
   602             if (connectCount < sizeof(connectList)/sizeof(connectList[0])) {
   603                 connectList[connectCount].osfd = osfd;
   604                 memcpy(&connectList[connectCount].addr, addr, addrlen);
   605                 connectList[connectCount].addrlen = addrlen;
   606                 connectList[connectCount].timeout = timeout;
   607                 connectCount++;
   608                 PR_Unlock(_connectLock);
   609                 _PR_MD_MAP_CONNECT_ERROR(err);
   610             } else {
   611                 PR_Unlock(_connectLock);
   612                 PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
   613             }
   614             return rv;
   615         }
   616 #else /* BONE_VERSION */
   617         if(!fd->secret->nonblocking && (err == EINTR)) {
   619             rv = socket_io_wait(osfd, WRITE_FD, timeout);
   620             if (rv == -1) {
   621                 return -1;
   622             }
   624             PR_ASSERT(rv == 1);
   625             if (_PR_PENDING_INTERRUPT(me)) {
   626                 me->flags &= ~_PR_INTERRUPT;
   627                 PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   628                 return -1;
   629             }
   630             err = _MD_beos_get_nonblocking_connect_error(osfd);
   631             if (err != 0) {
   632                 _PR_MD_MAP_CONNECT_ERROR(err);
   633                 return -1;
   634             }
   635             return 0;
   636         }
   637 #endif
   639         _PR_MD_MAP_CONNECT_ERROR(err);
   640     }
   642     return rv;
   643 }
   645 PRInt32
   646 _MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
   647 {
   648     PRInt32 rv, err;
   649 #ifdef _PR_HAVE_SOCKADDR_LEN
   650     PRNetAddr addrCopy;
   652     addrCopy = *addr;
   653     ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
   654     ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
   655     rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
   656 #else
   657     rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
   658 #endif
   659     if (rv < 0) {
   660         err = _MD_ERRNO();
   661         _PR_MD_MAP_BIND_ERROR(err);
   662     }
   664     return(rv);
   665 }
   667 PRInt32
   668 _MD_listen (PRFileDesc *fd, PRIntn backlog)
   669 {
   670     PRInt32 rv, err;
   672 #ifndef BONE_VERSION
   673     /* Bug workaround!  Setting listen to 0 on Be accepts no connections.
   674     ** On most UN*Xes this sets the default.
   675     */
   677     if( backlog == 0 ) backlog = 5;
   678 #endif
   680     rv = listen(fd->secret->md.osfd, backlog);
   681     if (rv < 0) {
   682         err = _MD_ERRNO();
   683         _PR_MD_MAP_LISTEN_ERROR(err);
   684     }
   686     return(rv);
   687 }
   689 PRInt32
   690 _MD_shutdown (PRFileDesc *fd, PRIntn how)
   691 {
   692     PRInt32 rv, err;
   694 #ifndef BONE_VERSION
   695     if (how == PR_SHUTDOWN_SEND)
   696         fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
   697     else if (how == PR_SHUTDOWN_RCV)
   698         fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
   699     else if (how == PR_SHUTDOWN_BOTH) {
   700         fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
   701     }
   703     return 0;
   704 #else /* BONE_VERSION */
   705     rv = shutdown(fd->secret->md.osfd, how);
   706     if (rv < 0) {
   707         err = _MD_ERRNO();
   708         _PR_MD_MAP_SHUTDOWN_ERROR(err);
   709     }
   710     return(rv);
   711 #endif
   712 }
   714 PRInt32
   715 _MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
   716 {
   717     return PR_NOT_IMPLEMENTED_ERROR;
   718 }
   720 PRInt32
   721 _MD_close_socket (PRInt32 osfd)
   722 {
   723 #ifdef BONE_VERSION
   724     close( osfd );
   725 #else
   726     closesocket( osfd );
   727 #endif
   728 }
   730 PRStatus
   731 _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
   732 {
   733     PRInt32 rv, err;
   735     rv = getsockname(fd->secret->md.osfd,
   736                      (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
   737 #ifdef _PR_HAVE_SOCKADDR_LEN
   738     if (rv == 0) {
   739         /* ignore the sa_len field of struct sockaddr */
   740         if (addr) {
   741             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
   742         }
   743     }
   744 #endif /* _PR_HAVE_SOCKADDR_LEN */
   745     if (rv < 0) {
   746         err = _MD_ERRNO();
   747         _PR_MD_MAP_GETSOCKNAME_ERROR(err);
   748     }
   750     return rv==0?PR_SUCCESS:PR_FAILURE;
   751 }
   753 PRStatus
   754 _MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
   755 {
   756     PRInt32 rv, err;
   758     rv = getpeername(fd->secret->md.osfd,
   759                      (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
   761 #ifdef _PR_HAVE_SOCKADDR_LEN
   762     if (rv == 0) {
   763         /* ignore the sa_len field of struct sockaddr */
   764         if (addr) {
   765             addr->raw.family = ((struct sockaddr *) addr)->sa_family;
   766         }
   767     }
   768 #endif /* _PR_HAVE_SOCKADDR_LEN */
   770     if (rv < 0) {
   771         err = _MD_ERRNO();
   772         _PR_MD_MAP_GETPEERNAME_ERROR(err);
   773     }
   774     return rv==0?PR_SUCCESS:PR_FAILURE;
   775 }
   777 PRStatus
   778 _MD_getsockopt (PRFileDesc *fd, PRInt32 level,
   779                 PRInt32 optname, char* optval, PRInt32* optlen)
   780 {
   781     PRInt32 rv, err;
   783     rv = getsockopt(fd->secret->md.osfd, level, optname,
   784                     optval, (_PRSockLen_t *)optlen);
   785     if (rv < 0) {
   786         err = _MD_ERRNO();
   787         _PR_MD_MAP_GETSOCKOPT_ERROR(err);
   788     }
   790     return rv==0?PR_SUCCESS:PR_FAILURE;
   791 }
   793 PRStatus
   794 _MD_setsockopt (PRFileDesc *fd, PRInt32 level,
   795                 PRInt32 optname, const char* optval, PRInt32 optlen)
   796 {
   797     PRInt32 rv, err;
   799     rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
   800     if (rv < 0) {
   801         err = _MD_ERRNO();
   802         _PR_MD_MAP_SETSOCKOPT_ERROR(err);
   803     }
   804     return rv==0?PR_SUCCESS:PR_FAILURE;
   805 }
   807 PRInt32
   808 _MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
   809                  void *buf, PRInt32 amount, PRIntervalTime timeout)
   810 {
   811     return PR_NOT_IMPLEMENTED_ERROR;
   812 }
   814 #ifndef BONE_VERSION
   815 PRInt32
   816 _MD_socket (int af, int type, int flags)
   817 {
   818     PRInt32 osfd, err;
   820     osfd = socket( af, type, 0 );
   822     if( -1 == osfd ) {
   824         err = _MD_ERRNO();
   825         _PR_MD_MAP_SOCKET_ERROR( err );
   826     }
   828     return( osfd );
   829 }
   830 #else
   831 PRInt32
   832 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
   833 {
   834     PRInt32 osfd, err;
   836     osfd = socket(domain, type, proto);
   838     if (osfd == -1) {
   839         err = _MD_ERRNO();
   840         _PR_MD_MAP_SOCKET_ERROR(err);
   841     }
   843     return(osfd);
   844 }
   845 #endif
   847 PRInt32
   848 _MD_socketavailable (PRFileDesc *fd)
   849 {
   850 #ifdef BONE_VERSION
   851     PRInt32 result;
   853     if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
   854         _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
   855         return -1;
   856     }
   857     return result;
   858 #else
   859     return PR_NOT_IMPLEMENTED_ERROR;
   860 #endif
   861 }
   863 PRInt32
   864 _MD_get_socket_error (void)
   865 {
   866     return PR_NOT_IMPLEMENTED_ERROR;
   867 }
   869 PRStatus
   870 _MD_gethostname (char *name, PRUint32 namelen)
   871 {
   872     PRInt32 rv, err;
   874     rv = gethostname(name, namelen);
   875     if (rv == 0)
   876     {
   877         err = _MD_ERRNO();
   878         _PR_MD_MAP_GETHOSTNAME_ERROR(err);
   879         return PR_FAILURE;
   880     }
   881     return PR_SUCCESS;
   882 }
   884 #ifndef BONE_VERSION
   885 PRInt32
   886 _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
   887 {
   888     int rv;
   889     int flags = 0;
   891     rv = recv(fd->secret->md.osfd, NULL, 0, flags);
   892     PR_ASSERT(-1 == rv || 0 == rv);
   893     if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
   894         return errno;
   895     }
   896     return 0;  /* no error */
   897 }
   898 #else
   899 PRInt32
   900 _MD_beos_get_nonblocking_connect_error(int osfd)
   901 {
   902     return PR_NOT_IMPLEMENTED_ERROR;
   903     //    int err;
   904     //    _PRSockLen_t optlen = sizeof(err);
   905     //    if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
   906     //        return errno;
   907     //    } else {
   908     //        return err;
   909     //    }
   910 }
   911 #endif /* BONE_VERSION */

mercurial