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

📄 sendrecv.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 2 页
字号:
    DWORD dwFlags = 0;
    DWORD nbytes;
    TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
    int ptr = 0;
    int bytes_to_send;   /* Bytes to send out of the file (not including headers) */
    int disconnected = 0;
    int sendv_trailers = 0;
    char hdtrbuf[4096];

    if (apr_os_level < APR_WIN_NT) {
        return APR_ENOTIMPL;
    }

    /* Use len to keep track of number of total bytes sent (including headers) */
    bytes_to_send = *len;
    *len = 0;

    /* Handle the goofy case of sending headers/trailers and a zero byte file */
    if (!bytes_to_send && hdtr) {
        if (hdtr->numheaders) {
            rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, 
                                  &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }
        if (hdtr->numtrailers) {
            rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers,
                                  &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }
        return APR_SUCCESS;
    }

    memset(&tfb, '\0', sizeof (tfb));
    /* Collapse the headers into a single buffer */
    if (hdtr && hdtr->numheaders) {
        ptfb = &tfb;
        nbytes = 0;
        rv = collapse_iovec((char **)&ptfb->Head, &ptfb->HeadLength, 
                            hdtr->headers, hdtr->numheaders, 
                            hdtrbuf, sizeof(hdtrbuf));
        /* If not enough buffer, punt to sendv */
        if (rv == APR_INCOMPLETE) {
            rv = apr_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
            ptfb = NULL;
        }
    }

    /* Initialize the overlapped structure used on TransmitFile 
     */
    if (!sock->overlapped) {
        sock->overlapped = apr_pcalloc(sock->cntxt, sizeof(OVERLAPPED));
        sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    }
    while (bytes_to_send) {
        if (bytes_to_send > MAX_SEGMENT_SIZE) {
            nbytes = MAX_SEGMENT_SIZE;
        }
        else {
            /* Last call to TransmitFile() */
            nbytes = bytes_to_send;
            /* Collapse the trailers into a single buffer */
            if (hdtr && hdtr->numtrailers) {
                ptfb = &tfb;
                rv = collapse_iovec((char**) &ptfb->Tail, &ptfb->TailLength,
                                    hdtr->trailers, hdtr->numtrailers,
                                    hdtrbuf + ptfb->HeadLength,
                                    sizeof(hdtrbuf) - ptfb->HeadLength);
                if (rv == APR_INCOMPLETE) {
                    /* If not enough buffer, punt to sendv, later */
                    sendv_trailers = 1;
                }
            }
            /* Disconnect the socket after last send */
            if ((flags & APR_SENDFILE_DISCONNECT_SOCKET)
                    && !sendv_trailers) {
                dwFlags |= TF_REUSE_SOCKET;
                dwFlags |= TF_DISCONNECT;
                disconnected = 1;
            }
        }

        sock->overlapped->Offset = (DWORD)(curoff);
#if APR_HAS_LARGE_FILES
        sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32);
#endif  
        /* XXX BoundsChecker claims dwFlags must not be zero. */
        rv = TransmitFile(sock->socketdes,  /* socket */
                          file->filehand, /* open file descriptor of the file to be sent */
                          nbytes,         /* number of bytes to send. 0=send all */
                          0,              /* Number of bytes per send. 0=use default */
                          sock->overlapped,    /* OVERLAPPED structure */
                          ptfb,           /* header and trailer buffers */
                          dwFlags);       /* flags to control various aspects of TransmitFile */
        if (!rv) {
            status = apr_get_netos_error();
            if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) ||
                (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) 
            {
                rv = WaitForSingleObject(sock->overlapped->hEvent, 
                                         (DWORD)(sock->timeout >= 0 
                                                 ? sock->timeout_ms : INFINITE));
                if (rv == WAIT_OBJECT_0) {
                    status = APR_SUCCESS;
                    if (!disconnected) {
                        if (!WSAGetOverlappedResult(sock->socketdes,
                                                    sock->overlapped,
                                                    &nbytes,
                                                    FALSE,
                                                    &dwFlags)) {
                            status = apr_get_netos_error();
                        }
                                               
                        /* Ugly code alert: WSAGetOverlappedResult returns
                         * a count of all bytes sent. This loop only
                         * tracks bytes sent out of the file.
                         */
                        else if (ptfb) {
                            nbytes -= (ptfb->HeadLength + ptfb->TailLength);
                        }
                    }
                }
                else if (rv == WAIT_TIMEOUT) {
                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
                }
                else if (rv == WAIT_ABANDONED) {
                    /* Hummm... WAIT_ABANDONDED is not an error code. It is
                     * a return specific to the Win32 WAIT functions that
                     * indicates that a thread exited while holding a
                     * mutex. Should consider triggering an assert
                     * to detect the condition...
                     */
                    status = APR_FROM_OS_ERROR(WAIT_TIMEOUT);
                }
                else
                    status = apr_get_os_error();
            }
        }
        if (status != APR_SUCCESS)
            break;

        bytes_to_send -= nbytes;
        curoff += nbytes;
        *len += nbytes;
        /* Adjust len for any headers/trailers sent */
        if (ptfb) {
            *len += (ptfb->HeadLength + ptfb->TailLength);
            memset(&tfb, '\0', sizeof (tfb));
            ptfb = NULL;
        }
    }

    if (status == APR_SUCCESS) {
        if (sendv_trailers) {
            rv = apr_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes);
            if (rv != APR_SUCCESS)
                return rv;
            *len += nbytes;
        }

    
        /* Mark the socket as disconnected, but do not close it.
         * Note: The application must have stored the socket prior to making
         * the call to apr_socket_sendfile in order to either reuse it 
         * or close it.
         */
        if (disconnected) {
            sock->disconnected = 1;
            sock->socketdes = INVALID_SOCKET;
        }
    }

    return status;
}

/* Deprecated */
APR_DECLARE(apr_status_t) apr_sendfile(apr_socket_t *sock, apr_file_t *file,
                                       apr_hdtr_t *hdtr, apr_off_t *offset,
                                       apr_size_t *len, apr_int32_t flags) 
{
    return apr_socket_sendfile(sock, file, hdtr, offset, len, flags);
}

#endif

/* Deprecated */
APR_DECLARE(apr_status_t) apr_send(apr_socket_t *sock, const char *buf,
                                   apr_size_t *len)
{
    return apr_socket_send(sock, buf, len);
}

/* Deprecated */
APR_DECLARE(apr_status_t) apr_sendv(apr_socket_t *sock,
                                    const struct iovec *vec,
                                    apr_int32_t nvec, apr_size_t *nbytes)
{
    return apr_socket_sendv(sock, vec, nvec, nbytes);
}

/* Deprecated */
APR_DECLARE(apr_status_t) apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where,
                                     apr_int32_t flags, const char *buf, 
                                     apr_size_t *len)
{
    return apr_socket_sendto(sock, where, flags, buf, len);
}

/* Deprecated */
APR_DECLARE(apr_status_t) apr_recvfrom(apr_sockaddr_t *from, 
                                       apr_socket_t *sock,
                                       apr_int32_t flags, 
                                       char *buf, apr_size_t *len)
{
    return apr_socket_recvfrom(from, sock, flags, buf, len);
}

/* Deprecated */
APR_DECLARE(apr_status_t) apr_recv(apr_socket_t *sock, char *buf,
                                   apr_size_t *len) 
{
    return apr_socket_recv(sock, buf, len);
}

⌨️ 快捷键说明

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