nsprpub/pr/src/md/os2/os2sock.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/src/md/os2/os2sock.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,654 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* OS/2 Sockets module
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +/*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2    */
    1.15 +/*There is standard BSD (which is kind of slow) and a new flavor of select() that takes      */
    1.16 +/*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
    1.17 +/*a millisecond count for timeout. In the interest of performance I have choosen the OS/2    */
    1.18 +/*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info.          */ 
    1.19 +
    1.20 +#include "primpl.h"
    1.21 +
    1.22 +#include <sys/time.h> /* For timeval. */
    1.23 +
    1.24 +#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
    1.25 +#define READ_FD   1
    1.26 +#define WRITE_FD  2
    1.27 +
    1.28 +/* --- SOCKET IO --------------------------------------------------------- */
    1.29 +
    1.30 +
    1.31 +PRInt32
    1.32 +_PR_MD_SOCKET(int domain, int type, int flags)
    1.33 +{
    1.34 +    PRInt32 osfd, err;
    1.35 +
    1.36 +    osfd = socket(domain, type, flags);
    1.37 +
    1.38 +    if (osfd == -1) 
    1.39 +    {
    1.40 +        err = sock_errno();
    1.41 +        _PR_MD_MAP_SOCKET_ERROR(err);
    1.42 +    }
    1.43 +
    1.44 +    return(osfd);
    1.45 +}
    1.46 +
    1.47 +/*
    1.48 +** _MD_CloseSocket() -- Close a socket
    1.49 +**
    1.50 +*/
    1.51 +PRInt32
    1.52 +_MD_CloseSocket(PRInt32 osfd)
    1.53 +{
    1.54 +    PRInt32 rv, err;
    1.55 +
    1.56 +    rv = soclose(osfd);
    1.57 +    if (rv == -1) {
    1.58 +        err = sock_errno();
    1.59 +        _PR_MD_MAP_CLOSE_ERROR(err);
    1.60 +    }
    1.61 +    return rv;
    1.62 +}
    1.63 +
    1.64 +PRInt32
    1.65 +_MD_SocketAvailable(PRFileDesc *fd)
    1.66 +{
    1.67 +    PRInt32 result;
    1.68 +
    1.69 +    if (so_ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
    1.70 +        PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
    1.71 +        return -1;
    1.72 +    }
    1.73 +    return result;
    1.74 +}
    1.75 +
    1.76 +static PRInt32
    1.77 +socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
    1.78 +{
    1.79 +    PRInt32 rv = -1;
    1.80 +    PRThread *me = _PR_MD_CURRENT_THREAD();
    1.81 +    PRIntervalTime epoch, now, elapsed, remaining;
    1.82 +    PRBool wait_for_remaining;
    1.83 +    PRInt32 syserror;
    1.84 +#ifdef BSD_SELECT
    1.85 +    struct timeval tv;
    1.86 +    fd_set rd_wr;
    1.87 +#else
    1.88 +    int socks[1];
    1.89 +    long lTimeout;
    1.90 +#endif
    1.91 +
    1.92 +    switch (timeout) {
    1.93 +        case PR_INTERVAL_NO_WAIT:
    1.94 +            PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
    1.95 +            break;
    1.96 +        case PR_INTERVAL_NO_TIMEOUT:
    1.97 +            /*
    1.98 +             * This is a special case of the 'default' case below.
    1.99 +             * Please see the comments there.
   1.100 +             */
   1.101 +#ifdef BSD_SELECT
   1.102 +            tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
   1.103 +            tv.tv_usec = 0;
   1.104 +            FD_ZERO(&rd_wr);
   1.105 +            do {
   1.106 +                FD_SET(osfd, &rd_wr);
   1.107 +                if (fd_type == READ_FD)
   1.108 +                    rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
   1.109 +                else
   1.110 +                    rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
   1.111 +#else
   1.112 +            lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; 
   1.113 +            do {
   1.114 +                socks[0] = osfd;
   1.115 +                if (fd_type == READ_FD)
   1.116 +                    rv = os2_select(socks, 1, 0, 0, lTimeout);
   1.117 +                else
   1.118 +                    rv = os2_select(socks, 0, 1, 0, lTimeout);
   1.119 +#endif                    
   1.120 +                if (rv == -1 && (syserror = sock_errno()) != EINTR) {
   1.121 +                    _PR_MD_MAP_SELECT_ERROR(syserror);
   1.122 +                    break;
   1.123 +                }
   1.124 +                if (_PR_PENDING_INTERRUPT(me)) {
   1.125 +                    me->flags &= ~_PR_INTERRUPT;
   1.126 +                    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   1.127 +                    rv = -1;
   1.128 +                    break;
   1.129 +                }
   1.130 +            } while (rv == 0 || (rv == -1 && syserror == EINTR));
   1.131 +            break;
   1.132 +        default:
   1.133 +            now = epoch = PR_IntervalNow();
   1.134 +            remaining = timeout;
   1.135 +#ifdef BSD_SELECT
   1.136 +            FD_ZERO(&rd_wr);
   1.137 +#endif
   1.138 +            do {
   1.139 +                /*
   1.140 +                 * We block in select for at most
   1.141 +                 * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
   1.142 +                 * so that there is an upper limit on the delay
   1.143 +                 * before the interrupt bit is checked.
   1.144 +                 */
   1.145 +#ifdef BSD_SELECT
   1.146 +                wait_for_remaining = PR_TRUE;
   1.147 +                tv.tv_sec = PR_IntervalToSeconds(remaining);
   1.148 +                if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
   1.149 +                    wait_for_remaining = PR_FALSE;
   1.150 +                    tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
   1.151 +                    tv.tv_usec = 0;
   1.152 +                } else {
   1.153 +                    tv.tv_usec = PR_IntervalToMicroseconds(
   1.154 +                        remaining -
   1.155 +                        PR_SecondsToInterval(tv.tv_sec));
   1.156 +                }
   1.157 +                FD_SET(osfd, &rd_wr);
   1.158 +                if (fd_type == READ_FD)
   1.159 +                    rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
   1.160 +                else
   1.161 +                    rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
   1.162 +#else
   1.163 +                wait_for_remaining = PR_TRUE;
   1.164 +                lTimeout = PR_IntervalToMilliseconds(remaining);
   1.165 +                if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
   1.166 +                    wait_for_remaining = PR_FALSE;
   1.167 +                    lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
   1.168 +                }
   1.169 +                socks[0] = osfd;
   1.170 +                if (fd_type == READ_FD)
   1.171 +                    rv = os2_select(socks, 1, 0, 0, lTimeout);
   1.172 +                else
   1.173 +                    rv = os2_select(socks, 0, 1, 0, lTimeout);
   1.174 +#endif
   1.175 +                /*
   1.176 +                 * we don't consider EINTR a real error
   1.177 +                 */
   1.178 +                if (rv == -1 && (syserror = sock_errno()) != EINTR) {
   1.179 +                    _PR_MD_MAP_SELECT_ERROR(syserror);
   1.180 +                    break;
   1.181 +                }
   1.182 +                if (_PR_PENDING_INTERRUPT(me)) {
   1.183 +                    me->flags &= ~_PR_INTERRUPT;
   1.184 +                    PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   1.185 +                    rv = -1;
   1.186 +                    break;
   1.187 +                }
   1.188 +                /*
   1.189 +                 * We loop again if select timed out or got interrupted
   1.190 +                 * by a signal, and the timeout deadline has not passed yet.
   1.191 +                 */
   1.192 +                if (rv == 0 || (rv == -1 && syserror == EINTR)) {
   1.193 +                    /*
   1.194 +                     * If select timed out, we know how much time
   1.195 +                     * we spent in blocking, so we can avoid a
   1.196 +                     * PR_IntervalNow() call.
   1.197 +                     */
   1.198 +                    if (rv == 0) {
   1.199 +                        if (wait_for_remaining) {
   1.200 +                            now += remaining;
   1.201 +                        } else {
   1.202 +#ifdef BSD_SELECT
   1.203 +                            now += PR_SecondsToInterval(tv.tv_sec)
   1.204 +                                + PR_MicrosecondsToInterval(tv.tv_usec);
   1.205 +#else
   1.206 +                            now += PR_MillisecondsToInterval(lTimeout);
   1.207 +#endif
   1.208 +                        }
   1.209 +                    } else {
   1.210 +                        now = PR_IntervalNow();
   1.211 +                    }
   1.212 +                    elapsed = (PRIntervalTime) (now - epoch);
   1.213 +                    if (elapsed >= timeout) {
   1.214 +                        PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
   1.215 +                        rv = -1;
   1.216 +                        break;
   1.217 +                    } else {
   1.218 +                        remaining = timeout - elapsed;
   1.219 +                    }
   1.220 +                }
   1.221 +            } while (rv == 0 || (rv == -1 && syserror == EINTR));
   1.222 +            break;
   1.223 +        }
   1.224 +    return(rv);
   1.225 +}
   1.226 +
   1.227 +PRInt32
   1.228 +_MD_Accept(PRFileDesc *fd, PRNetAddr *addr,
   1.229 +           PRUint32 *addrlen, PRIntervalTime timeout)
   1.230 +{
   1.231 +    PRInt32 osfd = fd->secret->md.osfd;
   1.232 +    PRInt32 rv, err;
   1.233 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.234 +
   1.235 +    while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1)
   1.236 +    {
   1.237 +        err = sock_errno();
   1.238 +        if ((err == EWOULDBLOCK) || (err == ECONNABORTED))
   1.239 +        {
   1.240 +            if (fd->secret->nonblocking) {
   1.241 +                break;
   1.242 +            }
   1.243 +                if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   1.244 +                    goto done;
   1.245 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.246 +            continue;
   1.247 +        } else {
   1.248 +            break;
   1.249 +        }
   1.250 +    }
   1.251 +    if (rv < 0) {
   1.252 +        _PR_MD_MAP_ACCEPT_ERROR(err);
   1.253 +    }
   1.254 +done:
   1.255 +    return(rv);
   1.256 +}
   1.257 +
   1.258 +PRInt32
   1.259 +_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, 
   1.260 +               PRIntervalTime timeout)
   1.261 +{
   1.262 +    PRInt32 rv, err;
   1.263 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.264 +    PRInt32 osfd = fd->secret->md.osfd;
   1.265 +    PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect
   1.266 +                                 * modifies the sockaddr structure.
   1.267 +                                 * See Bugzilla bug 100776. */
   1.268 +
   1.269 +     /*
   1.270 +      * We initiate the connection setup by making a nonblocking connect()
   1.271 +      * call.  If the connect() call fails, there are two cases we handle
   1.272 +      * specially:
   1.273 +      * 1. The connect() call was interrupted by a signal.  In this case
   1.274 +      *    we simply retry connect().
   1.275 +      * 2. The NSPR socket is nonblocking and connect() fails with
   1.276 +      *    EINPROGRESS.  We first wait until the socket becomes writable.
   1.277 +      *    Then we try to find out whether the connection setup succeeded
   1.278 +      *    or failed.
   1.279 +      */
   1.280 +
   1.281 +retry:
   1.282 +    if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1)
   1.283 +    {
   1.284 +        err = sock_errno();
   1.285 +
   1.286 +        if (err == EINTR) {
   1.287 +            if (_PR_PENDING_INTERRUPT(me)) {
   1.288 +                me->flags &= ~_PR_INTERRUPT;
   1.289 +                PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   1.290 +                return -1;
   1.291 +            }
   1.292 +            goto retry;
   1.293 +        }
   1.294 +
   1.295 +        if (!fd->secret->nonblocking && (err == EINPROGRESS))
   1.296 +        {
   1.297 +            /*
   1.298 +             * socket_io_wait() may return -1 or 1.
   1.299 +             */
   1.300 +
   1.301 +            rv = socket_io_wait(osfd, WRITE_FD, timeout);
   1.302 +            if (rv == -1) {
   1.303 +                return -1;
   1.304 +            }
   1.305 +
   1.306 +            PR_ASSERT(rv == 1);
   1.307 +            if (_PR_PENDING_INTERRUPT(me)) {
   1.308 +                me->flags &= ~_PR_INTERRUPT;
   1.309 +                PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
   1.310 +                return -1;
   1.311 +            }
   1.312 +            err = _MD_os2_get_nonblocking_connect_error(osfd);
   1.313 +            if (err != 0) {
   1.314 +                _PR_MD_MAP_CONNECT_ERROR(err);
   1.315 +                return -1;
   1.316 +            }
   1.317 +            return 0;
   1.318 +        }
   1.319 +        
   1.320 +        _PR_MD_MAP_CONNECT_ERROR(err);
   1.321 +    }
   1.322 +
   1.323 +    return rv;
   1.324 +}  /* _MD_connect */
   1.325 +
   1.326 +PRInt32
   1.327 +_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
   1.328 +{
   1.329 +    PRInt32 rv, err;
   1.330 +    rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
   1.331 +    if (rv < 0) {
   1.332 +        err = sock_errno();
   1.333 +        _PR_MD_MAP_BIND_ERROR(err);
   1.334 +    }
   1.335 +    return(rv);
   1.336 +}
   1.337 +
   1.338 +
   1.339 +PRInt32
   1.340 +_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
   1.341 +{
   1.342 +    PRInt32 rv, err;
   1.343 +    rv = listen(fd->secret->md.osfd, backlog);
   1.344 +    if (rv < 0)  {
   1.345 +        err = sock_errno();
   1.346 +        _PR_MD_MAP_DEFAULT_ERROR(err);
   1.347 +    }
   1.348 +    return(rv);
   1.349 +}
   1.350 +
   1.351 +
   1.352 +PRInt32
   1.353 +_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 
   1.354 +            PRIntervalTime timeout)
   1.355 +{
   1.356 +    PRInt32 osfd = fd->secret->md.osfd;
   1.357 +    PRInt32 rv, err;
   1.358 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.359 +
   1.360 +    while ((rv = recv(osfd,buf,amount,flags)) == -1)
   1.361 +    {
   1.362 +        err = sock_errno();
   1.363 +        if ((err == EWOULDBLOCK)) {
   1.364 +            if (fd->secret->nonblocking) {
   1.365 +                break;
   1.366 +            }
   1.367 +            if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   1.368 +                goto done;
   1.369 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.370 +            continue;
   1.371 +        } else {
   1.372 +            break;
   1.373 +        }
   1.374 +    }
   1.375 +    if (rv < 0) {
   1.376 +        _PR_MD_MAP_RECV_ERROR(err);
   1.377 +    }
   1.378 +done:
   1.379 +    return(rv);
   1.380 +}
   1.381 +
   1.382 +PRInt32
   1.383 +_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
   1.384 +            PRIntervalTime timeout)
   1.385 +{
   1.386 +    PRInt32 osfd = fd->secret->md.osfd;
   1.387 +    PRInt32 rv, err;
   1.388 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.389 +
   1.390 +    while ((rv = send(osfd,buf,amount,flags)) == -1)
   1.391 +    {
   1.392 +        err = sock_errno();
   1.393 +        if ((err == EWOULDBLOCK)) {
   1.394 +            if (fd->secret->nonblocking) {
   1.395 +                break;
   1.396 +            }
   1.397 +            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
   1.398 +                goto done;
   1.399 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.400 +            continue;
   1.401 +        } else {
   1.402 +            break;
   1.403 +        }
   1.404 +    }
   1.405 +
   1.406 +     /*
   1.407 +      * optimization; if bytes sent is less than "amount" call
   1.408 +      * select before returning. This is because it is likely that
   1.409 +      * the next send() call will return EWOULDBLOCK.
   1.410 +      */
   1.411 +    if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
   1.412 +        && (timeout != PR_INTERVAL_NO_WAIT))
   1.413 +    {
   1.414 +        if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
   1.415 +            rv = -1;
   1.416 +            goto done;
   1.417 +        }
   1.418 +    }
   1.419 +    if (rv < 0) {
   1.420 +        _PR_MD_MAP_SEND_ERROR(err);
   1.421 +    }
   1.422 +done:
   1.423 +    return(rv);
   1.424 +}
   1.425 +
   1.426 +PRInt32
   1.427 +_PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
   1.428 +              const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
   1.429 +{
   1.430 +    PRInt32 osfd = fd->secret->md.osfd;
   1.431 +    PRInt32 rv, err;
   1.432 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.433 +    while ((rv = sendto(osfd, buf, amount, flags,
   1.434 +           (struct sockaddr *) addr, addrlen)) == -1)
   1.435 +    {
   1.436 +        err = sock_errno();
   1.437 +        if ((err == EWOULDBLOCK))
   1.438 +        {
   1.439 +            if (fd->secret->nonblocking) {
   1.440 +                break;
   1.441 +            }
   1.442 +            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
   1.443 +                goto done;
   1.444 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.445 +            continue;
   1.446 +        } else {
   1.447 +            break;
   1.448 +        }
   1.449 +    }
   1.450 +    if (rv < 0) {
   1.451 +        _PR_MD_MAP_SENDTO_ERROR(err);
   1.452 +    }
   1.453 +done:
   1.454 +    return(rv);
   1.455 +}
   1.456 +
   1.457 +PRInt32
   1.458 +_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
   1.459 +                PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
   1.460 +{
   1.461 +    PRInt32 osfd = fd->secret->md.osfd;
   1.462 +    PRInt32 rv, err;
   1.463 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.464 +
   1.465 +    while( (*addrlen = PR_NETADDR_SIZE(addr)),
   1.466 +           ((rv = recvfrom(osfd, buf, amount, flags,
   1.467 +             (struct sockaddr *) addr, (int *)addrlen)) == -1))
   1.468 +    {
   1.469 +        err = sock_errno();
   1.470 +        if ((err == EWOULDBLOCK)) {
   1.471 +            if (fd->secret->nonblocking) {
   1.472 +                break;
   1.473 +            }
   1.474 +            if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
   1.475 +                goto done;
   1.476 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.477 +            continue;
   1.478 +        } else {
   1.479 +            break;
   1.480 +        }
   1.481 +    }
   1.482 +    if (rv < 0) {
   1.483 +        _PR_MD_MAP_RECVFROM_ERROR(err);
   1.484 +    }
   1.485 +done:
   1.486 +    return(rv);
   1.487 +}
   1.488 +
   1.489 +PRInt32
   1.490 +_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
   1.491 +              PRIntervalTime timeout)
   1.492 +{
   1.493 +    PRInt32 rv, err;
   1.494 +    PRThread *me = _PR_MD_CURRENT_THREAD();
   1.495 +    PRInt32 index, amount = 0;
   1.496 +    PRInt32 osfd = fd->secret->md.osfd;
   1.497 +    struct iovec osiov[PR_MAX_IOVECTOR_SIZE];
   1.498 +
   1.499 +    /* Ensured by PR_Writev */
   1.500 +    PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE);
   1.501 +
   1.502 +    /*
   1.503 +     * We can't pass iov to so_writev because PRIOVec and struct iovec
   1.504 +     * may not be binary compatible.  Make osiov a copy of iov and
   1.505 +     * pass osiov to so_writev .
   1.506 +     */
   1.507 +    for (index = 0; index < iov_size; index++) {
   1.508 +        osiov[index].iov_base = iov[index].iov_base;
   1.509 +        osiov[index].iov_len = iov[index].iov_len;
   1.510 +    }
   1.511 +
   1.512 +     /*
   1.513 +      * Calculate the total number of bytes to be sent; needed for
   1.514 +      * optimization later.
   1.515 +      * We could avoid this if this number was passed in; but it is
   1.516 +      * probably not a big deal because iov_size is usually small (less than
   1.517 +      * 3)
   1.518 +      */
   1.519 +    if (!fd->secret->nonblocking) {
   1.520 +        for (index=0; index<iov_size; index++) {
   1.521 +            amount += iov[index].iov_len;
   1.522 +        }
   1.523 +    }
   1.524 +
   1.525 +    while ((rv = so_writev(osfd, osiov, iov_size)) == -1) {
   1.526 +        err = sock_errno();
   1.527 +        if ((err == EWOULDBLOCK))    {
   1.528 +            if (fd->secret->nonblocking) {
   1.529 +                break;
   1.530 +            }
   1.531 +            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
   1.532 +                goto done;
   1.533 +        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
   1.534 +            continue;
   1.535 +        } else {
   1.536 +            break;
   1.537 +        }
   1.538 +    }
   1.539 +
   1.540 +     /*
   1.541 +      * optimization; if bytes sent is less than "amount" call
   1.542 +      * select before returning. This is because it is likely that
   1.543 +      * the next writev() call will return EWOULDBLOCK.
   1.544 +      */
   1.545 +    if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
   1.546 +          && (timeout != PR_INTERVAL_NO_WAIT)) {
   1.547 +        if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
   1.548 +            rv = -1;
   1.549 +            goto done;
   1.550 +        }
   1.551 +    }
   1.552 +    if (rv < 0) {
   1.553 +        _PR_MD_MAP_WRITEV_ERROR(err);
   1.554 +    }
   1.555 +done:
   1.556 +    return(rv);
   1.557 +}
   1.558 +
   1.559 +PRInt32
   1.560 +_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
   1.561 +{
   1.562 +    PRInt32 rv;
   1.563 +
   1.564 +    rv = shutdown(fd->secret->md.osfd, how);
   1.565 +    if (rv < 0)
   1.566 +        _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
   1.567 +    return rv;
   1.568 +}
   1.569 +
   1.570 +PRInt32
   1.571 +_PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd)
   1.572 +{
   1.573 +    PRInt32 rv, err;
   1.574 +
   1.575 +    rv = socketpair(af, type, flags, osfd);
   1.576 +    if (rv < 0) {
   1.577 +        err = _MD_ERRNO();
   1.578 +        _PR_MD_MAP_SOCKETPAIR_ERROR(err);
   1.579 +    }
   1.580 +    return rv;
   1.581 +}
   1.582 +
   1.583 +PRStatus
   1.584 +_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
   1.585 +{
   1.586 +    PRInt32 rv, err;
   1.587 +
   1.588 +    rv = getsockname(fd->secret->md.osfd,
   1.589 +                     (struct sockaddr *) addr, (int *)addrlen);
   1.590 +    if (rv < 0) {
   1.591 +        err = sock_errno();
   1.592 +        _PR_MD_MAP_GETSOCKNAME_ERROR(err);
   1.593 +    }
   1.594 +    return rv==0?PR_SUCCESS:PR_FAILURE;
   1.595 +}
   1.596 +
   1.597 +PRStatus
   1.598 +_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
   1.599 +{
   1.600 +    PRInt32 rv, err;
   1.601 +
   1.602 +    rv = getpeername(fd->secret->md.osfd,
   1.603 +                     (struct sockaddr *) addr, (int *)addrlen);
   1.604 +    if (rv < 0) {
   1.605 +        err = sock_errno();
   1.606 +        _PR_MD_MAP_GETPEERNAME_ERROR(err);
   1.607 +    }
   1.608 +    return rv==0?PR_SUCCESS:PR_FAILURE;
   1.609 +}
   1.610 +
   1.611 +PRStatus
   1.612 +_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
   1.613 +                  char* optval, PRInt32* optlen)
   1.614 +{
   1.615 +    PRInt32 rv, err;
   1.616 +
   1.617 +    rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
   1.618 +    if (rv < 0) {
   1.619 +        err = sock_errno();
   1.620 +        _PR_MD_MAP_GETSOCKOPT_ERROR(err);
   1.621 +    }
   1.622 +    return rv==0?PR_SUCCESS:PR_FAILURE;
   1.623 +}
   1.624 +
   1.625 +PRStatus
   1.626 +_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
   1.627 +                  const char* optval, PRInt32 optlen)
   1.628 +{
   1.629 +    PRInt32 rv, err;
   1.630 +
   1.631 +    rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
   1.632 +    if (rv < 0) {
   1.633 +        err = sock_errno();
   1.634 +        _PR_MD_MAP_SETSOCKOPT_ERROR(err);
   1.635 +    }
   1.636 +    return rv==0?PR_SUCCESS:PR_FAILURE;
   1.637 +}
   1.638 +
   1.639 +void
   1.640 +_MD_MakeNonblock(PRFileDesc *fd)
   1.641 +{
   1.642 +    PRInt32 osfd = fd->secret->md.osfd;
   1.643 +    PRInt32 err;
   1.644 +    PRUint32  one = 1;
   1.645 +    
   1.646 +    if (osfd <= 2) {
   1.647 +        /* Don't mess around with stdin, stdout or stderr */
   1.648 +        return;
   1.649 +    }
   1.650 +
   1.651 +    err = so_ioctl( osfd, FIONBIO, (char *) &one, sizeof(one));
   1.652 +    if ( err != 0 )
   1.653 +    {
   1.654 +        err = sock_errno();
   1.655 +        _PR_MD_MAP_SOCKET_ERROR(err);
   1.656 +    }
   1.657 +}

mercurial