view src/os/win32/ngx_win32_init.c @ 8099:b4ef79ef1c23 quic

QUIC: refined the "c->quic->initialized" flag usage. The flag is tied to the initial secret creation. The presence of c->quic pointer is sufficient to enable execution of ngx_quic_close_quic(). The ngx_quic_new_connection() function now returns the allocated quic connection object and the c->quic pointer is set by the caller. If an early error occurs before secrets initialization (i.e. in cases of invalid retry token or nginx exiting), it is still possible to generate an error response by trying to initialize secrets directly in the ngx_quic_send_cc() function. Before the change such early errors failed to send proper connection close message and logged an error. An auxilliary ngx_quic_init_secrets() function is introduced to avoid verbose call to ngx_quic_set_initial_secret() requiring local variable.
author Vladimir Homutov <vl@nginx.com>
date Wed, 30 Sep 2020 21:27:52 +0300
parents 4f6e315eef15
children d1079d6b2f19
line wrap: on
line source


/*
 * 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,
    NULL,
    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;


#if (NGX_LOAD_WSAPOLL)
ngx_wsapoll_pt             WSAPoll;
ngx_uint_t                 ngx_have_wsapoll;
#endif


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 (NGX_LOAD_WSAPOLL)
    {
    HMODULE  hmod;

    hmod = GetModuleHandle("ws2_32.dll");
    if (hmod == NULL) {
        ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
                      "GetModuleHandle(\"ws2_32.dll\") failed");
        goto nopoll;
    }

    WSAPoll = (ngx_wsapoll_pt) (void *) GetProcAddress(hmod, "WSAPoll");
    if (WSAPoll == NULL) {
        ngx_log_error(NGX_LOG_NOTICE, log, ngx_errno,
                      "GetProcAddress(\"WSAPoll\") failed");
        goto nopoll;
    }

    ngx_have_wsapoll = 1;

    }

nopoll:

#endif

    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);
        }
    }
}