1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Control socket for client/server test execution
4 * Copyright (C) 2017 Red Hat, Inc.
6 * Author: Stefan Hajnoczi <stefanha@redhat.com>
9 /* The client and server may need to coordinate to avoid race conditions like
10 * the client attempting to connect to a socket that the server is not
11 * listening on yet. The control socket offers a communications channel for
12 * such coordination tasks.
14 * If the client calls control_expectln("LISTENING"), then it will block until
15 * the server calls control_writeln("LISTENING"). This provides a simple
16 * mechanism for coordinating between the client and the server.
25 #include <sys/types.h>
26 #include <sys/socket.h>
31 static int control_fd
= -1;
33 /* Open the control socket, either in server or client mode */
34 void control_init(const char *control_host
,
35 const char *control_port
,
38 struct addrinfo hints
= {
39 .ai_socktype
= SOCK_STREAM
,
41 struct addrinfo
*result
= NULL
;
45 ret
= getaddrinfo(control_host
, control_port
, &hints
, &result
);
47 fprintf(stderr
, "%s\n", gai_strerror(ret
));
51 for (ai
= result
; ai
; ai
= ai
->ai_next
) {
55 fd
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
60 if (connect(fd
, ai
->ai_addr
, ai
->ai_addrlen
) < 0)
63 printf("Control socket connected to %s:%s.\n",
64 control_host
, control_port
);
68 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
69 &val
, sizeof(val
)) < 0) {
74 if (bind(fd
, ai
->ai_addr
, ai
->ai_addrlen
) < 0)
76 if (listen(fd
, 1) < 0)
79 printf("Control socket listening on %s:%s\n",
80 control_host
, control_port
);
83 control_fd
= accept(fd
, NULL
, 0);
90 printf("Control socket connection accepted...\n");
98 fprintf(stderr
, "Control socket initialization failed. Invalid address %s:%s?\n",
99 control_host
, control_port
);
103 freeaddrinfo(result
);
107 void control_cleanup(void)
113 /* Write a line to the control socket */
114 void control_writeln(const char *str
)
116 ssize_t len
= strlen(str
);
119 timeout_begin(TIMEOUT
);
122 ret
= send(control_fd
, str
, len
, MSG_MORE
);
123 timeout_check("send");
124 } while (ret
< 0 && errno
== EINTR
);
132 ret
= send(control_fd
, "\n", 1, 0);
133 timeout_check("send");
134 } while (ret
< 0 && errno
== EINTR
);
144 /* Return the next line from the control socket (without the trailing newline).
146 * The program terminates if a timeout occurs.
148 * The caller must free() the returned string.
150 char *control_readln(void)
156 timeout_begin(TIMEOUT
);
164 new_buf
= realloc(buf
, buflen
+ 80);
175 ret
= recv(control_fd
, &buf
[idx
], 1, 0);
176 timeout_check("recv");
177 } while (ret
< 0 && errno
== EINTR
);
180 fprintf(stderr
, "unexpected EOF on control socket\n");
189 if (buf
[idx
] == '\n') {
202 /* Wait until a given line is received or a timeout occurs */
203 void control_expectln(const char *str
)
207 line
= control_readln();
209 control_cmpln(line
, str
, true);
214 bool control_cmpln(char *line
, const char *str
, bool fail
)
216 if (strcmp(str
, line
) == 0)
220 fprintf(stderr
, "expected \"%s\" on control socket, got \"%s\"\n",