1*bbecb9d1SAndroid Build Coastguard Worker /**************************************************************************
2*bbecb9d1SAndroid Build Coastguard Worker *
3*bbecb9d1SAndroid Build Coastguard Worker * Copyright (C) 2015 Red Hat Inc.
4*bbecb9d1SAndroid Build Coastguard Worker *
5*bbecb9d1SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*bbecb9d1SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*bbecb9d1SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*bbecb9d1SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*bbecb9d1SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*bbecb9d1SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*bbecb9d1SAndroid Build Coastguard Worker *
12*bbecb9d1SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included
13*bbecb9d1SAndroid Build Coastguard Worker * in all copies or substantial portions of the Software.
14*bbecb9d1SAndroid Build Coastguard Worker *
15*bbecb9d1SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16*bbecb9d1SAndroid Build Coastguard Worker * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*bbecb9d1SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*bbecb9d1SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19*bbecb9d1SAndroid Build Coastguard Worker * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20*bbecb9d1SAndroid Build Coastguard Worker * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21*bbecb9d1SAndroid Build Coastguard Worker * OTHER DEALINGS IN THE SOFTWARE.
22*bbecb9d1SAndroid Build Coastguard Worker *
23*bbecb9d1SAndroid Build Coastguard Worker **************************************************************************/
24*bbecb9d1SAndroid Build Coastguard Worker
25*bbecb9d1SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
26*bbecb9d1SAndroid Build Coastguard Worker #include "config.h"
27*bbecb9d1SAndroid Build Coastguard Worker #endif
28*bbecb9d1SAndroid Build Coastguard Worker
29*bbecb9d1SAndroid Build Coastguard Worker #include <stdio.h>
30*bbecb9d1SAndroid Build Coastguard Worker #include <signal.h>
31*bbecb9d1SAndroid Build Coastguard Worker #include <stdbool.h>
32*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
33*bbecb9d1SAndroid Build Coastguard Worker #include <stdlib.h>
34*bbecb9d1SAndroid Build Coastguard Worker #include <sys/types.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <sys/socket.h>
36*bbecb9d1SAndroid Build Coastguard Worker #include <netinet/in.h>
37*bbecb9d1SAndroid Build Coastguard Worker #include <sys/un.h>
38*bbecb9d1SAndroid Build Coastguard Worker #include <fcntl.h>
39*bbecb9d1SAndroid Build Coastguard Worker #include <getopt.h>
40*bbecb9d1SAndroid Build Coastguard Worker #include <string.h>
41*bbecb9d1SAndroid Build Coastguard Worker
42*bbecb9d1SAndroid Build Coastguard Worker #include "util.h"
43*bbecb9d1SAndroid Build Coastguard Worker #include "util/u_double_list.h"
44*bbecb9d1SAndroid Build Coastguard Worker #include "util/u_math.h"
45*bbecb9d1SAndroid Build Coastguard Worker #include "util/u_memory.h"
46*bbecb9d1SAndroid Build Coastguard Worker #include "vtest.h"
47*bbecb9d1SAndroid Build Coastguard Worker #include "vtest_protocol.h"
48*bbecb9d1SAndroid Build Coastguard Worker #include "virglrenderer.h"
49*bbecb9d1SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
50*bbecb9d1SAndroid Build Coastguard Worker #include <sys/select.h>
51*bbecb9d1SAndroid Build Coastguard Worker #endif
52*bbecb9d1SAndroid Build Coastguard Worker
53*bbecb9d1SAndroid Build Coastguard Worker enum vtest_client_error {
54*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_INPUT_READ = 2, /* for backward compatibility */
55*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_CONTEXT_MISSING,
56*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_CONTEXT_FAILED,
57*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_COMMAND_ID,
58*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_COMMAND_UNEXPECTED,
59*bbecb9d1SAndroid Build Coastguard Worker VTEST_CLIENT_ERROR_COMMAND_DISPATCH,
60*bbecb9d1SAndroid Build Coastguard Worker };
61*bbecb9d1SAndroid Build Coastguard Worker
62*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client
63*bbecb9d1SAndroid Build Coastguard Worker {
64*bbecb9d1SAndroid Build Coastguard Worker int in_fd;
65*bbecb9d1SAndroid Build Coastguard Worker int out_fd;
66*bbecb9d1SAndroid Build Coastguard Worker struct vtest_input input;
67*bbecb9d1SAndroid Build Coastguard Worker
68*bbecb9d1SAndroid Build Coastguard Worker struct list_head head;
69*bbecb9d1SAndroid Build Coastguard Worker
70*bbecb9d1SAndroid Build Coastguard Worker bool in_fd_ready;
71*bbecb9d1SAndroid Build Coastguard Worker struct vtest_context *context;
72*bbecb9d1SAndroid Build Coastguard Worker int context_poll_fd;
73*bbecb9d1SAndroid Build Coastguard Worker bool context_need_poll;
74*bbecb9d1SAndroid Build Coastguard Worker };
75*bbecb9d1SAndroid Build Coastguard Worker
76*bbecb9d1SAndroid Build Coastguard Worker struct vtest_server
77*bbecb9d1SAndroid Build Coastguard Worker {
78*bbecb9d1SAndroid Build Coastguard Worker const char *socket_name;
79*bbecb9d1SAndroid Build Coastguard Worker int socket;
80*bbecb9d1SAndroid Build Coastguard Worker const char *read_file;
81*bbecb9d1SAndroid Build Coastguard Worker
82*bbecb9d1SAndroid Build Coastguard Worker const char *render_device;
83*bbecb9d1SAndroid Build Coastguard Worker
84*bbecb9d1SAndroid Build Coastguard Worker bool main_server;
85*bbecb9d1SAndroid Build Coastguard Worker bool do_fork;
86*bbecb9d1SAndroid Build Coastguard Worker bool loop;
87*bbecb9d1SAndroid Build Coastguard Worker bool multi_clients;
88*bbecb9d1SAndroid Build Coastguard Worker
89*bbecb9d1SAndroid Build Coastguard Worker bool use_glx;
90*bbecb9d1SAndroid Build Coastguard Worker bool use_egl_surfaceless;
91*bbecb9d1SAndroid Build Coastguard Worker bool use_gles;
92*bbecb9d1SAndroid Build Coastguard Worker
93*bbecb9d1SAndroid Build Coastguard Worker bool venus;
94*bbecb9d1SAndroid Build Coastguard Worker bool render_server;
95*bbecb9d1SAndroid Build Coastguard Worker
96*bbecb9d1SAndroid Build Coastguard Worker int ctx_flags;
97*bbecb9d1SAndroid Build Coastguard Worker
98*bbecb9d1SAndroid Build Coastguard Worker struct list_head new_clients;
99*bbecb9d1SAndroid Build Coastguard Worker struct list_head active_clients;
100*bbecb9d1SAndroid Build Coastguard Worker struct list_head inactive_clients;
101*bbecb9d1SAndroid Build Coastguard Worker };
102*bbecb9d1SAndroid Build Coastguard Worker
103*bbecb9d1SAndroid Build Coastguard Worker struct vtest_server server = {
104*bbecb9d1SAndroid Build Coastguard Worker .socket_name = VTEST_DEFAULT_SOCKET_NAME,
105*bbecb9d1SAndroid Build Coastguard Worker .socket = -1,
106*bbecb9d1SAndroid Build Coastguard Worker
107*bbecb9d1SAndroid Build Coastguard Worker .read_file = NULL,
108*bbecb9d1SAndroid Build Coastguard Worker
109*bbecb9d1SAndroid Build Coastguard Worker .render_device = 0,
110*bbecb9d1SAndroid Build Coastguard Worker
111*bbecb9d1SAndroid Build Coastguard Worker .main_server = true,
112*bbecb9d1SAndroid Build Coastguard Worker .do_fork = true,
113*bbecb9d1SAndroid Build Coastguard Worker .loop = true,
114*bbecb9d1SAndroid Build Coastguard Worker .multi_clients = false,
115*bbecb9d1SAndroid Build Coastguard Worker
116*bbecb9d1SAndroid Build Coastguard Worker .ctx_flags = 0,
117*bbecb9d1SAndroid Build Coastguard Worker };
118*bbecb9d1SAndroid Build Coastguard Worker
119*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_getenv(void);
120*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_parse_args(int argc, char **argv);
121*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_set_signal_child(void);
122*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_set_signal_segv(void);
123*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_open_read_file(void);
124*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_open_socket(void);
125*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_run(void);
126*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_close_socket(void);
127*bbecb9d1SAndroid Build Coastguard Worker static int vtest_client_dispatch_commands(struct vtest_client *client);
128*bbecb9d1SAndroid Build Coastguard Worker
129*bbecb9d1SAndroid Build Coastguard Worker
main(int argc,char ** argv)130*bbecb9d1SAndroid Build Coastguard Worker int main(int argc, char **argv)
131*bbecb9d1SAndroid Build Coastguard Worker {
132*bbecb9d1SAndroid Build Coastguard Worker #ifdef __AFL_LOOP
133*bbecb9d1SAndroid Build Coastguard Worker while (__AFL_LOOP(1000)) {
134*bbecb9d1SAndroid Build Coastguard Worker #endif
135*bbecb9d1SAndroid Build Coastguard Worker
136*bbecb9d1SAndroid Build Coastguard Worker vtest_server_getenv();
137*bbecb9d1SAndroid Build Coastguard Worker vtest_server_parse_args(argc, argv);
138*bbecb9d1SAndroid Build Coastguard Worker
139*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.new_clients);
140*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.active_clients);
141*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.inactive_clients);
142*bbecb9d1SAndroid Build Coastguard Worker
143*bbecb9d1SAndroid Build Coastguard Worker if (server.do_fork) {
144*bbecb9d1SAndroid Build Coastguard Worker vtest_server_set_signal_child();
145*bbecb9d1SAndroid Build Coastguard Worker } else {
146*bbecb9d1SAndroid Build Coastguard Worker vtest_server_set_signal_segv();
147*bbecb9d1SAndroid Build Coastguard Worker }
148*bbecb9d1SAndroid Build Coastguard Worker
149*bbecb9d1SAndroid Build Coastguard Worker vtest_server_run();
150*bbecb9d1SAndroid Build Coastguard Worker
151*bbecb9d1SAndroid Build Coastguard Worker #ifdef __AFL_LOOP
152*bbecb9d1SAndroid Build Coastguard Worker if (!server.main_server) {
153*bbecb9d1SAndroid Build Coastguard Worker exit(0);
154*bbecb9d1SAndroid Build Coastguard Worker }
155*bbecb9d1SAndroid Build Coastguard Worker }
156*bbecb9d1SAndroid Build Coastguard Worker #endif
157*bbecb9d1SAndroid Build Coastguard Worker }
158*bbecb9d1SAndroid Build Coastguard Worker
159*bbecb9d1SAndroid Build Coastguard Worker #define OPT_NO_FORK 'f'
160*bbecb9d1SAndroid Build Coastguard Worker #define OPT_NO_LOOP_OR_FORK 'l'
161*bbecb9d1SAndroid Build Coastguard Worker #define OPT_MULTI_CLIENTS 'm'
162*bbecb9d1SAndroid Build Coastguard Worker #define OPT_USE_GLX 'x'
163*bbecb9d1SAndroid Build Coastguard Worker #define OPT_USE_EGL_SURFACELESS 's'
164*bbecb9d1SAndroid Build Coastguard Worker #define OPT_USE_GLES 'e'
165*bbecb9d1SAndroid Build Coastguard Worker #define OPT_RENDERNODE 'r'
166*bbecb9d1SAndroid Build Coastguard Worker #define OPT_VENUS 'v'
167*bbecb9d1SAndroid Build Coastguard Worker #define OPT_RENDER_SERVER 'n'
168*bbecb9d1SAndroid Build Coastguard Worker #define OPT_SOCKET_PATH 'p'
169*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_parse_args(int argc,char ** argv)170*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_parse_args(int argc, char **argv)
171*bbecb9d1SAndroid Build Coastguard Worker {
172*bbecb9d1SAndroid Build Coastguard Worker int ret;
173*bbecb9d1SAndroid Build Coastguard Worker
174*bbecb9d1SAndroid Build Coastguard Worker static struct option long_options[] = {
175*bbecb9d1SAndroid Build Coastguard Worker {"no-fork", no_argument, NULL, OPT_NO_FORK},
176*bbecb9d1SAndroid Build Coastguard Worker {"no-loop-or-fork", no_argument, NULL, OPT_NO_LOOP_OR_FORK},
177*bbecb9d1SAndroid Build Coastguard Worker {"multi-clients", no_argument, NULL, OPT_MULTI_CLIENTS},
178*bbecb9d1SAndroid Build Coastguard Worker {"use-glx", no_argument, NULL, OPT_USE_GLX},
179*bbecb9d1SAndroid Build Coastguard Worker {"use-egl-surfaceless", no_argument, NULL, OPT_USE_EGL_SURFACELESS},
180*bbecb9d1SAndroid Build Coastguard Worker {"use-gles", no_argument, NULL, OPT_USE_GLES},
181*bbecb9d1SAndroid Build Coastguard Worker {"rendernode", required_argument, NULL, OPT_RENDERNODE},
182*bbecb9d1SAndroid Build Coastguard Worker {"venus", no_argument, NULL, OPT_VENUS},
183*bbecb9d1SAndroid Build Coastguard Worker {"render-server", no_argument, NULL, OPT_RENDER_SERVER},
184*bbecb9d1SAndroid Build Coastguard Worker {"socket-path", optional_argument, NULL, OPT_SOCKET_PATH},
185*bbecb9d1SAndroid Build Coastguard Worker {0, 0, 0, 0}
186*bbecb9d1SAndroid Build Coastguard Worker };
187*bbecb9d1SAndroid Build Coastguard Worker
188*bbecb9d1SAndroid Build Coastguard Worker /* getopt_long stores the option index here. */
189*bbecb9d1SAndroid Build Coastguard Worker int option_index = 0;
190*bbecb9d1SAndroid Build Coastguard Worker
191*bbecb9d1SAndroid Build Coastguard Worker do {
192*bbecb9d1SAndroid Build Coastguard Worker ret = getopt_long(argc, argv, "", long_options, &option_index);
193*bbecb9d1SAndroid Build Coastguard Worker
194*bbecb9d1SAndroid Build Coastguard Worker switch (ret) {
195*bbecb9d1SAndroid Build Coastguard Worker case -1:
196*bbecb9d1SAndroid Build Coastguard Worker break;
197*bbecb9d1SAndroid Build Coastguard Worker case OPT_NO_FORK:
198*bbecb9d1SAndroid Build Coastguard Worker server.do_fork = false;
199*bbecb9d1SAndroid Build Coastguard Worker break;
200*bbecb9d1SAndroid Build Coastguard Worker case OPT_NO_LOOP_OR_FORK:
201*bbecb9d1SAndroid Build Coastguard Worker server.do_fork = false;
202*bbecb9d1SAndroid Build Coastguard Worker server.loop = false;
203*bbecb9d1SAndroid Build Coastguard Worker break;
204*bbecb9d1SAndroid Build Coastguard Worker case OPT_MULTI_CLIENTS:
205*bbecb9d1SAndroid Build Coastguard Worker printf("multi-clients enabled: clients must trust each other\n");
206*bbecb9d1SAndroid Build Coastguard Worker server.multi_clients = true;
207*bbecb9d1SAndroid Build Coastguard Worker break;
208*bbecb9d1SAndroid Build Coastguard Worker case OPT_USE_GLX:
209*bbecb9d1SAndroid Build Coastguard Worker server.use_glx = true;
210*bbecb9d1SAndroid Build Coastguard Worker break;
211*bbecb9d1SAndroid Build Coastguard Worker case OPT_USE_EGL_SURFACELESS:
212*bbecb9d1SAndroid Build Coastguard Worker server.use_egl_surfaceless = true;
213*bbecb9d1SAndroid Build Coastguard Worker break;
214*bbecb9d1SAndroid Build Coastguard Worker case OPT_USE_GLES:
215*bbecb9d1SAndroid Build Coastguard Worker server.use_gles = true;
216*bbecb9d1SAndroid Build Coastguard Worker break;
217*bbecb9d1SAndroid Build Coastguard Worker case OPT_RENDERNODE:
218*bbecb9d1SAndroid Build Coastguard Worker server.render_device = optarg;
219*bbecb9d1SAndroid Build Coastguard Worker break;
220*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_VENUS
221*bbecb9d1SAndroid Build Coastguard Worker case OPT_VENUS:
222*bbecb9d1SAndroid Build Coastguard Worker server.venus = true;
223*bbecb9d1SAndroid Build Coastguard Worker break;
224*bbecb9d1SAndroid Build Coastguard Worker #endif
225*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_RENDER_SERVER
226*bbecb9d1SAndroid Build Coastguard Worker case OPT_RENDER_SERVER:
227*bbecb9d1SAndroid Build Coastguard Worker server.render_server = true;
228*bbecb9d1SAndroid Build Coastguard Worker break;
229*bbecb9d1SAndroid Build Coastguard Worker #endif
230*bbecb9d1SAndroid Build Coastguard Worker case OPT_SOCKET_PATH:
231*bbecb9d1SAndroid Build Coastguard Worker server.socket_name = optarg;
232*bbecb9d1SAndroid Build Coastguard Worker break;
233*bbecb9d1SAndroid Build Coastguard Worker default:
234*bbecb9d1SAndroid Build Coastguard Worker printf("Usage: %s [--no-fork] [--no-loop-or-fork] [--multi-clients] "
235*bbecb9d1SAndroid Build Coastguard Worker "[--use-glx] [--use-egl-surfaceless] [--use-gles] "
236*bbecb9d1SAndroid Build Coastguard Worker "[--rendernode <dev>] [--socket-path <path>] "
237*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_VENUS
238*bbecb9d1SAndroid Build Coastguard Worker " [--venus]"
239*bbecb9d1SAndroid Build Coastguard Worker #endif
240*bbecb9d1SAndroid Build Coastguard Worker #ifdef ENABLE_RENDER_SERVER
241*bbecb9d1SAndroid Build Coastguard Worker " [--render-server]"
242*bbecb9d1SAndroid Build Coastguard Worker #endif
243*bbecb9d1SAndroid Build Coastguard Worker " [file]\n", argv[0]);
244*bbecb9d1SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
245*bbecb9d1SAndroid Build Coastguard Worker break;
246*bbecb9d1SAndroid Build Coastguard Worker }
247*bbecb9d1SAndroid Build Coastguard Worker
248*bbecb9d1SAndroid Build Coastguard Worker } while (ret >= 0);
249*bbecb9d1SAndroid Build Coastguard Worker
250*bbecb9d1SAndroid Build Coastguard Worker if (optind < argc) {
251*bbecb9d1SAndroid Build Coastguard Worker server.read_file = argv[optind];
252*bbecb9d1SAndroid Build Coastguard Worker server.loop = false;
253*bbecb9d1SAndroid Build Coastguard Worker server.do_fork = false;
254*bbecb9d1SAndroid Build Coastguard Worker server.multi_clients = false;
255*bbecb9d1SAndroid Build Coastguard Worker }
256*bbecb9d1SAndroid Build Coastguard Worker
257*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags = VIRGL_RENDERER_USE_EGL;
258*bbecb9d1SAndroid Build Coastguard Worker if (server.use_glx) {
259*bbecb9d1SAndroid Build Coastguard Worker if (server.use_egl_surfaceless || server.use_gles) {
260*bbecb9d1SAndroid Build Coastguard Worker fprintf(stderr, "Cannot use surfaceless or GLES with GLX.\n");
261*bbecb9d1SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
262*bbecb9d1SAndroid Build Coastguard Worker }
263*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags = VIRGL_RENDERER_USE_GLX;
264*bbecb9d1SAndroid Build Coastguard Worker } else {
265*bbecb9d1SAndroid Build Coastguard Worker if (server.use_egl_surfaceless)
266*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags |= VIRGL_RENDERER_USE_SURFACELESS;
267*bbecb9d1SAndroid Build Coastguard Worker if (server.use_gles)
268*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags |= VIRGL_RENDERER_USE_GLES;
269*bbecb9d1SAndroid Build Coastguard Worker }
270*bbecb9d1SAndroid Build Coastguard Worker
271*bbecb9d1SAndroid Build Coastguard Worker if (server.venus) {
272*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags |= VIRGL_RENDERER_VENUS;
273*bbecb9d1SAndroid Build Coastguard Worker }
274*bbecb9d1SAndroid Build Coastguard Worker if (server.render_server) {
275*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags |= VIRGL_RENDERER_RENDER_SERVER;
276*bbecb9d1SAndroid Build Coastguard Worker }
277*bbecb9d1SAndroid Build Coastguard Worker }
278*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_getenv(void)279*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_getenv(void)
280*bbecb9d1SAndroid Build Coastguard Worker {
281*bbecb9d1SAndroid Build Coastguard Worker server.use_glx = getenv("VTEST_USE_GLX") != NULL;
282*bbecb9d1SAndroid Build Coastguard Worker server.use_egl_surfaceless = getenv("VTEST_USE_EGL_SURFACELESS") != NULL;
283*bbecb9d1SAndroid Build Coastguard Worker server.use_gles = getenv("VTEST_USE_GLES") != NULL;
284*bbecb9d1SAndroid Build Coastguard Worker server.render_device = getenv("VTEST_RENDERNODE");
285*bbecb9d1SAndroid Build Coastguard Worker }
286*bbecb9d1SAndroid Build Coastguard Worker
handler(int sig,siginfo_t * si,void * unused)287*bbecb9d1SAndroid Build Coastguard Worker static void handler(int sig, siginfo_t *si, void *unused)
288*bbecb9d1SAndroid Build Coastguard Worker {
289*bbecb9d1SAndroid Build Coastguard Worker (void)sig; (void)si, (void)unused;
290*bbecb9d1SAndroid Build Coastguard Worker
291*bbecb9d1SAndroid Build Coastguard Worker printf("SIGSEGV!\n");
292*bbecb9d1SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
293*bbecb9d1SAndroid Build Coastguard Worker }
294*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_set_signal_child(void)295*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_set_signal_child(void)
296*bbecb9d1SAndroid Build Coastguard Worker {
297*bbecb9d1SAndroid Build Coastguard Worker struct sigaction sa;
298*bbecb9d1SAndroid Build Coastguard Worker int ret;
299*bbecb9d1SAndroid Build Coastguard Worker
300*bbecb9d1SAndroid Build Coastguard Worker memset(&sa, 0, sizeof(sa));
301*bbecb9d1SAndroid Build Coastguard Worker sigemptyset(&sa.sa_mask);
302*bbecb9d1SAndroid Build Coastguard Worker sa.sa_handler = SIG_IGN;
303*bbecb9d1SAndroid Build Coastguard Worker sa.sa_flags = 0;
304*bbecb9d1SAndroid Build Coastguard Worker
305*bbecb9d1SAndroid Build Coastguard Worker ret = sigaction(SIGCHLD, &sa, NULL);
306*bbecb9d1SAndroid Build Coastguard Worker if (ret == -1) {
307*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to set SIGCHLD");
308*bbecb9d1SAndroid Build Coastguard Worker exit(1);
309*bbecb9d1SAndroid Build Coastguard Worker }
310*bbecb9d1SAndroid Build Coastguard Worker }
311*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_set_signal_segv(void)312*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_set_signal_segv(void)
313*bbecb9d1SAndroid Build Coastguard Worker {
314*bbecb9d1SAndroid Build Coastguard Worker struct sigaction sa;
315*bbecb9d1SAndroid Build Coastguard Worker int ret;
316*bbecb9d1SAndroid Build Coastguard Worker
317*bbecb9d1SAndroid Build Coastguard Worker memset(&sa, 0, sizeof(sa));
318*bbecb9d1SAndroid Build Coastguard Worker sigemptyset(&sa.sa_mask);
319*bbecb9d1SAndroid Build Coastguard Worker sa.sa_flags = SA_SIGINFO;
320*bbecb9d1SAndroid Build Coastguard Worker sa.sa_sigaction = handler;
321*bbecb9d1SAndroid Build Coastguard Worker
322*bbecb9d1SAndroid Build Coastguard Worker ret = sigaction(SIGSEGV, &sa, NULL);
323*bbecb9d1SAndroid Build Coastguard Worker if (ret == -1) {
324*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to set SIGSEGV");
325*bbecb9d1SAndroid Build Coastguard Worker exit(1);
326*bbecb9d1SAndroid Build Coastguard Worker }
327*bbecb9d1SAndroid Build Coastguard Worker }
328*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_add_client(int in_fd,int out_fd)329*bbecb9d1SAndroid Build Coastguard Worker static int vtest_server_add_client(int in_fd, int out_fd)
330*bbecb9d1SAndroid Build Coastguard Worker {
331*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client;
332*bbecb9d1SAndroid Build Coastguard Worker
333*bbecb9d1SAndroid Build Coastguard Worker client = calloc(1, sizeof(*client));
334*bbecb9d1SAndroid Build Coastguard Worker if (!client)
335*bbecb9d1SAndroid Build Coastguard Worker return -1;
336*bbecb9d1SAndroid Build Coastguard Worker
337*bbecb9d1SAndroid Build Coastguard Worker client->in_fd = in_fd;
338*bbecb9d1SAndroid Build Coastguard Worker client->out_fd = out_fd;
339*bbecb9d1SAndroid Build Coastguard Worker
340*bbecb9d1SAndroid Build Coastguard Worker client->input.data.fd = in_fd;
341*bbecb9d1SAndroid Build Coastguard Worker client->input.read = vtest_block_read;
342*bbecb9d1SAndroid Build Coastguard Worker
343*bbecb9d1SAndroid Build Coastguard Worker client->context_poll_fd = -1;
344*bbecb9d1SAndroid Build Coastguard Worker
345*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.new_clients);
346*bbecb9d1SAndroid Build Coastguard Worker
347*bbecb9d1SAndroid Build Coastguard Worker return 0;
348*bbecb9d1SAndroid Build Coastguard Worker }
349*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_open_read_file(void)350*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_open_read_file(void)
351*bbecb9d1SAndroid Build Coastguard Worker {
352*bbecb9d1SAndroid Build Coastguard Worker int in_fd;
353*bbecb9d1SAndroid Build Coastguard Worker int out_fd;
354*bbecb9d1SAndroid Build Coastguard Worker
355*bbecb9d1SAndroid Build Coastguard Worker in_fd = open(server.read_file, O_RDONLY);
356*bbecb9d1SAndroid Build Coastguard Worker if (in_fd == -1) {
357*bbecb9d1SAndroid Build Coastguard Worker perror(NULL);
358*bbecb9d1SAndroid Build Coastguard Worker exit(1);
359*bbecb9d1SAndroid Build Coastguard Worker }
360*bbecb9d1SAndroid Build Coastguard Worker
361*bbecb9d1SAndroid Build Coastguard Worker out_fd = open("/dev/null", O_WRONLY);
362*bbecb9d1SAndroid Build Coastguard Worker if (out_fd == -1) {
363*bbecb9d1SAndroid Build Coastguard Worker perror(NULL);
364*bbecb9d1SAndroid Build Coastguard Worker exit(1);
365*bbecb9d1SAndroid Build Coastguard Worker }
366*bbecb9d1SAndroid Build Coastguard Worker
367*bbecb9d1SAndroid Build Coastguard Worker if (vtest_server_add_client(in_fd, out_fd)) {
368*bbecb9d1SAndroid Build Coastguard Worker perror(NULL);
369*bbecb9d1SAndroid Build Coastguard Worker exit(1);
370*bbecb9d1SAndroid Build Coastguard Worker }
371*bbecb9d1SAndroid Build Coastguard Worker }
372*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_open_socket(void)373*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_open_socket(void)
374*bbecb9d1SAndroid Build Coastguard Worker {
375*bbecb9d1SAndroid Build Coastguard Worker struct sockaddr_un un;
376*bbecb9d1SAndroid Build Coastguard Worker
377*bbecb9d1SAndroid Build Coastguard Worker server.socket = socket(PF_UNIX, SOCK_STREAM, 0);
378*bbecb9d1SAndroid Build Coastguard Worker if (server.socket < 0) {
379*bbecb9d1SAndroid Build Coastguard Worker goto err;
380*bbecb9d1SAndroid Build Coastguard Worker }
381*bbecb9d1SAndroid Build Coastguard Worker
382*bbecb9d1SAndroid Build Coastguard Worker memset(&un, 0, sizeof(un));
383*bbecb9d1SAndroid Build Coastguard Worker un.sun_family = AF_UNIX;
384*bbecb9d1SAndroid Build Coastguard Worker
385*bbecb9d1SAndroid Build Coastguard Worker snprintf(un.sun_path, sizeof(un.sun_path), "%s", server.socket_name);
386*bbecb9d1SAndroid Build Coastguard Worker
387*bbecb9d1SAndroid Build Coastguard Worker unlink(un.sun_path);
388*bbecb9d1SAndroid Build Coastguard Worker
389*bbecb9d1SAndroid Build Coastguard Worker if (bind(server.socket, (struct sockaddr *)&un, sizeof(un)) < 0) {
390*bbecb9d1SAndroid Build Coastguard Worker goto err;
391*bbecb9d1SAndroid Build Coastguard Worker }
392*bbecb9d1SAndroid Build Coastguard Worker
393*bbecb9d1SAndroid Build Coastguard Worker if (listen(server.socket, 1) < 0){
394*bbecb9d1SAndroid Build Coastguard Worker goto err;
395*bbecb9d1SAndroid Build Coastguard Worker }
396*bbecb9d1SAndroid Build Coastguard Worker
397*bbecb9d1SAndroid Build Coastguard Worker return;
398*bbecb9d1SAndroid Build Coastguard Worker
399*bbecb9d1SAndroid Build Coastguard Worker err:
400*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to setup socket.");
401*bbecb9d1SAndroid Build Coastguard Worker exit(1);
402*bbecb9d1SAndroid Build Coastguard Worker }
403*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_wait_clients(void)404*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_wait_clients(void)
405*bbecb9d1SAndroid Build Coastguard Worker {
406*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client;
407*bbecb9d1SAndroid Build Coastguard Worker fd_set read_fds;
408*bbecb9d1SAndroid Build Coastguard Worker int max_fd = -1;
409*bbecb9d1SAndroid Build Coastguard Worker int ret;
410*bbecb9d1SAndroid Build Coastguard Worker
411*bbecb9d1SAndroid Build Coastguard Worker FD_ZERO(&read_fds);
412*bbecb9d1SAndroid Build Coastguard Worker
413*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY(client, &server.active_clients, head) {
414*bbecb9d1SAndroid Build Coastguard Worker FD_SET(client->in_fd, &read_fds);
415*bbecb9d1SAndroid Build Coastguard Worker max_fd = MAX2(client->in_fd, max_fd);
416*bbecb9d1SAndroid Build Coastguard Worker
417*bbecb9d1SAndroid Build Coastguard Worker if (client->context_poll_fd >= 0) {
418*bbecb9d1SAndroid Build Coastguard Worker FD_SET(client->context_poll_fd, &read_fds);
419*bbecb9d1SAndroid Build Coastguard Worker max_fd = MAX2(client->context_poll_fd, max_fd);
420*bbecb9d1SAndroid Build Coastguard Worker }
421*bbecb9d1SAndroid Build Coastguard Worker }
422*bbecb9d1SAndroid Build Coastguard Worker
423*bbecb9d1SAndroid Build Coastguard Worker /* accept new clients when there is none or when multi_clients is set */
424*bbecb9d1SAndroid Build Coastguard Worker if (server.socket >= 0 && (max_fd < 0 || server.multi_clients)) {
425*bbecb9d1SAndroid Build Coastguard Worker FD_SET(server.socket, &read_fds);
426*bbecb9d1SAndroid Build Coastguard Worker max_fd = MAX2(server.socket, max_fd);
427*bbecb9d1SAndroid Build Coastguard Worker }
428*bbecb9d1SAndroid Build Coastguard Worker
429*bbecb9d1SAndroid Build Coastguard Worker if (max_fd < 0) {
430*bbecb9d1SAndroid Build Coastguard Worker if (!LIST_IS_EMPTY(&server.new_clients)) {
431*bbecb9d1SAndroid Build Coastguard Worker return;
432*bbecb9d1SAndroid Build Coastguard Worker }
433*bbecb9d1SAndroid Build Coastguard Worker
434*bbecb9d1SAndroid Build Coastguard Worker fprintf(stderr, "server has no fd to wait\n");
435*bbecb9d1SAndroid Build Coastguard Worker exit(1);
436*bbecb9d1SAndroid Build Coastguard Worker }
437*bbecb9d1SAndroid Build Coastguard Worker
438*bbecb9d1SAndroid Build Coastguard Worker ret = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
439*bbecb9d1SAndroid Build Coastguard Worker if (ret < 0) {
440*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to select on socket!");
441*bbecb9d1SAndroid Build Coastguard Worker exit(1);
442*bbecb9d1SAndroid Build Coastguard Worker }
443*bbecb9d1SAndroid Build Coastguard Worker
444*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY(client, &server.active_clients, head) {
445*bbecb9d1SAndroid Build Coastguard Worker if (FD_ISSET(client->in_fd, &read_fds)) {
446*bbecb9d1SAndroid Build Coastguard Worker client->in_fd_ready = true;
447*bbecb9d1SAndroid Build Coastguard Worker }
448*bbecb9d1SAndroid Build Coastguard Worker
449*bbecb9d1SAndroid Build Coastguard Worker if (client->context_poll_fd >= 0) {
450*bbecb9d1SAndroid Build Coastguard Worker if (FD_ISSET(client->context_poll_fd, &read_fds)) {
451*bbecb9d1SAndroid Build Coastguard Worker client->context_need_poll = true;
452*bbecb9d1SAndroid Build Coastguard Worker }
453*bbecb9d1SAndroid Build Coastguard Worker } else if (client->context) {
454*bbecb9d1SAndroid Build Coastguard Worker client->context_need_poll = true;
455*bbecb9d1SAndroid Build Coastguard Worker }
456*bbecb9d1SAndroid Build Coastguard Worker }
457*bbecb9d1SAndroid Build Coastguard Worker
458*bbecb9d1SAndroid Build Coastguard Worker if (server.socket >= 0 && FD_ISSET(server.socket, &read_fds)) {
459*bbecb9d1SAndroid Build Coastguard Worker int new_fd = accept(server.socket, NULL, NULL);
460*bbecb9d1SAndroid Build Coastguard Worker if (new_fd < 0) {
461*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to accept socket.");
462*bbecb9d1SAndroid Build Coastguard Worker exit(1);
463*bbecb9d1SAndroid Build Coastguard Worker }
464*bbecb9d1SAndroid Build Coastguard Worker
465*bbecb9d1SAndroid Build Coastguard Worker if (vtest_server_add_client(new_fd, new_fd)) {
466*bbecb9d1SAndroid Build Coastguard Worker perror("Failed to add client.");
467*bbecb9d1SAndroid Build Coastguard Worker exit(1);
468*bbecb9d1SAndroid Build Coastguard Worker }
469*bbecb9d1SAndroid Build Coastguard Worker }
470*bbecb9d1SAndroid Build Coastguard Worker }
471*bbecb9d1SAndroid Build Coastguard Worker
vtest_client_error_string(enum vtest_client_error err)472*bbecb9d1SAndroid Build Coastguard Worker static const char *vtest_client_error_string(enum vtest_client_error err)
473*bbecb9d1SAndroid Build Coastguard Worker {
474*bbecb9d1SAndroid Build Coastguard Worker switch (err) {
475*bbecb9d1SAndroid Build Coastguard Worker #define CASE(e) case e: return #e;
476*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_INPUT_READ)
477*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_CONTEXT_MISSING)
478*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_CONTEXT_FAILED)
479*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_COMMAND_ID)
480*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_COMMAND_UNEXPECTED)
481*bbecb9d1SAndroid Build Coastguard Worker CASE(VTEST_CLIENT_ERROR_COMMAND_DISPATCH)
482*bbecb9d1SAndroid Build Coastguard Worker #undef CASE
483*bbecb9d1SAndroid Build Coastguard Worker default: return "VTEST_CLIENT_ERROR_UNKNOWN";
484*bbecb9d1SAndroid Build Coastguard Worker }
485*bbecb9d1SAndroid Build Coastguard Worker }
486*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_dispatch_clients(void)487*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_dispatch_clients(void)
488*bbecb9d1SAndroid Build Coastguard Worker {
489*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client, *tmp;
490*bbecb9d1SAndroid Build Coastguard Worker
491*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.active_clients, head) {
492*bbecb9d1SAndroid Build Coastguard Worker int err;
493*bbecb9d1SAndroid Build Coastguard Worker
494*bbecb9d1SAndroid Build Coastguard Worker if (client->context_need_poll) {
495*bbecb9d1SAndroid Build Coastguard Worker vtest_poll_context(client->context);
496*bbecb9d1SAndroid Build Coastguard Worker client->context_need_poll = false;
497*bbecb9d1SAndroid Build Coastguard Worker }
498*bbecb9d1SAndroid Build Coastguard Worker
499*bbecb9d1SAndroid Build Coastguard Worker if (!client->in_fd_ready)
500*bbecb9d1SAndroid Build Coastguard Worker continue;
501*bbecb9d1SAndroid Build Coastguard Worker client->in_fd_ready = false;
502*bbecb9d1SAndroid Build Coastguard Worker
503*bbecb9d1SAndroid Build Coastguard Worker err = vtest_client_dispatch_commands(client);
504*bbecb9d1SAndroid Build Coastguard Worker if (err) {
505*bbecb9d1SAndroid Build Coastguard Worker fprintf(stderr, "client failed: %s\n",
506*bbecb9d1SAndroid Build Coastguard Worker vtest_client_error_string(err));
507*bbecb9d1SAndroid Build Coastguard Worker list_del(&client->head);
508*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.inactive_clients);
509*bbecb9d1SAndroid Build Coastguard Worker }
510*bbecb9d1SAndroid Build Coastguard Worker }
511*bbecb9d1SAndroid Build Coastguard Worker }
512*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_fork(void)513*bbecb9d1SAndroid Build Coastguard Worker static pid_t vtest_server_fork(void)
514*bbecb9d1SAndroid Build Coastguard Worker {
515*bbecb9d1SAndroid Build Coastguard Worker pid_t pid = fork();
516*bbecb9d1SAndroid Build Coastguard Worker
517*bbecb9d1SAndroid Build Coastguard Worker if (pid == 0) {
518*bbecb9d1SAndroid Build Coastguard Worker /* child */
519*bbecb9d1SAndroid Build Coastguard Worker vtest_server_set_signal_segv();
520*bbecb9d1SAndroid Build Coastguard Worker vtest_server_close_socket();
521*bbecb9d1SAndroid Build Coastguard Worker server.main_server = false;
522*bbecb9d1SAndroid Build Coastguard Worker server.do_fork = false;
523*bbecb9d1SAndroid Build Coastguard Worker server.loop = false;
524*bbecb9d1SAndroid Build Coastguard Worker server.multi_clients = false;
525*bbecb9d1SAndroid Build Coastguard Worker }
526*bbecb9d1SAndroid Build Coastguard Worker
527*bbecb9d1SAndroid Build Coastguard Worker return pid;
528*bbecb9d1SAndroid Build Coastguard Worker }
529*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_fork_clients(void)530*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_fork_clients(void)
531*bbecb9d1SAndroid Build Coastguard Worker {
532*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client, *tmp;
533*bbecb9d1SAndroid Build Coastguard Worker
534*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.new_clients, head) {
535*bbecb9d1SAndroid Build Coastguard Worker if (vtest_server_fork()) {
536*bbecb9d1SAndroid Build Coastguard Worker /* parent: move new clients to the inactive list */
537*bbecb9d1SAndroid Build Coastguard Worker list_del(&client->head);
538*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.inactive_clients);
539*bbecb9d1SAndroid Build Coastguard Worker } else {
540*bbecb9d1SAndroid Build Coastguard Worker /* child: move the first new client to the active list */
541*bbecb9d1SAndroid Build Coastguard Worker list_del(&client->head);
542*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.active_clients);
543*bbecb9d1SAndroid Build Coastguard Worker
544*bbecb9d1SAndroid Build Coastguard Worker /* move the rest new clients to the inactive list */
545*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.new_clients, head) {
546*bbecb9d1SAndroid Build Coastguard Worker list_del(&client->head);
547*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.inactive_clients);
548*bbecb9d1SAndroid Build Coastguard Worker }
549*bbecb9d1SAndroid Build Coastguard Worker }
550*bbecb9d1SAndroid Build Coastguard Worker }
551*bbecb9d1SAndroid Build Coastguard Worker }
552*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_activate_clients(void)553*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_activate_clients(void)
554*bbecb9d1SAndroid Build Coastguard Worker {
555*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client, *tmp;
556*bbecb9d1SAndroid Build Coastguard Worker
557*bbecb9d1SAndroid Build Coastguard Worker /* move new clients to the active list */
558*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.new_clients, head) {
559*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.active_clients);
560*bbecb9d1SAndroid Build Coastguard Worker }
561*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.new_clients);
562*bbecb9d1SAndroid Build Coastguard Worker }
563*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_inactivate_clients(void)564*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_inactivate_clients(void)
565*bbecb9d1SAndroid Build Coastguard Worker {
566*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client, *tmp;
567*bbecb9d1SAndroid Build Coastguard Worker
568*bbecb9d1SAndroid Build Coastguard Worker /* move active clients to the inactive list */
569*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.active_clients, head) {
570*bbecb9d1SAndroid Build Coastguard Worker list_addtail(&client->head, &server.inactive_clients);
571*bbecb9d1SAndroid Build Coastguard Worker }
572*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.active_clients);
573*bbecb9d1SAndroid Build Coastguard Worker }
574*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_tidy_clients(void)575*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_tidy_clients(void)
576*bbecb9d1SAndroid Build Coastguard Worker {
577*bbecb9d1SAndroid Build Coastguard Worker struct vtest_client *client, *tmp;
578*bbecb9d1SAndroid Build Coastguard Worker
579*bbecb9d1SAndroid Build Coastguard Worker LIST_FOR_EACH_ENTRY_SAFE(client, tmp, &server.inactive_clients, head) {
580*bbecb9d1SAndroid Build Coastguard Worker if (client->context) {
581*bbecb9d1SAndroid Build Coastguard Worker vtest_destroy_context(client->context);
582*bbecb9d1SAndroid Build Coastguard Worker }
583*bbecb9d1SAndroid Build Coastguard Worker
584*bbecb9d1SAndroid Build Coastguard Worker if (client->in_fd >= 0) {
585*bbecb9d1SAndroid Build Coastguard Worker close(client->in_fd);
586*bbecb9d1SAndroid Build Coastguard Worker }
587*bbecb9d1SAndroid Build Coastguard Worker
588*bbecb9d1SAndroid Build Coastguard Worker if (client->out_fd >= 0 && client->out_fd != client->in_fd) {
589*bbecb9d1SAndroid Build Coastguard Worker close(client->out_fd);
590*bbecb9d1SAndroid Build Coastguard Worker }
591*bbecb9d1SAndroid Build Coastguard Worker
592*bbecb9d1SAndroid Build Coastguard Worker free(client);
593*bbecb9d1SAndroid Build Coastguard Worker }
594*bbecb9d1SAndroid Build Coastguard Worker
595*bbecb9d1SAndroid Build Coastguard Worker list_inithead(&server.inactive_clients);
596*bbecb9d1SAndroid Build Coastguard Worker }
597*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_run(void)598*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_run(void)
599*bbecb9d1SAndroid Build Coastguard Worker {
600*bbecb9d1SAndroid Build Coastguard Worker bool run = true;
601*bbecb9d1SAndroid Build Coastguard Worker
602*bbecb9d1SAndroid Build Coastguard Worker if (server.read_file) {
603*bbecb9d1SAndroid Build Coastguard Worker vtest_server_open_read_file();
604*bbecb9d1SAndroid Build Coastguard Worker } else {
605*bbecb9d1SAndroid Build Coastguard Worker vtest_server_open_socket();
606*bbecb9d1SAndroid Build Coastguard Worker }
607*bbecb9d1SAndroid Build Coastguard Worker
608*bbecb9d1SAndroid Build Coastguard Worker while (run) {
609*bbecb9d1SAndroid Build Coastguard Worker const bool was_empty = LIST_IS_EMPTY(&server.active_clients);
610*bbecb9d1SAndroid Build Coastguard Worker bool is_empty;
611*bbecb9d1SAndroid Build Coastguard Worker
612*bbecb9d1SAndroid Build Coastguard Worker vtest_server_wait_clients();
613*bbecb9d1SAndroid Build Coastguard Worker vtest_server_dispatch_clients();
614*bbecb9d1SAndroid Build Coastguard Worker
615*bbecb9d1SAndroid Build Coastguard Worker if (server.do_fork) {
616*bbecb9d1SAndroid Build Coastguard Worker vtest_server_fork_clients();
617*bbecb9d1SAndroid Build Coastguard Worker } else {
618*bbecb9d1SAndroid Build Coastguard Worker vtest_server_activate_clients();
619*bbecb9d1SAndroid Build Coastguard Worker }
620*bbecb9d1SAndroid Build Coastguard Worker
621*bbecb9d1SAndroid Build Coastguard Worker /* init renderer after the first active client is added */
622*bbecb9d1SAndroid Build Coastguard Worker is_empty = LIST_IS_EMPTY(&server.active_clients);
623*bbecb9d1SAndroid Build Coastguard Worker if (was_empty && !is_empty) {
624*bbecb9d1SAndroid Build Coastguard Worker int ret = vtest_init_renderer(server.multi_clients,
625*bbecb9d1SAndroid Build Coastguard Worker server.ctx_flags,
626*bbecb9d1SAndroid Build Coastguard Worker server.render_device);
627*bbecb9d1SAndroid Build Coastguard Worker if (ret) {
628*bbecb9d1SAndroid Build Coastguard Worker vtest_server_inactivate_clients();
629*bbecb9d1SAndroid Build Coastguard Worker run = false;
630*bbecb9d1SAndroid Build Coastguard Worker }
631*bbecb9d1SAndroid Build Coastguard Worker }
632*bbecb9d1SAndroid Build Coastguard Worker
633*bbecb9d1SAndroid Build Coastguard Worker vtest_server_tidy_clients();
634*bbecb9d1SAndroid Build Coastguard Worker
635*bbecb9d1SAndroid Build Coastguard Worker /* clean up renderer after the last active client is removed */
636*bbecb9d1SAndroid Build Coastguard Worker if (!was_empty && is_empty) {
637*bbecb9d1SAndroid Build Coastguard Worker vtest_cleanup_renderer();
638*bbecb9d1SAndroid Build Coastguard Worker if (!server.loop) {
639*bbecb9d1SAndroid Build Coastguard Worker run = false;
640*bbecb9d1SAndroid Build Coastguard Worker }
641*bbecb9d1SAndroid Build Coastguard Worker }
642*bbecb9d1SAndroid Build Coastguard Worker }
643*bbecb9d1SAndroid Build Coastguard Worker
644*bbecb9d1SAndroid Build Coastguard Worker vtest_server_close_socket();
645*bbecb9d1SAndroid Build Coastguard Worker }
646*bbecb9d1SAndroid Build Coastguard Worker
647*bbecb9d1SAndroid Build Coastguard Worker static const struct vtest_command {
648*bbecb9d1SAndroid Build Coastguard Worker int (*dispatch)(uint32_t);
649*bbecb9d1SAndroid Build Coastguard Worker bool init_context;
650*bbecb9d1SAndroid Build Coastguard Worker } vtest_commands[] = {
651*bbecb9d1SAndroid Build Coastguard Worker /* CMD ids starts at 1 */
652*bbecb9d1SAndroid Build Coastguard Worker [0] = { NULL, false },
653*bbecb9d1SAndroid Build Coastguard Worker [VCMD_GET_CAPS] = { vtest_send_caps, false },
654*bbecb9d1SAndroid Build Coastguard Worker [VCMD_RESOURCE_CREATE] = { vtest_create_resource, true },
655*bbecb9d1SAndroid Build Coastguard Worker [VCMD_RESOURCE_UNREF] = { vtest_resource_unref, true },
656*bbecb9d1SAndroid Build Coastguard Worker [VCMD_TRANSFER_GET] = { vtest_transfer_get, true },
657*bbecb9d1SAndroid Build Coastguard Worker [VCMD_TRANSFER_PUT] = { vtest_transfer_put, true },
658*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SUBMIT_CMD] = { vtest_submit_cmd, true },
659*bbecb9d1SAndroid Build Coastguard Worker [VCMD_RESOURCE_BUSY_WAIT] = { vtest_resource_busy_wait, false },
660*bbecb9d1SAndroid Build Coastguard Worker /* VCMD_CREATE_RENDERER is a special case */
661*bbecb9d1SAndroid Build Coastguard Worker [VCMD_CREATE_RENDERER] = { NULL, false },
662*bbecb9d1SAndroid Build Coastguard Worker [VCMD_GET_CAPS2] = { vtest_send_caps2, false },
663*bbecb9d1SAndroid Build Coastguard Worker [VCMD_PING_PROTOCOL_VERSION] = { vtest_ping_protocol_version, false },
664*bbecb9d1SAndroid Build Coastguard Worker [VCMD_PROTOCOL_VERSION] = { vtest_protocol_version, false },
665*bbecb9d1SAndroid Build Coastguard Worker
666*bbecb9d1SAndroid Build Coastguard Worker /* since protocol version 2 */
667*bbecb9d1SAndroid Build Coastguard Worker [VCMD_RESOURCE_CREATE2] = { vtest_create_resource2, true },
668*bbecb9d1SAndroid Build Coastguard Worker [VCMD_TRANSFER_GET2] = { vtest_transfer_get2, true },
669*bbecb9d1SAndroid Build Coastguard Worker [VCMD_TRANSFER_PUT2] = { vtest_transfer_put2, true },
670*bbecb9d1SAndroid Build Coastguard Worker
671*bbecb9d1SAndroid Build Coastguard Worker /* since protocol version 3 */
672*bbecb9d1SAndroid Build Coastguard Worker [VCMD_GET_PARAM] = { vtest_get_param, false },
673*bbecb9d1SAndroid Build Coastguard Worker [VCMD_GET_CAPSET] = { vtest_get_capset, false },
674*bbecb9d1SAndroid Build Coastguard Worker [VCMD_CONTEXT_INIT] = { vtest_context_init, false },
675*bbecb9d1SAndroid Build Coastguard Worker [VCMD_RESOURCE_CREATE_BLOB] = { vtest_resource_create_blob, true },
676*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SYNC_CREATE] = { vtest_sync_create, true },
677*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SYNC_UNREF] = { vtest_sync_unref, true },
678*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SYNC_READ] = { vtest_sync_read, true },
679*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SYNC_WRITE] = { vtest_sync_write, true },
680*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SYNC_WAIT] = { vtest_sync_wait, true },
681*bbecb9d1SAndroid Build Coastguard Worker [VCMD_SUBMIT_CMD2] = { vtest_submit_cmd2, true },
682*bbecb9d1SAndroid Build Coastguard Worker };
683*bbecb9d1SAndroid Build Coastguard Worker
vtest_client_dispatch_commands(struct vtest_client * client)684*bbecb9d1SAndroid Build Coastguard Worker static int vtest_client_dispatch_commands(struct vtest_client *client)
685*bbecb9d1SAndroid Build Coastguard Worker {
686*bbecb9d1SAndroid Build Coastguard Worker const struct vtest_command *cmd;
687*bbecb9d1SAndroid Build Coastguard Worker int ret;
688*bbecb9d1SAndroid Build Coastguard Worker uint32_t header[VTEST_HDR_SIZE];
689*bbecb9d1SAndroid Build Coastguard Worker
690*bbecb9d1SAndroid Build Coastguard Worker ret = client->input.read(&client->input, &header, sizeof(header));
691*bbecb9d1SAndroid Build Coastguard Worker if (ret < 0 || (size_t)ret < sizeof(header)) {
692*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_INPUT_READ;
693*bbecb9d1SAndroid Build Coastguard Worker }
694*bbecb9d1SAndroid Build Coastguard Worker
695*bbecb9d1SAndroid Build Coastguard Worker if (!client->context) {
696*bbecb9d1SAndroid Build Coastguard Worker /* The first command MUST be VCMD_CREATE_RENDERER */
697*bbecb9d1SAndroid Build Coastguard Worker if (header[1] != VCMD_CREATE_RENDERER) {
698*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_CONTEXT_MISSING;
699*bbecb9d1SAndroid Build Coastguard Worker }
700*bbecb9d1SAndroid Build Coastguard Worker
701*bbecb9d1SAndroid Build Coastguard Worker ret = vtest_create_context(&client->input, client->out_fd,
702*bbecb9d1SAndroid Build Coastguard Worker header[0], &client->context);
703*bbecb9d1SAndroid Build Coastguard Worker if (ret < 0) {
704*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_CONTEXT_FAILED;
705*bbecb9d1SAndroid Build Coastguard Worker }
706*bbecb9d1SAndroid Build Coastguard Worker printf("%s: client context created.\n", __func__);
707*bbecb9d1SAndroid Build Coastguard Worker vtest_poll_resource_busy_wait();
708*bbecb9d1SAndroid Build Coastguard Worker
709*bbecb9d1SAndroid Build Coastguard Worker return 0;
710*bbecb9d1SAndroid Build Coastguard Worker }
711*bbecb9d1SAndroid Build Coastguard Worker
712*bbecb9d1SAndroid Build Coastguard Worker vtest_poll_resource_busy_wait();
713*bbecb9d1SAndroid Build Coastguard Worker if (header[1] <= 0 || header[1] >= ARRAY_SIZE(vtest_commands)) {
714*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_COMMAND_ID;
715*bbecb9d1SAndroid Build Coastguard Worker }
716*bbecb9d1SAndroid Build Coastguard Worker
717*bbecb9d1SAndroid Build Coastguard Worker cmd = &vtest_commands[header[1]];
718*bbecb9d1SAndroid Build Coastguard Worker if (cmd->dispatch == NULL) {
719*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_COMMAND_UNEXPECTED;
720*bbecb9d1SAndroid Build Coastguard Worker }
721*bbecb9d1SAndroid Build Coastguard Worker
722*bbecb9d1SAndroid Build Coastguard Worker /* we should consider per-context dispatch table to get rid of if's */
723*bbecb9d1SAndroid Build Coastguard Worker if (cmd->init_context) {
724*bbecb9d1SAndroid Build Coastguard Worker ret = vtest_lazy_init_context(client->context);
725*bbecb9d1SAndroid Build Coastguard Worker if (ret) {
726*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_CONTEXT_FAILED;
727*bbecb9d1SAndroid Build Coastguard Worker }
728*bbecb9d1SAndroid Build Coastguard Worker client->context_poll_fd = vtest_get_context_poll_fd(client->context);
729*bbecb9d1SAndroid Build Coastguard Worker }
730*bbecb9d1SAndroid Build Coastguard Worker
731*bbecb9d1SAndroid Build Coastguard Worker vtest_set_current_context(client->context);
732*bbecb9d1SAndroid Build Coastguard Worker
733*bbecb9d1SAndroid Build Coastguard Worker ret = cmd->dispatch(header[0]);
734*bbecb9d1SAndroid Build Coastguard Worker if (ret < 0) {
735*bbecb9d1SAndroid Build Coastguard Worker return VTEST_CLIENT_ERROR_COMMAND_DISPATCH;
736*bbecb9d1SAndroid Build Coastguard Worker }
737*bbecb9d1SAndroid Build Coastguard Worker
738*bbecb9d1SAndroid Build Coastguard Worker return 0;
739*bbecb9d1SAndroid Build Coastguard Worker }
740*bbecb9d1SAndroid Build Coastguard Worker
vtest_server_close_socket(void)741*bbecb9d1SAndroid Build Coastguard Worker static void vtest_server_close_socket(void)
742*bbecb9d1SAndroid Build Coastguard Worker {
743*bbecb9d1SAndroid Build Coastguard Worker if (server.socket != -1) {
744*bbecb9d1SAndroid Build Coastguard Worker close(server.socket);
745*bbecb9d1SAndroid Build Coastguard Worker server.socket = -1;
746*bbecb9d1SAndroid Build Coastguard Worker }
747*bbecb9d1SAndroid Build Coastguard Worker }
748