^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Control socket for client/server test execution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2017 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Stefan Hajnoczi <stefanha@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /* The client and server may need to coordinate to avoid race conditions like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the client attempting to connect to a socket that the server is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * listening on yet. The control socket offers a communications channel for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * such coordination tasks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * If the client calls control_expectln("LISTENING"), then it will block until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * the server calls control_writeln("LISTENING"). This provides a simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * mechanism for coordinating between the client and the server.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <netdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sys/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "timeout.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "control.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int control_fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Open the control socket, either in server or client mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void control_init(const char *control_host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) const char *control_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) bool server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct addrinfo hints = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .ai_socktype = SOCK_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct addrinfo *result = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct addrinfo *ai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = getaddrinfo(control_host, control_port, &hints, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) fprintf(stderr, "%s\n", gai_strerror(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) for (ai = result; ai; ai = ai->ai_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int val = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) control_fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) printf("Control socket connected to %s:%s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) control_host, control_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) &val, sizeof(val)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) perror("setsockopt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (listen(fd, 1) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) printf("Control socket listening on %s:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) control_host, control_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) control_fd = accept(fd, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (control_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) perror("accept");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) printf("Control socket connection accepted...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (control_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) fprintf(stderr, "Control socket initialization failed. Invalid address %s:%s?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) control_host, control_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) freeaddrinfo(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Free resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) void control_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) close(control_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) control_fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Write a line to the control socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void control_writeln(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ssize_t len = strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) timeout_begin(TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ret = send(control_fd, str, len, MSG_MORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) timeout_check("send");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) } while (ret < 0 && errno == EINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (ret != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) perror("send");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = send(control_fd, "\n", 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) timeout_check("send");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } while (ret < 0 && errno == EINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (ret != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) perror("send");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) timeout_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Return the next line from the control socket (without the trailing newline).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * The program terminates if a timeout occurs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * The caller must free() the returned string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) char *control_readln(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) char *buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) size_t idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) size_t buflen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) timeout_begin(TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (idx >= buflen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) char *new_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) new_buf = realloc(buf, buflen + 80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!new_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) perror("realloc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) buf = new_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) buflen += 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = recv(control_fd, &buf[idx], 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) timeout_check("recv");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) } while (ret < 0 && errno == EINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fprintf(stderr, "unexpected EOF on control socket\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ret != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) perror("recv");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (buf[idx] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) buf[idx] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) timeout_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Wait until a given line is received or a timeout occurs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) void control_expectln(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) char *line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) line = control_readln();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) control_cmpln(line, str, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bool control_cmpln(char *line, const char *str, bool fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (strcmp(str, line) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (fail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) fprintf(stderr, "expected \"%s\" on control socket, got \"%s\"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) str, line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }