stoddard    00/01/31 11:21:44

  Modified:    src/main http_protocol.c
               src/lib/apr/network_io/win32 sendrecv.c
  Log:
  Set timeouts to sendfile operation in http_protocol.c. Fix bugs in Win32
  sendfile implementation.
  
  Revision  Changes    Path
  1.53      +20 -10    apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -r1.52 -r1.53
  --- http_protocol.c   2000/01/28 18:01:16     1.52
  +++ http_protocol.c   2000/01/31 19:21:37     1.53
  @@ -963,9 +963,9 @@
   #endif
   
       ap_bsetopt(conn->client, BO_TIMEOUT,
  -        conn->keptalive
  -            ? &r->server->keep_alive_timeout
  -            : &r->server->timeout);
  +               conn->keptalive
  +               ? &r->server->keep_alive_timeout
  +               : &r->server->timeout);
   
       /* Get the request... */
       if (!read_request_line(r)) {
  @@ -2015,18 +2015,28 @@
    */
   API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
   {
  +    ap_status_t rv;
       long len = r->finfo.size;
   #ifdef HAVE_SENDFILE
       if (!r->chunked) {
  +        ap_bsetopt(r->connection->client, BO_TIMEOUT,
  +                   r->connection->keptalive
  +                   ? &r->server->keep_alive_timeout
  +                   : &r->server->timeout);
           ap_bflush(r->connection->client);
  -        if (iol_sendfile(r->connection->client->iol, 
  -                         fd,  /* The file to send */
  -                         NULL, /* header and trailer iovecs */
  -                         0,   /* Offset in file to begin sending from */
  -                         &len,
  -                         0) != APR_SUCCESS) {
  -            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +        rv = iol_sendfile(r->connection->client->iol, 
  +                          fd,     /* The file to send */
  +                          NULL,   /* header and trailer iovecs */
  +                          0,      /* Offset in file to begin sending from */
  +                          &len,
  +                          0);
  +        if (rv != APR_SUCCESS) {
  +            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                             "ap_send_fd: iol_sendfile failed.");
  +        }
  +        if (r->connection->keptalive) {
  +            ap_bsetopt(r->connection->client, BO_TIMEOUT, 
  +                       &r->server->timeout);
           }
       }
       else {
  
  
  
  1.7       +42 -60    apache-2.0/src/lib/apr/network_io/win32/sendrecv.c
  
  Index: sendrecv.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sendrecv.c,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- sendrecv.c        2000/01/27 05:57:34     1.6
  +++ sendrecv.c        2000/01/31 19:21:41     1.7
  @@ -69,26 +69,13 @@
       WSABUF wsaData;
       int lasterror;
       DWORD dwBytes = 0;
  -    int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
   
       wsaData.len = *len;
       wsaData.buf = (char*) buf;
   
  -    rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, 
  -                    sizeof(timeout));
  -    if (rv == SOCKET_ERROR) {
  -        return WSAGetLastError();
  -    }
  -
       rv = WSASend(sock->sock, &wsaData, 1, &dwBytes, 0, NULL, NULL);
       if (rv == SOCKET_ERROR) {
           lasterror = WSAGetLastError();
  -        /* Test code: Remove before release */
  -        if (lasterror == WSAETIMEDOUT)
  -            printf("wsasend: Connection timed out\n");
  -        else
  -            printf("wsasend: connection failed. lasterror = %d\n", 
lasterror);            
  -
           return lasterror;
       }
   
  @@ -104,25 +91,13 @@
       int lasterror;
       DWORD dwBytes = 0;
       DWORD flags = 0;
  -    int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
   
       wsaData.len = *len;
       wsaData.buf = (char*) buf;
   
  -    rv = setsockopt(sock->sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, 
  -                    sizeof(timeout));
  -    if (rv == SOCKET_ERROR) {
  -        return WSAGetLastError();
  -    }
  -
       rv = WSARecv(sock->sock, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
       if (rv == SOCKET_ERROR) {
           lasterror = WSAGetLastError();
  -        /* Test code: remove before release */
  -        if (lasterror == WSAETIMEDOUT)
  -            printf("wsarecv: Connection timed out\n");
  -        else
  -            printf("wsarecv: connection failed. lasterror = %d\n", 
lasterror);            
           return lasterror;
       }
   
  @@ -137,7 +112,6 @@
       int i;
       int lasterror;
       DWORD dwBytes = 0;
  -    int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
   
       LPWSABUF pWsaData = (LPWSABUF) malloc(sizeof(WSABUF) * nvec);
   
  @@ -149,25 +123,9 @@
           pWsaData[i].len = vec[i].iov_len;
       }
   
  -    rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, 
  -                    sizeof(timeout));
  -    if (rv == SOCKET_ERROR) {
  -        lasterror = WSAGetLastError();
  -        /* Test code: remove before release */
  -        printf("win32_writev: setsockopt failed. errno = %d\n", lasterror);
  -        free(pWsaData);
  -        return lasterror;
  -    }
  -
       rv = WSASend(sock->sock, pWsaData, nvec, &dwBytes, 0, NULL, NULL);
       if (rv == SOCKET_ERROR) {
           lasterror = WSAGetLastError();
  -        /* Test code: remove before release */
  -        if (lasterror == WSAETIMEDOUT)
  -            printf("wsasend: Connection timed out\n");
  -        else
  -            printf("wsasend: connection failed. lasterror = %d\n", 
lasterror);            
  -
           free(pWsaData);
           return lasterror;
       }
  @@ -194,17 +152,24 @@
                        ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
                        ap_int32_t flags) 
   {
  +/*
  + *#define WAIT_FOR_EVENT
  + * Note: Waiting for the socket directly is much faster than creating a 
seperate
  + * wait event. There are a couple of dangerous aspects to waiting directly 
  + * for the socket. First, we should not wait on the socket if concurrent 
threads
  + * can wait-on/signal the same socket. This shouldn't be happening with 
Apache since 
  + * a socket is uniquely tied to a thread. This will change when we begin 
using 
  + * async I/O with completion ports on the socket. Second, I am not sure how 
the
  + * socket timeout code will work. I am hoping the socket will be signaled if 
the
  + * setsockopt timeout expires. Need to verify this...
  + */
       ap_ssize_t rv;
  -#ifdef OVERLAPPED
       OVERLAPPED overlapped;
  -#endif
       TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
  -    int i, lasterror, ptr = 0;
  +    int i, ptr = 0;
  +    int lasterror = APR_SUCCESS;
       DWORD dwFlags = 0;
  -    int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
   
  -    rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO,
  -               (char*) &timeout, sizeof(timeout));
   #if 0
       if (flags | APR_SENDFILE_KEEP_SOCKET)
           dwFlags |= TF_REUSE_SOCKET;
  @@ -215,7 +180,7 @@
   #endif
   
       /* TransmitFile can only send one header and one footer */
  -    memset(&tfb, '0', sizeof (tfb));
  +    memset(&tfb, '\0', sizeof (tfb));
       if (hdtr && hdtr->numheaders) {
           ptfb = &tfb;
           for (i = 0; i < hdtr->numheaders; i++) {
  @@ -243,27 +208,44 @@
                      hdtr->trailers[i].iov_len);
               ptr += hdtr->trailers[i].iov_len;
           }
  +    }
  +    /* Initialize the overlapped structure */
  +    memset(&overlapped,'\0', sizeof(overlapped));
  +    if (offset && *offset) {
  +        overlapped.Offset = *offset;
       }
  -#ifdef OVERLAPPED
  -    memset(&overlapped,'0', sizeof(overlapped));
  +#ifdef WAIT_FOR_EVENT
  +    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   #endif
  + 
       rv = TransmitFile(sock->sock,     /* socket */
                         file->filehand, /* open file descriptor of the file to 
be sent */
                         *len,           /* number of bytes to send. 0=send all 
*/
                         0,              /* Number of bytes per send. 0=use 
default */
  -#ifdef OVERLAPPED
  -                      &overlapped,
  -#else
  -                      NULL,           /* OVERLAPPED structure */
  -#endif
  +                      &overlapped,    /* OVERLAPPED structure */
                         ptfb,           /* header and trailer buffers */
                         dwFlags);       /* flags to control various aspects of 
TransmitFile */
       if (!rv) {
           lasterror = WSAGetLastError();
  -        printf("TransmitFile failed with error %d\n", lasterror);
  -        return lasterror;
  +        if (lasterror == ERROR_IO_PENDING) {
  +#ifdef WAIT_FOR_EVENT
  +            rv = WaitForSingleObject(overlapped.hEvent, sock->timeout * 
1000);
  +#else
  +            rv = WaitForSingleObject((HANDLE) sock->sock, sock->timeout * 
1000);
  +#endif
  +            if (rv == WAIT_OBJECT_0)
  +                lasterror = APR_SUCCESS;
  +            else if (rv == WAIT_TIMEOUT)
  +                lasterror = WAIT_TIMEOUT;
  +            else if (rv == WAIT_ABANDONED)
  +                lasterror = WAIT_ABANDONED;
  +            else
  +                lasterror = GetLastError();
  +        }
       }
  -
  -    return APR_SUCCESS;
  +#ifdef WAIT_FOR_EVENT
  +    CloseHandle(overlapped.hEvent);
  +#endif
  +    return lasterror;
   }
   #endif
  
  
  

Reply via email to