1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker * Copyright 2021 Google LLC
3*bbecb9d1SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*bbecb9d1SAndroid Build Coastguard Worker */
5*bbecb9d1SAndroid Build Coastguard Worker
6*bbecb9d1SAndroid Build Coastguard Worker #include "proxy_server.h"
7*bbecb9d1SAndroid Build Coastguard Worker
8*bbecb9d1SAndroid Build Coastguard Worker #include <signal.h>
9*bbecb9d1SAndroid Build Coastguard Worker #include <sys/wait.h>
10*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
11*bbecb9d1SAndroid Build Coastguard Worker
12*bbecb9d1SAndroid Build Coastguard Worker #include "server/render_protocol.h"
13*bbecb9d1SAndroid Build Coastguard Worker
14*bbecb9d1SAndroid Build Coastguard Worker int
proxy_server_connect(struct proxy_server * srv)15*bbecb9d1SAndroid Build Coastguard Worker proxy_server_connect(struct proxy_server *srv)
16*bbecb9d1SAndroid Build Coastguard Worker {
17*bbecb9d1SAndroid Build Coastguard Worker int client_fd = srv->client_fd;
18*bbecb9d1SAndroid Build Coastguard Worker /* transfer ownership */
19*bbecb9d1SAndroid Build Coastguard Worker srv->client_fd = -1;
20*bbecb9d1SAndroid Build Coastguard Worker return client_fd;
21*bbecb9d1SAndroid Build Coastguard Worker }
22*bbecb9d1SAndroid Build Coastguard Worker
23*bbecb9d1SAndroid Build Coastguard Worker void
proxy_server_destroy(struct proxy_server * srv)24*bbecb9d1SAndroid Build Coastguard Worker proxy_server_destroy(struct proxy_server *srv)
25*bbecb9d1SAndroid Build Coastguard Worker {
26*bbecb9d1SAndroid Build Coastguard Worker if (srv->pid >= 0) {
27*bbecb9d1SAndroid Build Coastguard Worker kill(srv->pid, SIGKILL);
28*bbecb9d1SAndroid Build Coastguard Worker
29*bbecb9d1SAndroid Build Coastguard Worker siginfo_t siginfo = { 0 };
30*bbecb9d1SAndroid Build Coastguard Worker waitid(P_PID, srv->pid, &siginfo, WEXITED);
31*bbecb9d1SAndroid Build Coastguard Worker }
32*bbecb9d1SAndroid Build Coastguard Worker
33*bbecb9d1SAndroid Build Coastguard Worker if (srv->client_fd >= 0)
34*bbecb9d1SAndroid Build Coastguard Worker close(srv->client_fd);
35*bbecb9d1SAndroid Build Coastguard Worker
36*bbecb9d1SAndroid Build Coastguard Worker free(srv);
37*bbecb9d1SAndroid Build Coastguard Worker }
38*bbecb9d1SAndroid Build Coastguard Worker
39*bbecb9d1SAndroid Build Coastguard Worker static bool
proxy_server_fork(struct proxy_server * srv)40*bbecb9d1SAndroid Build Coastguard Worker proxy_server_fork(struct proxy_server *srv)
41*bbecb9d1SAndroid Build Coastguard Worker {
42*bbecb9d1SAndroid Build Coastguard Worker int socket_fds[2];
43*bbecb9d1SAndroid Build Coastguard Worker if (!proxy_socket_pair(socket_fds))
44*bbecb9d1SAndroid Build Coastguard Worker return false;
45*bbecb9d1SAndroid Build Coastguard Worker const int client_fd = socket_fds[0];
46*bbecb9d1SAndroid Build Coastguard Worker const int remote_fd = socket_fds[1];
47*bbecb9d1SAndroid Build Coastguard Worker
48*bbecb9d1SAndroid Build Coastguard Worker pid_t pid = fork();
49*bbecb9d1SAndroid Build Coastguard Worker if (pid < 0) {
50*bbecb9d1SAndroid Build Coastguard Worker proxy_log("failed to fork proxy server");
51*bbecb9d1SAndroid Build Coastguard Worker close(client_fd);
52*bbecb9d1SAndroid Build Coastguard Worker close(remote_fd);
53*bbecb9d1SAndroid Build Coastguard Worker return false;
54*bbecb9d1SAndroid Build Coastguard Worker }
55*bbecb9d1SAndroid Build Coastguard Worker
56*bbecb9d1SAndroid Build Coastguard Worker if (pid > 0) {
57*bbecb9d1SAndroid Build Coastguard Worker srv->pid = pid;
58*bbecb9d1SAndroid Build Coastguard Worker srv->client_fd = client_fd;
59*bbecb9d1SAndroid Build Coastguard Worker close(remote_fd);
60*bbecb9d1SAndroid Build Coastguard Worker } else {
61*bbecb9d1SAndroid Build Coastguard Worker close(client_fd);
62*bbecb9d1SAndroid Build Coastguard Worker
63*bbecb9d1SAndroid Build Coastguard Worker /* do not receive signals from terminal */
64*bbecb9d1SAndroid Build Coastguard Worker setpgid(0, 0);
65*bbecb9d1SAndroid Build Coastguard Worker
66*bbecb9d1SAndroid Build Coastguard Worker char fd_str[16];
67*bbecb9d1SAndroid Build Coastguard Worker snprintf(fd_str, sizeof(fd_str), "%d", remote_fd);
68*bbecb9d1SAndroid Build Coastguard Worker
69*bbecb9d1SAndroid Build Coastguard Worker char *const argv[] = {
70*bbecb9d1SAndroid Build Coastguard Worker RENDER_SERVER_EXEC_PATH,
71*bbecb9d1SAndroid Build Coastguard Worker "--socket-fd",
72*bbecb9d1SAndroid Build Coastguard Worker fd_str,
73*bbecb9d1SAndroid Build Coastguard Worker NULL,
74*bbecb9d1SAndroid Build Coastguard Worker };
75*bbecb9d1SAndroid Build Coastguard Worker execv(argv[0], argv);
76*bbecb9d1SAndroid Build Coastguard Worker
77*bbecb9d1SAndroid Build Coastguard Worker proxy_log("failed to exec %s: %s", argv[0], strerror(errno));
78*bbecb9d1SAndroid Build Coastguard Worker close(remote_fd);
79*bbecb9d1SAndroid Build Coastguard Worker exit(-1);
80*bbecb9d1SAndroid Build Coastguard Worker }
81*bbecb9d1SAndroid Build Coastguard Worker
82*bbecb9d1SAndroid Build Coastguard Worker return true;
83*bbecb9d1SAndroid Build Coastguard Worker }
84*bbecb9d1SAndroid Build Coastguard Worker
85*bbecb9d1SAndroid Build Coastguard Worker static bool
proxy_server_init_fd(struct proxy_server * srv)86*bbecb9d1SAndroid Build Coastguard Worker proxy_server_init_fd(struct proxy_server *srv)
87*bbecb9d1SAndroid Build Coastguard Worker {
88*bbecb9d1SAndroid Build Coastguard Worker /* the fd represents a connection to the server */
89*bbecb9d1SAndroid Build Coastguard Worker srv->client_fd = proxy_renderer.cbs->get_server_fd(RENDER_SERVER_VERSION);
90*bbecb9d1SAndroid Build Coastguard Worker if (srv->client_fd < 0)
91*bbecb9d1SAndroid Build Coastguard Worker return false;
92*bbecb9d1SAndroid Build Coastguard Worker
93*bbecb9d1SAndroid Build Coastguard Worker return true;
94*bbecb9d1SAndroid Build Coastguard Worker }
95*bbecb9d1SAndroid Build Coastguard Worker
96*bbecb9d1SAndroid Build Coastguard Worker struct proxy_server *
proxy_server_create(void)97*bbecb9d1SAndroid Build Coastguard Worker proxy_server_create(void)
98*bbecb9d1SAndroid Build Coastguard Worker {
99*bbecb9d1SAndroid Build Coastguard Worker struct proxy_server *srv = calloc(1, sizeof(*srv));
100*bbecb9d1SAndroid Build Coastguard Worker if (!srv)
101*bbecb9d1SAndroid Build Coastguard Worker return NULL;
102*bbecb9d1SAndroid Build Coastguard Worker
103*bbecb9d1SAndroid Build Coastguard Worker srv->pid = -1;
104*bbecb9d1SAndroid Build Coastguard Worker
105*bbecb9d1SAndroid Build Coastguard Worker if (!proxy_server_init_fd(srv)) {
106*bbecb9d1SAndroid Build Coastguard Worker /* start the render server on demand when the client does not provide a
107*bbecb9d1SAndroid Build Coastguard Worker * server fd
108*bbecb9d1SAndroid Build Coastguard Worker */
109*bbecb9d1SAndroid Build Coastguard Worker if (!proxy_server_fork(srv)) {
110*bbecb9d1SAndroid Build Coastguard Worker free(srv);
111*bbecb9d1SAndroid Build Coastguard Worker return NULL;
112*bbecb9d1SAndroid Build Coastguard Worker }
113*bbecb9d1SAndroid Build Coastguard Worker }
114*bbecb9d1SAndroid Build Coastguard Worker
115*bbecb9d1SAndroid Build Coastguard Worker if (!proxy_socket_is_seqpacket(srv->client_fd)) {
116*bbecb9d1SAndroid Build Coastguard Worker proxy_log("invalid client fd type");
117*bbecb9d1SAndroid Build Coastguard Worker close(srv->client_fd);
118*bbecb9d1SAndroid Build Coastguard Worker free(srv);
119*bbecb9d1SAndroid Build Coastguard Worker return NULL;
120*bbecb9d1SAndroid Build Coastguard Worker }
121*bbecb9d1SAndroid Build Coastguard Worker
122*bbecb9d1SAndroid Build Coastguard Worker proxy_log("proxy server with pid %d", srv->pid);
123*bbecb9d1SAndroid Build Coastguard Worker
124*bbecb9d1SAndroid Build Coastguard Worker return srv;
125*bbecb9d1SAndroid Build Coastguard Worker }
126