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


void ngx_event_acceptex(ngx_event_t *rev)
{
    ngx_connection_t  *c;

    c = (ngx_connection_t *) rev->data;

    if (rev->ovlp.error) {
        ngx_log_error(NGX_LOG_CRIT, c->log, rev->ovlp.error,
                      "AcceptEx() %s failed", c->listening->addr_text.data);
        return;
    }

    /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */

    if (setsockopt(c->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
                   (char *)&c->listening->fd, sizeof(ngx_socket_t)) == -1)
    {
        ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
                      "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed for %s",
                      c->addr_text.data);
    } else {
        c->accept_context_updated = 1;
    }

    getacceptexsockaddrs(c->buffer->pos, c->listening->post_accept_buffer_size,
                         c->listening->socklen + 16,
                         c->listening->socklen + 16,
                         &c->local_sockaddr, &c->local_socklen,
                         &c->sockaddr, &c->socklen);

    if (c->listening->post_accept_buffer_size) {
        c->buffer->last += rev->available;
        c->buffer->end = c->buffer->start
                                       + c->listening->post_accept_buffer_size;

    } else {
        c->buffer = NULL;
    }

    ngx_event_post_acceptex(c->listening, 1);

    /* TODO: MT */
    c->number = ngx_connection_counter++;

    c->listening->handler(c);

    return;

}


int ngx_event_post_acceptex(ngx_listening_t *ls, int n)
{
    int                i;
    u_int              rcvd;
    ngx_err_t          err;
    ngx_event_t       *rev, *wev;
    ngx_socket_t       s;
    ngx_connection_t  *c;

    for (i = 0; i < n; i++) {

        /* TODO: look up reused sockets */

        s = ngx_socket(ls->family, ls->type, ls->protocol, ls->flags);
        ngx_log_debug(ls->log, ngx_socket_n ": %d:%d" _ s _ ls->flags);

        if (s == -1) {
            ngx_log_error(NGX_LOG_ALERT, ls->log, ngx_socket_errno,
                          ngx_socket_n " for AcceptEx() %s post failed",
                          ls->addr_text.data);

            return NGX_ERROR;
        }

        /*
         * Winsock assignes a socket number divisible by 4
         * so to find a connection we divide a socket number by 4.
         */

        if (s % 4) {
            ngx_log_error(NGX_LOG_EMERG, ls->log, 0,
                          ngx_socket_n
                          " created socket %d, not divisible by 4", s);

            exit(1);
        }

        c = &ngx_cycle->connections[s / 4];
        rev = &ngx_cycle->read_events[s / 4];
        wev = &ngx_cycle->write_events[s / 4];

        ngx_memzero(c, sizeof(ngx_connection_t));
        ngx_memzero(rev, sizeof(ngx_event_t));
        ngx_memzero(wev, sizeof(ngx_event_t));

        rev->index = wev->index = NGX_INVALID_INDEX;

        rev->ovlp.event = rev;
        wev->ovlp.event = wev;

        rev->data = wev->data = c;
        c->read = rev;
        c->write = wev;

        c->listening = ls;
        c->fd = s;

        c->ctx = ls->ctx;
        c->servers = ls->servers;

        c->unexpected_eof = 1;
        wev->write = 1;
        rev->event_handler = ngx_event_acceptex;

        rev->ready = 1;
        wev->ready = 1;

        ngx_test_null(c->pool,
                      ngx_create_pool(ls->pool_size, ls->log),
                      NGX_ERROR);

        ngx_test_null(c->buffer,
                      ngx_create_temp_hunk(c->pool,
                                           ls->post_accept_buffer_size
                                           + 2 * (c->listening->socklen + 16)),
                      NGX_ERROR);

        ngx_test_null(c->local_sockaddr, ngx_palloc(c->pool, ls->socklen),
                      NGX_ERROR);

        ngx_test_null(c->sockaddr, ngx_palloc(c->pool, ls->socklen),
                      NGX_ERROR);

        ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)),
                      NGX_ERROR);

        ngx_memcpy(c->log, ls->log, sizeof(ngx_log_t));
        c->read->log = c->write->log = c->log;

        if (ngx_add_event(rev, 0, NGX_IOCP_IO) == NGX_ERROR) {
            return NGX_ERROR;
        }

        if (acceptex(ls->fd, s, c->buffer->pos, ls->post_accept_buffer_size,
                     ls->socklen + 16, ls->socklen + 16,
                     &rcvd, (LPOVERLAPPED) &rev->ovlp) == 0)
        {

            err = ngx_socket_errno;
            if (err != WSA_IO_PENDING) {
                ngx_log_error(NGX_LOG_ALERT, ls->log, err,
                              "AcceptEx() %s falied", ls->addr_text.data);

                return NGX_ERROR;
            }
        }
    }

    return NGX_OK;
}
