// Servidor TCP de conteo con un proceso por cliente.
//   wc_fork_server <puerto>
#define _POSIX_C_SOURCE 200809L

#include "io_util.h"
#include "wc_service.h"

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "uso: %s <puerto>\n", argv[0]);
        return EXIT_FAILURE;
    }

    // Ignorar SIGCHLD: el kernel recoge a los hijos y no quedan zombis.
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = 0;
    if (sigemptyset(&sa.sa_mask) == -1 || sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        return EXIT_FAILURE;
    }

    int listener = tcp_listen(parse_port(argv[1]));
    if (listener == -1 || print_bound_port(listener) == -1) {
        return EXIT_FAILURE;
    }

    for (;;) {
        int conn = accept(listener, NULL, NULL);
        if (conn == -1) {
            perror("accept");
            continue;
        }
        pid_t pid = fork();
        if (pid == -1) {
            perror("fork");
            close_checked(conn);
            continue;
        }
        if (pid == 0) {
            // Hijo: solo necesita la conexión.
            close_checked(listener);
            int rc = wc_serve_client(conn);
            close_checked(conn);
            _exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
        }
        // Padre: solo necesita el socket que escucha.
        close_checked(conn);
    }
}
