ngx_win32_init.c revision e18a033b
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <nginx.h>
11
12
13ngx_uint_t  ngx_win32_version;
14ngx_uint_t  ngx_ncpu;
15ngx_uint_t  ngx_max_wsabufs;
16ngx_int_t   ngx_max_sockets;
17ngx_uint_t  ngx_inherited_nonblocking = 1;
18ngx_uint_t  ngx_tcp_nodelay_and_tcp_nopush;
19
20char        ngx_unique[NGX_INT32_LEN + 1];
21
22
23ngx_os_io_t ngx_os_io = {
24    ngx_wsarecv,
25    ngx_wsarecv_chain,
26    ngx_udp_wsarecv,
27    ngx_wsasend,
28    NULL,
29    NULL,
30    ngx_wsasend_chain,
31    0
32};
33
34
35typedef struct {
36    WORD  wServicePackMinor;
37    WORD  wSuiteMask;
38    BYTE  wProductType;
39} ngx_osviex_stub_t;
40
41
42static u_int               osviex;
43static OSVERSIONINFOEX     osvi;
44
45/* Should these pointers be per protocol ? */
46LPFN_ACCEPTEX              ngx_acceptex;
47LPFN_GETACCEPTEXSOCKADDRS  ngx_getacceptexsockaddrs;
48LPFN_TRANSMITFILE          ngx_transmitfile;
49LPFN_TRANSMITPACKETS       ngx_transmitpackets;
50LPFN_CONNECTEX             ngx_connectex;
51LPFN_DISCONNECTEX          ngx_disconnectex;
52
53static GUID ax_guid = WSAID_ACCEPTEX;
54static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS;
55static GUID tf_guid = WSAID_TRANSMITFILE;
56static GUID tp_guid = WSAID_TRANSMITPACKETS;
57static GUID cx_guid = WSAID_CONNECTEX;
58static GUID dx_guid = WSAID_DISCONNECTEX;
59
60
61ngx_int_t
62ngx_os_init(ngx_log_t *log)
63{
64    DWORD         bytes;
65    SOCKET        s;
66    WSADATA       wsd;
67    ngx_err_t     err;
68    ngx_time_t   *tp;
69    ngx_uint_t    n;
70    SYSTEM_INFO   si;
71
72    /* get Windows version */
73
74    ngx_memzero(&osvi, sizeof(OSVERSIONINFOEX));
75    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
76
77#ifdef _MSC_VER
78#pragma warning(disable:4996)
79#endif
80
81    osviex = GetVersionEx((OSVERSIONINFO *) &osvi);
82
83    if (osviex == 0) {
84        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
85        if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0) {
86            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
87                          "GetVersionEx() failed");
88            return NGX_ERROR;
89        }
90    }
91
92#ifdef _MSC_VER
93#pragma warning(default:4996)
94#endif
95
96    /*
97     *  Windows 3.1 Win32s   0xxxxx
98     *
99     *  Windows 95           140000
100     *  Windows 98           141000
101     *  Windows ME           149000
102     *  Windows NT 3.51      235100
103     *  Windows NT 4.0       240000
104     *  Windows NT 4.0 SP5   240050
105     *  Windows 2000         250000
106     *  Windows XP           250100
107     *  Windows 2003         250200
108     *  Windows Vista/2008   260000
109     *
110     *  Windows CE x.x       3xxxxx
111     */
112
113    ngx_win32_version = osvi.dwPlatformId * 100000
114                        + osvi.dwMajorVersion * 10000
115                        + osvi.dwMinorVersion * 100;
116
117    if (osviex) {
118        ngx_win32_version += osvi.wServicePackMajor * 10
119                             + osvi.wServicePackMinor;
120    }
121
122    GetSystemInfo(&si);
123    ngx_pagesize = si.dwPageSize;
124    ngx_allocation_granularity = si.dwAllocationGranularity;
125    ngx_ncpu = si.dwNumberOfProcessors;
126    ngx_cacheline_size = NGX_CPU_CACHE_LINE;
127
128    for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
129
130    /* delete default "C" locale for _wcsicmp() */
131    setlocale(LC_ALL, "");
132
133
134    /* init Winsock */
135
136    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
137        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
138                      "WSAStartup() failed");
139        return NGX_ERROR;
140    }
141
142    if (ngx_win32_version < NGX_WIN_NT) {
143        ngx_max_wsabufs = 16;
144        return NGX_OK;
145    }
146
147    /* STUB: ngx_uint_t max */
148    ngx_max_wsabufs = 1024 * 1024;
149
150    /*
151     * get AcceptEx(), GetAcceptExSockAddrs(), TransmitFile(),
152     * TransmitPackets(), ConnectEx(), and DisconnectEx() addresses
153     */
154
155    s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
156    if (s == (ngx_socket_t) -1) {
157        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
158                      ngx_socket_n " failed");
159        return NGX_ERROR;
160    }
161
162    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ax_guid, sizeof(GUID),
163                 &ngx_acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL)
164        == -1)
165    {
166        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
167                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
168                               "WSAID_ACCEPTEX) failed");
169    }
170
171    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID),
172                 &ngx_getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS),
173                 &bytes, NULL, NULL)
174        == -1)
175    {
176        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
177                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
178                               "WSAID_GETACCEPTEXSOCKADDRS) failed");
179    }
180
181    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID),
182                 &ngx_transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes,
183                 NULL, NULL)
184        == -1)
185    {
186        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
187                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
188                               "WSAID_TRANSMITFILE) failed");
189    }
190
191    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tp_guid, sizeof(GUID),
192                 &ngx_transmitpackets, sizeof(LPFN_TRANSMITPACKETS), &bytes,
193                 NULL, NULL)
194        == -1)
195    {
196        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
197                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
198                               "WSAID_TRANSMITPACKETS) failed");
199    }
200
201    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &cx_guid, sizeof(GUID),
202                 &ngx_connectex, sizeof(LPFN_CONNECTEX), &bytes,
203                 NULL, NULL)
204        == -1)
205    {
206        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
207                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
208                               "WSAID_CONNECTEX) failed");
209    }
210
211    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &dx_guid, sizeof(GUID),
212                 &ngx_disconnectex, sizeof(LPFN_DISCONNECTEX), &bytes,
213                 NULL, NULL)
214        == -1)
215    {
216        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
217                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
218                               "WSAID_DISCONNECTEX) failed");
219    }
220
221    if (ngx_close_socket(s) == -1) {
222        ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
223                      ngx_close_socket_n " failed");
224    }
225
226    if (GetEnvironmentVariable("ngx_unique", ngx_unique, NGX_INT32_LEN + 1)
227        != 0)
228    {
229        ngx_process = NGX_PROCESS_WORKER;
230
231    } else {
232        err = ngx_errno;
233
234        if (err != ERROR_ENVVAR_NOT_FOUND) {
235            ngx_log_error(NGX_LOG_EMERG, log, err,
236                          "GetEnvironmentVariable(\"ngx_unique\") failed");
237            return NGX_ERROR;
238        }
239
240        ngx_sprintf((u_char *) ngx_unique, "%P%Z", ngx_pid);
241    }
242
243    tp = ngx_timeofday();
244    srand((ngx_pid << 16) ^ (unsigned) tp->sec ^ tp->msec);
245
246    return NGX_OK;
247}
248
249
250void
251ngx_os_status(ngx_log_t *log)
252{
253    ngx_osviex_stub_t  *osviex_stub;
254
255    ngx_log_error(NGX_LOG_NOTICE, log, 0, NGINX_VER_BUILD);
256
257    if (osviex) {
258
259        /*
260         * the MSVC 6.0 SP2 defines wSuiteMask and wProductType
261         * as WORD wReserved[2]
262         */
263        osviex_stub = (ngx_osviex_stub_t *) &osvi.wServicePackMinor;
264
265        ngx_log_error(NGX_LOG_INFO, log, 0,
266                      "OS: %ud build:%ud, \"%s\", suite:%Xd, type:%ud",
267                      ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
268                      osviex_stub->wSuiteMask, osviex_stub->wProductType);
269
270    } else {
271        if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
272
273            /* Win9x build */
274
275            ngx_log_error(NGX_LOG_INFO, log, 0,
276                          "OS: %u build:%ud.%ud.%ud, \"%s\"",
277                          ngx_win32_version,
278                          osvi.dwBuildNumber >> 24,
279                          (osvi.dwBuildNumber >> 16) & 0xff,
280                          osvi.dwBuildNumber & 0xffff,
281                          osvi.szCSDVersion);
282
283        } else {
284
285            /*
286             * VER_PLATFORM_WIN32_NT
287             *
288             * we do not currently support VER_PLATFORM_WIN32_CE
289             * and we do not support VER_PLATFORM_WIN32s at all
290             */
291
292            ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %ud build:%ud, \"%s\"",
293                          ngx_win32_version, osvi.dwBuildNumber,
294                          osvi.szCSDVersion);
295        }
296    }
297}
298