]> git.kaiwu.me - nginx.git/commitdiff
nginx-0.0.1-2003-11-14-10:20:34 import
authorIgor Sysoev <igor@sysoev.ru>
Fri, 14 Nov 2003 07:20:34 +0000 (07:20 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Fri, 14 Nov 2003 07:20:34 +0000 (07:20 +0000)
16 files changed:
src/event/modules/ngx_iocp_module.c
src/http/ngx_http_cache.c
src/os/unix/ngx_aio_read.c
src/os/unix/ngx_files.h
src/os/unix/ngx_os.h
src/os/unix/ngx_recv.c
src/os/unix/ngx_unix_init.c
src/os/unix/ngx_writev_chain.c
src/os/win32/ngx_files.c
src/os/win32/ngx_files.h
src/os/win32/ngx_os.h
src/os/win32/ngx_os_init.h [deleted file]
src/os/win32/ngx_recv.c [deleted file]
src/os/win32/ngx_win32_init.c
src/os/win32/ngx_wsarecv.c
src/os/win32/ngx_wsasend_chain.c

index 0fc7a715382d2e3c48feab0fb3b0e67417d2ec7a..7b89227a35cd477aebed7a289b34d80ea19b98ef 100644 (file)
@@ -77,6 +77,15 @@ ngx_module_t  ngx_iocp_module = {
 };
 
 
+ngx_os_io_t ngx_iocp_io = {
+    ngx_overlapped_wsarecv,
+    NULL,
+    NULL,
+    ngx_wsasend_chain,
+    0
+};
+
+
 static HANDLE  iocp;
 
 
@@ -225,6 +234,7 @@ ngx_log_debug(log, "iocp ev: %08x" _ ev);
 
         switch (key) {
         case NGX_IOCP_IO:
+            ev->complete = 1;
             ev->ready = 1;
             break;
 
index 299455ba3a2b3a0ef197c350ad0b5cef01e7e86b..6e64af1408fe0a57cb73f2f5e52fd99dcc512a05 100644 (file)
@@ -140,9 +140,7 @@ int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx,
     retry = 0;
 
     for ( ;; ) {
-        if (ngx_rename_file(temp_file->data, ctx->file.name.data)
-                                                             != NGX_FILE_ERROR)
-        {
+        if (ngx_rename_file(temp_file, (&ctx->file.name), r->pool) == NGX_OK) {
             return NGX_OK;
         }
 
index 28deac6d229ac3867ddfb4bd1417cb6088948b4b..c5fb4a55f59ed35d34d1238e2e6ad9551db49290 100644 (file)
@@ -25,12 +25,12 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
     rev = c->read;
 
     if (!rev->ready) {
-        ngx_log_error(NGX_LOG_ALERT, rev->log, 0, "SECOND AIO POST");
+        ngx_log_error(NGX_LOG_ALERT, c->log, 0, "SECOND AIO POST");
         return NGX_AGAIN;
     }
 
-    ngx_log_debug(rev->log, "rev->complete: %d" _ rev->complete);
-    ngx_log_debug(rev->log, "aio size: %d" _ size);
+    ngx_log_debug(c->log, "rev->complete: %d" _ rev->complete);
+    ngx_log_debug(c->log, "aio size: %d" _ size);
 
     if (!rev->complete) {
         ngx_memzero(&rev->aiocb, sizeof(struct aiocb));
@@ -52,7 +52,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
             return NGX_ERROR;
         }
 
-        ngx_log_debug(rev->log, "aio_read: #%d OK" _ c->fd);
+        ngx_log_debug(c->log, "aio_read: #%d OK" _ c->fd);
 
         rev->active = 1;
         rev->ready = 0;
@@ -62,7 +62,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
 
     n = aio_error(&rev->aiocb);
     if (n == -1) {
-        ngx_log_error(NGX_LOG_ALERT, rev->log, ngx_errno, "aio_error() failed");
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "aio_error() failed");
         rev->error = 1;
         return NGX_ERROR;
     }
@@ -70,14 +70,14 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
     if (n != 0) {
         if (n == NGX_EINPROGRESS) {
             if (rev->ready) {
-                ngx_log_error(NGX_LOG_ALERT, rev->log, n,
+                ngx_log_error(NGX_LOG_ALERT, c->log, n,
                               "aio_read() still in progress");
                 rev->ready = 0;
             }
             return NGX_AGAIN;
         }
 
-        ngx_log_error(NGX_LOG_CRIT, rev->log, n, "aio_read() failed");
+        ngx_log_error(NGX_LOG_CRIT, c->log, n, "aio_read() failed");
         rev->error = 1;
         rev->ready = 0;
         return NGX_ERROR;
@@ -85,7 +85,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size)
 
     n = aio_return(&rev->aiocb);
     if (n == -1) {
-        ngx_log_error(NGX_LOG_ALERT, rev->log, ngx_errno,
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                       "aio_return() failed");
 
         rev->error = 1;
index 9990ae8c30ec2fc802c9acaa2ae5fd4dd4b7d7c3..369c3ad5dcb3c14748a76b5295504869848ffc7b 100644 (file)
@@ -45,7 +45,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
                                 off_t offset, ngx_pool_t *pool);
 
 
-#define ngx_rename_file          rename
+#define ngx_rename_file(from, to, pool)  rename(from->data, to->data)
 #define ngx_rename_file_n        "rename"
 
 
index 33e3943199d915c62f77002faf4ba20df7eacb8b..658c0a4003dc46ef76ebf100baa62a28f3c66feb 100644 (file)
@@ -35,6 +35,8 @@ typedef struct {
 int ngx_os_init(ngx_log_t *log);
 int ngx_daemon(ngx_log_t *log);
 int ngx_posix_init(ngx_log_t *log);
+int ngx_posix_post_conf_init(ngx_log_t *log);
+
 
 ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size);
 ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
index 1a14fd963a8b3094fda7ee23fa0716c781a02714..e759379576da0c37c55203410cdd034c6230d9ba 100644 (file)
@@ -40,6 +40,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
     }
 
     do {
+        rev->ready = 1;
+
         n = recv(c->fd, buf, size, 0);
 
         ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
@@ -78,11 +80,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
         }
 
         rev->ready = 0;
-        rev->error = 1;
         n = ngx_unix_recv_error(rev, ngx_socket_errno);
 
     } while (n == NGX_EINTR);
 
+    if (n == NGX_ERROR){
+        rev->error = 1;
+    }
+
     return n;
 }
 
@@ -96,6 +101,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
     rev = c->read;
 
     do {
+        rev->ready = 1;
+
         n = recv(c->fd, buf, size, 0);
 
         ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
@@ -113,11 +120,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
         }
 
         rev->ready = 0;
-        rev->error = 1;
         n = ngx_unix_recv_error(rev, ngx_socket_errno);
 
     } while (n == NGX_EINTR);
 
+    if (n == NGX_ERROR){
+        rev->error = 1;
+    }
+
     return n;
 }
 
index 95741642bc1bb5240f3705e9dc500caa14240c94..ab33979ec85e42873dc78043d2e6df9331708305 100644 (file)
@@ -3,17 +3,19 @@
 #include <ngx_core.h>
 
 
+#if 0
 /* STUB */
 ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size);
 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in);
 int ngx_posix_init(ngx_log_t *log);
 int ngx_posix_post_conf_init(ngx_log_t *log);
 /* */
+#endif
 
 
 ngx_os_io_t ngx_os_io = {
     ngx_unix_recv,
-    NULL,
+    ngx_readv_chain,
     NULL,
     ngx_writev_chain,
     NGX_HAVE_ZEROCOPY
index 6ead65f3a4d9d8c480f85333e09d0fbd5967ffac..9b9e62939a5f69747b8a392fa404288c3cb65b51 100644 (file)
@@ -24,6 +24,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
     iov = NULL;
 
     /* create the iovec and coalesce the neighbouring hunks */
+
     for (cl = in; cl; cl = cl->next) {
 
         if (prev == cl->hunk->pos) {
@@ -57,7 +58,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
     sent = n > 0 ? n : 0;
 
 #if (NGX_DEBUG_WRITE_CHAIN)
-    ngx_log_debug(c->log, "writev: %qd" _ sent);
+    ngx_log_debug(c->log, "writev: " OFF_FMT  _ sent);
 #endif
 
     c->sent += sent;
@@ -75,12 +76,6 @@ ngx_log_debug(c->log, "SIZE: %d" _ size);
                 cl->hunk->pos = cl->hunk->last;
             }
 
-#if 0
-            if (cl->hunk->type & NGX_HUNK_FILE) {
-                cl->hunk->file_pos = cl->hunk->file_last;
-            }
-#endif
-
             continue;
         }
 
@@ -88,12 +83,6 @@ ngx_log_debug(c->log, "SIZE: %d" _ size);
             cl->hunk->pos += sent;
         }
 
-#if 0
-        if (cl->hunk->type & NGX_HUNK_FILE) {
-            cl->hunk->file_pos += sent;
-        }
-#endif
-
         break;
     }
 
index 139d141cb0f92e182cec505ea7f05aad838f23e1..35e83bfd669df9effc5a7afe9bbd0d364304c62a 100644 (file)
@@ -6,13 +6,11 @@
 ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
 {
     size_t      n;
+    long        high_offset;
+    ngx_err_t   err;
     OVERLAPPED  ovlp, *povlp;
 
-#if (WIN9X)
-
     if (ngx_win32_version < NGX_WIN_NT) {
-        long        high_offset;
-        ngx_err_t   err;
 
         /*
          * in Win9X the overlapped pointer must be NULL
@@ -47,8 +45,6 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
         povlp = NULL;
 
     } else {
-
-#endif
         ovlp.Internal = 0;
         ovlp.InternalHigh = 0;
         ovlp.Offset = (DWORD) offset;
@@ -56,10 +52,7 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
         ovlp.hEvent = NULL;
 
         povlp = &ovlp;
-
-#if (WIN9X)
     }
-#endif
 
     if (ReadFile(file->fd, buf, size, &n, povlp) == 0) {
         ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "ReadFile() failed");
@@ -75,13 +68,11 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
 ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
 {
     size_t      n;
+    long        high_offset;
+    ngx_err_t   err;
     OVERLAPPED  ovlp, *povlp;
 
-#if (WIN9X)
-
     if (ngx_win32_version < NGX_WIN_NT) {
-        long        high_offset;
-        ngx_err_t   err;
 
         /*
          * in Win9X the overlapped pointer must be NULL
@@ -116,9 +107,6 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
         povlp = NULL;
 
     } else {
-
-#endif
-
         ovlp.Internal = 0;
         ovlp.InternalHigh = 0;
         ovlp.Offset = (DWORD) offset;
@@ -126,10 +114,7 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
         ovlp.hEvent = NULL;
 
         povlp = &ovlp;
-
-#if (WIN9X)
     }
-#endif
 
     if (WriteFile(file->fd, buf, size, &n, povlp) == 0) {
         ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "WriteFile() failed");
@@ -142,15 +127,103 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset)
 }
 
 
-int ngx_file_append_mode(ngx_fd_t fd)
+ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
+                                off_t offset, ngx_pool_t *pool)
 {
-    ngx_err_t  err;
+    char     *buf, *prev;
+    size_t    size;
+    ssize_t   total, n;
+
+    total = 0;
+
+    while (cl) {
+        buf = cl->hunk->pos;
+        prev = buf;
+        size = 0;
+
+        /* coalesce the neighbouring hunks */
+
+        while (cl && prev == cl->hunk->pos) {
+            size += cl->hunk->last - cl->hunk->pos;
+            prev = cl->hunk->last;
+            cl = cl->next;
+        }
+
+        n = ngx_write_file(file, buf, size, offset);
+
+        if (n == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        total += n;
+        offset += n;
+    }
+
+    return total;
+}
+
+
+int ngx_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_pool_t *pool)
+{
+    int         rc, collision;
+    u_int       num;
+    char       *name;
+    ngx_err_t   err;
+
+    name = ngx_palloc(pool, to->len + 1 + 10 + 1 + sizeof("DELETE"));
+    ngx_memcpy(name, to->data, to->len);
 
+    collision = 0;
+
+    /* mutex_lock() (per cache or single ?) */
+
+    do {
+        num = ngx_next_temp_number(collision);
+
+        ngx_snprintf(name + to->len, 1 + 10 + 1 + sizeof("DELETE"),
+                     ".%010u.DELETE", num);
+
+        if (MoveFile(to->data, name) == 0) {
+            err = ngx_errno;
+            if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+                return NGX_ERROR;
+            }
+
+            collision = 1;
+            ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno,
+                          "MoveFile() failed");
+        }
+
+    } while (collision);
+
+    if (ngx_win32_version >= NGX_WIN_NT) {
+        if (DeleteFile(name) == 0) {
+            ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno,
+                          "DeleteFile() failed");
+        }
+    }
+
+    if (MoveFile(from->data, to->data) == 0) {
+        rc = NGX_ERROR;
+
+    } else {
+        rc = NGX_OK;
+    }
+
+    if (rc == NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno, "MoveFile() failed");
+    }
+
+    /* mutex_unlock() */
+
+    return rc;
+}
+
+
+int ngx_file_append_mode(ngx_fd_t fd)
+{
     if (SetFilePointer(fd, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) {
-        err = ngx_errno;
-        if (err != NO_ERROR) {
-            ngx_log_error(NGX_LOG_ERR, file->log, err,
-                          "SeekFilePointer() failed");
+        if (ngx_errno != NO_ERROR) {
             return NGX_ERROR;
         }
     }
index 8e386e8ca755ed070ac3218f670da4b656453ec3..9885c5f785f08b60bf349edb4640cd076eb2220c 100644 (file)
@@ -58,8 +58,7 @@ int ngx_file_append_mode(ngx_fd_t fd);
 #define ngx_close_file              CloseHandle
 #define ngx_close_file_n            "CloseHandle()"
 
-/* STUB */
-#define ngx_rename_file             MoveFile
+int ngx_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_pool_t *pool);
 #define ngx_rename_file_n           "MoveFile()"
 
 #define ngx_mkdir(name)             CreateDirectory(name, NULL)
index 96f1c2d1f529addcf9c1e7b204c3d94189cc45b0..52a7c05a871a61ce2f8043a3a4e6abdd7d85abe1 100644 (file)
@@ -1,4 +1,4 @@
-ifndef _NGX_OS_H_INCLUDED_
+#ifndef _NGX_OS_H_INCLUDED_
 #define _NGX_OS_H_INCLUDED_
 
 
@@ -33,6 +33,11 @@ typedef struct {
 
 int ngx_os_init(ngx_log_t *log);
 
+ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size);
+ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, char *buf, size_t size);
+ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in);
+ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in);
+
 
 extern ngx_os_io_t  ngx_os_io;
 extern int          ngx_max_sockets;
diff --git a/src/os/win32/ngx_os_init.h b/src/os/win32/ngx_os_init.h
deleted file mode 100644 (file)
index 8ab8206..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _NGX_OS_INIT_H_INCLUDED_
-#define _NGX_OS_INIT_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-int ngx_os_init(ngx_log_t *log);
-
-ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size);
-
-
-#endif /* _NGX_OS_INIT_H_INCLUDED_ */
diff --git a/src/os/win32/ngx_recv.c b/src/os/win32/ngx_recv.c
deleted file mode 100644 (file)
index ad2232c..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-
-
-ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
-{
-    int           rc;
-    u_int         flags;
-    size_t        bytes;
-    ngx_err_t     err;
-    WSABUF        wsabuf[1];
-    ngx_event_t  *ev;
-    LPWSAOVERLAPPED_COMPLETION_ROUTINE  handler;
-
-    ev = c->read;
-
-/* DEBUG */ bytes = 0;
-
-    if (ev->timedout) {
-        ngx_set_socket_errno(NGX_ETIMEDOUT);
-        ngx_log_error(NGX_LOG_ERR, ev->log, 0, "WSARecv() timed out");
-
-        return NGX_ERROR;
-    }
-
-    if (ev->ready) {
-        ev->ready = 0;
-
-#if (HAVE_IOCP_EVENT) /* iocp */
-
-        if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
-            if (ev->ovlp.error) {
-                ngx_log_error(NGX_LOG_ERR, c->log, ev->ovlp.error,
-                              "WSARecv() failed");
-                return NGX_ERROR;
-            }
-
-            return ev->available;
-        }
-
-#endif
-
-        if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &ev->ovlp,
-                                   &bytes, 0, NULL) == 0) {
-            err = ngx_socket_errno;
-            ngx_log_error(NGX_LOG_CRIT, ev->log, err,
-                         "WSARecv() or WSAGetOverlappedResult() failed");
-
-            return NGX_ERROR;
-        }
-
-        return bytes;
-    }
-
-    ngx_memzero(&ev->ovlp, sizeof(WSAOVERLAPPED));
-    wsabuf[0].buf = buf;
-    wsabuf[0].len = size;
-    flags = 0;
-
-#if 0
-    handler = ev->handler;
-#else
-    handler = NULL;
-#endif
-
-    rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags,
-                 (LPWSAOVERLAPPED) &ev->ovlp, handler);
-
-    ngx_log_debug(ev->log, "WSARecv: %d:%d" _ rc _ bytes);
-
-    if (rc == -1) {
-        err = ngx_socket_errno;
-        if (err == WSA_IO_PENDING) {
-            return NGX_AGAIN;
-
-        } else {
-            ngx_log_error(NGX_LOG_CRIT, ev->log, err, "WSARecv() failed");
-            return NGX_ERROR;
-        }
-    }
-
-#if (HAVE_IOCP_EVENT) /* iocp */
-
-    if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
-        return NGX_AGAIN;
-    }
-
-#endif
-
-    return bytes;
-}
index c522c9e95b46eaffe2d25da45b72e3291e074e37..77e4462d0041cb2d52617739fec1767a38ca95e1 100644 (file)
@@ -2,11 +2,6 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 
-/* STUB */
-ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size);
-ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in);
-/* */
-
 
 int  ngx_win32_version;
 int  ngx_max_sockets;
index 883bed80516bbf5516ef71632a01278d5c69b2c1..2a43498adcfffb0f03f64998e46287abd993a314 100644 (file)
@@ -4,6 +4,149 @@
 #include <ngx_event.h>
 
 
+ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
+{
+    int           rc;
+    u_int         flags;
+    size_t        bytes;
+    WSABUF        wsabuf[1];
+    ngx_err_t     err;
+    ngx_event_t  *rev;
+
+    wsabuf[0].buf = buf;
+    wsabuf[0].len = size;
+    flags = 0;
+    bytes = 0;
+
+    rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL);
+
+    ngx_log_debug(c->log, "WSARecv: %d:%d" _ rc _ bytes);
+
+    rev = c->read;
+
+    if (rc == -1) {
+        rev->ready = 0;
+        err = ngx_socket_errno;
+
+        if (err == WSAEWOULDBLOCK) {
+            ngx_log_error(NGX_LOG_INFO, c->log, err, "WSARecv() EAGAIN");
+            return NGX_AGAIN;
+        }
+
+        rev->error = 1;
+        ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSARecv() failed");
+        return NGX_ERROR;
+    }
+
+    if (bytes < size) {
+        rev->ready = 0;
+    }
+
+    if (bytes == 0) {
+        rev->eof = 1;
+    }
+
+    return bytes;
+}
+
+
+ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, char *buf, size_t size)
+{
+    int               rc;
+    u_int             flags;
+    size_t            bytes;
+    WSABUF            wsabuf[1];
+    ngx_err_t         err;
+    ngx_event_t      *rev;
+    LPWSAOVERLAPPED   ovlp;
+
+    rev = c->read;
+
+    if (!rev->ready) {
+        ngx_log_error(NGX_LOG_ALERT, rev->log, 0, "SECOND WSA POST");
+        return NGX_AGAIN;
+    }
+
+    ngx_log_debug(c->log, "rev->complete: %d" _ rev->complete);
+
+    if (rev->complete) {
+        rev->complete = 0;
+
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+            if (rev->ovlp.error) {
+                ngx_log_error(NGX_LOG_ERR, c->log, rev->ovlp.error,
+                              "WSARecv() failed");
+                return NGX_ERROR;
+            }
+
+            return rev->available;
+        }
+
+        if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp,
+                                   &bytes, 0, NULL) == 0) {
+            ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
+                         "WSARecv() or WSAGetOverlappedResult() failed");
+
+            return NGX_ERROR;
+        }
+
+        return bytes;
+    }
+
+    ovlp = (LPWSAOVERLAPPED) &rev->ovlp;
+    ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
+    wsabuf[0].buf = buf;
+    wsabuf[0].len = size;
+    flags = 0;
+    bytes = 0;
+
+    rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL);
+
+    rev->complete = 0;
+
+    ngx_log_debug(c->log, "WSARecv: %d:%d" _ rc _ bytes);
+
+    if (rc == -1) {
+        err = ngx_socket_errno;
+        if (err == WSA_IO_PENDING) {
+            rev->active = 1;
+            return NGX_AGAIN;
+        }
+
+        rev->error = 1;
+        ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSARecv() failed");
+        return NGX_ERROR;
+    }
+
+    if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+
+        /*
+         * if a socket was bound with I/O completion port
+         * then GetQueuedCompletionStatus() would anyway return its status
+         * despite that WSARecv() was already complete
+         */
+
+        rev->active = 1;
+        return NGX_AGAIN;
+    }
+
+    if (bytes == 0) {
+        rev->eof = 1;
+        rev->ready = 0;
+
+    } else {
+        rev->ready = 1;
+    }
+
+    rev->active = 0;
+
+    return bytes;
+}
+
+#if 0
+
+/* DELELTE IT WHEN ABOVE FUNC WOULD BE TESTED */
+
 ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
 {
     int               rc;
@@ -88,3 +231,5 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size)
 
     return bytes;
 }
+
+#endif
index 5bfd71542ab5fe1cd04b70ea098a92193afde3a3..f0b5fe24c163fd204872b7179d9f58106931080f 100644 (file)
@@ -4,6 +4,249 @@
 #include <ngx_event.h>
 
 
+ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in)
+{
+    int           rc;
+    char         *prev;
+    size_t        size, sent;
+    LPWSABUF      wsabuf;
+    ngx_err_t     err;
+    ngx_event_t  *wev;
+    ngx_array_t   wsabufs;
+    ngx_chain_t  *cl;
+
+    wev = c->write;
+
+    if (!wev->ready) {
+        return in;
+    }
+
+    /*
+     * WSABUFs must be 4-byte aligned otherwise
+     * WSASend() will return undocumented WSAEINVAL error.
+     */
+
+    ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR);
+
+    prev = NULL;
+    wsabuf = NULL;
+
+    /* create the WSABUF and coalesce the neighbouring bufs */
+
+    for (cl = in; cl; cl = cl->next) {
+
+        if (prev == cl->hunk->pos) {
+            wsabuf->len += cl->hunk->last - cl->hunk->pos;
+            prev = cl->hunk->last;
+
+        } else {
+            ngx_test_null(wsabuf, ngx_push_array(&wsabufs), NGX_CHAIN_ERROR);
+            wsabuf->buf = cl->hunk->pos;
+            wsabuf->len = cl->hunk->last - cl->hunk->pos;
+            prev = cl->hunk->last;
+        }
+    }
+
+    rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, NULL, NULL);
+
+    if (rc == -1) {
+        err = ngx_errno;
+
+        if (err == WSAEWOULDBLOCK) {
+            ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() EAGAIN");
+            wev->ready = 0;
+            return in;
+
+        } else {
+            wev->error = 1;
+            ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed");
+            return NGX_CHAIN_ERROR;
+        }
+    }
+
+#if (NGX_DEBUG_WRITE_CHAIN)
+    ngx_log_debug(c->log, "WSASend(): %d" _ sent);
+#endif
+
+    c->sent += sent;
+
+    for (cl = in; cl && sent > 0; cl = cl->next) {
+
+        size = cl->hunk->last - cl->hunk->pos;
+
+        if (sent >= size) {
+            sent -= size;
+
+            if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+                cl->hunk->pos = cl->hunk->last;
+            }
+
+            continue;
+        }
+
+        if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+            cl->hunk->pos += sent;
+        }
+
+        break;
+    }
+
+    if (cl) {
+        wev->ready = 0;
+    }
+
+    return cl;
+}
+
+
+ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in)
+{
+    int               rc;
+    char             *prev;
+    size_t            size, sent;
+    LPWSABUF          wsabuf;
+    ngx_err_t         err;
+    ngx_event_t      *wev;
+    ngx_array_t       wsabufs;
+    ngx_chain_t      *cl;
+    LPWSAOVERLAPPED   ovlp;
+
+    wev = c->write;
+
+    if (!wev->ready) {
+        return in;
+    }
+
+    if (!wev->complete) {
+
+        /* post the overlapped WSASend() */
+        /*
+         * WSABUFs must be 4-byte aligned otherwise
+         * WSASend() will return undocumented WSAEINVAL error.
+         */
+
+        ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR);
+
+        prev = NULL;
+        wsabuf = NULL;
+        /* create the WSABUF and coalesce the neighbouring bufs */
+
+        for (cl = in; cl; cl = cl->next) {
+
+            if (prev == cl->hunk->pos) {
+                wsabuf->len += cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
+            } else {
+                ngx_test_null(wsabuf, ngx_push_array(&wsabufs),
+                              NGX_CHAIN_ERROR);
+                wsabuf->buf = cl->hunk->pos;
+                wsabuf->len = cl->hunk->last - cl->hunk->pos;
+                prev = cl->hunk->last;
+            }
+        }
+
+        ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
+        ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
+        rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL);
+
+        wev->complete = 0;
+
+        if (rc == -1) {
+            err = ngx_errno;
+
+            if (err == WSA_IO_PENDING) {
+                wev->active = 1;
+                return in;
+
+            } else {
+                wev->error = 1;
+                ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed");
+                return NGX_CHAIN_ERROR;
+            }
+        } else if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+
+             /*
+              * if a socket was bound with I/O completion port then
+              * GetQueuedCompletionStatus() would anyway return its status
+              * despite that WSASend() was already complete
+              */
+
+            wev->active = 1;
+            return in;
+        }
+
+    } else {
+
+        /* the overlapped WSASend() complete */
+
+        wev->complete = 0;
+        wev->active = 0;
+
+        if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+            if (wev->ovlp.error) {
+                ngx_log_error(NGX_LOG_ERR, c->log, wev->ovlp.error,
+                              "WSASend() failed");
+                return NGX_CHAIN_ERROR;
+            }
+
+            sent = wev->available;
+
+        } else {
+            if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &wev->ovlp,
+                                       &sent, 0, NULL) == 0) {
+                ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
+                             "WSASend() or WSAGetOverlappedResult() failed");
+    
+                return NGX_CHAIN_ERROR;
+            }
+        }
+    }
+
+#if (NGX_DEBUG_WRITE_CHAIN)
+    ngx_log_debug(c->log, "WSASend(): %d" _ sent);
+#endif
+
+    c->sent += sent;
+
+    for (cl = in; cl && sent > 0; cl = cl->next) {
+
+        size = cl->hunk->last - cl->hunk->pos;
+
+        if (sent >= size) {
+            sent -= size;
+
+            if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+                cl->hunk->pos = cl->hunk->last;
+            }
+
+            continue;
+        }
+
+        if (cl->hunk->type & NGX_HUNK_IN_MEMORY) {
+            cl->hunk->pos += sent;
+        }
+
+        break;
+    }
+
+    if (cl) {
+        wev->ready = 0;
+
+    } else {
+        wev->ready = 1;
+    }
+
+    return cl;
+}
+
+
+#if 0
+
 ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in)
 {
     int               rc;
@@ -175,7 +418,7 @@ non-block
         break;
     }
 
-    ngx_destroy_array(&wsabufs);
-
     return ce;
 }
+
+#endif