static void s_incoming_pipe_connection_event()

in source/windows/iocp/socket.c [1592:1752]


static void s_incoming_pipe_connection_event(
    struct aws_event_loop *event_loop,
    struct aws_overlapped *overlapped,
    int status_code,
    size_t num_bytes_transferred) {
    (void)event_loop;
    (void)num_bytes_transferred;

    struct io_operation_data *operation_data = AWS_CONTAINER_OF(overlapped, struct io_operation_data, signal);
    struct aws_socket *socket = overlapped->user_data;

    if (!operation_data->socket) {
        aws_mem_release(operation_data->allocator, operation_data);
        return;
    }

    if (status_code == IO_OPERATION_CANCELLED) {
        operation_data->in_use = false;
        return;
    }

    AWS_LOGF_DEBUG(
        AWS_LS_IO_SOCKET,
        "id=%p handle=%p: named-pipe listening event received",
        (void *)socket,
        (void *)socket->io_handle.data.handle);
    struct iocp_socket *socket_impl = socket->impl;

    if (status_code) {
        if (status_code == IO_PIPE_BROKEN) {
            AWS_LOGF_ERROR(
                AWS_LS_IO_SOCKET,
                "id=%p handle=%p: named-pipe is closed",
                (void *)socket,
                (void *)socket->io_handle.data.handle);
            aws_raise_error(AWS_IO_SOCKET_CLOSED);
            socket->state = CLOSED;
        } else {
            AWS_LOGF_ERROR(
                AWS_LS_IO_SOCKET,
                "id=%p handle=%p: named-pipe error %d",
                (void *)socket,
                (void *)socket->io_handle.data.handle,
                (int)GetLastError());
            aws_raise_error(s_determine_socket_error(status_code));
            socket->state = ERRORED;
        }

        socket_impl->vtable->connection_error(socket, aws_last_error());
        operation_data->in_use = false;
        return;
    }

    bool continue_accept_loop = !socket_impl->stop_accept;

    do {
        AWS_LOGF_DEBUG(
            AWS_LS_IO_SOCKET,
            "id=%p handle=%p: incoming connection",
            (void *)socket,
            (void *)socket->io_handle.data.handle);
        struct aws_socket *new_socket = aws_mem_acquire(socket->allocator, sizeof(struct aws_socket));

        if (!new_socket) {
            socket->state = ERRORED;
            operation_data->in_use = false;
            socket_impl->vtable->connection_error(socket, AWS_ERROR_OOM);
            return;
        }

        if (s_socket_init(new_socket, socket->allocator, &socket->options, false)) {
            aws_mem_release(socket->allocator, new_socket);
            socket->state = ERRORED;
            operation_data->in_use = false;
            socket_impl->vtable->connection_error(socket, aws_last_error());
            return;
        }

        new_socket->state = CONNECTED_WRITE | CONNECTED_READ;

        /* Named pipes don't work like traditional socket APIs. The original handle is used
           for the incoming connection. so we copy it over and do some trickery with the
           event loop registrations. */
        new_socket->io_handle = socket->io_handle;
        aws_event_loop_unsubscribe_from_io_events(event_loop, &new_socket->io_handle);
        new_socket->event_loop = NULL;

        socket->io_handle.data.handle = CreateNamedPipeA(
            socket->local_endpoint.address,
            PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_ACCEPT_REMOTE_CLIENTS,
            PIPE_UNLIMITED_INSTANCES,
            PIPE_BUFFER_SIZE,
            PIPE_BUFFER_SIZE,
            0,
            NULL);

        if (socket->io_handle.data.handle == INVALID_HANDLE_VALUE) {
            AWS_LOGF_ERROR(
                AWS_LS_IO_SOCKET,
                "id=%p handle=%p: error rebinding named pipe with error %d",
                (void *)socket,
                (void *)socket->io_handle.data.handle,
                (int)GetLastError());
            socket->state = ERRORED;
            operation_data->in_use = false;
            socket_impl->vtable->connection_error(socket, aws_last_error());
            return;
        }

        aws_overlapped_init(&socket_impl->read_io_data->signal, s_incoming_pipe_connection_event, socket);
        socket->event_loop = NULL;
        if (aws_socket_assign_to_event_loop(socket, event_loop)) {
            socket->state = ERRORED;
            operation_data->in_use = false;
            aws_socket_clean_up(new_socket);
            socket_impl->vtable->connection_error(socket, aws_last_error());
            return;
        }

        socket->accept_result_fn(socket, AWS_ERROR_SUCCESS, new_socket, socket->connect_accept_user_data);

        if (!operation_data->socket) {
            socket->state = ERRORED;
            operation_data->in_use = false;
            aws_mem_release(operation_data->allocator, operation_data);
            return;
        }

        socket_impl->read_io_data->in_use = true;
        BOOL res = ConnectNamedPipe(
            socket->io_handle.data.handle, aws_overlapped_to_windows_overlapped(&socket_impl->read_io_data->signal));

        continue_accept_loop = false;

        if (!res) {
            int error_code = GetLastError();
            if (error_code != ERROR_IO_PENDING && error_code != ERROR_PIPE_CONNECTED) {
                AWS_LOGF_ERROR(
                    AWS_LS_IO_SOCKET,
                    "id=%p handle=%p: named-pipe connect failed with error %d",
                    (void *)socket,
                    (void *)socket->io_handle.data.handle,
                    (int)GetLastError());
                socket->state = ERRORED;
                socket_impl->read_io_data->in_use = false;
                int aws_err = s_determine_socket_error(error_code);
                socket_impl->vtable->connection_error(socket, aws_err);
                return;
            } else if (error_code == ERROR_PIPE_CONNECTED) {
                continue_accept_loop = true;
            } else {
                AWS_LOGF_TRACE(
                    AWS_LS_IO_SOCKET,
                    "id=%p handle=%p: no pending connections exiting accept loop.",
                    (void *)socket,
                    (void *)socket->io_handle.data.handle);
            }
        }
    } while (continue_accept_loop && !socket_impl->stop_accept);
}