
/*
 * Copyright (C) Igor Sysoev
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>


#define NGX_MAX_PENDING_CONN  10


static CRITICAL_SECTION  connect_lock;
static int               nconnects;
static ngx_connection_t  pending_connects[NGX_MAX_PENDING_CONN];

static HANDLE            pending_connect_event;

__declspec(thread) int                nevents = 0;
__declspec(thread) WSAEVENT           events[WSA_MAXIMUM_WAIT_EVENTS + 1];
__declspec(thread) ngx_connection_t  *conn[WSA_MAXIMUM_WAIT_EVENTS + 1];



int ngx_iocp_wait_connect(ngx_connection_t *c)
{
    for ( ;; ) {
        EnterCriticalSection(&connect_lock);

        if (nconnects < NGX_MAX_PENDING_CONN) {
            pending_connects[--nconnects] = c;
            LeaveCriticalSection(&connect_lock);

            if (SetEvent(pending_connect_event) == 0) {
                ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                              "SetEvent() failed");
                return NGX_ERROR;

            break;
        }

        LeaveCriticalSection(&connect_lock);
        ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
                      "max number of pending connect()s is %d",
                      NGX_MAX_PENDING_CONN);
        msleep(100);
    }

    if (!started) {
        if (ngx_iocp_new_thread(1) == NGX_ERROR) {
            return NGX_ERROR;
        }
        started = 1;
    }

    return NGX_OK;
}


int ngx_iocp_new_thread(int main)
{
    u_int  id;

    if (main) {
        pending_connect_event = CreateEvent(NULL, 0, 1, NULL);
        if (pending_connect_event == INVALID_HANDLE_VALUE) {
            ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                          "CreateThread() failed");
            return NGX_ERROR;
        }
    }

    if (CreateThread(NULL, 0, ngx_iocp_wait_events, main, 0, &id)
                                                       == INVALID_HANDLE_VALUE)
    {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      "CreateThread() failed");
        return NGX_ERROR;
    }

    SetEvent(event) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      "SetEvent() failed");
        return NGX_ERROR;
    }

    return NGX_OK;
}


int ngx_iocp_new_connect()
{
    EnterCriticalSection(&connect_lock);
    c = pending_connects[--nconnects];
    LeaveCriticalSection(&connect_lock);

    conn[nevents] = c;

    events[nevents] = WSACreateEvent();
    if (events[nevents] == INVALID_HANDLE_VALUE) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
                      "WSACreateEvent() failed");
        return NGX_ERROR;
    }

    if (WSAEventSelect(c->fd, events[nevents], FD_CONNECT) == -1)
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
                      "WSAEventSelect() failed");
        return NGX_ERROR;
    }

    nevents++;

    return NGX_OK;
}


void ngx_iocp_wait_events(int main)
{
    WSANETWORKEVENTS  ne;

    nevents = 1;
    events[0] = pending_connect_event;
    conn[0] = NULL;

    for ( ;; ) {
        offset = (nevents == WSA_MAXIMUM_WAIT_EVENTS + 1) ? 1: 0;
        timeout = (nevents == 1 && !first) ? 60000: INFINITE;

        n = WSAWaitForMultipleEvents(nevents - offset, events[offset],
                                     0, timeout, 0);
        if (n == WAIT_FAILED) {
            ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
                          "WSAWaitForMultipleEvents() failed");
            continue;
        }

        if (n == WAIT_TIMEOUT) {
            if (nevents == 2 && !main) {
                ExitThread(0);
            }

            ngx_log_error(NGX_LOG_ALERT, log, 0,
                          "WSAWaitForMultipleEvents() "
                          "returned unexpected WAIT_TIMEOUT");
            continue;
        }

        n -= WSA_WAIT_EVENT_0;

        if (events[n] == NULL) {

            /* the pending_connect_event */

            if (nevents == WSA_MAXIMUM_WAIT_EVENTS) {
                ngx_iocp_new_thread(0);
            } else {
                ngx_iocp_new_connect();
            }

            continue;
        }

        if (WSAEnumNetworkEvents(c[n].fd, events[n], &ne) == -1) {
            ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
                          "WSAEnumNetworkEvents() failed");
            continue;
        }

        if (ne.lNetworkEvents & FD_CONNECT) {
            conn[n].write->ovlp.error = ne.iErrorCode[FD_CONNECT_BIT];

            if (PostQueuedCompletionStatus(iocp, 0, NGX_IOCP_CONNECT,
                                           &conn[n].write->ovlp) == 0)
            {
                ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
                              "PostQueuedCompletionStatus() failed");
                continue;
            }

            if (n < nevents) {
                conn[n] = conn[nevents];
                events[n] = events[nevents];
            }

            nevents--;
            continue;
        }

        if (ne.lNetworkEvents & FD_ACCEPT) {

            /* CHECK ERROR ??? */

            ngx_event_post_acceptex(conn[n].listening, 1);
            continue;
        }

        ngx_log_error(NGX_LOG_ALERT, c[n].log, 0,
                      "WSAWaitForMultipleEvents() "
                      "returned unexpected network event %ul",
                      ne.lNetworkEvents);
    }
}
