⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bnet.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- 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 * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "primpl.h"#include <signal.h>#include <unistd.h>#include <memory.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>/* * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */#define _PRSockLen_t int/*** 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/*** 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){    PRInt32 rv = -1;    struct timeval tv;    PRThread *me = _PR_MD_CURRENT_THREAD();    PRIntervalTime epoch, now, elapsed, remaining;    PRBool wait_for_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) {#ifdef BONE_VERSION                _PR_MD_MAP_SELECT_ERROR(syserror);#else                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.             */            wait_for_remaining = PR_TRUE;            tv.tv_sec = PR_IntervalToSeconds(remaining);            if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {                wait_for_remaining = PR_FALSE;                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);#else                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) {                    if (wait_for_remaining) {                        now += remaining;                    } else {                        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;    }#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();        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;    }    if (rv < 0) {        _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();        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;        }    }    if (rv < 0) {        _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;    }#endif    while ((rv = send(osfd, buf, amount, flags)) == -1) {        err = _MD_ERRNO();        if ((err == EAGAIN) || (err == EWOULDBLOCK)) {            if (fd->secret->nonblocking) {                break;            }#ifndef BONE_VERSION            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;#else /* BONE_VERSION */            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)                goto done;#endif        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {            continue;        } else {            break;        }    }    if (rv < 0) {        _PR_MD_MAP_SEND_ERROR(err);    }#ifdef BONE_VERSIONdone:#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 *) &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;            }#ifdef BONE_VERSION            if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)                goto done;#endif        } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {            continue;        } else {            break;        }    }    if (rv < 0) {        _PR_MD_MAP_SENDTO_ERROR(err);    }#ifdef BONE_VERSIONdone:#endif    return(rv);}#ifdef BONE_VERSIONPRInt32 _MD_writev(    PRFileDesc *fd, const PRIOVec *iov,    PRInt32 iov_size, PRIntervalTime timeout){    PRInt32 rv, err;    PRThread *me = _PR_MD_CURRENT_THREAD();    PRInt32 index, amount = 0;    PRInt32 osfd = fd->secret->md.osfd;    /*     * 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;        }    }    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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -