// Envía datagramas UDP numerados.
//   seq_send <ip> <puerto> <cantidad> <tamaño> <pausa_us>
// Formato: número de secuencia de 4 bytes en orden de red, y relleno.
#define _POSIX_C_SOURCE 200809L

#include "io_util.h"

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>

#define MAX_DATAGRAM 1400

int main(int argc, char *argv[]) {
    if (argc != 6) {
        fprintf(stderr, "uso: %s <ip> <puerto> <cantidad> <tamaño> <pausa_us>\n", argv[0]);
        return EXIT_FAILURE;
    }
    long count = strtol(argv[3], NULL, 10);
    long size = strtol(argv[4], NULL, 10);
    long gap_us = strtol(argv[5], NULL, 10);
    if (count <= 0 || size < 4 || size > MAX_DATAGRAM || gap_us < 0) {
        fprintf(stderr, "valores fuera de rango\n");
        return EXIT_FAILURE;
    }
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(parse_port(argv[2]));
    if (inet_pton(AF_INET, argv[1], &addr.sin_addr) != 1) {
        fprintf(stderr, "dirección no válida: %s\n", argv[1]);
        return EXIT_FAILURE;
    }
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1) {
        perror("socket");
        return EXIT_FAILURE;
    }

    char packet[MAX_DATAGRAM];
    memset(packet, 'x', sizeof packet);
    for (long i = 0; i < count; i++) {
        uint32_t seq = htonl((uint32_t)i);
        memcpy(packet, &seq, sizeof seq);
        if (sendto(fd, packet, (size_t)size, 0,
                   (struct sockaddr *)&addr, sizeof addr) == -1) {
            perror("sendto");
            return EXIT_FAILURE;
        }
        if (gap_us > 0) {
            struct timespec pause = {gap_us / 1000000, (gap_us % 1000000) * 1000L};
            if (nanosleep(&pause, NULL) == -1) {
                perror("nanosleep");
            }
        }
    }
    printf("enviados: %ld datagramas de %ld bytes\n", count, size);
    close_checked(fd);
    return EXIT_SUCCESS;
}
