summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@collabora.com>2018-11-15 16:20:09 +0000
committerJakob Bornecrantz <jakob@collabora.com>2018-11-15 18:12:20 +0000
commitd2c0b9b43b4ccf941fa8b79f4242c6caa26eb9a1 (patch)
tree058337d845c1c8133f01542e8b2c4e29517ed99f
parent36117a7cb426343f3e5b3e93c064ae0488b84b95 (diff)
vtest: Refactor vtest_server.cjakob-vtest-refactor
Refactor the main loop into smaller functions so that it is easier to extend with more functionality. There should be no functional change with the exception of some socket listening code would return error codes as fds, where they now instead call perrno and exit(1). Signed-off-by: Jakob Bornecrantz <jakob@collabora.com>
-rw-r--r--vtest/vtest_server.c277
1 files changed, 176 insertions, 101 deletions
diff --git a/vtest/vtest_server.c b/vtest/vtest_server.c
index 578c474..4234de1 100644
--- a/vtest/vtest_server.c
+++ b/vtest/vtest_server.c
@@ -21,7 +21,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
-
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>
@@ -39,55 +38,195 @@
#include "vtest_protocol.h"
-static int vtest_open_socket(const char *path)
+
+struct vtest_program
+{
+ const char *socket_name;
+ int socket;
+ const char *read_file;
+ int out_fd;
+ int in_fd;
+
+ bool do_fork;
+ bool loop;
+};
+
+struct vtest_program prog = {
+ .socket_name = VTEST_DEFAULT_SOCKET_NAME,
+ .socket = -1,
+
+ .read_file = NULL,
+
+ .in_fd = -1,
+ .out_fd = -1,
+ .do_fork = true,
+ .loop = true,
+};
+
+static void vtest_main_parse_args(int argc, char **argv);
+static void vtest_main_set_signal(void);
+static void vtest_main_open_read_file(void);
+static void vtest_main_open_socket(void);
+static void vtest_main_run_renderer(int in_fd, int out_fd);
+static void vtest_main_wait_for_socket_accept(void);
+static void vtest_main_tidy_fds(void);
+static void vtest_main_close_socket(void);
+
+
+int main(int argc, char **argv)
+{
+#ifdef __AFL_LOOP
+while (__AFL_LOOP(1000)) {
+#endif
+
+ vtest_main_parse_args(argc, argv);
+
+ if (prog.read_file != NULL) {
+ vtest_main_open_read_file();
+ goto start;
+ }
+
+ if (prog.do_fork) {
+ vtest_main_set_signal();
+ }
+
+ vtest_main_open_socket();
+restart:
+ vtest_main_wait_for_socket_accept();
+
+start:
+ if (prog.do_fork) {
+ /* fork a renderer process */
+ if (fork() == 0) {
+ vtest_main_run_renderer(prog.in_fd, prog.out_fd);
+ exit(0);
+ }
+ } else {
+ vtest_main_run_renderer(prog.in_fd, prog.out_fd);
+ }
+
+ vtest_main_tidy_fds();
+
+ if (prog.loop) {
+ goto restart;
+ }
+
+ vtest_main_close_socket();
+
+#ifdef __AFL_LOOP
+}
+#endif
+}
+
+static void vtest_main_parse_args(int argc, char **argv)
+{
+ if (argc > 1) {
+ if (!strcmp(argv[1], "--no-loop-or-fork")) {
+ prog.do_fork = false;
+ prog.loop = false;
+ } else if (!strcmp(argv[1], "--no-fork")) {
+ prog.do_fork = false;
+ } else {
+ prog.read_file = argv[1];
+ prog.loop = false;
+ prog.do_fork = false;
+ }
+ }
+}
+
+static void vtest_main_set_signal(void)
+{
+ struct sigaction sa;
+ int ret;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ ret = sigaction(SIGCHLD, &sa, 0);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+}
+
+static void vtest_main_open_read_file(void)
+{
+ int ret;
+
+ ret = open(prog.read_file, O_RDONLY);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+ prog.in_fd = ret;
+
+ ret = open("/dev/null", O_WRONLY);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+ prog.out_fd = ret;
+}
+
+static void vtest_main_open_socket(void)
{
struct sockaddr_un un;
- int sock;
- sock = socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- return -1;
+ prog.socket = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (prog.socket < 0) {
+ goto err;
}
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+ snprintf(un.sun_path, sizeof(un.sun_path), "%s", prog.socket_name);
unlink(un.sun_path);
- if (bind(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
+ if (bind(prog.socket, (struct sockaddr *)&un, sizeof(un)) < 0) {
goto err;
}
- if (listen(sock, 1) < 0){
+ if (listen(prog.socket, 1) < 0){
goto err;
}
- return sock;
+ return;
+
err:
- close(sock);
- return -1;
+ perror("Failed to setup socket.");
+ exit(1);
}
-static int wait_for_socket_accept(int sock)
+static void vtest_main_wait_for_socket_accept(void)
{
fd_set read_fds;
int new_fd;
int ret;
FD_ZERO(&read_fds);
- FD_SET(sock, &read_fds);
+ FD_SET(prog.socket, &read_fds);
- ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
+ ret = select(prog.socket + 1, &read_fds, NULL, NULL, NULL);
if (ret < 0) {
- return ret;
+ perror("Failed to select on socket!");
+ exit(1);
+ }
+
+ if (!FD_ISSET(prog.socket, &read_fds)) {
+ perror("Odd state in fd_set.");
+ exit(1);
}
- if (FD_ISSET(sock, &read_fds)) {
- new_fd = accept(sock, NULL, NULL);
- return new_fd;
+ new_fd = accept(prog.socket, NULL, NULL);
+ if (new_fd < 0) {
+ perror("Failed to accept socket.");
+ exit(1);
}
- return -1;
+
+ prog.in_fd = new_fd;
+ prog.out_fd = new_fd;
}
typedef int (*vtest_cmd_fptr_t)(uint32_t);
@@ -110,7 +249,7 @@ static const vtest_cmd_fptr_t vtest_commands[] = {
vtest_transfer_put2,
};
-static int run_renderer(int in_fd, int out_fd)
+static void vtest_main_run_renderer(int in_fd, int out_fd)
{
int err, ret;
uint32_t header[VTEST_HDR_SIZE];
@@ -164,94 +303,30 @@ static int run_renderer(int in_fd, int out_fd)
fprintf(stderr, "socket failed (%d) - closing renderer\n", err);
vtest_destroy_renderer();
- close(in_fd);
-
- return 0;
}
-int main(int argc, char **argv)
+static void vtest_main_tidy_fds(void)
{
- int ret, sock = -1, in_fd, out_fd;
- pid_t pid;
- bool do_fork = true, loop = true;
- struct sigaction sa;
- char *socket_name = VTEST_DEFAULT_SOCKET_NAME;
-
-#ifdef __AFL_LOOP
-while (__AFL_LOOP(1000)) {
-#endif
-
- if (argc > 1) {
- if (!strcmp(argv[1], "--no-loop-or-fork")) {
- do_fork = false;
- loop = false;
- } else if (!strcmp(argv[1], "--no-fork")) {
- do_fork = false;
- } else {
- ret = open(argv[1], O_RDONLY);
- if (ret == -1) {
- perror(0);
- exit(1);
- }
- in_fd = ret;
- ret = open("/dev/null", O_WRONLY);
- if (ret == -1) {
- perror(0);
- exit(1);
- }
- out_fd = ret;
- loop = false;
- do_fork = false;
- goto start;
- }
+ // out_fd will be closed by the in_fd clause if they are the same.
+ if (prog.out_fd == prog.in_fd) {
+ prog.out_fd = -1;
}
- if (do_fork) {
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- if (sigaction(SIGCHLD, &sa, 0) == -1) {
- perror(0);
- exit(1);
- }
+ if (prog.in_fd != -1) {
+ close(prog.in_fd);
+ prog.in_fd = -1;
}
- sock = vtest_open_socket(socket_name);
-restart:
- in_fd = wait_for_socket_accept(sock);
- out_fd = in_fd;
-
-start:
- if (do_fork) {
- /* fork a renderer process */
- switch ((pid = fork())) {
- case 0:
- run_renderer(in_fd, out_fd);
- exit(0);
- break;
- case -1:
- default:
- close(in_fd);
- if (loop) {
- goto restart;
- }
- }
- } else {
- run_renderer(in_fd, out_fd);
- vtest_destroy_renderer();
- if (loop) {
- goto restart;
- }
+ if (prog.out_fd != -1) {
+ close(prog.out_fd);
+ prog.out_fd = -1;
}
+}
- if (sock != -1) {
- close(sock);
- }
- if (in_fd != out_fd) {
- close(out_fd);
+static void vtest_main_close_socket(void)
+{
+ if (prog.socket != -1) {
+ close(prog.socket);
+ prog.socket = -1;
}
-
-#ifdef __AFL_LOOP
-}
-#endif
}