/*
 * DF-3462: minimal UDP receiver. Binds 0.0.0.0:<port>, prints one line per
 * received datagram, exits after <secs> seconds.
 * usage: udprx <port> <secs>
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

int
main(int argc, char **argv)
{
	struct sockaddr_in bindaddr, from;
	socklen_t fromlen;
	char buf[512];
	int s, n, secs;
	time_t t0;

	if (argc < 3) {
		fprintf(stderr, "usage: %s <port> <secs>\n", argv[0]);
		return (2);
	}
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		perror("socket");
		return (2);
	}
	n = 1;
	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) {
		perror("setsockopt");
		return (2);
	}
	memset(&bindaddr, 0, sizeof(bindaddr));
	bindaddr.sin_family = AF_INET;
	bindaddr.sin_port = htons((u_short)atoi(argv[1]));
	bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
		perror("bind");
		return (2);
	}
	secs = atoi(argv[2]);
	struct timeval tv;

	tv.tv_sec = 1;
	tv.tv_usec = 0;
	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
		perror("setsockopt");
		return (2);
	}
	t0 = time(NULL);
	for (;;) {
		if (time(NULL) - t0 >= secs)
			break;
		fromlen = sizeof(from);
		n = recvfrom(s, buf, sizeof(buf) - 1, 0,
		    (struct sockaddr *)&from, &fromlen);
		if (n < 0) {
			if (errno == EINTR)
				continue;
			perror("recvfrom");
			return (1);
		}
		buf[n] = '\0';
		printf("RECV from %s: %s\n", inet_ntoa(from.sin_addr), buf);
		fflush(stdout);
	}
	printf("udprx: done\n");
	return (0);
}
