
#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 %lu",
                      ne.lNetworkEvents);
    }
}
