// SPDX-License-Identifier: GPL-2.0-only
/* Control socket for client/server test execution
 *
 * Copyright (C) 2017 Red Hat, Inc.
 *
 * Author: Stefan Hajnoczi <stefanha@redhat.com>
 */

/* The client and server may need to coordinate to avoid race conditions like
 * the client attempting to connect to a socket that the server is not
 * listening on yet.  The control socket offers a communications channel for
 * such coordination tasks.
 *
 * If the client calls control_expectln("LISTENING"), then it will block until
 * the server calls control_writeln("LISTENING").  This provides a simple
 * mechanism for coordinating between the client and the server.
 */

#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "timeout.h"
#include "control.h"

static int control_fd = -1;

/* Open the control socket, either in server or client mode */
void control_init(const char *control_host,
		  const char *control_port,
		  bool server)
{
	struct addrinfo hints = {
		.ai_socktype = SOCK_STREAM,
	};
	struct addrinfo *result = NULL;
	struct addrinfo *ai;
	int ret;

	ret = getaddrinfo(control_host, control_port, &hints, &result);
	if (ret != 0) {
		fprintf(stderr, "%s\n", gai_strerror(ret));
		exit(EXIT_FAILURE);
	}

	for (ai = result; ai; ai = ai->ai_next) {
		int fd;
		int val = 1;

		fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (fd < 0)
			continue;

		if (!server) {
			if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0)
				goto next;
			control_fd = fd;
			printf("Control socket connected to %s:%s.\n",
			       control_host, control_port);
			break;
		}

		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
			       &val, sizeof(val)) < 0) {
			perror("setsockopt");
			exit(EXIT_FAILURE);
		}

		if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
			goto next;
		if (listen(fd, 1) < 0)
			goto next;

		printf("Control socket listening on %s:%s\n",
		       control_host, control_port);
		fflush(stdout);

		control_fd = accept(fd, NULL, 0);
		close(fd);

		if (control_fd < 0) {
			perror("accept");
			exit(EXIT_FAILURE);
		}
		printf("Control socket connection accepted...\n");
		break;

next:
		close(fd);
	}

	if (control_fd < 0) {
		fprintf(stderr, "Control socket initialization failed.  Invalid address %s:%s?\n",
			control_host, control_port);
		exit(EXIT_FAILURE);
	}

	freeaddrinfo(result);
}

/* Free resources */
void control_cleanup(void)
{
	close(control_fd);
	control_fd = -1;
}

/* Write a line to the control socket */
void control_writeln(const char *str)
{
	ssize_t len = strlen(str);
	ssize_t ret;

	timeout_begin(TIMEOUT);

	do {
		ret = send(control_fd, str, len, MSG_MORE);
		timeout_check("send");
	} while (ret < 0 && errno == EINTR);

	if (ret != len) {
		perror("send");
		exit(EXIT_FAILURE);
	}

	do {
		ret = send(control_fd, "\n", 1, 0);
		timeout_check("send");
	} while (ret < 0 && errno == EINTR);

	if (ret != 1) {
		perror("send");
		exit(EXIT_FAILURE);
	}

	timeout_end();
}

void control_writeulong(unsigned long value)
{
	char str[32];

	if (snprintf(str, sizeof(str), "%lu", value) >= sizeof(str)) {
		perror("snprintf");
		exit(EXIT_FAILURE);
	}

	control_writeln(str);
}

unsigned long control_readulong(void)
{
	unsigned long value;
	char *str;

	str = control_readln();

	if (!str)
		exit(EXIT_FAILURE);

	value = strtoul(str, NULL, 10);
	free(str);

	return value;
}

/* Return the next line from the control socket (without the trailing newline).
 *
 * The program terminates if a timeout occurs.
 *
 * The caller must free() the returned string.
 */
char *control_readln(void)
{
	char *buf = NULL;
	size_t idx = 0;
	size_t buflen = 0;

	timeout_begin(TIMEOUT);

	for (;;) {
		ssize_t ret;

		if (idx >= buflen) {
			char *new_buf;

			new_buf = realloc(buf, buflen + 80);
			if (!new_buf) {
				perror("realloc");
				exit(EXIT_FAILURE);
			}

			buf = new_buf;
			buflen += 80;
		}

		do {
			ret = recv(control_fd, &buf[idx], 1, 0);
			timeout_check("recv");
		} while (ret < 0 && errno == EINTR);

		if (ret == 0) {
			fprintf(stderr, "unexpected EOF on control socket\n");
			exit(EXIT_FAILURE);
		}

		if (ret != 1) {
			perror("recv");
			exit(EXIT_FAILURE);
		}

		if (buf[idx] == '\n') {
			buf[idx] = '\0';
			break;
		}

		idx++;
	}

	timeout_end();

	return buf;
}

/* Wait until a given line is received or a timeout occurs */
void control_expectln(const char *str)
{
	char *line;

	line = control_readln();

	control_cmpln(line, str, true);

	free(line);
}

bool control_cmpln(char *line, const char *str, bool fail)
{
	if (strcmp(str, line) == 0)
		return true;

	if (fail) {
		fprintf(stderr, "expected \"%s\" on control socket, got \"%s\"\n",
			str, line);
		exit(EXIT_FAILURE);
	}

	return false;
}
