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>
32 static int control_fd
= -1;
34 /* Open the control socket, either in server or client mode */
35 void control_init(const char *control_host
,
36 const char *control_port
,
39 struct addrinfo hints
= {
40 .ai_socktype
= SOCK_STREAM
,
42 struct addrinfo
*result
= NULL
;
46 ret
= getaddrinfo(control_host
, control_port
, &hints
, &result
);
48 fprintf(stderr
, "%s\n", gai_strerror(ret
));
52 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 setsockopt_int_check(fd
, SOL_SOCKET
, SO_REUSEADDR
, 1,
69 "setsockopt SO_REUSEADDR");
71 if (bind(fd
, ai
->ai_addr
, ai
->ai_addrlen
) < 0)
73 if (listen(fd
, 1) < 0)
76 printf("Control socket listening on %s:%s\n",
77 control_host
, control_port
);
80 control_fd
= accept(fd
, NULL
, 0);
87 printf("Control socket connection accepted...\n");
95 fprintf(stderr
, "Control socket initialization failed. Invalid address %s:%s?\n",
96 control_host
, control_port
);
100 freeaddrinfo(result
);
104 void control_cleanup(void)
110 /* Write a line to the control socket */
111 void control_writeln(const char *str
)
113 ssize_t len
= strlen(str
);
116 timeout_begin(TIMEOUT
);
119 ret
= send(control_fd
, str
, len
, MSG_MORE
);
120 timeout_check("send");
121 } while (ret
< 0 && errno
== EINTR
);
129 ret
= send(control_fd
, "\n", 1, 0);
130 timeout_check("send");
131 } while (ret
< 0 && errno
== EINTR
);
141 void control_writeulong(unsigned long value
)
145 if (snprintf(str
, sizeof(str
), "%lu", value
) >= sizeof(str
)) {
150 control_writeln(str
);
153 unsigned long control_readulong(void)
158 str
= control_readln();
163 value
= strtoul(str
, NULL
, 10);
169 /* Return the next line from the control socket (without the trailing newline).
171 * The program terminates if a timeout occurs.
173 * The caller must free() the returned string.
175 char *control_readln(void)
181 timeout_begin(TIMEOUT
);
189 new_buf
= realloc(buf
, buflen
+ 80);
200 ret
= recv(control_fd
, &buf
[idx
], 1, 0);
201 timeout_check("recv");
202 } while (ret
< 0 && errno
== EINTR
);
205 fprintf(stderr
, "unexpected EOF on control socket\n");
214 if (buf
[idx
] == '\n') {
227 /* Wait until a given line is received or a timeout occurs */
228 void control_expectln(const char *str
)
232 line
= control_readln();
234 control_cmpln(line
, str
, true);
239 bool control_cmpln(char *line
, const char *str
, bool fail
)
241 if (strcmp(str
, line
) == 0)
245 fprintf(stderr
, "expected \"%s\" on control socket, got \"%s\"\n",