Initial commit
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,6 @@
|
||||
|
||||
// Copyright (C) Igor Sysoev
|
||||
// Copyright (C) Nginx, Inc.
|
||||
|
||||
|
||||
nginx icon discardable "src\\os\\win32\\nginx.ico"
|
||||
@@ -0,0 +1,24 @@
|
||||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"16 16 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGGGGGGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGG GGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" "
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"32 32 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG ",
|
||||
" GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGG GGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "
|
||||
@@ -0,0 +1,55 @@
|
||||
/* XPM */
|
||||
static char * nginx_xpm[] = {
|
||||
"48 48 2 2",
|
||||
/* colors */
|
||||
" c none",
|
||||
"GG c #009900",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGG GGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
ngx_uint_t ngx_pagesize;
|
||||
ngx_uint_t ngx_pagesize_shift;
|
||||
ngx_uint_t ngx_cacheline_size;
|
||||
|
||||
|
||||
void *ngx_alloc(size_t size, ngx_log_t *log)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(size);
|
||||
if (p == NULL) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"malloc(%uz) failed", size);
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void *ngx_calloc(size_t size, ngx_log_t *log)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = ngx_alloc(size, log);
|
||||
|
||||
if (p) {
|
||||
ngx_memzero(p, size);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ALLOC_H_INCLUDED_
|
||||
#define _NGX_ALLOC_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
void *ngx_alloc(size_t size, ngx_log_t *log);
|
||||
void *ngx_calloc(size_t size, ngx_log_t *log);
|
||||
|
||||
#define ngx_free free
|
||||
#define ngx_memalign(alignment, size, log) ngx_alloc(size, log)
|
||||
|
||||
extern ngx_uint_t ngx_pagesize;
|
||||
extern ngx_uint_t ngx_pagesize_shift;
|
||||
extern ngx_uint_t ngx_cacheline_size;
|
||||
|
||||
|
||||
#endif /* _NGX_ALLOC_H_INCLUDED_ */
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ATOMIC_H_INCLUDED_
|
||||
#define _NGX_ATOMIC_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_HAVE_ATOMIC_OPS 1
|
||||
|
||||
typedef int32_t ngx_atomic_int_t;
|
||||
typedef uint32_t ngx_atomic_uint_t;
|
||||
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
|
||||
#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1)
|
||||
|
||||
|
||||
#if defined( __WATCOMC__ ) || defined( __BORLANDC__ ) || defined(__GNUC__) \
|
||||
|| ( _MSC_VER >= 1300 )
|
||||
|
||||
/* the new SDK headers */
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
((ngx_atomic_uint_t) InterlockedCompareExchange((long *) lock, set, old) \
|
||||
== old)
|
||||
|
||||
#else
|
||||
|
||||
/* the old MS VC6.0SP2 SDK headers */
|
||||
|
||||
#define ngx_atomic_cmp_set(lock, old, set) \
|
||||
(InterlockedCompareExchange((void **) lock, (void *) set, (void *) old) \
|
||||
== (void *) old)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define ngx_atomic_fetch_add(p, add) InterlockedExchangeAdd((long *) p, add)
|
||||
|
||||
|
||||
#define ngx_memory_barrier()
|
||||
|
||||
|
||||
#if defined( __BORLANDC__ ) || ( __WATCOMC__ < 1230 )
|
||||
|
||||
/*
|
||||
* Borland C++ 5.5 (tasm32) and Open Watcom C prior to 1.3
|
||||
* do not understand the "pause" instruction
|
||||
*/
|
||||
|
||||
#define ngx_cpu_pause()
|
||||
#else
|
||||
#define ngx_cpu_pause() __asm { pause }
|
||||
#endif
|
||||
|
||||
|
||||
void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);
|
||||
|
||||
#define ngx_trylock(lock) (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
|
||||
#define ngx_unlock(lock) *(lock) = 0
|
||||
|
||||
|
||||
#endif /* _NGX_ATOMIC_H_INCLUDED_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Maxim Dounin
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
char *
|
||||
ngx_dlerror(void)
|
||||
{
|
||||
u_char *p;
|
||||
static u_char errstr[NGX_MAX_ERROR_STR];
|
||||
|
||||
p = ngx_strerror(ngx_errno, errstr, NGX_MAX_ERROR_STR);
|
||||
*p = '\0';
|
||||
|
||||
return (char *) errstr;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Maxim Dounin
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_DLOPEN_H_INCLUDED_
|
||||
#define _NGX_DLOPEN_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_HAVE_DLOPEN 1
|
||||
|
||||
|
||||
#define ngx_dlopen(path) LoadLibrary((char *) path)
|
||||
#define ngx_dlopen_n "LoadLibrary()"
|
||||
|
||||
#define ngx_dlsym(handle, symbol) (void *) GetProcAddress(handle, symbol)
|
||||
#define ngx_dlsym_n "GetProcAddress()"
|
||||
|
||||
#define ngx_dlclose(handle) (FreeLibrary(handle) ? 0 : -1)
|
||||
#define ngx_dlclose_n "FreeLibrary()"
|
||||
|
||||
|
||||
char *ngx_dlerror(void);
|
||||
|
||||
|
||||
#endif /* _NGX_DLOPEN_H_INCLUDED_ */
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
u_char *
|
||||
ngx_strerror(ngx_err_t err, u_char *errstr, size_t size)
|
||||
{
|
||||
u_int len;
|
||||
static u_long lang = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
|
||||
|
||||
if (size == 0) {
|
||||
return errstr;
|
||||
}
|
||||
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, lang, (char *) errstr, size, NULL);
|
||||
|
||||
if (len == 0 && lang && GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND) {
|
||||
|
||||
/*
|
||||
* Try to use English messages first and fallback to a language,
|
||||
* based on locale: non-English Windows have no English messages
|
||||
* at all. This way allows to use English messages at least on
|
||||
* Windows with MUI.
|
||||
*/
|
||||
|
||||
lang = 0;
|
||||
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, lang, (char *) errstr, size, NULL);
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
return ngx_snprintf(errstr, size,
|
||||
"FormatMessage() error:(%d)", GetLastError());
|
||||
}
|
||||
|
||||
/* remove ".\r\n\0" */
|
||||
while (errstr[len] == '\0' || errstr[len] == CR
|
||||
|| errstr[len] == LF || errstr[len] == '.')
|
||||
{
|
||||
--len;
|
||||
}
|
||||
|
||||
return &errstr[++len];
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_strerror_init(void)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_ERRNO_H_INCLUDED_
|
||||
#define _NGX_ERRNO_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef DWORD ngx_err_t;
|
||||
|
||||
#define ngx_errno GetLastError()
|
||||
#define ngx_set_errno(err) SetLastError(err)
|
||||
#define ngx_socket_errno WSAGetLastError()
|
||||
#define ngx_set_socket_errno(err) WSASetLastError(err)
|
||||
|
||||
#define NGX_EPERM ERROR_ACCESS_DENIED
|
||||
#define NGX_ENOENT ERROR_FILE_NOT_FOUND
|
||||
#define NGX_ENOPATH ERROR_PATH_NOT_FOUND
|
||||
#define NGX_ENOMEM ERROR_NOT_ENOUGH_MEMORY
|
||||
#define NGX_EACCES ERROR_ACCESS_DENIED
|
||||
/*
|
||||
* there are two EEXIST error codes:
|
||||
* ERROR_FILE_EXISTS used by CreateFile(CREATE_NEW),
|
||||
* and ERROR_ALREADY_EXISTS used by CreateDirectory();
|
||||
* MoveFile() uses both
|
||||
*/
|
||||
#define NGX_EEXIST ERROR_ALREADY_EXISTS
|
||||
#define NGX_EEXIST_FILE ERROR_FILE_EXISTS
|
||||
#define NGX_EXDEV ERROR_NOT_SAME_DEVICE
|
||||
#define NGX_ENOTDIR ERROR_PATH_NOT_FOUND
|
||||
#define NGX_EISDIR ERROR_CANNOT_MAKE
|
||||
#define NGX_ENOSPC ERROR_DISK_FULL
|
||||
#define NGX_EPIPE EPIPE
|
||||
#define NGX_EAGAIN WSAEWOULDBLOCK
|
||||
#define NGX_EINPROGRESS WSAEINPROGRESS
|
||||
#define NGX_ENOPROTOOPT WSAENOPROTOOPT
|
||||
#define NGX_EOPNOTSUPP WSAEOPNOTSUPP
|
||||
#define NGX_EADDRINUSE WSAEADDRINUSE
|
||||
#define NGX_ECONNABORTED WSAECONNABORTED
|
||||
#define NGX_ECONNRESET WSAECONNRESET
|
||||
#define NGX_ENOTCONN WSAENOTCONN
|
||||
#define NGX_ETIMEDOUT WSAETIMEDOUT
|
||||
#define NGX_ECONNREFUSED WSAECONNREFUSED
|
||||
#define NGX_ENAMETOOLONG ERROR_BAD_PATHNAME
|
||||
#define NGX_ENETDOWN WSAENETDOWN
|
||||
#define NGX_ENETUNREACH WSAENETUNREACH
|
||||
#define NGX_EHOSTDOWN WSAEHOSTDOWN
|
||||
#define NGX_EHOSTUNREACH WSAEHOSTUNREACH
|
||||
#define NGX_ENOMOREFILES ERROR_NO_MORE_FILES
|
||||
#define NGX_EILSEQ ERROR_NO_UNICODE_TRANSLATION
|
||||
#define NGX_ELOOP 0
|
||||
#define NGX_EBADF WSAEBADF
|
||||
|
||||
#define NGX_EALREADY WSAEALREADY
|
||||
#define NGX_EINVAL WSAEINVAL
|
||||
#define NGX_EMFILE WSAEMFILE
|
||||
#define NGX_ENFILE WSAEMFILE
|
||||
|
||||
|
||||
u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
|
||||
ngx_int_t ngx_strerror_init(void);
|
||||
|
||||
|
||||
#endif /* _NGX_ERRNO_H_INCLUDED_ */
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_MAX_ERROR_STR 2048
|
||||
|
||||
|
||||
void ngx_cdecl
|
||||
ngx_event_log(ngx_err_t err, const char *fmt, ...)
|
||||
{
|
||||
u_char *p, *last;
|
||||
long types;
|
||||
HKEY key;
|
||||
HANDLE ev;
|
||||
va_list args;
|
||||
u_char text[NGX_MAX_ERROR_STR];
|
||||
const char *msgarg[9];
|
||||
static u_char netmsg[] = "%SystemRoot%\\System32\\netmsg.dll";
|
||||
|
||||
last = text + NGX_MAX_ERROR_STR;
|
||||
p = text + GetModuleFileName(NULL, (char *) text, NGX_MAX_ERROR_STR - 50);
|
||||
|
||||
*p++ = ':';
|
||||
ngx_linefeed(p);
|
||||
|
||||
va_start(args, fmt);
|
||||
p = ngx_vslprintf(p, last, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (err) {
|
||||
p = ngx_log_errno(p, last, err);
|
||||
}
|
||||
|
||||
if (p > last - NGX_LINEFEED_SIZE - 1) {
|
||||
p = last - NGX_LINEFEED_SIZE - 1;
|
||||
}
|
||||
|
||||
ngx_linefeed(p);
|
||||
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
* we do not log errors here since we use
|
||||
* Event Log only to log our own logs open errors
|
||||
*/
|
||||
|
||||
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\nginx",
|
||||
0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, NULL)
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RegSetValueEx(key, "EventMessageFile", 0, REG_EXPAND_SZ,
|
||||
netmsg, sizeof(netmsg) - 1)
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
types = EVENTLOG_ERROR_TYPE;
|
||||
|
||||
if (RegSetValueEx(key, "TypesSupported", 0, REG_DWORD,
|
||||
(u_char *) &types, sizeof(long))
|
||||
!= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
|
||||
ev = RegisterEventSource(NULL, "nginx");
|
||||
|
||||
msgarg[0] = (char *) text;
|
||||
msgarg[1] = NULL;
|
||||
msgarg[2] = NULL;
|
||||
msgarg[3] = NULL;
|
||||
msgarg[4] = NULL;
|
||||
msgarg[5] = NULL;
|
||||
msgarg[6] = NULL;
|
||||
msgarg[7] = NULL;
|
||||
msgarg[8] = NULL;
|
||||
|
||||
/*
|
||||
* the 3299 event id in netmsg.dll has the generic message format:
|
||||
* "%1 %2 %3 %4 %5 %6 %7 %8 %9"
|
||||
*/
|
||||
|
||||
ReportEvent(ev, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, 9, 0, msgarg, NULL);
|
||||
|
||||
DeregisterEventSource(ev);
|
||||
}
|
||||
@@ -0,0 +1,884 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_UTF16_BUFLEN 256
|
||||
|
||||
static ngx_int_t ngx_win32_check_filename(u_char *name, u_short *u,
|
||||
size_t len);
|
||||
static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len);
|
||||
|
||||
|
||||
/* FILE_FLAG_BACKUP_SEMANTICS allows to obtain a handle to a directory */
|
||||
|
||||
ngx_fd_t
|
||||
ngx_open_file(u_char *name, u_long mode, u_long create, u_long access)
|
||||
{
|
||||
size_t len;
|
||||
u_short *u;
|
||||
ngx_fd_t fd;
|
||||
ngx_err_t err;
|
||||
u_short utf16[NGX_UTF16_BUFLEN];
|
||||
|
||||
len = NGX_UTF16_BUFLEN;
|
||||
u = ngx_utf8_to_utf16(utf16, name, &len);
|
||||
|
||||
if (u == NULL) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
fd = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (create == NGX_FILE_OPEN
|
||||
&& ngx_win32_check_filename(name, u, len) != NGX_OK)
|
||||
{
|
||||
goto failed;
|
||||
}
|
||||
|
||||
fd = CreateFileW(u, mode,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
|
||||
failed:
|
||||
|
||||
if (u != utf16) {
|
||||
err = ngx_errno;
|
||||
ngx_free(u);
|
||||
ngx_set_errno(err);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
||||
{
|
||||
u_long n;
|
||||
ngx_err_t err;
|
||||
OVERLAPPED ovlp, *povlp;
|
||||
|
||||
ovlp.Internal = 0;
|
||||
ovlp.InternalHigh = 0;
|
||||
ovlp.Offset = (u_long) offset;
|
||||
ovlp.OffsetHigh = (u_long) (offset >> 32);
|
||||
ovlp.hEvent = NULL;
|
||||
|
||||
povlp = &ovlp;
|
||||
|
||||
if (ReadFile(file->fd, buf, size, &n, povlp) == 0) {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == ERROR_HANDLE_EOF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, file->log, err,
|
||||
"ReadFile() \"%s\" failed", file->name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
file->offset += n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
||||
{
|
||||
u_long n;
|
||||
OVERLAPPED ovlp, *povlp;
|
||||
|
||||
ovlp.Internal = 0;
|
||||
ovlp.InternalHigh = 0;
|
||||
ovlp.Offset = (u_long) offset;
|
||||
ovlp.OffsetHigh = (u_long) (offset >> 32);
|
||||
ovlp.hEvent = NULL;
|
||||
|
||||
povlp = &ovlp;
|
||||
|
||||
if (WriteFile(file->fd, buf, size, &n, povlp) == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno,
|
||||
"WriteFile() \"%s\" failed", file->name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (n != size) {
|
||||
ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
||||
"WriteFile() \"%s\" has written only %ul of %uz",
|
||||
file->name.data, n, size);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
file->offset += n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
|
||||
ngx_pool_t *pool)
|
||||
{
|
||||
u_char *buf, *prev;
|
||||
size_t size;
|
||||
ssize_t total, n;
|
||||
|
||||
total = 0;
|
||||
|
||||
while (cl) {
|
||||
buf = cl->buf->pos;
|
||||
prev = buf;
|
||||
size = 0;
|
||||
|
||||
/* coalesce the neighbouring bufs */
|
||||
|
||||
while (cl && prev == cl->buf->pos) {
|
||||
size += cl->buf->last - cl->buf->pos;
|
||||
prev = cl->buf->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;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_read_fd(ngx_fd_t fd, void *buf, size_t size)
|
||||
{
|
||||
u_long n;
|
||||
|
||||
if (ReadFile(fd, buf, size, &n, NULL) != 0) {
|
||||
return (size_t) n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_write_fd(ngx_fd_t fd, void *buf, size_t size)
|
||||
{
|
||||
u_long n;
|
||||
|
||||
if (WriteFile(fd, buf, size, &n, NULL) != 0) {
|
||||
return (size_t) n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_write_console(ngx_fd_t fd, void *buf, size_t size)
|
||||
{
|
||||
u_long n;
|
||||
|
||||
(void) CharToOemBuff(buf, buf, size);
|
||||
|
||||
if (WriteFile(fd, buf, size, &n, NULL) != 0) {
|
||||
return (size_t) n;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ngx_err_t
|
||||
ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log)
|
||||
{
|
||||
u_char *name;
|
||||
ngx_err_t err;
|
||||
ngx_uint_t collision;
|
||||
ngx_atomic_uint_t num;
|
||||
|
||||
name = ngx_alloc(to->len + 1 + NGX_ATOMIC_T_LEN + 1 + sizeof("DELETE"),
|
||||
log);
|
||||
if (name == NULL) {
|
||||
return NGX_ENOMEM;
|
||||
}
|
||||
|
||||
ngx_memcpy(name, to->data, to->len);
|
||||
|
||||
collision = 0;
|
||||
|
||||
/* mutex_lock() (per cache or single ?) */
|
||||
|
||||
for ( ;; ) {
|
||||
num = ngx_next_temp_number(collision);
|
||||
|
||||
ngx_sprintf(name + to->len, ".%0muA.DELETE%Z", num);
|
||||
|
||||
if (MoveFile((const char *) to->data, (const char *) name) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
collision = 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
|
||||
"MoveFile() \"%s\" to \"%s\" failed", to->data, name);
|
||||
}
|
||||
|
||||
if (MoveFile((const char *) from->data, (const char *) to->data) == 0) {
|
||||
err = ngx_errno;
|
||||
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (DeleteFile((const char *) name) == 0) {
|
||||
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
|
||||
"DeleteFile() \"%s\" failed", name);
|
||||
}
|
||||
|
||||
/* mutex_unlock() */
|
||||
|
||||
ngx_free(name);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_file_info(u_char *file, ngx_file_info_t *sb)
|
||||
{
|
||||
size_t len;
|
||||
long rc;
|
||||
u_short *u;
|
||||
ngx_err_t err;
|
||||
WIN32_FILE_ATTRIBUTE_DATA fa;
|
||||
u_short utf16[NGX_UTF16_BUFLEN];
|
||||
|
||||
len = NGX_UTF16_BUFLEN;
|
||||
|
||||
u = ngx_utf8_to_utf16(utf16, file, &len);
|
||||
|
||||
if (u == NULL) {
|
||||
return NGX_FILE_ERROR;
|
||||
}
|
||||
|
||||
rc = NGX_FILE_ERROR;
|
||||
|
||||
if (ngx_win32_check_filename(file, u, len) != NGX_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rc = GetFileAttributesExW(u, GetFileExInfoStandard, &fa);
|
||||
|
||||
sb->dwFileAttributes = fa.dwFileAttributes;
|
||||
sb->ftCreationTime = fa.ftCreationTime;
|
||||
sb->ftLastAccessTime = fa.ftLastAccessTime;
|
||||
sb->ftLastWriteTime = fa.ftLastWriteTime;
|
||||
sb->nFileSizeHigh = fa.nFileSizeHigh;
|
||||
sb->nFileSizeLow = fa.nFileSizeLow;
|
||||
|
||||
failed:
|
||||
|
||||
if (u != utf16) {
|
||||
err = ngx_errno;
|
||||
ngx_free(u);
|
||||
ngx_set_errno(err);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
|
||||
{
|
||||
uint64_t intervals;
|
||||
FILETIME ft;
|
||||
|
||||
/* 116444736000000000 is commented in src/os/win32/ngx_time.c */
|
||||
|
||||
intervals = s * 10000000 + 116444736000000000;
|
||||
|
||||
ft.dwLowDateTime = (DWORD) intervals;
|
||||
ft.dwHighDateTime = (DWORD) (intervals >> 32);
|
||||
|
||||
if (SetFileTime(fd, NULL, NULL, &ft) != 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_create_file_mapping(ngx_file_mapping_t *fm)
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
|
||||
fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
|
||||
NGX_FILE_DEFAULT_ACCESS);
|
||||
|
||||
if (fm->fd == NGX_INVALID_FILE) {
|
||||
ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
|
||||
ngx_open_file_n " \"%s\" failed", fm->name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
fm->handle = NULL;
|
||||
|
||||
size.QuadPart = fm->size;
|
||||
|
||||
if (SetFilePointerEx(fm->fd, size, NULL, FILE_BEGIN) == 0) {
|
||||
ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
|
||||
"SetFilePointerEx(\"%s\", %uz) failed",
|
||||
fm->name, fm->size);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (SetEndOfFile(fm->fd) == 0) {
|
||||
ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
|
||||
"SetEndOfFile() \"%s\" failed", fm->name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
fm->handle = CreateFileMapping(fm->fd, NULL, PAGE_READWRITE,
|
||||
(u_long) ((off_t) fm->size >> 32),
|
||||
(u_long) ((off_t) fm->size & 0xffffffff),
|
||||
NULL);
|
||||
if (fm->handle == NULL) {
|
||||
ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
|
||||
"CreateFileMapping(%s, %uz) failed",
|
||||
fm->name, fm->size);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
fm->addr = MapViewOfFile(fm->handle, FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if (fm->addr != NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno,
|
||||
"MapViewOfFile(%uz) of file mapping \"%s\" failed",
|
||||
fm->size, fm->name);
|
||||
|
||||
failed:
|
||||
|
||||
if (fm->handle) {
|
||||
if (CloseHandle(fm->handle) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
|
||||
"CloseHandle() of file mapping \"%s\" failed",
|
||||
fm->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed", fm->name);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_close_file_mapping(ngx_file_mapping_t *fm)
|
||||
{
|
||||
if (UnmapViewOfFile(fm->addr) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
|
||||
"UnmapViewOfFile(%p) of file mapping \"%s\" failed",
|
||||
fm->addr, &fm->name);
|
||||
}
|
||||
|
||||
if (CloseHandle(fm->handle) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
|
||||
"CloseHandle() of file mapping \"%s\" failed",
|
||||
&fm->name);
|
||||
}
|
||||
|
||||
if (ngx_close_file(fm->fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, fm->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed", fm->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u_char *
|
||||
ngx_realpath(u_char *path, u_char *resolved)
|
||||
{
|
||||
/* STUB */
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
|
||||
{
|
||||
ngx_cpystrn(name->data + name->len, NGX_DIR_MASK, NGX_DIR_MASK_LEN + 1);
|
||||
|
||||
dir->dir = FindFirstFile((const char *) name->data, &dir->finddata);
|
||||
|
||||
name->data[name->len] = '\0';
|
||||
|
||||
if (dir->dir == INVALID_HANDLE_VALUE) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
dir->valid_info = 1;
|
||||
dir->ready = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_read_dir(ngx_dir_t *dir)
|
||||
{
|
||||
if (dir->ready) {
|
||||
dir->ready = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (FindNextFile(dir->dir, &dir->finddata) != 0) {
|
||||
dir->type = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_close_dir(ngx_dir_t *dir)
|
||||
{
|
||||
if (FindClose(dir->dir) == 0) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_open_glob(ngx_glob_t *gl)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_err_t err;
|
||||
|
||||
gl->dir = FindFirstFile((const char *) gl->pattern, &gl->finddata);
|
||||
|
||||
if (gl->dir == INVALID_HANDLE_VALUE) {
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
if ((err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
|
||||
&& gl->test)
|
||||
{
|
||||
gl->no_match = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
for (p = gl->pattern; *p; p++) {
|
||||
if (*p == '/') {
|
||||
gl->last = p + 1 - gl->pattern;
|
||||
}
|
||||
}
|
||||
|
||||
len = ngx_strlen(gl->finddata.cFileName);
|
||||
gl->name.len = gl->last + len;
|
||||
|
||||
gl->name.data = ngx_alloc(gl->name.len + 1, gl->log);
|
||||
if (gl->name.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(gl->name.data, gl->pattern, gl->last);
|
||||
ngx_cpystrn(gl->name.data + gl->last, (u_char *) gl->finddata.cFileName,
|
||||
len + 1);
|
||||
|
||||
gl->ready = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
|
||||
{
|
||||
size_t len;
|
||||
ngx_err_t err;
|
||||
|
||||
if (gl->no_match) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (gl->ready) {
|
||||
*name = gl->name;
|
||||
|
||||
gl->ready = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_free(gl->name.data);
|
||||
gl->name.data = NULL;
|
||||
|
||||
if (FindNextFile(gl->dir, &gl->finddata) != 0) {
|
||||
|
||||
len = ngx_strlen(gl->finddata.cFileName);
|
||||
gl->name.len = gl->last + len;
|
||||
|
||||
gl->name.data = ngx_alloc(gl->name.len + 1, gl->log);
|
||||
if (gl->name.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(gl->name.data, gl->pattern, gl->last);
|
||||
ngx_cpystrn(gl->name.data + gl->last, (u_char *) gl->finddata.cFileName,
|
||||
len + 1);
|
||||
|
||||
*name = gl->name;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == NGX_ENOMOREFILES) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, gl->log, err,
|
||||
"FindNextFile(%s) failed", gl->pattern);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_close_glob(ngx_glob_t *gl)
|
||||
{
|
||||
if (gl->name.data) {
|
||||
ngx_free(gl->name.data);
|
||||
}
|
||||
|
||||
if (gl->dir == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FindClose(gl->dir) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, gl->log, ngx_errno,
|
||||
"FindClose(%s) failed", gl->pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_de_info(u_char *name, ngx_dir_t *dir)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_de_link_info(u_char *name, ngx_dir_t *dir)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_read_ahead(ngx_fd_t fd, size_t n)
|
||||
{
|
||||
return ~NGX_FILE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_directio_on(ngx_fd_t fd)
|
||||
{
|
||||
return ~NGX_FILE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_directio_off(ngx_fd_t fd)
|
||||
{
|
||||
return ~NGX_FILE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
ngx_fs_bsize(u_char *name)
|
||||
{
|
||||
u_char root[4];
|
||||
u_long sc, bs, nfree, ncl;
|
||||
|
||||
if (name[2] == ':') {
|
||||
ngx_cpystrn(root, name, 4);
|
||||
name = root;
|
||||
}
|
||||
|
||||
if (GetDiskFreeSpace((const char *) name, &sc, &bs, &nfree, &ncl) == 0) {
|
||||
return 512;
|
||||
}
|
||||
|
||||
return sc * bs;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
|
||||
{
|
||||
u_char *p, ch;
|
||||
u_long n;
|
||||
u_short *lu;
|
||||
ngx_err_t err;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_normal,
|
||||
sw_after_slash,
|
||||
sw_after_colon,
|
||||
sw_after_dot
|
||||
} state;
|
||||
|
||||
/* check for NTFS streams (":"), trailing dots and spaces */
|
||||
|
||||
lu = NULL;
|
||||
state = sw_start;
|
||||
|
||||
for (p = name; *p; p++) {
|
||||
ch = *p;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case sw_start:
|
||||
|
||||
/*
|
||||
* skip till first "/" to allow paths starting with drive and
|
||||
* relative path, like "c:html/"
|
||||
*/
|
||||
|
||||
if (ch == '/' || ch == '\\') {
|
||||
state = sw_after_slash;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case sw_normal:
|
||||
|
||||
if (ch == ':') {
|
||||
state = sw_after_colon;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '.' || ch == ' ') {
|
||||
state = sw_after_dot;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '/' || ch == '\\') {
|
||||
state = sw_after_slash;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case sw_after_slash:
|
||||
|
||||
if (ch == '/' || ch == '\\') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '.') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == ':') {
|
||||
state = sw_after_colon;
|
||||
break;
|
||||
}
|
||||
|
||||
state = sw_normal;
|
||||
break;
|
||||
|
||||
case sw_after_colon:
|
||||
|
||||
if (ch == '/' || ch == '\\') {
|
||||
state = sw_after_slash;
|
||||
break;
|
||||
}
|
||||
|
||||
goto invalid;
|
||||
|
||||
case sw_after_dot:
|
||||
|
||||
if (ch == '/' || ch == '\\') {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (ch == ':') {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (ch == '.' || ch == ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
state = sw_normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == sw_after_dot) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* check if long name match */
|
||||
|
||||
lu = malloc(len * 2);
|
||||
if (lu == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
n = GetLongPathNameW(u, lu, len);
|
||||
|
||||
if (n == 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (n != len - 1 || _wcsicmp(u, lu) != 0) {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
ngx_free(lu);
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
invalid:
|
||||
|
||||
ngx_set_errno(NGX_ENOENT);
|
||||
|
||||
failed:
|
||||
|
||||
if (lu) {
|
||||
err = ngx_errno;
|
||||
ngx_free(lu);
|
||||
ngx_set_errno(err);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static u_short *
|
||||
ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len)
|
||||
{
|
||||
u_char *p;
|
||||
u_short *u, *last;
|
||||
uint32_t n;
|
||||
|
||||
p = utf8;
|
||||
u = utf16;
|
||||
last = utf16 + *len;
|
||||
|
||||
while (u < last) {
|
||||
|
||||
if (*p < 0x80) {
|
||||
*u++ = (u_short) *p;
|
||||
|
||||
if (*p == 0) {
|
||||
*len = u - utf16;
|
||||
return utf16;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u + 1 == last) {
|
||||
*len = u - utf16;
|
||||
break;
|
||||
}
|
||||
|
||||
n = ngx_utf8_decode(&p, 4);
|
||||
|
||||
if (n > 0x10ffff) {
|
||||
ngx_set_errno(NGX_EILSEQ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (n > 0xffff) {
|
||||
n -= 0x10000;
|
||||
*u++ = (u_short) (0xd800 + (n >> 10));
|
||||
*u++ = (u_short) (0xdc00 + (n & 0x03ff));
|
||||
continue;
|
||||
}
|
||||
|
||||
*u++ = (u_short) n;
|
||||
}
|
||||
|
||||
/* the given buffer is not enough, allocate a new one */
|
||||
|
||||
u = malloc(((p - utf8) + ngx_strlen(p) + 1) * sizeof(u_short));
|
||||
if (u == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ngx_memcpy(u, utf16, *len * 2);
|
||||
|
||||
utf16 = u;
|
||||
u += *len;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
if (*p < 0x80) {
|
||||
*u++ = (u_short) *p;
|
||||
|
||||
if (*p == 0) {
|
||||
*len = u - utf16;
|
||||
return utf16;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
n = ngx_utf8_decode(&p, 4);
|
||||
|
||||
if (n > 0x10ffff) {
|
||||
ngx_free(utf16);
|
||||
ngx_set_errno(NGX_EILSEQ);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (n > 0xffff) {
|
||||
n -= 0x10000;
|
||||
*u++ = (u_short) (0xd800 + (n >> 10));
|
||||
*u++ = (u_short) (0xdc00 + (n & 0x03ff));
|
||||
continue;
|
||||
}
|
||||
|
||||
*u++ = (u_short) n;
|
||||
}
|
||||
|
||||
/* unreachable */
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_FILES_H_INCLUDED_
|
||||
#define _NGX_FILES_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef HANDLE ngx_fd_t;
|
||||
typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t;
|
||||
typedef uint64_t ngx_file_uniq_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char *name;
|
||||
size_t size;
|
||||
void *addr;
|
||||
ngx_fd_t fd;
|
||||
HANDLE handle;
|
||||
ngx_log_t *log;
|
||||
} ngx_file_mapping_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATA finddata;
|
||||
|
||||
unsigned valid_info:1;
|
||||
unsigned type:1;
|
||||
unsigned ready:1;
|
||||
} ngx_dir_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATA finddata;
|
||||
|
||||
unsigned ready:1;
|
||||
unsigned test:1;
|
||||
unsigned no_match:1;
|
||||
|
||||
u_char *pattern;
|
||||
ngx_str_t name;
|
||||
size_t last;
|
||||
ngx_log_t *log;
|
||||
} ngx_glob_t;
|
||||
|
||||
|
||||
|
||||
/* INVALID_FILE_ATTRIBUTES is specified but not defined at least in MSVC6SP2 */
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES 0xffffffff
|
||||
#endif
|
||||
|
||||
/* INVALID_SET_FILE_POINTER is not defined at least in MSVC6SP2 */
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER 0xffffffff
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_INVALID_FILE INVALID_HANDLE_VALUE
|
||||
#define NGX_FILE_ERROR 0
|
||||
|
||||
|
||||
ngx_fd_t ngx_open_file(u_char *name, u_long mode, u_long create, u_long access);
|
||||
#define ngx_open_file_n "CreateFile()"
|
||||
|
||||
#define NGX_FILE_RDONLY GENERIC_READ
|
||||
#define NGX_FILE_WRONLY GENERIC_WRITE
|
||||
#define NGX_FILE_RDWR GENERIC_READ|GENERIC_WRITE
|
||||
#define NGX_FILE_APPEND FILE_APPEND_DATA|SYNCHRONIZE
|
||||
#define NGX_FILE_NONBLOCK 0
|
||||
|
||||
#define NGX_FILE_CREATE_OR_OPEN OPEN_ALWAYS
|
||||
#define NGX_FILE_OPEN OPEN_EXISTING
|
||||
#define NGX_FILE_TRUNCATE CREATE_ALWAYS
|
||||
|
||||
#define NGX_FILE_DEFAULT_ACCESS 0
|
||||
#define NGX_FILE_OWNER_ACCESS 0
|
||||
|
||||
|
||||
#define ngx_open_tempfile(name, persistent, access) \
|
||||
CreateFile((const char *) name, \
|
||||
GENERIC_READ|GENERIC_WRITE, \
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, \
|
||||
NULL, \
|
||||
CREATE_NEW, \
|
||||
persistent ? 0: \
|
||||
FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, \
|
||||
NULL);
|
||||
|
||||
#define ngx_open_tempfile_n "CreateFile()"
|
||||
|
||||
|
||||
#define ngx_close_file CloseHandle
|
||||
#define ngx_close_file_n "CloseHandle()"
|
||||
|
||||
|
||||
ssize_t ngx_read_fd(ngx_fd_t fd, void *buf, size_t size);
|
||||
#define ngx_read_fd_n "ReadFile()"
|
||||
|
||||
|
||||
ssize_t ngx_write_fd(ngx_fd_t fd, void *buf, size_t size);
|
||||
#define ngx_write_fd_n "WriteFile()"
|
||||
|
||||
|
||||
ssize_t ngx_write_console(ngx_fd_t fd, void *buf, size_t size);
|
||||
|
||||
|
||||
#define ngx_linefeed(p) *p++ = CR; *p++ = LF;
|
||||
#define NGX_LINEFEED_SIZE 2
|
||||
#define NGX_LINEFEED CRLF
|
||||
|
||||
|
||||
#define ngx_delete_file(name) DeleteFile((const char *) name)
|
||||
#define ngx_delete_file_n "DeleteFile()"
|
||||
|
||||
|
||||
#define ngx_rename_file(o, n) MoveFile((const char *) o, (const char *) n)
|
||||
#define ngx_rename_file_n "MoveFile()"
|
||||
ngx_err_t ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log);
|
||||
|
||||
|
||||
|
||||
ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
|
||||
#define ngx_set_file_time_n "SetFileTime()"
|
||||
|
||||
|
||||
ngx_int_t ngx_file_info(u_char *filename, ngx_file_info_t *fi);
|
||||
#define ngx_file_info_n "GetFileAttributesEx()"
|
||||
|
||||
|
||||
#define ngx_fd_info(fd, fi) GetFileInformationByHandle(fd, fi)
|
||||
#define ngx_fd_info_n "GetFileInformationByHandle()"
|
||||
|
||||
|
||||
#define ngx_link_info(name, fi) ngx_file_info(name, fi)
|
||||
#define ngx_link_info_n "GetFileAttributesEx()"
|
||||
|
||||
|
||||
#define ngx_is_dir(fi) \
|
||||
(((fi)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
#define ngx_is_file(fi) \
|
||||
(((fi)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
#define ngx_is_link(fi) 0
|
||||
#define ngx_is_exec(fi) 0
|
||||
|
||||
#define ngx_file_access(fi) 0
|
||||
|
||||
#define ngx_file_size(fi) \
|
||||
(((off_t) (fi)->nFileSizeHigh << 32) | (fi)->nFileSizeLow)
|
||||
#define ngx_file_fs_size(fi) ngx_file_size(fi)
|
||||
|
||||
#define ngx_file_uniq(fi) (*(ngx_file_uniq_t *) &(fi)->nFileIndexHigh)
|
||||
|
||||
|
||||
/* 116444736000000000 is commented in src/os/win32/ngx_time.c */
|
||||
|
||||
#define ngx_file_mtime(fi) \
|
||||
(time_t) (((((unsigned __int64) (fi)->ftLastWriteTime.dwHighDateTime << 32) \
|
||||
| (fi)->ftLastWriteTime.dwLowDateTime) \
|
||||
- 116444736000000000) / 10000000)
|
||||
|
||||
ngx_int_t ngx_create_file_mapping(ngx_file_mapping_t *fm);
|
||||
void ngx_close_file_mapping(ngx_file_mapping_t *fm);
|
||||
|
||||
|
||||
u_char *ngx_realpath(u_char *path, u_char *resolved);
|
||||
#define ngx_realpath_n ""
|
||||
#define ngx_getcwd(buf, size) GetCurrentDirectory(size, (char *) buf)
|
||||
#define ngx_getcwd_n "GetCurrentDirectory()"
|
||||
#define ngx_path_separator(c) ((c) == '/' || (c) == '\\')
|
||||
|
||||
#define NGX_HAVE_MAX_PATH 1
|
||||
#define NGX_MAX_PATH MAX_PATH
|
||||
|
||||
#define NGX_DIR_MASK (u_char *) "/*"
|
||||
#define NGX_DIR_MASK_LEN 2
|
||||
|
||||
|
||||
ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir);
|
||||
#define ngx_open_dir_n "FindFirstFile()"
|
||||
|
||||
|
||||
ngx_int_t ngx_read_dir(ngx_dir_t *dir);
|
||||
#define ngx_read_dir_n "FindNextFile()"
|
||||
|
||||
|
||||
ngx_int_t ngx_close_dir(ngx_dir_t *dir);
|
||||
#define ngx_close_dir_n "FindClose()"
|
||||
|
||||
|
||||
#define ngx_create_dir(name, access) CreateDirectory((const char *) name, NULL)
|
||||
#define ngx_create_dir_n "CreateDirectory()"
|
||||
|
||||
|
||||
#define ngx_delete_dir(name) RemoveDirectory((const char *) name)
|
||||
#define ngx_delete_dir_n "RemoveDirectory()"
|
||||
|
||||
|
||||
#define ngx_dir_access(a) (a)
|
||||
|
||||
|
||||
#define ngx_de_name(dir) ((u_char *) (dir)->finddata.cFileName)
|
||||
#define ngx_de_namelen(dir) ngx_strlen((dir)->finddata.cFileName)
|
||||
|
||||
ngx_int_t ngx_de_info(u_char *name, ngx_dir_t *dir);
|
||||
#define ngx_de_info_n "dummy()"
|
||||
|
||||
ngx_int_t ngx_de_link_info(u_char *name, ngx_dir_t *dir);
|
||||
#define ngx_de_link_info_n "dummy()"
|
||||
|
||||
#define ngx_de_is_dir(dir) \
|
||||
(((dir)->finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
#define ngx_de_is_file(dir) \
|
||||
(((dir)->finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
#define ngx_de_is_link(dir) 0
|
||||
#define ngx_de_access(dir) 0
|
||||
#define ngx_de_size(dir) \
|
||||
(((off_t) (dir)->finddata.nFileSizeHigh << 32) | (dir)->finddata.nFileSizeLow)
|
||||
#define ngx_de_fs_size(dir) ngx_de_size(dir)
|
||||
|
||||
/* 116444736000000000 is commented in src/os/win32/ngx_time.c */
|
||||
|
||||
#define ngx_de_mtime(dir) \
|
||||
(time_t) (((((unsigned __int64) \
|
||||
(dir)->finddata.ftLastWriteTime.dwHighDateTime << 32) \
|
||||
| (dir)->finddata.ftLastWriteTime.dwLowDateTime) \
|
||||
- 116444736000000000) / 10000000)
|
||||
|
||||
|
||||
ngx_int_t ngx_open_glob(ngx_glob_t *gl);
|
||||
#define ngx_open_glob_n "FindFirstFile()"
|
||||
|
||||
ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name);
|
||||
void ngx_close_glob(ngx_glob_t *gl);
|
||||
|
||||
|
||||
ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset);
|
||||
#define ngx_read_file_n "ReadFile()"
|
||||
|
||||
ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size,
|
||||
off_t offset);
|
||||
|
||||
ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
off_t offset, ngx_pool_t *pool);
|
||||
|
||||
ngx_int_t ngx_read_ahead(ngx_fd_t fd, size_t n);
|
||||
#define ngx_read_ahead_n "ngx_read_ahead_n"
|
||||
|
||||
ngx_int_t ngx_directio_on(ngx_fd_t fd);
|
||||
#define ngx_directio_on_n "ngx_directio_on_n"
|
||||
|
||||
ngx_int_t ngx_directio_off(ngx_fd_t fd);
|
||||
#define ngx_directio_off_n "ngx_directio_off_n"
|
||||
|
||||
size_t ngx_fs_bsize(u_char *name);
|
||||
|
||||
|
||||
#define ngx_stdout GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
#define ngx_stderr GetStdHandle(STD_ERROR_HANDLE)
|
||||
#define ngx_set_stderr(fd) SetStdHandle(STD_ERROR_HANDLE, fd)
|
||||
#define ngx_set_stderr_n "SetStdHandle(STD_ERROR_HANDLE)"
|
||||
|
||||
|
||||
#endif /* _NGX_FILES_H_INCLUDED_ */
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_OS_H_INCLUDED_
|
||||
#define _NGX_OS_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_IO_SENDFILE 1
|
||||
|
||||
|
||||
typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in,
|
||||
off_t limit);
|
||||
typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in,
|
||||
off_t limit);
|
||||
|
||||
typedef struct {
|
||||
ngx_recv_pt recv;
|
||||
ngx_recv_chain_pt recv_chain;
|
||||
ngx_recv_pt udp_recv;
|
||||
ngx_send_pt send;
|
||||
ngx_send_pt udp_send;
|
||||
ngx_send_chain_pt udp_send_chain;
|
||||
ngx_send_chain_pt send_chain;
|
||||
ngx_uint_t flags;
|
||||
} ngx_os_io_t;
|
||||
|
||||
|
||||
ngx_int_t ngx_os_init(ngx_log_t *log);
|
||||
void ngx_os_status(ngx_log_t *log);
|
||||
ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_pid_t pid);
|
||||
|
||||
ssize_t ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf,
|
||||
size_t size);
|
||||
ssize_t ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit);
|
||||
ssize_t ngx_wsasend(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_udp_wsasend(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ssize_t ngx_overlapped_wsasend(ngx_connection_t *c, u_char *buf, size_t size);
|
||||
ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||
off_t limit);
|
||||
ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in,
|
||||
off_t limit);
|
||||
|
||||
void ngx_cdecl ngx_event_log(ngx_err_t err, const char *fmt, ...);
|
||||
|
||||
|
||||
extern ngx_os_io_t ngx_os_io;
|
||||
extern ngx_uint_t ngx_ncpu;
|
||||
extern ngx_uint_t ngx_max_wsabufs;
|
||||
extern ngx_int_t ngx_max_sockets;
|
||||
extern ngx_uint_t ngx_inherited_nonblocking;
|
||||
extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush;
|
||||
extern ngx_uint_t ngx_win32_version;
|
||||
extern char ngx_unique[];
|
||||
|
||||
|
||||
#endif /* _NGX_OS_H_INCLUDED_ */
|
||||
@@ -0,0 +1,238 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
int ngx_argc;
|
||||
char **ngx_argv;
|
||||
char **ngx_os_argv;
|
||||
|
||||
ngx_int_t ngx_last_process;
|
||||
ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
|
||||
|
||||
|
||||
ngx_pid_t
|
||||
ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn)
|
||||
{
|
||||
u_long rc, n, code;
|
||||
ngx_int_t s;
|
||||
ngx_pid_t pid;
|
||||
ngx_exec_ctx_t ctx;
|
||||
HANDLE events[2];
|
||||
char file[MAX_PATH + 1];
|
||||
|
||||
if (respawn >= 0) {
|
||||
s = respawn;
|
||||
|
||||
} else {
|
||||
for (s = 0; s < ngx_last_process; s++) {
|
||||
if (ngx_processes[s].handle == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NGX_MAX_PROCESSES) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"no more than %d processes can be spawned",
|
||||
NGX_MAX_PROCESSES);
|
||||
return NGX_INVALID_PID;
|
||||
}
|
||||
}
|
||||
|
||||
n = GetModuleFileName(NULL, file, MAX_PATH);
|
||||
|
||||
if (n == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"GetModuleFileName() failed");
|
||||
return NGX_INVALID_PID;
|
||||
}
|
||||
|
||||
file[n] = '\0';
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"GetModuleFileName: \"%s\"", file);
|
||||
|
||||
ctx.path = file;
|
||||
ctx.name = name;
|
||||
ctx.args = GetCommandLine();
|
||||
ctx.argv = NULL;
|
||||
ctx.envp = NULL;
|
||||
|
||||
pid = ngx_execute(cycle, &ctx);
|
||||
|
||||
if (pid == NGX_INVALID_PID) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
ngx_memzero(&ngx_processes[s], sizeof(ngx_process_t));
|
||||
|
||||
ngx_processes[s].handle = ctx.child;
|
||||
ngx_processes[s].pid = pid;
|
||||
ngx_processes[s].name = name;
|
||||
|
||||
ngx_sprintf(ngx_processes[s].term_event, "ngx_%s_term_%P%Z", name, pid);
|
||||
ngx_sprintf(ngx_processes[s].quit_event, "ngx_%s_quit_%P%Z", name, pid);
|
||||
ngx_sprintf(ngx_processes[s].reopen_event, "ngx_%s_reopen_%P%Z",
|
||||
name, pid);
|
||||
|
||||
events[0] = ngx_master_process_event;
|
||||
events[1] = ctx.child;
|
||||
|
||||
rc = WaitForMultipleObjects(2, events, 0, 5000);
|
||||
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"WaitForMultipleObjects: %ul", rc);
|
||||
|
||||
switch (rc) {
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
|
||||
ngx_processes[s].term = OpenEvent(EVENT_MODIFY_STATE, 0,
|
||||
(char *) ngx_processes[s].term_event);
|
||||
if (ngx_processes[s].term == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"OpenEvent(\"%s\") failed",
|
||||
ngx_processes[s].term_event);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ngx_processes[s].quit = OpenEvent(EVENT_MODIFY_STATE, 0,
|
||||
(char *) ngx_processes[s].quit_event);
|
||||
if (ngx_processes[s].quit == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"OpenEvent(\"%s\") failed",
|
||||
ngx_processes[s].quit_event);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ngx_processes[s].reopen = OpenEvent(EVENT_MODIFY_STATE, 0,
|
||||
(char *) ngx_processes[s].reopen_event);
|
||||
if (ngx_processes[s].reopen == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"OpenEvent(\"%s\") failed",
|
||||
ngx_processes[s].reopen_event);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ResetEvent(ngx_master_process_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"ResetEvent(\"%s\") failed",
|
||||
ngx_master_process_event_name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
if (GetExitCodeProcess(ctx.child, &code) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"GetExitCodeProcess(%P) failed", pid);
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"%s process %P exited with code %Xl",
|
||||
name, pid, code);
|
||||
|
||||
goto failed;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"the event \"%s\" was not signaled for 5s",
|
||||
ngx_master_process_event_name);
|
||||
goto failed;
|
||||
|
||||
case WAIT_FAILED:
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"WaitForSingleObject(\"%s\") failed",
|
||||
ngx_master_process_event_name);
|
||||
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (respawn >= 0) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
switch (respawn) {
|
||||
|
||||
case NGX_PROCESS_RESPAWN:
|
||||
ngx_processes[s].just_spawn = 0;
|
||||
break;
|
||||
|
||||
case NGX_PROCESS_JUST_RESPAWN:
|
||||
ngx_processes[s].just_spawn = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s == ngx_last_process) {
|
||||
ngx_last_process++;
|
||||
}
|
||||
|
||||
return pid;
|
||||
|
||||
failed:
|
||||
|
||||
if (ngx_processes[s].reopen) {
|
||||
ngx_close_handle(ngx_processes[s].reopen);
|
||||
}
|
||||
|
||||
if (ngx_processes[s].quit) {
|
||||
ngx_close_handle(ngx_processes[s].quit);
|
||||
}
|
||||
|
||||
if (ngx_processes[s].term) {
|
||||
ngx_close_handle(ngx_processes[s].term);
|
||||
}
|
||||
|
||||
TerminateProcess(ngx_processes[s].handle, 2);
|
||||
|
||||
if (ngx_processes[s].handle) {
|
||||
ngx_close_handle(ngx_processes[s].handle);
|
||||
ngx_processes[s].handle = NULL;
|
||||
}
|
||||
|
||||
return NGX_INVALID_PID;
|
||||
}
|
||||
|
||||
|
||||
ngx_pid_t
|
||||
ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ngx_memzero(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
|
||||
ngx_memzero(&pi, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
if (CreateProcess(ctx->path, ctx->args,
|
||||
NULL, NULL, 0, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)
|
||||
== 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
|
||||
"CreateProcess(\"%s\") failed", ngx_argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->child = pi.hProcess;
|
||||
|
||||
if (CloseHandle(pi.hThread) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CloseHandle(pi.hThread) failed");
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
|
||||
"start %s process %P", ctx->name, pi.dwProcessId);
|
||||
|
||||
return pi.dwProcessId;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_PROCESS_H_INCLUDED_
|
||||
#define _NGX_PROCESS_H_INCLUDED_
|
||||
|
||||
|
||||
typedef DWORD ngx_pid_t;
|
||||
#define NGX_INVALID_PID 0
|
||||
|
||||
|
||||
#define ngx_getpid GetCurrentProcessId
|
||||
#define ngx_getppid() 0
|
||||
#define ngx_log_pid ngx_pid
|
||||
|
||||
#define NGX_PROCESS_SYNC_NAME \
|
||||
(sizeof("ngx_cache_manager_mutex_") + NGX_INT32_LEN)
|
||||
|
||||
|
||||
typedef uint64_t ngx_cpuset_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HANDLE handle;
|
||||
ngx_pid_t pid;
|
||||
char *name;
|
||||
|
||||
HANDLE term;
|
||||
HANDLE quit;
|
||||
HANDLE reopen;
|
||||
|
||||
u_char term_event[NGX_PROCESS_SYNC_NAME];
|
||||
u_char quit_event[NGX_PROCESS_SYNC_NAME];
|
||||
u_char reopen_event[NGX_PROCESS_SYNC_NAME];
|
||||
|
||||
unsigned just_spawn:1;
|
||||
unsigned exiting:1;
|
||||
} ngx_process_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
char *name;
|
||||
char *args;
|
||||
char *const *argv;
|
||||
char *const *envp;
|
||||
HANDLE child;
|
||||
} ngx_exec_ctx_t;
|
||||
|
||||
|
||||
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, char *name, ngx_int_t respawn);
|
||||
ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
|
||||
|
||||
#define ngx_debug_point()
|
||||
#define ngx_sched_yield() SwitchToThread()
|
||||
|
||||
|
||||
#define NGX_MAX_PROCESSES (MAXIMUM_WAIT_OBJECTS - 4)
|
||||
|
||||
#define NGX_PROCESS_RESPAWN -2
|
||||
#define NGX_PROCESS_JUST_RESPAWN -3
|
||||
|
||||
|
||||
extern int ngx_argc;
|
||||
extern char **ngx_argv;
|
||||
extern char **ngx_os_argv;
|
||||
|
||||
extern ngx_int_t ngx_last_process;
|
||||
extern ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
|
||||
|
||||
extern ngx_pid_t ngx_pid;
|
||||
extern ngx_pid_t ngx_parent;
|
||||
|
||||
|
||||
#endif /* _NGX_PROCESS_H_INCLUDED_ */
|
||||
@@ -0,0 +1,1043 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static void ngx_console_init(ngx_cycle_t *cycle);
|
||||
static int __stdcall ngx_console_handler(u_long type);
|
||||
static ngx_int_t ngx_create_signal_events(ngx_cycle_t *cycle);
|
||||
static ngx_int_t ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type);
|
||||
static void ngx_reopen_worker_processes(ngx_cycle_t *cycle);
|
||||
static void ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old);
|
||||
static void ngx_terminate_worker_processes(ngx_cycle_t *cycle);
|
||||
static ngx_uint_t ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h);
|
||||
static void ngx_master_process_exit(ngx_cycle_t *cycle);
|
||||
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn);
|
||||
static void ngx_worker_process_exit(ngx_cycle_t *cycle);
|
||||
static ngx_thread_value_t __stdcall ngx_worker_thread(void *data);
|
||||
static ngx_thread_value_t __stdcall ngx_cache_manager_thread(void *data);
|
||||
static void ngx_cache_manager_process_handler(void);
|
||||
static ngx_thread_value_t __stdcall ngx_cache_loader_thread(void *data);
|
||||
|
||||
|
||||
ngx_uint_t ngx_process;
|
||||
ngx_uint_t ngx_worker;
|
||||
ngx_pid_t ngx_pid;
|
||||
ngx_pid_t ngx_parent;
|
||||
|
||||
ngx_uint_t ngx_inherited;
|
||||
ngx_pid_t ngx_new_binary;
|
||||
|
||||
sig_atomic_t ngx_terminate;
|
||||
sig_atomic_t ngx_quit;
|
||||
sig_atomic_t ngx_reopen;
|
||||
sig_atomic_t ngx_reconfigure;
|
||||
ngx_uint_t ngx_exiting;
|
||||
|
||||
|
||||
HANDLE ngx_master_process_event;
|
||||
char ngx_master_process_event_name[NGX_PROCESS_SYNC_NAME];
|
||||
|
||||
static HANDLE ngx_stop_event;
|
||||
static char ngx_stop_event_name[NGX_PROCESS_SYNC_NAME];
|
||||
static HANDLE ngx_quit_event;
|
||||
static char ngx_quit_event_name[NGX_PROCESS_SYNC_NAME];
|
||||
static HANDLE ngx_reopen_event;
|
||||
static char ngx_reopen_event_name[NGX_PROCESS_SYNC_NAME];
|
||||
static HANDLE ngx_reload_event;
|
||||
static char ngx_reload_event_name[NGX_PROCESS_SYNC_NAME];
|
||||
|
||||
HANDLE ngx_cache_manager_mutex;
|
||||
char ngx_cache_manager_mutex_name[NGX_PROCESS_SYNC_NAME];
|
||||
HANDLE ngx_cache_manager_event;
|
||||
|
||||
|
||||
void
|
||||
ngx_master_process_cycle(ngx_cycle_t *cycle)
|
||||
{
|
||||
u_long nev, ev, timeout;
|
||||
ngx_err_t err;
|
||||
ngx_int_t n;
|
||||
ngx_msec_t timer;
|
||||
ngx_uint_t live;
|
||||
HANDLE events[MAXIMUM_WAIT_OBJECTS];
|
||||
|
||||
ngx_sprintf((u_char *) ngx_master_process_event_name,
|
||||
"ngx_master_%s%Z", ngx_unique);
|
||||
|
||||
if (ngx_process == NGX_PROCESS_WORKER) {
|
||||
ngx_worker_process_cycle(cycle, ngx_master_process_event_name);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "master started");
|
||||
|
||||
ngx_console_init(cycle);
|
||||
|
||||
SetEnvironmentVariable("ngx_unique", ngx_unique);
|
||||
|
||||
ngx_master_process_event = CreateEvent(NULL, 1, 0,
|
||||
ngx_master_process_event_name);
|
||||
if (ngx_master_process_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed",
|
||||
ngx_master_process_event_name);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (ngx_create_signal_events(cycle) != NGX_OK) {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
|
||||
"ngx_cache_manager_mutex_%s%Z", ngx_unique);
|
||||
|
||||
ngx_cache_manager_mutex = CreateMutex(NULL, 0,
|
||||
ngx_cache_manager_mutex_name);
|
||||
if (ngx_cache_manager_mutex == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
events[0] = ngx_stop_event;
|
||||
events[1] = ngx_quit_event;
|
||||
events[2] = ngx_reopen_event;
|
||||
events[3] = ngx_reload_event;
|
||||
|
||||
ngx_close_listening_sockets(cycle);
|
||||
|
||||
if (ngx_start_worker_processes(cycle, NGX_PROCESS_RESPAWN) == 0) {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
timer = 0;
|
||||
timeout = INFINITE;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
nev = 4;
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
if (ngx_processes[n].handle) {
|
||||
events[nev++] = ngx_processes[n].handle;
|
||||
}
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
timeout = timer > ngx_current_msec ? timer - ngx_current_msec : 0;
|
||||
}
|
||||
|
||||
ev = WaitForMultipleObjects(nev, events, 0, timeout);
|
||||
|
||||
err = ngx_errno;
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"master WaitForMultipleObjects: %ul", ev);
|
||||
|
||||
if (ev == WAIT_OBJECT_0) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
|
||||
|
||||
if (ResetEvent(ngx_stop_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"ResetEvent(\"%s\") failed", ngx_stop_event_name);
|
||||
}
|
||||
|
||||
if (timer == 0) {
|
||||
timer = ngx_current_msec + 5000;
|
||||
}
|
||||
|
||||
ngx_terminate = 1;
|
||||
ngx_quit_worker_processes(cycle, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 1) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "shutting down");
|
||||
|
||||
if (ResetEvent(ngx_quit_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"ResetEvent(\"%s\") failed", ngx_quit_event_name);
|
||||
}
|
||||
|
||||
ngx_quit = 1;
|
||||
ngx_quit_worker_processes(cycle, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 2) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
|
||||
|
||||
if (ResetEvent(ngx_reopen_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"ResetEvent(\"%s\") failed",
|
||||
ngx_reopen_event_name);
|
||||
}
|
||||
|
||||
ngx_reopen_files(cycle, -1);
|
||||
ngx_reopen_worker_processes(cycle);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 3) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");
|
||||
|
||||
if (ResetEvent(ngx_reload_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"ResetEvent(\"%s\") failed",
|
||||
ngx_reload_event_name);
|
||||
}
|
||||
|
||||
cycle = ngx_init_cycle(cycle);
|
||||
if (cycle == NULL) {
|
||||
cycle = (ngx_cycle_t *) ngx_cycle;
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_cycle = cycle;
|
||||
|
||||
ngx_close_listening_sockets(cycle);
|
||||
|
||||
if (ngx_start_worker_processes(cycle, NGX_PROCESS_JUST_RESPAWN)) {
|
||||
ngx_quit_worker_processes(cycle, 1);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev > WAIT_OBJECT_0 + 3 && ev < WAIT_OBJECT_0 + nev) {
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "reap worker");
|
||||
|
||||
live = ngx_reap_worker(cycle, events[ev]);
|
||||
|
||||
if (!live && (ngx_terminate || ngx_quit)) {
|
||||
ngx_master_process_exit(cycle);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_TIMEOUT) {
|
||||
ngx_terminate_worker_processes(cycle);
|
||||
|
||||
ngx_master_process_exit(cycle);
|
||||
}
|
||||
|
||||
if (ev == WAIT_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
||||
"WaitForMultipleObjects() failed");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"WaitForMultipleObjects() returned unexpected value %ul", ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_console_init(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_core_conf_t *ccf;
|
||||
|
||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
||||
|
||||
if (ccf->daemon) {
|
||||
if (FreeConsole() == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"FreeConsole() failed");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (SetConsoleCtrlHandler(ngx_console_handler, 1) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"SetConsoleCtrlHandler() failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int __stdcall
|
||||
ngx_console_handler(u_long type)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case CTRL_C_EVENT:
|
||||
msg = "Ctrl-C pressed, exiting";
|
||||
break;
|
||||
|
||||
case CTRL_BREAK_EVENT:
|
||||
msg = "Ctrl-Break pressed, exiting";
|
||||
break;
|
||||
|
||||
case CTRL_CLOSE_EVENT:
|
||||
msg = "console closing, exiting";
|
||||
break;
|
||||
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
msg = "user logs off, exiting";
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, msg);
|
||||
|
||||
if (ngx_stop_event == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SetEvent(ngx_stop_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
|
||||
"SetEvent(\"%s\") failed", ngx_stop_event_name);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_create_signal_events(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_sprintf((u_char *) ngx_stop_event_name,
|
||||
"Global\\ngx_stop_%s%Z", ngx_unique);
|
||||
|
||||
ngx_stop_event = CreateEvent(NULL, 1, 0, ngx_stop_event_name);
|
||||
if (ngx_stop_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", ngx_stop_event_name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_sprintf((u_char *) ngx_quit_event_name,
|
||||
"Global\\ngx_quit_%s%Z", ngx_unique);
|
||||
|
||||
ngx_quit_event = CreateEvent(NULL, 1, 0, ngx_quit_event_name);
|
||||
if (ngx_quit_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", ngx_quit_event_name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_sprintf((u_char *) ngx_reopen_event_name,
|
||||
"Global\\ngx_reopen_%s%Z", ngx_unique);
|
||||
|
||||
ngx_reopen_event = CreateEvent(NULL, 1, 0, ngx_reopen_event_name);
|
||||
if (ngx_reopen_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", ngx_reopen_event_name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_sprintf((u_char *) ngx_reload_event_name,
|
||||
"Global\\ngx_reload_%s%Z", ngx_unique);
|
||||
|
||||
ngx_reload_event = CreateEvent(NULL, 1, 0, ngx_reload_event_name);
|
||||
if (ngx_reload_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", ngx_reload_event_name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t type)
|
||||
{
|
||||
ngx_int_t n;
|
||||
ngx_core_conf_t *ccf;
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
|
||||
|
||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
||||
|
||||
for (n = 0; n < ccf->worker_processes; n++) {
|
||||
if (ngx_spawn_process(cycle, "worker", type) == NGX_INVALID_PID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_reopen_worker_processes(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_int_t n;
|
||||
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
|
||||
if (ngx_processes[n].handle == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SetEvent(ngx_processes[n].reopen) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"SetEvent(\"%s\") failed",
|
||||
ngx_processes[n].reopen_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_quit_worker_processes(ngx_cycle_t *cycle, ngx_uint_t old)
|
||||
{
|
||||
ngx_int_t n;
|
||||
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
|
||||
ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"process: %d %P %p e:%d j:%d",
|
||||
n,
|
||||
ngx_processes[n].pid,
|
||||
ngx_processes[n].handle,
|
||||
ngx_processes[n].exiting,
|
||||
ngx_processes[n].just_spawn);
|
||||
|
||||
if (old && ngx_processes[n].just_spawn) {
|
||||
ngx_processes[n].just_spawn = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_processes[n].handle == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SetEvent(ngx_processes[n].quit) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"SetEvent(\"%s\") failed",
|
||||
ngx_processes[n].quit_event);
|
||||
}
|
||||
|
||||
ngx_processes[n].exiting = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_terminate_worker_processes(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_int_t n;
|
||||
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
|
||||
if (ngx_processes[n].handle == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TerminateProcess(ngx_processes[n].handle, 0) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"TerminateProcess(\"%p\") failed",
|
||||
ngx_processes[n].handle);
|
||||
}
|
||||
|
||||
ngx_processes[n].exiting = 1;
|
||||
|
||||
ngx_close_handle(ngx_processes[n].reopen);
|
||||
ngx_close_handle(ngx_processes[n].quit);
|
||||
ngx_close_handle(ngx_processes[n].term);
|
||||
ngx_close_handle(ngx_processes[n].handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ngx_uint_t
|
||||
ngx_reap_worker(ngx_cycle_t *cycle, HANDLE h)
|
||||
{
|
||||
u_long code;
|
||||
ngx_int_t n;
|
||||
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
|
||||
if (ngx_processes[n].handle != h) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetExitCodeProcess(h, &code) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"GetExitCodeProcess(%P) failed",
|
||||
ngx_processes[n].pid);
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
|
||||
"%s process %P exited with code %Xl",
|
||||
ngx_processes[n].name, ngx_processes[n].pid, code);
|
||||
|
||||
ngx_close_handle(ngx_processes[n].reopen);
|
||||
ngx_close_handle(ngx_processes[n].quit);
|
||||
ngx_close_handle(ngx_processes[n].term);
|
||||
ngx_close_handle(h);
|
||||
|
||||
ngx_processes[n].handle = NULL;
|
||||
ngx_processes[n].term = NULL;
|
||||
ngx_processes[n].quit = NULL;
|
||||
ngx_processes[n].reopen = NULL;
|
||||
|
||||
if (!ngx_processes[n].exiting && !ngx_terminate && !ngx_quit) {
|
||||
|
||||
if (ngx_spawn_process(cycle, ngx_processes[n].name, n)
|
||||
== NGX_INVALID_PID)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"could not respawn %s", ngx_processes[n].name);
|
||||
|
||||
if (n == ngx_last_process - 1) {
|
||||
ngx_last_process--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unknown process handle %p", h);
|
||||
|
||||
found:
|
||||
|
||||
for (n = 0; n < ngx_last_process; n++) {
|
||||
|
||||
ngx_log_debug5(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"process: %d %P %p e:%d j:%d",
|
||||
n,
|
||||
ngx_processes[n].pid,
|
||||
ngx_processes[n].handle,
|
||||
ngx_processes[n].exiting,
|
||||
ngx_processes[n].just_spawn);
|
||||
|
||||
if (ngx_processes[n].handle) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_master_process_exit(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
|
||||
ngx_delete_pidfile(cycle);
|
||||
|
||||
ngx_close_handle(ngx_cache_manager_mutex);
|
||||
ngx_close_handle(ngx_stop_event);
|
||||
ngx_close_handle(ngx_quit_event);
|
||||
ngx_close_handle(ngx_reopen_event);
|
||||
ngx_close_handle(ngx_reload_event);
|
||||
ngx_close_handle(ngx_master_process_event);
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
|
||||
|
||||
for (i = 0; cycle->modules[i]; i++) {
|
||||
if (cycle->modules[i]->exit_master) {
|
||||
cycle->modules[i]->exit_master(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_destroy_pool(cycle->pool);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_worker_process_cycle(ngx_cycle_t *cycle, char *mevn)
|
||||
{
|
||||
char wtevn[NGX_PROCESS_SYNC_NAME];
|
||||
char wqevn[NGX_PROCESS_SYNC_NAME];
|
||||
char wroevn[NGX_PROCESS_SYNC_NAME];
|
||||
HANDLE mev, events[3];
|
||||
u_long nev, ev;
|
||||
ngx_err_t err;
|
||||
ngx_tid_t wtid, cmtid, cltid;
|
||||
ngx_log_t *log;
|
||||
|
||||
log = cycle->log;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "worker started");
|
||||
|
||||
ngx_sprintf((u_char *) wtevn, "ngx_worker_term_%P%Z", ngx_pid);
|
||||
events[0] = CreateEvent(NULL, 1, 0, wtevn);
|
||||
if (events[0] == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", wtevn);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ngx_sprintf((u_char *) wqevn, "ngx_worker_quit_%P%Z", ngx_pid);
|
||||
events[1] = CreateEvent(NULL, 1, 0, wqevn);
|
||||
if (events[1] == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", wqevn);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ngx_sprintf((u_char *) wroevn, "ngx_worker_reopen_%P%Z", ngx_pid);
|
||||
events[2] = CreateEvent(NULL, 1, 0, wroevn);
|
||||
if (events[2] == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"CreateEvent(\"%s\") failed", wroevn);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
mev = OpenEvent(EVENT_MODIFY_STATE, 0, mevn);
|
||||
if (mev == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"OpenEvent(\"%s\") failed", mevn);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (SetEvent(mev) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"SetEvent(\"%s\") failed", mevn);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
||||
ngx_sprintf((u_char *) ngx_cache_manager_mutex_name,
|
||||
"ngx_cache_manager_mutex_%s%Z", ngx_unique);
|
||||
|
||||
ngx_cache_manager_mutex = OpenMutex(SYNCHRONIZE, 0,
|
||||
ngx_cache_manager_mutex_name);
|
||||
if (ngx_cache_manager_mutex == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"OpenMutex(\"%s\") failed", ngx_cache_manager_mutex_name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ngx_cache_manager_event = CreateEvent(NULL, 1, 0, NULL);
|
||||
if (ngx_cache_manager_event == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"CreateEvent(\"ngx_cache_manager_event\") failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
||||
if (ngx_create_thread(&wtid, ngx_worker_thread, NULL, log) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ngx_create_thread(&cmtid, ngx_cache_manager_thread, NULL, log) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ngx_create_thread(&cltid, ngx_cache_loader_thread, NULL, log) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for ( ;; ) {
|
||||
ev = WaitForMultipleObjects(3, events, 0, INFINITE);
|
||||
|
||||
err = ngx_errno;
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
|
||||
"worker WaitForMultipleObjects: %ul", ev);
|
||||
|
||||
if (ev == WAIT_OBJECT_0) {
|
||||
ngx_terminate = 1;
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "exiting");
|
||||
|
||||
if (ResetEvent(events[0]) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
||||
"ResetEvent(\"%s\") failed", wtevn);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 1) {
|
||||
ngx_quit = 1;
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "gracefully shutting down");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 2) {
|
||||
ngx_reopen = 1;
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, "reopening logs");
|
||||
|
||||
if (ResetEvent(events[2]) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, 0,
|
||||
"ResetEvent(\"%s\") failed", wroevn);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, err,
|
||||
"WaitForMultipleObjects() failed");
|
||||
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait threads */
|
||||
|
||||
if (SetEvent(ngx_cache_manager_event) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
"SetEvent(\"ngx_cache_manager_event\") failed");
|
||||
}
|
||||
|
||||
events[1] = wtid;
|
||||
events[2] = cmtid;
|
||||
|
||||
nev = 3;
|
||||
|
||||
for ( ;; ) {
|
||||
ev = WaitForMultipleObjects(nev, events, 0, INFINITE);
|
||||
|
||||
err = ngx_errno;
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0,
|
||||
"worker exit WaitForMultipleObjects: %ul", ev);
|
||||
|
||||
if (ev == WAIT_OBJECT_0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 1) {
|
||||
if (nev == 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
events[1] = events[2];
|
||||
nev = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_OBJECT_0 + 2) {
|
||||
nev = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev == WAIT_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, err,
|
||||
"WaitForMultipleObjects() failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_close_handle(ngx_cache_manager_event);
|
||||
ngx_close_handle(events[0]);
|
||||
ngx_close_handle(events[1]);
|
||||
ngx_close_handle(events[2]);
|
||||
ngx_close_handle(mev);
|
||||
|
||||
ngx_worker_process_exit(cycle);
|
||||
|
||||
failed:
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
static ngx_thread_value_t __stdcall
|
||||
ngx_worker_thread(void *data)
|
||||
{
|
||||
ngx_int_t n;
|
||||
ngx_time_t *tp;
|
||||
ngx_cycle_t *cycle;
|
||||
|
||||
tp = ngx_timeofday();
|
||||
srand((ngx_pid << 16) ^ (unsigned) tp->sec ^ tp->msec);
|
||||
|
||||
cycle = (ngx_cycle_t *) ngx_cycle;
|
||||
|
||||
for (n = 0; cycle->modules[n]; n++) {
|
||||
if (cycle->modules[n]->init_process) {
|
||||
if (cycle->modules[n]->init_process(cycle) == NGX_ERROR) {
|
||||
/* fatal */
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!ngx_quit) {
|
||||
|
||||
if (ngx_exiting) {
|
||||
if (ngx_event_no_timers_left() == NGX_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "worker cycle");
|
||||
|
||||
ngx_process_events_and_timers(cycle);
|
||||
|
||||
if (ngx_terminate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ngx_quit) {
|
||||
ngx_quit = 0;
|
||||
|
||||
if (!ngx_exiting) {
|
||||
ngx_exiting = 1;
|
||||
ngx_set_shutdown_timer(cycle);
|
||||
ngx_close_listening_sockets(cycle);
|
||||
ngx_close_idle_connections(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_reopen) {
|
||||
ngx_reopen = 0;
|
||||
ngx_reopen_files(cycle, -1);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_worker_process_exit(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
ngx_connection_t *c;
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit");
|
||||
|
||||
for (i = 0; cycle->modules[i]; i++) {
|
||||
if (cycle->modules[i]->exit_process) {
|
||||
cycle->modules[i]->exit_process(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_exiting) {
|
||||
c = cycle->connections;
|
||||
for (i = 0; i < cycle->connection_n; i++) {
|
||||
if (c[i].fd != (ngx_socket_t) -1
|
||||
&& c[i].read
|
||||
&& !c[i].read->accept
|
||||
&& !c[i].read->channel
|
||||
&& !c[i].read->resolver)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
|
||||
"*%uA open socket #%d left in connection %ui",
|
||||
c[i].number, c[i].fd, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngx_destroy_pool(cycle->pool);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static ngx_thread_value_t __stdcall
|
||||
ngx_cache_manager_thread(void *data)
|
||||
{
|
||||
u_long ev;
|
||||
HANDLE events[2];
|
||||
ngx_err_t err;
|
||||
ngx_cycle_t *cycle;
|
||||
|
||||
cycle = (ngx_cycle_t *) ngx_cycle;
|
||||
|
||||
events[0] = ngx_cache_manager_event;
|
||||
events[1] = ngx_cache_manager_mutex;
|
||||
|
||||
for ( ;; ) {
|
||||
ev = WaitForMultipleObjects(2, events, 0, INFINITE);
|
||||
|
||||
err = ngx_errno;
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
|
||||
"cache manager WaitForMultipleObjects: %ul", ev);
|
||||
|
||||
if (ev == WAIT_FAILED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
|
||||
"WaitForMultipleObjects() failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* ev == WAIT_OBJECT_0
|
||||
* ev == WAIT_OBJECT_0 + 1
|
||||
* ev == WAIT_ABANDONED_0 + 1
|
||||
*/
|
||||
|
||||
if (ngx_terminate || ngx_quit || ngx_exiting) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
if (ngx_terminate || ngx_quit || ngx_exiting) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_cache_manager_process_handler();
|
||||
}
|
||||
|
||||
if (ReleaseMutex(ngx_cache_manager_mutex) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"ReleaseMutex() failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_cache_manager_process_handler(void)
|
||||
{
|
||||
u_long ev;
|
||||
ngx_uint_t i;
|
||||
ngx_msec_t next, n;
|
||||
ngx_path_t **path;
|
||||
|
||||
next = 60 * 60 * 1000;
|
||||
|
||||
path = ngx_cycle->paths.elts;
|
||||
for (i = 0; i < ngx_cycle->paths.nelts; i++) {
|
||||
|
||||
if (path[i]->manager) {
|
||||
n = path[i]->manager(path[i]->data);
|
||||
|
||||
next = (n <= next) ? n : next;
|
||||
|
||||
ngx_time_update();
|
||||
}
|
||||
}
|
||||
|
||||
if (next == 0) {
|
||||
next = 1;
|
||||
}
|
||||
|
||||
ev = WaitForSingleObject(ngx_cache_manager_event, (u_long) next);
|
||||
|
||||
if (ev != WAIT_TIMEOUT) {
|
||||
|
||||
ngx_time_update();
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
|
||||
"cache manager WaitForSingleObject: %ul", ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ngx_thread_value_t __stdcall
|
||||
ngx_cache_loader_thread(void *data)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
ngx_path_t **path;
|
||||
ngx_cycle_t *cycle;
|
||||
|
||||
ngx_msleep(60000);
|
||||
|
||||
cycle = (ngx_cycle_t *) ngx_cycle;
|
||||
|
||||
path = cycle->paths.elts;
|
||||
for (i = 0; i < cycle->paths.nelts; i++) {
|
||||
|
||||
if (ngx_terminate || ngx_quit || ngx_exiting) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (path[i]->loader) {
|
||||
path[i]->loader(path[i]->data);
|
||||
ngx_time_update();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_single_process_cycle(ngx_cycle_t *cycle)
|
||||
{
|
||||
ngx_tid_t tid;
|
||||
|
||||
ngx_console_init(cycle);
|
||||
|
||||
if (ngx_create_signal_events(cycle) != NGX_OK) {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (ngx_create_thread(&tid, ngx_worker_thread, NULL, cycle->log) != 0) {
|
||||
/* fatal */
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* STUB */
|
||||
WaitForSingleObject(ngx_stop_event, INFINITE);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_pid_t pid)
|
||||
{
|
||||
HANDLE ev;
|
||||
ngx_int_t rc;
|
||||
char evn[NGX_PROCESS_SYNC_NAME];
|
||||
|
||||
ngx_sprintf((u_char *) evn, "Global\\ngx_%s_%P%Z", sig, pid);
|
||||
|
||||
ev = OpenEvent(EVENT_MODIFY_STATE, 0, evn);
|
||||
if (ev == NULL) {
|
||||
ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
|
||||
"OpenEvent(\"%s\") failed", evn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SetEvent(ev) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
|
||||
"SetEvent(\"%s\") failed", evn);
|
||||
rc = 1;
|
||||
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
ngx_close_handle(ev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_close_handle(HANDLE h)
|
||||
{
|
||||
if (CloseHandle(h) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
|
||||
"CloseHandle(%p) failed", h);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_PROCESS_CYCLE_H_INCLUDED_
|
||||
#define _NGX_PROCESS_CYCLE_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_PROCESS_SINGLE 0
|
||||
#define NGX_PROCESS_MASTER 1
|
||||
#define NGX_PROCESS_SIGNALLER 2
|
||||
#define NGX_PROCESS_WORKER 3
|
||||
|
||||
|
||||
void ngx_master_process_cycle(ngx_cycle_t *cycle);
|
||||
void ngx_single_process_cycle(ngx_cycle_t *cycle);
|
||||
void ngx_close_handle(HANDLE h);
|
||||
|
||||
|
||||
extern ngx_uint_t ngx_process;
|
||||
extern ngx_uint_t ngx_worker;
|
||||
extern ngx_pid_t ngx_pid;
|
||||
extern ngx_uint_t ngx_exiting;
|
||||
|
||||
extern sig_atomic_t ngx_quit;
|
||||
extern sig_atomic_t ngx_terminate;
|
||||
extern sig_atomic_t ngx_reopen;
|
||||
|
||||
extern ngx_uint_t ngx_inherited;
|
||||
extern ngx_pid_t ngx_new_binary;
|
||||
|
||||
|
||||
extern HANDLE ngx_master_process_event;
|
||||
extern char ngx_master_process_event_name[];
|
||||
|
||||
|
||||
#endif /* _NGX_PROCESS_CYCLE_H_INCLUDED_ */
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define NGX_SERVICE_CONTROL_SHUTDOWN 128
|
||||
#define NGX_SERVICE_CONTROL_REOPEN 129
|
||||
|
||||
|
||||
SERVICE_TABLE_ENTRY st[] = {
|
||||
{ "nginx", service_main },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_service(ngx_log_t *log)
|
||||
{
|
||||
/* primary thread */
|
||||
|
||||
/* StartServiceCtrlDispatcher() should be called within 30 seconds */
|
||||
|
||||
if (StartServiceCtrlDispatcher(st) == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"StartServiceCtrlDispatcher() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
service_main(u_int argc, char **argv)
|
||||
{
|
||||
SERVICE_STATUS status;
|
||||
SERVICE_STATUS_HANDLE service;
|
||||
|
||||
/* thread spawned by SCM */
|
||||
|
||||
service = RegisterServiceCtrlHandlerEx("nginx", service_handler, ctx);
|
||||
if (service == INVALID_HANDLE_VALUE) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"RegisterServiceCtrlHandlerEx() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
status.dwCurrentState = SERVICE_START_PENDING;
|
||||
status.dwControlsAccepted = SERVICE_ACCEPT_STOP
|
||||
|SERVICE_ACCEPT_PARAMCHANGE;
|
||||
status.dwWin32ExitCode = NO_ERROR;
|
||||
status.dwServiceSpecificExitCode = 0;
|
||||
status.dwCheckPoint = 1;
|
||||
status.dwWaitHint = 2000;
|
||||
|
||||
/* SetServiceStatus() should be called within 80 seconds */
|
||||
|
||||
if (SetServiceStatus(service, &status) == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"SetServiceStatus() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* init */
|
||||
|
||||
status.dwCurrentState = SERVICE_RUNNING;
|
||||
status.dwCheckPoint = 0;
|
||||
status.dwWaitHint = 0;
|
||||
|
||||
if (SetServiceStatus(service, &status) == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"SetServiceStatus() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* call master or worker loop */
|
||||
|
||||
/*
|
||||
* master should use event notification and look status
|
||||
* single should use iocp to get notifications from service handler
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
u_int
|
||||
service_handler(u_int control, u_int type, void *data, void *ctx)
|
||||
{
|
||||
/* primary thread */
|
||||
|
||||
switch (control) {
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
status = NGX_IOCP_INTERROGATE;
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_STOP:
|
||||
status = NGX_IOCP_STOP;
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_PARAMCHANGE:
|
||||
status = NGX_IOCP_RECONFIGURE;
|
||||
break;
|
||||
|
||||
case NGX_SERVICE_CONTROL_SHUTDOWN:
|
||||
status = NGX_IOCP_REOPEN;
|
||||
break;
|
||||
|
||||
case NGX_SERVICE_CONTROL_REOPEN:
|
||||
status = NGX_IOCP_REOPEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (ngx_single) {
|
||||
if (PostQueuedCompletionStatus(iocp, ... status, ...) == 0) {
|
||||
err = ngx_errno;
|
||||
ngx_log_error(NGX_LOG_ALERT, log, err,
|
||||
"PostQueuedCompletionStatus() failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
} else {
|
||||
Event
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
/*
|
||||
* Base addresses selected by system for shared memory mappings are likely
|
||||
* to be different on Windows Vista and later versions due to address space
|
||||
* layout randomization. This is however incompatible with storing absolute
|
||||
* addresses within the shared memory.
|
||||
*
|
||||
* To make it possible to store absolute addresses we create mappings
|
||||
* at the same address in all processes by starting mappings at predefined
|
||||
* addresses. The addresses were selected somewhat randomly in order to
|
||||
* minimize the probability that some other library doing something similar
|
||||
* conflicts with us. The addresses are from the following typically free
|
||||
* blocks:
|
||||
*
|
||||
* - 0x10000000 .. 0x70000000 (about 1.5 GB in total) on 32-bit platforms
|
||||
* - 0x000000007fff0000 .. 0x000007f68e8b0000 (about 8 TB) on 64-bit platforms
|
||||
*
|
||||
* Additionally, we allow to change the mapping address once it was detected
|
||||
* to be different from one originally used. This is needed to support
|
||||
* reconfiguration.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
#define NGX_SHMEM_BASE 0x0000047047e00000
|
||||
#else
|
||||
#define NGX_SHMEM_BASE 0x2efe0000
|
||||
#endif
|
||||
|
||||
|
||||
ngx_uint_t ngx_allocation_granularity;
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_shm_alloc(ngx_shm_t *shm)
|
||||
{
|
||||
u_char *name;
|
||||
uint64_t size;
|
||||
static u_char *base = (u_char *) NGX_SHMEM_BASE;
|
||||
|
||||
name = ngx_alloc(shm->name.len + 2 + NGX_INT32_LEN, shm->log);
|
||||
if (name == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
(void) ngx_sprintf(name, "%V_%s%Z", &shm->name, ngx_unique);
|
||||
|
||||
ngx_set_errno(0);
|
||||
|
||||
size = shm->size;
|
||||
|
||||
shm->handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||
(u_long) (size >> 32),
|
||||
(u_long) (size & 0xffffffff),
|
||||
(char *) name);
|
||||
|
||||
if (shm->handle == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"CreateFileMapping(%uz, %s) failed",
|
||||
shm->size, name);
|
||||
ngx_free(name);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_free(name);
|
||||
|
||||
if (ngx_errno == ERROR_ALREADY_EXISTS) {
|
||||
shm->exists = 1;
|
||||
}
|
||||
|
||||
shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, base);
|
||||
|
||||
if (shm->addr != NULL) {
|
||||
base += ngx_align(size, ngx_allocation_granularity);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_CORE, shm->log, ngx_errno,
|
||||
"MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed, "
|
||||
"retry without a base address",
|
||||
shm->size, base, &shm->name);
|
||||
|
||||
/*
|
||||
* Order of shared memory zones may be different in the master process
|
||||
* and worker processes after reconfiguration. As a result, the above
|
||||
* may fail due to a conflict with a previously created mapping remapped
|
||||
* to a different address. Additionally, there may be a conflict with
|
||||
* some other uses of the memory. In this case we retry without a base
|
||||
* address to let the system assign the address itself.
|
||||
*/
|
||||
|
||||
shm->addr = MapViewOfFile(shm->handle, FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if (shm->addr != NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"MapViewOfFile(%uz) of file mapping \"%V\" failed",
|
||||
shm->size, &shm->name);
|
||||
|
||||
if (CloseHandle(shm->handle) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"CloseHandle() of file mapping \"%V\" failed",
|
||||
&shm->name);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_shm_remap(ngx_shm_t *shm, u_char *addr)
|
||||
{
|
||||
if (UnmapViewOfFile(shm->addr) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"UnmapViewOfFile(%p) of file mapping \"%V\" failed",
|
||||
shm->addr, &shm->name);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, addr);
|
||||
|
||||
if (shm->addr != NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed",
|
||||
shm->size, addr, &shm->name);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_shm_free(ngx_shm_t *shm)
|
||||
{
|
||||
if (UnmapViewOfFile(shm->addr) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"UnmapViewOfFile(%p) of file mapping \"%V\" failed",
|
||||
shm->addr, &shm->name);
|
||||
}
|
||||
|
||||
if (CloseHandle(shm->handle) == 0) {
|
||||
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
|
||||
"CloseHandle() of file mapping \"%V\" failed",
|
||||
&shm->name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_SHMEM_H_INCLUDED_
|
||||
#define _NGX_SHMEM_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char *addr;
|
||||
size_t size;
|
||||
ngx_str_t name;
|
||||
HANDLE handle;
|
||||
ngx_log_t *log;
|
||||
ngx_uint_t exists; /* unsigned exists:1; */
|
||||
} ngx_shm_t;
|
||||
|
||||
|
||||
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
|
||||
ngx_int_t ngx_shm_remap(ngx_shm_t *shm, u_char *addr);
|
||||
void ngx_shm_free(ngx_shm_t *shm);
|
||||
|
||||
extern ngx_uint_t ngx_allocation_granularity;
|
||||
|
||||
|
||||
#endif /* _NGX_SHMEM_H_INCLUDED_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
int
|
||||
ngx_nonblocking(ngx_socket_t s)
|
||||
{
|
||||
unsigned long nb = 1;
|
||||
|
||||
return ioctlsocket(s, FIONBIO, &nb);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ngx_blocking(ngx_socket_t s)
|
||||
{
|
||||
unsigned long nb = 0;
|
||||
|
||||
return ioctlsocket(s, FIONBIO, &nb);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ngx_tcp_push(ngx_socket_t s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_SOCKET_H_INCLUDED_
|
||||
#define _NGX_SOCKET_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#define NGX_WRITE_SHUTDOWN SD_SEND
|
||||
|
||||
|
||||
typedef SOCKET ngx_socket_t;
|
||||
typedef int socklen_t;
|
||||
|
||||
|
||||
#define ngx_socket(af, type, proto) \
|
||||
WSASocketW(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED)
|
||||
|
||||
#define ngx_socket_n "WSASocketW()"
|
||||
|
||||
int ngx_nonblocking(ngx_socket_t s);
|
||||
int ngx_blocking(ngx_socket_t s);
|
||||
|
||||
#define ngx_nonblocking_n "ioctlsocket(FIONBIO)"
|
||||
#define ngx_blocking_n "ioctlsocket(!FIONBIO)"
|
||||
|
||||
#define ngx_shutdown_socket shutdown
|
||||
#define ngx_shutdown_socket_n "shutdown()"
|
||||
|
||||
#define ngx_close_socket closesocket
|
||||
#define ngx_close_socket_n "closesocket()"
|
||||
|
||||
|
||||
#ifndef WSAID_ACCEPTEX
|
||||
|
||||
typedef BOOL (PASCAL FAR * LPFN_ACCEPTEX)(
|
||||
IN SOCKET sListenSocket,
|
||||
IN SOCKET sAcceptSocket,
|
||||
IN PVOID lpOutputBuffer,
|
||||
IN DWORD dwReceiveDataLength,
|
||||
IN DWORD dwLocalAddressLength,
|
||||
IN DWORD dwRemoteAddressLength,
|
||||
OUT LPDWORD lpdwBytesReceived,
|
||||
IN LPOVERLAPPED lpOverlapped
|
||||
);
|
||||
|
||||
#define WSAID_ACCEPTEX \
|
||||
{0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WSAID_GETACCEPTEXSOCKADDRS
|
||||
|
||||
typedef VOID (PASCAL FAR * LPFN_GETACCEPTEXSOCKADDRS)(
|
||||
IN PVOID lpOutputBuffer,
|
||||
IN DWORD dwReceiveDataLength,
|
||||
IN DWORD dwLocalAddressLength,
|
||||
IN DWORD dwRemoteAddressLength,
|
||||
OUT struct sockaddr **LocalSockaddr,
|
||||
OUT LPINT LocalSockaddrLength,
|
||||
OUT struct sockaddr **RemoteSockaddr,
|
||||
OUT LPINT RemoteSockaddrLength
|
||||
);
|
||||
|
||||
#define WSAID_GETACCEPTEXSOCKADDRS \
|
||||
{0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WSAID_TRANSMITFILE
|
||||
|
||||
#ifndef TF_DISCONNECT
|
||||
|
||||
#define TF_DISCONNECT 1
|
||||
#define TF_REUSE_SOCKET 2
|
||||
#define TF_WRITE_BEHIND 4
|
||||
#define TF_USE_DEFAULT_WORKER 0
|
||||
#define TF_USE_SYSTEM_THREAD 16
|
||||
#define TF_USE_KERNEL_APC 32
|
||||
|
||||
typedef struct _TRANSMIT_FILE_BUFFERS {
|
||||
LPVOID Head;
|
||||
DWORD HeadLength;
|
||||
LPVOID Tail;
|
||||
DWORD TailLength;
|
||||
} TRANSMIT_FILE_BUFFERS, *PTRANSMIT_FILE_BUFFERS, FAR *LPTRANSMIT_FILE_BUFFERS;
|
||||
|
||||
#endif
|
||||
|
||||
typedef BOOL (PASCAL FAR * LPFN_TRANSMITFILE)(
|
||||
IN SOCKET hSocket,
|
||||
IN HANDLE hFile,
|
||||
IN DWORD nNumberOfBytesToWrite,
|
||||
IN DWORD nNumberOfBytesPerSend,
|
||||
IN LPOVERLAPPED lpOverlapped,
|
||||
IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
|
||||
IN DWORD dwReserved
|
||||
);
|
||||
|
||||
#define WSAID_TRANSMITFILE \
|
||||
{0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WSAID_TRANSMITPACKETS
|
||||
|
||||
/* OpenWatcom has a swapped TP_ELEMENT_FILE and TP_ELEMENT_MEMORY definition */
|
||||
|
||||
#ifndef TP_ELEMENT_FILE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4201) /* Nonstandard extension, nameless struct/union */
|
||||
#endif
|
||||
|
||||
typedef struct _TRANSMIT_PACKETS_ELEMENT {
|
||||
ULONG dwElFlags;
|
||||
#define TP_ELEMENT_MEMORY 1
|
||||
#define TP_ELEMENT_FILE 2
|
||||
#define TP_ELEMENT_EOP 4
|
||||
ULONG cLength;
|
||||
union {
|
||||
struct {
|
||||
LARGE_INTEGER nFileOffset;
|
||||
HANDLE hFile;
|
||||
};
|
||||
PVOID pBuffer;
|
||||
};
|
||||
} TRANSMIT_PACKETS_ELEMENT, *PTRANSMIT_PACKETS_ELEMENT,
|
||||
FAR *LPTRANSMIT_PACKETS_ELEMENT;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4201)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef BOOL (PASCAL FAR * LPFN_TRANSMITPACKETS) (
|
||||
SOCKET hSocket,
|
||||
TRANSMIT_PACKETS_ELEMENT *lpPacketArray,
|
||||
DWORD nElementCount,
|
||||
DWORD nSendSize,
|
||||
LPOVERLAPPED lpOverlapped,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
#define WSAID_TRANSMITPACKETS \
|
||||
{0xd9689da0,0x1f90,0x11d3,{0x99,0x71,0x00,0xc0,0x4f,0x68,0xc8,0x76}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WSAID_CONNECTEX
|
||||
|
||||
typedef BOOL (PASCAL FAR * LPFN_CONNECTEX) (
|
||||
IN SOCKET s,
|
||||
IN const struct sockaddr FAR *name,
|
||||
IN int namelen,
|
||||
IN PVOID lpSendBuffer OPTIONAL,
|
||||
IN DWORD dwSendDataLength,
|
||||
OUT LPDWORD lpdwBytesSent,
|
||||
IN LPOVERLAPPED lpOverlapped
|
||||
);
|
||||
|
||||
#define WSAID_CONNECTEX \
|
||||
{0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WSAID_DISCONNECTEX
|
||||
|
||||
typedef BOOL (PASCAL FAR * LPFN_DISCONNECTEX) (
|
||||
IN SOCKET s,
|
||||
IN LPOVERLAPPED lpOverlapped,
|
||||
IN DWORD dwFlags,
|
||||
IN DWORD dwReserved
|
||||
);
|
||||
|
||||
#define WSAID_DISCONNECTEX \
|
||||
{0x7fda2e11,0x8630,0x436f,{0xa0,0x31,0xf5,0x36,0xa6,0xee,0xc1,0x57}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern LPFN_ACCEPTEX ngx_acceptex;
|
||||
extern LPFN_GETACCEPTEXSOCKADDRS ngx_getacceptexsockaddrs;
|
||||
extern LPFN_TRANSMITFILE ngx_transmitfile;
|
||||
extern LPFN_TRANSMITPACKETS ngx_transmitpackets;
|
||||
extern LPFN_CONNECTEX ngx_connectex;
|
||||
extern LPFN_DISCONNECTEX ngx_disconnectex;
|
||||
|
||||
|
||||
int ngx_tcp_push(ngx_socket_t s);
|
||||
#define ngx_tcp_push_n "tcp_push()"
|
||||
|
||||
|
||||
#endif /* _NGX_SOCKET_H_INCLUDED_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
int ngx_file_type(char *file, ngx_file_info_t *sb)
|
||||
{
|
||||
sb->dwFileAttributes = GetFileAttributes(file);
|
||||
|
||||
if (sb->dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int ngx_stat(char *file, ngx_stat_t *sb)
|
||||
{
|
||||
*sb = GetFileAttributes(file);
|
||||
|
||||
if (*sb == INVALID_FILE_ATTRIBUTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
ngx_err_t
|
||||
ngx_create_thread(ngx_tid_t *tid,
|
||||
ngx_thread_value_t (__stdcall *func)(void *arg), void *arg, ngx_log_t *log)
|
||||
{
|
||||
u_long id;
|
||||
ngx_err_t err;
|
||||
|
||||
*tid = CreateThread(NULL, 0, func, arg, 0, &id);
|
||||
|
||||
if (*tid != NULL) {
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0,
|
||||
"create thread " NGX_TID_T_FMT, id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
ngx_log_error(NGX_LOG_ALERT, log, err, "CreateThread() failed");
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_THREAD_H_INCLUDED_
|
||||
#define _NGX_THREAD_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef HANDLE ngx_tid_t;
|
||||
typedef DWORD ngx_thread_value_t;
|
||||
|
||||
|
||||
ngx_err_t ngx_create_thread(ngx_tid_t *tid,
|
||||
ngx_thread_value_t (__stdcall *func)(void *arg), void *arg, ngx_log_t *log);
|
||||
|
||||
#define ngx_log_tid GetCurrentThreadId()
|
||||
#define NGX_TID_T_FMT "%ud"
|
||||
|
||||
|
||||
#endif /* _NGX_THREAD_H_INCLUDED_ */
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
void
|
||||
ngx_gettimeofday(struct timeval *tp)
|
||||
{
|
||||
uint64_t intervals;
|
||||
FILETIME ft;
|
||||
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
|
||||
/*
|
||||
* A file time is a 64-bit value that represents the number
|
||||
* of 100-nanosecond intervals that have elapsed since
|
||||
* January 1, 1601 12:00 A.M. UTC.
|
||||
*
|
||||
* Between January 1, 1970 (Epoch) and January 1, 1601 there were
|
||||
* 134744 days,
|
||||
* 11644473600 seconds or
|
||||
* 11644473600,000,000,0 100-nanosecond intervals.
|
||||
*
|
||||
* See also MSKB Q167296.
|
||||
*/
|
||||
|
||||
intervals = ((uint64_t) ft.dwHighDateTime << 32) | ft.dwLowDateTime;
|
||||
intervals -= 116444736000000000;
|
||||
|
||||
tp->tv_sec = (long) (intervals / 10000000);
|
||||
tp->tv_usec = (long) ((intervals % 10000000) / 10);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_libc_localtime(time_t s, struct tm *tm)
|
||||
{
|
||||
struct tm *t;
|
||||
|
||||
t = localtime(&s);
|
||||
*tm = *t;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_libc_gmtime(time_t s, struct tm *tm)
|
||||
{
|
||||
struct tm *t;
|
||||
|
||||
t = gmtime(&s);
|
||||
*tm = *t;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_gettimezone(void)
|
||||
{
|
||||
u_long n;
|
||||
TIME_ZONE_INFORMATION tz;
|
||||
|
||||
n = GetTimeZoneInformation(&tz);
|
||||
|
||||
switch (n) {
|
||||
|
||||
case TIME_ZONE_ID_UNKNOWN:
|
||||
return -tz.Bias;
|
||||
|
||||
case TIME_ZONE_ID_STANDARD:
|
||||
return -(tz.Bias + tz.StandardBias);
|
||||
|
||||
case TIME_ZONE_ID_DAYLIGHT:
|
||||
return -(tz.Bias + tz.DaylightBias);
|
||||
|
||||
default: /* TIME_ZONE_ID_INVALID */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_TIME_H_INCLUDED_
|
||||
#define _NGX_TIME_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef ngx_rbtree_key_t ngx_msec_t;
|
||||
typedef ngx_rbtree_key_int_t ngx_msec_int_t;
|
||||
|
||||
typedef SYSTEMTIME ngx_tm_t;
|
||||
typedef FILETIME ngx_mtime_t;
|
||||
|
||||
#define ngx_tm_sec wSecond
|
||||
#define ngx_tm_min wMinute
|
||||
#define ngx_tm_hour wHour
|
||||
#define ngx_tm_mday wDay
|
||||
#define ngx_tm_mon wMonth
|
||||
#define ngx_tm_year wYear
|
||||
#define ngx_tm_wday wDayOfWeek
|
||||
|
||||
#define ngx_tm_sec_t u_short
|
||||
#define ngx_tm_min_t u_short
|
||||
#define ngx_tm_hour_t u_short
|
||||
#define ngx_tm_mday_t u_short
|
||||
#define ngx_tm_mon_t u_short
|
||||
#define ngx_tm_year_t u_short
|
||||
#define ngx_tm_wday_t u_short
|
||||
|
||||
|
||||
#define ngx_msleep Sleep
|
||||
|
||||
#define NGX_HAVE_GETTIMEZONE 1
|
||||
|
||||
#define ngx_timezone_update()
|
||||
|
||||
ngx_int_t ngx_gettimezone(void);
|
||||
void ngx_libc_localtime(time_t s, struct tm *tm);
|
||||
void ngx_libc_gmtime(time_t s, struct tm *tm);
|
||||
void ngx_gettimeofday(struct timeval *tp);
|
||||
|
||||
|
||||
#endif /* _NGX_TIME_H_INCLUDED_ */
|
||||
@@ -0,0 +1,149 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
u_long bytes, flags;
|
||||
WSABUF wsabuf[1];
|
||||
ngx_err_t err;
|
||||
ngx_event_t *rev;
|
||||
|
||||
wsabuf[0].buf = (char *) buf;
|
||||
wsabuf[0].len = size;
|
||||
flags = 0;
|
||||
bytes = 0;
|
||||
|
||||
rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL);
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv: fd:%d rc:%d %ul of %z", c->fd, rc, bytes, size);
|
||||
|
||||
rev = c->read;
|
||||
|
||||
if (rc == -1) {
|
||||
rev->ready = 0;
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSARecv() not ready");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
rev->error = 1;
|
||||
ngx_connection_error(c, err, "WSARecv() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
u_long bytes, flags;
|
||||
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, c->log, 0, "second wsa post");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"rev->complete: %d", rev->complete);
|
||||
|
||||
if (rev->complete) {
|
||||
rev->complete = 0;
|
||||
|
||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
||||
if (rev->ovlp.error) {
|
||||
ngx_connection_error(c, rev->ovlp.error, "WSARecv() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv ovlp: fd:%d %ul of %z",
|
||||
c->fd, rev->available, size);
|
||||
|
||||
return rev->available;
|
||||
}
|
||||
|
||||
if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp,
|
||||
&bytes, 0, NULL)
|
||||
== 0)
|
||||
{
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
"WSARecv() or WSAGetOverlappedResult() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv: fd:%d %ul of %z", c->fd, bytes, size);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ovlp = (LPWSAOVERLAPPED) &rev->ovlp;
|
||||
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
|
||||
wsabuf[0].buf = (char *) buf;
|
||||
wsabuf[0].len = size;
|
||||
flags = 0;
|
||||
bytes = 0;
|
||||
|
||||
rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL);
|
||||
|
||||
rev->complete = 0;
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv ovlp: fd:%d rc:%d %ul of %z",
|
||||
c->fd, rc, bytes, size);
|
||||
|
||||
if (rc == -1) {
|
||||
err = ngx_socket_errno;
|
||||
if (err == WSA_IO_PENDING) {
|
||||
rev->active = 1;
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSARecv() posted");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
rev->error = 1;
|
||||
ngx_connection_error(c, 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;
|
||||
}
|
||||
|
||||
rev->active = 0;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_udp_wsasend(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
u_long sent;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *wev;
|
||||
WSABUF wsabuf;
|
||||
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* WSABUF must be 4-byte aligned otherwise
|
||||
* WSASend() will return undocumented WSAEINVAL error.
|
||||
*/
|
||||
|
||||
wsabuf.buf = (char *) buf;
|
||||
wsabuf.len = size;
|
||||
|
||||
sent = 0;
|
||||
|
||||
n = WSASendTo(c->fd,&wsabuf,1,&sent,0,c->sockaddr, c->socklen,NULL,NULL);
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size);
|
||||
|
||||
if (n == 0) {
|
||||
if (sent < size) {
|
||||
wev->ready = 0;
|
||||
}
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSASend() not ready");
|
||||
wev->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
wev->error = 1;
|
||||
ngx_connection_error(c, err, "WSASend() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
#if (NGX_CRYPT)
|
||||
|
||||
ngx_int_t
|
||||
ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
|
||||
{
|
||||
/* STUB: a plain text password */
|
||||
|
||||
*encrypted = key;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif /* NGX_CRYPT */
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_USER_H_INCLUDED_
|
||||
#define _NGX_USER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
/* STUB */
|
||||
#define ngx_uid_t ngx_int_t
|
||||
#define ngx_gid_t ngx_int_t
|
||||
|
||||
|
||||
ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
|
||||
u_char **encrypted);
|
||||
|
||||
|
||||
#endif /* _NGX_USER_H_INCLUDED_ */
|
||||
@@ -0,0 +1,282 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_WIN32_CONFIG_H_INCLUDED_
|
||||
#define _NGX_WIN32_CONFIG_H_INCLUDED_
|
||||
|
||||
|
||||
#undef WIN32
|
||||
#define WIN32 0x0400
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
|
||||
#define STRICT
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
/* enable getenv() and gmtime() in msvc8 */
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
/* enable gethostbyname() in msvc2015 */
|
||||
#if !(NGX_HAVE_INET6)
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* we need to include <windows.h> explicitly before <winsock2.h> because
|
||||
* the warning 4201 is enabled in <windows.h>
|
||||
*/
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4201)
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h> /* ipv6 */
|
||||
#include <mswsock.h>
|
||||
#include <shellapi.h>
|
||||
#include <stddef.h> /* offsetof() */
|
||||
|
||||
#ifdef __MINGW64_VERSION_MAJOR
|
||||
|
||||
/* GCC MinGW-w64 supports _FILE_OFFSET_BITS */
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#elif defined __GNUC__
|
||||
|
||||
/* GCC MinGW's stdio.h includes sys/types.h */
|
||||
#define _OFF_T_
|
||||
#define __have_typedef_off_t
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __GNUC__
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#define _TIME_T_DEFINED
|
||||
typedef long time_t;
|
||||
/* OpenWatcom defines time_t as "unsigned long" */
|
||||
#endif
|
||||
|
||||
#include <time.h> /* localtime(), strftime() */
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
/* the end of the precompiled headers */
|
||||
#pragma hdrstop
|
||||
|
||||
#pragma warning(default:4201)
|
||||
|
||||
/* disable some "-W4" level warnings */
|
||||
|
||||
/* 'type cast': from function pointer to data pointer */
|
||||
#pragma warning(disable:4054)
|
||||
|
||||
/* 'type cast': from data pointer to function pointer */
|
||||
#pragma warning(disable:4055)
|
||||
|
||||
/* 'function' : different 'const' qualifiers */
|
||||
#pragma warning(disable:4090)
|
||||
|
||||
/* unreferenced formal parameter */
|
||||
#pragma warning(disable:4100)
|
||||
|
||||
/* FD_SET() and FD_CLR(): conditional expression is constant */
|
||||
#pragma warning(disable:4127)
|
||||
|
||||
/* conversion from 'type1' to 'type2', possible loss of data */
|
||||
#pragma warning(disable:4244)
|
||||
|
||||
/* conversion from 'size_t' to 'type', possible loss of data */
|
||||
#pragma warning(disable:4267)
|
||||
|
||||
/* array is too small to include a terminating null character */
|
||||
#pragma warning(disable:4295)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
|
||||
/* symbol 'ngx_rbtree_min' has been defined, but not referenced */
|
||||
#pragma disable_message(202)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
|
||||
/* the end of the precompiled headers */
|
||||
#pragma hdrstop
|
||||
|
||||
/* functions containing (for|while|some if) are not expanded inline */
|
||||
#pragma warn -8027
|
||||
|
||||
/* unreferenced formal parameter */
|
||||
#pragma warn -8057
|
||||
|
||||
/* suspicious pointer arithmetic */
|
||||
#pragma warn -8072
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include <ngx_auto_config.h>
|
||||
|
||||
|
||||
#define ngx_inline __inline
|
||||
#define ngx_cdecl __cdecl
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
#define ngx_libc_cdecl __cdecl
|
||||
|
||||
#elif defined __BORLANDC__
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
#define ngx_libc_cdecl __cdecl
|
||||
|
||||
#else /* __WATCOMC__ */
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
#define ngx_libc_cdecl
|
||||
|
||||
#endif
|
||||
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#if __BORLANDC__
|
||||
typedef int intptr_t;
|
||||
typedef u_int uintptr_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __MINGW64_VERSION_MAJOR
|
||||
|
||||
/* Windows defines off_t as long, which is 32-bit */
|
||||
typedef __int64 off_t;
|
||||
#define _OFF_T_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
|
||||
/* off_t is redefined by sys/types.h used by zlib.h */
|
||||
#define __TYPES_H_INCLUDED
|
||||
typedef int dev_t;
|
||||
typedef unsigned int ino_t;
|
||||
|
||||
#elif __BORLANDC__
|
||||
|
||||
/* off_t is redefined by sys/types.h used by zlib.h */
|
||||
#define __TYPES_H
|
||||
|
||||
typedef int dev_t;
|
||||
typedef unsigned int ino_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __GNUC__
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ssize_t;
|
||||
#else
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef uint32_t in_addr_t;
|
||||
typedef u_short in_port_t;
|
||||
typedef int sig_atomic_t;
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
#define NGX_PTR_SIZE 8
|
||||
#define NGX_SIZE_T_LEN (sizeof("-9223372036854775808") - 1)
|
||||
#define NGX_MAX_SIZE_T_VALUE 9223372036854775807
|
||||
#define NGX_TIME_T_LEN (sizeof("-9223372036854775808") - 1)
|
||||
#define NGX_TIME_T_SIZE 8
|
||||
#define NGX_MAX_TIME_T_VALUE 9223372036854775807
|
||||
|
||||
#else
|
||||
|
||||
#define NGX_PTR_SIZE 4
|
||||
#define NGX_SIZE_T_LEN (sizeof("-2147483648") - 1)
|
||||
#define NGX_MAX_SIZE_T_VALUE 2147483647
|
||||
#define NGX_TIME_T_LEN (sizeof("-2147483648") - 1)
|
||||
#define NGX_TIME_T_SIZE 4
|
||||
#define NGX_MAX_TIME_T_VALUE 2147483647
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_OFF_T_LEN (sizeof("-9223372036854775807") - 1)
|
||||
#define NGX_MAX_OFF_T_VALUE 9223372036854775807
|
||||
#define NGX_SIG_ATOMIC_T_SIZE 4
|
||||
|
||||
|
||||
#define NGX_HAVE_LITTLE_ENDIAN 1
|
||||
#define NGX_HAVE_NONALIGNED 1
|
||||
|
||||
|
||||
#define NGX_WIN_NT 200000
|
||||
|
||||
|
||||
#define NGX_LISTEN_BACKLOG 511
|
||||
|
||||
|
||||
#ifndef NGX_HAVE_INHERITED_NONBLOCK
|
||||
#define NGX_HAVE_INHERITED_NONBLOCK 1
|
||||
#endif
|
||||
|
||||
#ifndef NGX_HAVE_CASELESS_FILESYSTEM
|
||||
#define NGX_HAVE_CASELESS_FILESYSTEM 1
|
||||
#endif
|
||||
|
||||
#ifndef NGX_HAVE_WIN32_TRANSMITPACKETS
|
||||
#define NGX_HAVE_WIN32_TRANSMITPACKETS 1
|
||||
#define NGX_HAVE_WIN32_TRANSMITFILE 0
|
||||
#endif
|
||||
|
||||
#ifndef NGX_HAVE_WIN32_TRANSMITFILE
|
||||
#define NGX_HAVE_WIN32_TRANSMITFILE 1
|
||||
#endif
|
||||
|
||||
#if (NGX_HAVE_WIN32_TRANSMITPACKETS) || (NGX_HAVE_WIN32_TRANSMITFILE)
|
||||
#define NGX_HAVE_SENDFILE 1
|
||||
#endif
|
||||
|
||||
#ifndef NGX_HAVE_SO_SNDLOWAT
|
||||
/* setsockopt(SO_SNDLOWAT) returns error WSAENOPROTOOPT */
|
||||
#define NGX_HAVE_SO_SNDLOWAT 0
|
||||
#endif
|
||||
|
||||
#define NGX_HAVE_GETADDRINFO 1
|
||||
|
||||
#define ngx_random rand
|
||||
#define ngx_debug_init()
|
||||
|
||||
|
||||
#endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */
|
||||
@@ -0,0 +1,297 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
ngx_uint_t ngx_win32_version;
|
||||
ngx_uint_t ngx_ncpu;
|
||||
ngx_uint_t ngx_max_wsabufs;
|
||||
ngx_int_t ngx_max_sockets;
|
||||
ngx_uint_t ngx_inherited_nonblocking = 1;
|
||||
ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush;
|
||||
|
||||
char ngx_unique[NGX_INT32_LEN + 1];
|
||||
|
||||
|
||||
ngx_os_io_t ngx_os_io = {
|
||||
ngx_wsarecv,
|
||||
ngx_wsarecv_chain,
|
||||
ngx_udp_wsarecv,
|
||||
ngx_wsasend,
|
||||
ngx_udp_wsasend,
|
||||
NULL,
|
||||
ngx_wsasend_chain,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
WORD wServicePackMinor;
|
||||
WORD wSuiteMask;
|
||||
BYTE wProductType;
|
||||
} ngx_osviex_stub_t;
|
||||
|
||||
|
||||
static u_int osviex;
|
||||
static OSVERSIONINFOEX osvi;
|
||||
|
||||
/* Should these pointers be per protocol ? */
|
||||
LPFN_ACCEPTEX ngx_acceptex;
|
||||
LPFN_GETACCEPTEXSOCKADDRS ngx_getacceptexsockaddrs;
|
||||
LPFN_TRANSMITFILE ngx_transmitfile;
|
||||
LPFN_TRANSMITPACKETS ngx_transmitpackets;
|
||||
LPFN_CONNECTEX ngx_connectex;
|
||||
LPFN_DISCONNECTEX ngx_disconnectex;
|
||||
|
||||
static GUID ax_guid = WSAID_ACCEPTEX;
|
||||
static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS;
|
||||
static GUID tf_guid = WSAID_TRANSMITFILE;
|
||||
static GUID tp_guid = WSAID_TRANSMITPACKETS;
|
||||
static GUID cx_guid = WSAID_CONNECTEX;
|
||||
static GUID dx_guid = WSAID_DISCONNECTEX;
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_os_init(ngx_log_t *log)
|
||||
{
|
||||
DWORD bytes;
|
||||
SOCKET s;
|
||||
WSADATA wsd;
|
||||
ngx_err_t err;
|
||||
ngx_time_t *tp;
|
||||
ngx_uint_t n;
|
||||
SYSTEM_INFO si;
|
||||
|
||||
/* get Windows version */
|
||||
|
||||
ngx_memzero(&osvi, sizeof(OSVERSIONINFOEX));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
osviex = GetVersionEx((OSVERSIONINFO *) &osvi);
|
||||
|
||||
if (osviex == 0) {
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
|
||||
"GetVersionEx() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default:4996)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Windows 3.1 Win32s 0xxxxx
|
||||
*
|
||||
* Windows 95 140000
|
||||
* Windows 98 141000
|
||||
* Windows ME 149000
|
||||
* Windows NT 3.51 235100
|
||||
* Windows NT 4.0 240000
|
||||
* Windows NT 4.0 SP5 240050
|
||||
* Windows 2000 250000
|
||||
* Windows XP 250100
|
||||
* Windows 2003 250200
|
||||
* Windows Vista/2008 260000
|
||||
*
|
||||
* Windows CE x.x 3xxxxx
|
||||
*/
|
||||
|
||||
ngx_win32_version = osvi.dwPlatformId * 100000
|
||||
+ osvi.dwMajorVersion * 10000
|
||||
+ osvi.dwMinorVersion * 100;
|
||||
|
||||
if (osviex) {
|
||||
ngx_win32_version += osvi.wServicePackMajor * 10
|
||||
+ osvi.wServicePackMinor;
|
||||
}
|
||||
|
||||
GetSystemInfo(&si);
|
||||
ngx_pagesize = si.dwPageSize;
|
||||
ngx_allocation_granularity = si.dwAllocationGranularity;
|
||||
ngx_ncpu = si.dwNumberOfProcessors;
|
||||
ngx_cacheline_size = NGX_CPU_CACHE_LINE;
|
||||
|
||||
for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
|
||||
|
||||
/* delete default "C" locale for _wcsicmp() */
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
|
||||
/* init Winsock */
|
||||
|
||||
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
"WSAStartup() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_win32_version < NGX_WIN_NT) {
|
||||
ngx_max_wsabufs = 16;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* STUB: ngx_uint_t max */
|
||||
ngx_max_wsabufs = 1024 * 1024;
|
||||
|
||||
/*
|
||||
* get AcceptEx(), GetAcceptExSockAddrs(), TransmitFile(),
|
||||
* TransmitPackets(), ConnectEx(), and DisconnectEx() addresses
|
||||
*/
|
||||
|
||||
s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
||||
if (s == (ngx_socket_t) -1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
|
||||
ngx_socket_n " failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ax_guid, sizeof(GUID),
|
||||
&ngx_acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_ACCEPTEX) failed");
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID),
|
||||
&ngx_getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS),
|
||||
&bytes, NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_GETACCEPTEXSOCKADDRS) failed");
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID),
|
||||
&ngx_transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes,
|
||||
NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_TRANSMITFILE) failed");
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tp_guid, sizeof(GUID),
|
||||
&ngx_transmitpackets, sizeof(LPFN_TRANSMITPACKETS), &bytes,
|
||||
NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_TRANSMITPACKETS) failed");
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &cx_guid, sizeof(GUID),
|
||||
&ngx_connectex, sizeof(LPFN_CONNECTEX), &bytes,
|
||||
NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_CONNECTEX) failed");
|
||||
}
|
||||
|
||||
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &dx_guid, sizeof(GUID),
|
||||
&ngx_disconnectex, sizeof(LPFN_DISCONNECTEX), &bytes,
|
||||
NULL, NULL)
|
||||
== -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
|
||||
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
|
||||
"WSAID_DISCONNECTEX) failed");
|
||||
}
|
||||
|
||||
if (ngx_close_socket(s) == -1) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
|
||||
ngx_close_socket_n " failed");
|
||||
}
|
||||
|
||||
if (GetEnvironmentVariable("ngx_unique", ngx_unique, NGX_INT32_LEN + 1)
|
||||
!= 0)
|
||||
{
|
||||
ngx_process = NGX_PROCESS_WORKER;
|
||||
|
||||
} else {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err != ERROR_ENVVAR_NOT_FOUND) {
|
||||
ngx_log_error(NGX_LOG_EMERG, log, err,
|
||||
"GetEnvironmentVariable(\"ngx_unique\") failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_sprintf((u_char *) ngx_unique, "%P%Z", ngx_pid);
|
||||
}
|
||||
|
||||
tp = ngx_timeofday();
|
||||
srand((ngx_pid << 16) ^ (unsigned) tp->sec ^ tp->msec);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_os_status(ngx_log_t *log)
|
||||
{
|
||||
ngx_osviex_stub_t *osviex_stub;
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, log, 0, NGINX_VER_BUILD);
|
||||
|
||||
if (osviex) {
|
||||
|
||||
/*
|
||||
* the MSVC 6.0 SP2 defines wSuiteMask and wProductType
|
||||
* as WORD wReserved[2]
|
||||
*/
|
||||
osviex_stub = (ngx_osviex_stub_t *) &osvi.wServicePackMinor;
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, log, 0,
|
||||
"OS: %ud build:%ud, \"%s\", suite:%Xd, type:%ud",
|
||||
ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
|
||||
osviex_stub->wSuiteMask, osviex_stub->wProductType);
|
||||
|
||||
} else {
|
||||
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||
|
||||
/* Win9x build */
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, log, 0,
|
||||
"OS: %u build:%ud.%ud.%ud, \"%s\"",
|
||||
ngx_win32_version,
|
||||
osvi.dwBuildNumber >> 24,
|
||||
(osvi.dwBuildNumber >> 16) & 0xff,
|
||||
osvi.dwBuildNumber & 0xffff,
|
||||
osvi.szCSDVersion);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* VER_PLATFORM_WIN32_NT
|
||||
*
|
||||
* we do not currently support VER_PLATFORM_WIN32_CE
|
||||
* and we do not support VER_PLATFORM_WIN32s at all
|
||||
*/
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %ud build:%ud, \"%s\"",
|
||||
ngx_win32_version, osvi.dwBuildNumber,
|
||||
osvi.szCSDVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
u_long bytes, flags;
|
||||
WSABUF wsabuf[1];
|
||||
ngx_err_t err;
|
||||
ngx_int_t n;
|
||||
ngx_event_t *rev;
|
||||
|
||||
wsabuf[0].buf = (char *) buf;
|
||||
wsabuf[0].len = size;
|
||||
flags = 0;
|
||||
bytes = 0;
|
||||
|
||||
rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL);
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv: fd:%d rc:%d %ul of %z", c->fd, rc, bytes, size);
|
||||
|
||||
rev = c->read;
|
||||
|
||||
if (rc == -1) {
|
||||
rev->ready = 0;
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSARecv() not ready");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
n = ngx_connection_error(c, err, "WSARecv() failed");
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
rev->error = 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
if (bytes < size) {
|
||||
rev->ready = 0;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
rev->eof = 1;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
u_long bytes, flags;
|
||||
WSABUF wsabuf[1];
|
||||
ngx_err_t err;
|
||||
ngx_int_t n;
|
||||
ngx_event_t *rev;
|
||||
LPWSAOVERLAPPED ovlp;
|
||||
|
||||
rev = c->read;
|
||||
|
||||
if (!rev->ready) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "second wsa post");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"rev->complete: %d", rev->complete);
|
||||
|
||||
if (rev->complete) {
|
||||
rev->complete = 0;
|
||||
|
||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
||||
if (rev->ovlp.error) {
|
||||
ngx_connection_error(c, rev->ovlp.error, "WSARecv() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv ovlp: fd:%d %ul of %z",
|
||||
c->fd, rev->available, size);
|
||||
|
||||
return rev->available;
|
||||
}
|
||||
|
||||
if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp,
|
||||
&bytes, 0, NULL)
|
||||
== 0)
|
||||
{
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
"WSARecv() or WSAGetOverlappedResult() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv: fd:%d %ul of %z", c->fd, bytes, size);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ovlp = (LPWSAOVERLAPPED) &rev->ovlp;
|
||||
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
|
||||
wsabuf[0].buf = (char *) buf;
|
||||
wsabuf[0].len = size;
|
||||
flags = 0;
|
||||
bytes = 0;
|
||||
|
||||
rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL);
|
||||
|
||||
rev->complete = 0;
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv ovlp: fd:%d rc:%d %ul of %z",
|
||||
c->fd, rc, bytes, size);
|
||||
|
||||
if (rc == -1) {
|
||||
err = ngx_socket_errno;
|
||||
if (err == WSA_IO_PENDING) {
|
||||
rev->active = 1;
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSARecv() posted");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
n = ngx_connection_error(c, err, "WSARecv() failed");
|
||||
|
||||
if (n == NGX_ERROR) {
|
||||
rev->error = 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
#define NGX_WSABUFS 8
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain, off_t limit)
|
||||
{
|
||||
int rc;
|
||||
u_char *prev;
|
||||
u_long bytes, flags;
|
||||
size_t n, size;
|
||||
ngx_err_t err;
|
||||
ngx_array_t vec;
|
||||
ngx_event_t *rev;
|
||||
LPWSABUF wsabuf;
|
||||
WSABUF wsabufs[NGX_WSABUFS];
|
||||
|
||||
prev = NULL;
|
||||
wsabuf = NULL;
|
||||
flags = 0;
|
||||
size = 0;
|
||||
bytes = 0;
|
||||
|
||||
vec.elts = wsabufs;
|
||||
vec.nelts = 0;
|
||||
vec.size = sizeof(WSABUF);
|
||||
vec.nalloc = NGX_WSABUFS;
|
||||
vec.pool = c->pool;
|
||||
|
||||
/* coalesce the neighbouring bufs */
|
||||
|
||||
while (chain) {
|
||||
n = chain->buf->end - chain->buf->last;
|
||||
|
||||
if (limit) {
|
||||
if (size >= (size_t) limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (size + n > (size_t) limit) {
|
||||
n = (size_t) limit - size;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev == chain->buf->last) {
|
||||
wsabuf->len += n;
|
||||
|
||||
} else {
|
||||
wsabuf = ngx_array_push(&vec);
|
||||
if (wsabuf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
wsabuf->buf = (char *) chain->buf->last;
|
||||
wsabuf->len = n;
|
||||
}
|
||||
|
||||
size += n;
|
||||
prev = chain->buf->end;
|
||||
chain = chain->next;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSARecv: %d:%d", vec.nelts, wsabuf->len);
|
||||
|
||||
|
||||
rc = WSARecv(c->fd, vec.elts, vec.nelts, &bytes, &flags, NULL, NULL);
|
||||
|
||||
rev = c->read;
|
||||
|
||||
if (rc == -1) {
|
||||
rev->ready = 0;
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSARecv() not ready");
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
rev->error = 1;
|
||||
ngx_connection_error(c, err, "WSARecv() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (bytes < size) {
|
||||
rev->ready = 0;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
rev->eof = 1;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_wsasend(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
u_long sent;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *wev;
|
||||
WSABUF wsabuf;
|
||||
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* WSABUF must be 4-byte aligned otherwise
|
||||
* WSASend() will return undocumented WSAEINVAL error.
|
||||
*/
|
||||
|
||||
wsabuf.buf = (char *) buf;
|
||||
wsabuf.len = size;
|
||||
|
||||
sent = 0;
|
||||
|
||||
n = WSASend(c->fd, &wsabuf, 1, &sent, 0, NULL, NULL);
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size);
|
||||
|
||||
if (n == 0) {
|
||||
if (sent < size) {
|
||||
wev->ready = 0;
|
||||
}
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "WSASend() not ready");
|
||||
wev->ready = 0;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
wev->error = 1;
|
||||
ngx_connection_error(c, err, "WSASend() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ngx_overlapped_wsasend(ngx_connection_t *c, u_char *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
u_long sent;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *wev;
|
||||
LPWSAOVERLAPPED ovlp;
|
||||
WSABUF wsabuf;
|
||||
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"wev->complete: %d", wev->complete);
|
||||
|
||||
if (!wev->complete) {
|
||||
|
||||
/* post the overlapped WSASend() */
|
||||
|
||||
/*
|
||||
* WSABUFs must be 4-byte aligned otherwise
|
||||
* WSASend() will return undocumented WSAEINVAL error.
|
||||
*/
|
||||
|
||||
wsabuf.buf = (char *) buf;
|
||||
wsabuf.len = size;
|
||||
|
||||
sent = 0;
|
||||
|
||||
ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
|
||||
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
|
||||
|
||||
n = WSASend(c->fd, &wsabuf, 1, &sent, 0, ovlp, NULL);
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend: fd:%d, %d, %ul of %uz", c->fd, n, sent, size);
|
||||
|
||||
wev->complete = 0;
|
||||
|
||||
if (n == 0) {
|
||||
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 NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (sent < size) {
|
||||
wev->ready = 0;
|
||||
}
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
err = ngx_socket_errno;
|
||||
|
||||
if (err == WSA_IO_PENDING) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSASend() posted");
|
||||
wev->active = 1;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
wev->error = 1;
|
||||
ngx_connection_error(c, err, "WSASend() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* the overlapped WSASend() complete */
|
||||
|
||||
wev->complete = 0;
|
||||
wev->active = 0;
|
||||
|
||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
||||
|
||||
if (wev->ovlp.error) {
|
||||
ngx_connection_error(c, wev->ovlp.error, "WSASend() failed");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
sent = wev->available;
|
||||
|
||||
} else {
|
||||
if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &wev->ovlp,
|
||||
&sent, 0, NULL)
|
||||
== 0)
|
||||
{
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
"WSASend() or WSAGetOverlappedResult() failed");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSAGetOverlappedResult: fd:%d, %ul of %uz",
|
||||
c->fd, sent, size);
|
||||
|
||||
if (sent < size) {
|
||||
wev->ready = 0;
|
||||
}
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
return sent;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
|
||||
|
||||
#define NGX_WSABUFS 8
|
||||
|
||||
|
||||
ngx_chain_t *
|
||||
ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
{
|
||||
int rc;
|
||||
u_char *prev;
|
||||
u_long size, sent, send, prev_send;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *wev;
|
||||
ngx_array_t vec;
|
||||
ngx_chain_t *cl;
|
||||
LPWSABUF wsabuf;
|
||||
WSABUF wsabufs[NGX_WSABUFS];
|
||||
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return in;
|
||||
}
|
||||
|
||||
/* the maximum limit size is the maximum u_long value - the page size */
|
||||
|
||||
if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize)) {
|
||||
limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
|
||||
}
|
||||
|
||||
send = 0;
|
||||
|
||||
/*
|
||||
* WSABUFs must be 4-byte aligned otherwise
|
||||
* WSASend() will return undocumented WSAEINVAL error.
|
||||
*/
|
||||
|
||||
vec.elts = wsabufs;
|
||||
vec.size = sizeof(WSABUF);
|
||||
vec.nalloc = NGX_WSABUFS;
|
||||
vec.pool = c->pool;
|
||||
|
||||
for ( ;; ) {
|
||||
prev = NULL;
|
||||
wsabuf = NULL;
|
||||
prev_send = send;
|
||||
|
||||
vec.nelts = 0;
|
||||
|
||||
/* create the WSABUF and coalesce the neighbouring bufs */
|
||||
|
||||
for (cl = in;
|
||||
cl && vec.nelts < ngx_max_wsabufs && send < limit;
|
||||
cl = cl->next)
|
||||
{
|
||||
if (ngx_buf_special(cl->buf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size = cl->buf->last - cl->buf->pos;
|
||||
|
||||
if (send + size > limit) {
|
||||
size = (u_long) (limit - send);
|
||||
}
|
||||
|
||||
if (prev == cl->buf->pos) {
|
||||
wsabuf->len += cl->buf->last - cl->buf->pos;
|
||||
|
||||
} else {
|
||||
wsabuf = ngx_array_push(&vec);
|
||||
if (wsabuf == NULL) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
wsabuf->buf = (char *) cl->buf->pos;
|
||||
wsabuf->len = cl->buf->last - cl->buf->pos;
|
||||
}
|
||||
|
||||
prev = cl->buf->last;
|
||||
send += size;
|
||||
}
|
||||
|
||||
sent = 0;
|
||||
|
||||
rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, NULL, NULL);
|
||||
|
||||
if (rc == -1) {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSASend() not ready");
|
||||
|
||||
} else {
|
||||
wev->error = 1;
|
||||
ngx_connection_error(c, err, "WSASend() failed");
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend: fd:%d, s:%ul", c->fd, sent);
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
in = ngx_chain_update_sent(in, sent);
|
||||
|
||||
if (send - prev_send != sent) {
|
||||
wev->ready = 0;
|
||||
return in;
|
||||
}
|
||||
|
||||
if (send >= limit || in == NULL) {
|
||||
return in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngx_chain_t *
|
||||
ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||
{
|
||||
int rc;
|
||||
u_char *prev;
|
||||
u_long size, send, sent;
|
||||
ngx_err_t err;
|
||||
ngx_event_t *wev;
|
||||
ngx_array_t vec;
|
||||
ngx_chain_t *cl;
|
||||
LPWSAOVERLAPPED ovlp;
|
||||
LPWSABUF wsabuf;
|
||||
WSABUF wsabufs[NGX_WSABUFS];
|
||||
|
||||
wev = c->write;
|
||||
|
||||
if (!wev->ready) {
|
||||
return in;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"wev->complete: %d", wev->complete);
|
||||
|
||||
if (!wev->complete) {
|
||||
|
||||
/* post the overlapped WSASend() */
|
||||
|
||||
/* the maximum limit size is the maximum u_long value - the page size */
|
||||
|
||||
if (limit == 0 || limit > (off_t) (NGX_MAX_UINT32_VALUE - ngx_pagesize))
|
||||
{
|
||||
limit = NGX_MAX_UINT32_VALUE - ngx_pagesize;
|
||||
}
|
||||
|
||||
/*
|
||||
* WSABUFs must be 4-byte aligned otherwise
|
||||
* WSASend() will return undocumented WSAEINVAL error.
|
||||
*/
|
||||
|
||||
vec.elts = wsabufs;
|
||||
vec.nelts = 0;
|
||||
vec.size = sizeof(WSABUF);
|
||||
vec.nalloc = NGX_WSABUFS;
|
||||
vec.pool = c->pool;
|
||||
|
||||
send = 0;
|
||||
prev = NULL;
|
||||
wsabuf = NULL;
|
||||
|
||||
/* create the WSABUF and coalesce the neighbouring bufs */
|
||||
|
||||
for (cl = in;
|
||||
cl && vec.nelts < ngx_max_wsabufs && send < limit;
|
||||
cl = cl->next)
|
||||
{
|
||||
if (ngx_buf_special(cl->buf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size = cl->buf->last - cl->buf->pos;
|
||||
|
||||
if (send + size > limit) {
|
||||
size = (u_long) (limit - send);
|
||||
}
|
||||
|
||||
if (prev == cl->buf->pos) {
|
||||
wsabuf->len += cl->buf->last - cl->buf->pos;
|
||||
|
||||
} else {
|
||||
wsabuf = ngx_array_push(&vec);
|
||||
if (wsabuf == NULL) {
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
|
||||
wsabuf->buf = (char *) cl->buf->pos;
|
||||
wsabuf->len = cl->buf->last - cl->buf->pos;
|
||||
}
|
||||
|
||||
prev = cl->buf->last;
|
||||
send += size;
|
||||
}
|
||||
|
||||
ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
|
||||
ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
|
||||
|
||||
rc = WSASend(c->fd, vec.elts, vec.nelts, &sent, 0, ovlp, NULL);
|
||||
|
||||
wev->complete = 0;
|
||||
|
||||
if (rc == -1) {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == WSA_IO_PENDING) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
|
||||
"WSASend() posted");
|
||||
wev->active = 1;
|
||||
return in;
|
||||
|
||||
} else {
|
||||
wev->error = 1;
|
||||
ngx_connection_error(c, 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;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend: fd:%d, s:%ul", c->fd, sent);
|
||||
|
||||
} else {
|
||||
|
||||
/* the overlapped WSASend() complete */
|
||||
|
||||
wev->complete = 0;
|
||||
wev->active = 0;
|
||||
|
||||
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
|
||||
if (wev->ovlp.error) {
|
||||
ngx_connection_error(c, 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_connection_error(c, ngx_socket_errno,
|
||||
"WSASend() or WSAGetOverlappedResult() failed");
|
||||
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
|
||||
"WSASend ovlp: fd:%d, s:%ul", c->fd, sent);
|
||||
|
||||
c->sent += sent;
|
||||
|
||||
in = ngx_chain_update_sent(in, sent);
|
||||
|
||||
if (in) {
|
||||
wev->ready = 0;
|
||||
|
||||
} else {
|
||||
wev->ready = 1;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
Reference in New Issue
Block a user