Contributors: 1
	  
        
          | Author | 
          Tokens | 
          Token Proportion | 
          Commits | 
          Commit Proportion | 
        
	  
	  
        
        
          | Florian Westphal | 
          536 | 
          100.00% | 
          1 | 
          100.00% | 
        
	  
	  
        
          | Total | 
          536 | 
           | 
          1 | 
           | 
	    
	  
    
 
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 12345
#define RUNTIME 10
static struct {
	unsigned int timeout;
	unsigned int port;
} opts = {
	.timeout = RUNTIME,
	.port = PORT,
};
static void handler(int sig)
{
	_exit(sig == SIGALRM ? 0 : 1);
}
static void set_timeout(void)
{
	struct sigaction action = {
		.sa_handler = handler,
	};
	sigaction(SIGALRM, &action, NULL);
	alarm(opts.timeout);
}
static void do_connect(const struct sockaddr_in *dst)
{
	int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s >= 0)
		fcntl(s, F_SETFL, O_NONBLOCK);
	connect(s, (struct sockaddr *)dst, sizeof(*dst));
	close(s);
}
static void do_accept(const struct sockaddr_in *src)
{
	int c, one = 1, s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s < 0)
		return;
	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
	setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
	bind(s, (struct sockaddr *)src, sizeof(*src));
	listen(s, 16);
	c = accept(s, NULL, NULL);
	if (c >= 0)
		close(c);
	close(s);
}
static int accept_loop(void)
{
	struct sockaddr_in src = {
		.sin_family = AF_INET,
		.sin_port = htons(opts.port),
	};
	inet_pton(AF_INET, "127.0.0.1", &src.sin_addr);
	set_timeout();
	for (;;)
		do_accept(&src);
	return 1;
}
static int connect_loop(void)
{
	struct sockaddr_in dst = {
		.sin_family = AF_INET,
		.sin_port = htons(opts.port),
	};
	inet_pton(AF_INET, "127.0.0.1", &dst.sin_addr);
	set_timeout();
	for (;;)
		do_connect(&dst);
	return 1;
}
static void parse_opts(int argc, char **argv)
{
	int c;
	while ((c = getopt(argc, argv, "t:p:")) != -1) {
		switch (c) {
		case 't':
			opts.timeout = atoi(optarg);
			break;
		case 'p':
			opts.port = atoi(optarg);
			break;
		}
	}
}
int main(int argc, char *argv[])
{
	pid_t p;
	parse_opts(argc, argv);
	p = fork();
	if (p < 0)
		return 111;
	if (p > 0)
		return accept_loop();
	return connect_loop();
}