xref: /aosp_15_r20/platform_testing/tools/automotive/proxy/proxy.cpp (revision dd0948b35e70be4c0246aabd6c72554a5eb8b22a)
1*dd0948b3SAndroid Build Coastguard Worker /*
2*dd0948b3SAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*dd0948b3SAndroid Build Coastguard Worker  *
4*dd0948b3SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*dd0948b3SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*dd0948b3SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*dd0948b3SAndroid Build Coastguard Worker  *
8*dd0948b3SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*dd0948b3SAndroid Build Coastguard Worker  *
10*dd0948b3SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*dd0948b3SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*dd0948b3SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*dd0948b3SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*dd0948b3SAndroid Build Coastguard Worker  * limitations under the License.
15*dd0948b3SAndroid Build Coastguard Worker  */
16*dd0948b3SAndroid Build Coastguard Worker 
17*dd0948b3SAndroid Build Coastguard Worker #include <errno.h>
18*dd0948b3SAndroid Build Coastguard Worker #include <iostream>
19*dd0948b3SAndroid Build Coastguard Worker #include <stdlib.h>
20*dd0948b3SAndroid Build Coastguard Worker #include <string.h>
21*dd0948b3SAndroid Build Coastguard Worker #include <sys/select.h>
22*dd0948b3SAndroid Build Coastguard Worker #include <sys/socket.h>
23*dd0948b3SAndroid Build Coastguard Worker #include <thread>
24*dd0948b3SAndroid Build Coastguard Worker #include <unistd.h>
25*dd0948b3SAndroid Build Coastguard Worker 
26*dd0948b3SAndroid Build Coastguard Worker #include <libProxyConfig/libProxyConfig.h>
27*dd0948b3SAndroid Build Coastguard Worker 
28*dd0948b3SAndroid Build Coastguard Worker #include <linux/vm_sockets.h>
29*dd0948b3SAndroid Build Coastguard Worker 
30*dd0948b3SAndroid Build Coastguard Worker #define MAX(x, y) (((x) > (y)) ? (x) : (y))
31*dd0948b3SAndroid Build Coastguard Worker #define BUFFER_SIZE 16384
32*dd0948b3SAndroid Build Coastguard Worker #define CLIENT_QUEUE_SIZE 128
33*dd0948b3SAndroid Build Coastguard Worker 
setupServerSocket(sockaddr_vm & addr)34*dd0948b3SAndroid Build Coastguard Worker int setupServerSocket(sockaddr_vm& addr) {
35*dd0948b3SAndroid Build Coastguard Worker     int vsock_socket = socket(AF_VSOCK, SOCK_STREAM, 0);
36*dd0948b3SAndroid Build Coastguard Worker 
37*dd0948b3SAndroid Build Coastguard Worker     if (vsock_socket == -1) {
38*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to create server VSOCK socket, ERROR = "
39*dd0948b3SAndroid Build Coastguard Worker                   << strerror(errno) << std::endl;
40*dd0948b3SAndroid Build Coastguard Worker         return -1;
41*dd0948b3SAndroid Build Coastguard Worker     }
42*dd0948b3SAndroid Build Coastguard Worker 
43*dd0948b3SAndroid Build Coastguard Worker     if (bind(vsock_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) != 0) {
44*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to bind to server VSOCK socket, ERROR = "
45*dd0948b3SAndroid Build Coastguard Worker                   << strerror(errno) << std::endl;
46*dd0948b3SAndroid Build Coastguard Worker         return -1;
47*dd0948b3SAndroid Build Coastguard Worker     }
48*dd0948b3SAndroid Build Coastguard Worker 
49*dd0948b3SAndroid Build Coastguard Worker     if (listen(vsock_socket, CLIENT_QUEUE_SIZE) != 0) {
50*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to listen on server VSOCK socket, ERROR = "
51*dd0948b3SAndroid Build Coastguard Worker                   << strerror(errno) << std::endl;
52*dd0948b3SAndroid Build Coastguard Worker         return -1;
53*dd0948b3SAndroid Build Coastguard Worker     }
54*dd0948b3SAndroid Build Coastguard Worker 
55*dd0948b3SAndroid Build Coastguard Worker     return vsock_socket;
56*dd0948b3SAndroid Build Coastguard Worker }
57*dd0948b3SAndroid Build Coastguard Worker 
closeFileDescriptor(int fd)58*dd0948b3SAndroid Build Coastguard Worker void closeFileDescriptor(int fd) {
59*dd0948b3SAndroid Build Coastguard Worker     close(fd);
60*dd0948b3SAndroid Build Coastguard Worker     shutdown(fd, SHUT_RDWR);
61*dd0948b3SAndroid Build Coastguard Worker }
62*dd0948b3SAndroid Build Coastguard Worker 
63*dd0948b3SAndroid Build Coastguard Worker // transfers a max of BUFFER_SIZE bytes between a source file descriptor and a
64*dd0948b3SAndroid Build Coastguard Worker // destination file descriptor. Returns true on success, false otherwise
transferBytes(int src_fd,int dst_fd)65*dd0948b3SAndroid Build Coastguard Worker bool transferBytes(int src_fd, int dst_fd) {
66*dd0948b3SAndroid Build Coastguard Worker     char buf[BUFFER_SIZE];
67*dd0948b3SAndroid Build Coastguard Worker     int readBytes = read(src_fd, buf, BUFFER_SIZE);
68*dd0948b3SAndroid Build Coastguard Worker     if (readBytes <= 0) {
69*dd0948b3SAndroid Build Coastguard Worker         return false;
70*dd0948b3SAndroid Build Coastguard Worker     }
71*dd0948b3SAndroid Build Coastguard Worker     int writtenBytes = write(dst_fd, buf, readBytes);
72*dd0948b3SAndroid Build Coastguard Worker     return writtenBytes >= 0;
73*dd0948b3SAndroid Build Coastguard Worker }
74*dd0948b3SAndroid Build Coastguard Worker 
75*dd0948b3SAndroid Build Coastguard Worker // Handles a client requesting to connect with the forwarding address
handleConnection(int client_sock,int fwd_cid,int fwd_port)76*dd0948b3SAndroid Build Coastguard Worker void* handleConnection(int client_sock, int fwd_cid, int fwd_port) {
77*dd0948b3SAndroid Build Coastguard Worker     int server_sock = socket(AF_VSOCK, SOCK_STREAM, 0);
78*dd0948b3SAndroid Build Coastguard Worker 
79*dd0948b3SAndroid Build Coastguard Worker     if (server_sock < 0) {
80*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to create forwarding VSOCK socket, ERROR = "
81*dd0948b3SAndroid Build Coastguard Worker                   <<  strerror(errno) << std::endl;
82*dd0948b3SAndroid Build Coastguard Worker         closeFileDescriptor(server_sock);
83*dd0948b3SAndroid Build Coastguard Worker         closeFileDescriptor(client_sock);
84*dd0948b3SAndroid Build Coastguard Worker         return nullptr;
85*dd0948b3SAndroid Build Coastguard Worker     }
86*dd0948b3SAndroid Build Coastguard Worker 
87*dd0948b3SAndroid Build Coastguard Worker     sockaddr_vm fwd_addr{};
88*dd0948b3SAndroid Build Coastguard Worker     fwd_addr.svm_family = AF_VSOCK;
89*dd0948b3SAndroid Build Coastguard Worker     fwd_addr.svm_cid = fwd_cid;
90*dd0948b3SAndroid Build Coastguard Worker     fwd_addr.svm_port = fwd_port;
91*dd0948b3SAndroid Build Coastguard Worker 
92*dd0948b3SAndroid Build Coastguard Worker     if (connect(server_sock, reinterpret_cast<sockaddr*>(&fwd_addr),
93*dd0948b3SAndroid Build Coastguard Worker               sizeof(fwd_addr)) < 0) {
94*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to connect to forwarding vsock socket, ERROR = "
95*dd0948b3SAndroid Build Coastguard Worker                   <<  strerror(errno) << std::endl;
96*dd0948b3SAndroid Build Coastguard Worker         closeFileDescriptor(server_sock);
97*dd0948b3SAndroid Build Coastguard Worker         closeFileDescriptor(client_sock);
98*dd0948b3SAndroid Build Coastguard Worker         return nullptr;
99*dd0948b3SAndroid Build Coastguard Worker     }
100*dd0948b3SAndroid Build Coastguard Worker 
101*dd0948b3SAndroid Build Coastguard Worker     bool connected = true;
102*dd0948b3SAndroid Build Coastguard Worker     while (connected) {
103*dd0948b3SAndroid Build Coastguard Worker       fd_set file_descriptors;
104*dd0948b3SAndroid Build Coastguard Worker       FD_ZERO(&file_descriptors);
105*dd0948b3SAndroid Build Coastguard Worker       FD_SET(client_sock, &file_descriptors);
106*dd0948b3SAndroid Build Coastguard Worker       FD_SET(server_sock, &file_descriptors);
107*dd0948b3SAndroid Build Coastguard Worker 
108*dd0948b3SAndroid Build Coastguard Worker       int rv = select(MAX(client_sock, server_sock) + 1, &file_descriptors, nullptr, nullptr,
109*dd0948b3SAndroid Build Coastguard Worker                     nullptr);
110*dd0948b3SAndroid Build Coastguard Worker       if (rv == -1) {
111*dd0948b3SAndroid Build Coastguard Worker           std::cerr << "ERROR in Select!. Error = " << strerror(errno) << std::endl;
112*dd0948b3SAndroid Build Coastguard Worker           break;
113*dd0948b3SAndroid Build Coastguard Worker       }
114*dd0948b3SAndroid Build Coastguard Worker 
115*dd0948b3SAndroid Build Coastguard Worker       if (FD_ISSET(client_sock, &file_descriptors)) {
116*dd0948b3SAndroid Build Coastguard Worker           // transfer bytes from client to forward address
117*dd0948b3SAndroid Build Coastguard Worker           connected = transferBytes(client_sock, server_sock);
118*dd0948b3SAndroid Build Coastguard Worker       }
119*dd0948b3SAndroid Build Coastguard Worker 
120*dd0948b3SAndroid Build Coastguard Worker       if (FD_ISSET(server_sock, &file_descriptors)) {
121*dd0948b3SAndroid Build Coastguard Worker           // transfer bytes from forward address to client
122*dd0948b3SAndroid Build Coastguard Worker           connected = transferBytes(server_sock, client_sock);
123*dd0948b3SAndroid Build Coastguard Worker       }
124*dd0948b3SAndroid Build Coastguard Worker     }
125*dd0948b3SAndroid Build Coastguard Worker 
126*dd0948b3SAndroid Build Coastguard Worker     closeFileDescriptor(client_sock);
127*dd0948b3SAndroid Build Coastguard Worker     closeFileDescriptor(server_sock);
128*dd0948b3SAndroid Build Coastguard Worker 
129*dd0948b3SAndroid Build Coastguard Worker     return nullptr;
130*dd0948b3SAndroid Build Coastguard Worker }
131*dd0948b3SAndroid Build Coastguard Worker 
setupRoute(int cid,const android::automotive::proxyconfig::Service & service)132*dd0948b3SAndroid Build Coastguard Worker void setupRoute(int cid, const android::automotive::proxyconfig::Service& service) {
133*dd0948b3SAndroid Build Coastguard Worker 
134*dd0948b3SAndroid Build Coastguard Worker     sockaddr_vm addr{};
135*dd0948b3SAndroid Build Coastguard Worker     addr.svm_family = AF_VSOCK;
136*dd0948b3SAndroid Build Coastguard Worker     addr.svm_cid = 2;
137*dd0948b3SAndroid Build Coastguard Worker     addr.svm_port = service.port;
138*dd0948b3SAndroid Build Coastguard Worker 
139*dd0948b3SAndroid Build Coastguard Worker     int fwd_cid = cid;
140*dd0948b3SAndroid Build Coastguard Worker     int fwd_port = service.port;
141*dd0948b3SAndroid Build Coastguard Worker 
142*dd0948b3SAndroid Build Coastguard Worker     int proxy_socket = setupServerSocket(addr);
143*dd0948b3SAndroid Build Coastguard Worker 
144*dd0948b3SAndroid Build Coastguard Worker     if (proxy_socket == -1) {
145*dd0948b3SAndroid Build Coastguard Worker         std::cerr << "Failed to set up proxy server VSOCK socket, ERROR = " <<
146*dd0948b3SAndroid Build Coastguard Worker            strerror(errno) << std::endl;
147*dd0948b3SAndroid Build Coastguard Worker         return;
148*dd0948b3SAndroid Build Coastguard Worker     }
149*dd0948b3SAndroid Build Coastguard Worker 
150*dd0948b3SAndroid Build Coastguard Worker     int client_sock;
151*dd0948b3SAndroid Build Coastguard Worker     int len = sizeof(addr);
152*dd0948b3SAndroid Build Coastguard Worker 
153*dd0948b3SAndroid Build Coastguard Worker     while (true) {
154*dd0948b3SAndroid Build Coastguard Worker         if ((client_sock = accept(proxy_socket, reinterpret_cast<sockaddr*>(&addr),
155*dd0948b3SAndroid Build Coastguard Worker                               reinterpret_cast<socklen_t*>(&len))) < 0) {
156*dd0948b3SAndroid Build Coastguard Worker             std::cerr << "Failed to accept VSOCK connection, ERROR = " <<
157*dd0948b3SAndroid Build Coastguard Worker                strerror(errno) << std::endl;
158*dd0948b3SAndroid Build Coastguard Worker             closeFileDescriptor(client_sock);
159*dd0948b3SAndroid Build Coastguard Worker             continue;
160*dd0948b3SAndroid Build Coastguard Worker         }
161*dd0948b3SAndroid Build Coastguard Worker 
162*dd0948b3SAndroid Build Coastguard Worker         std::thread t(handleConnection, client_sock, fwd_cid, fwd_port);
163*dd0948b3SAndroid Build Coastguard Worker         t.detach();
164*dd0948b3SAndroid Build Coastguard Worker     }
165*dd0948b3SAndroid Build Coastguard Worker 
166*dd0948b3SAndroid Build Coastguard Worker     closeFileDescriptor(proxy_socket);
167*dd0948b3SAndroid Build Coastguard Worker }
168*dd0948b3SAndroid Build Coastguard Worker 
169*dd0948b3SAndroid Build Coastguard Worker 
170*dd0948b3SAndroid Build Coastguard Worker static constexpr const char *kProxyConfigFile =
171*dd0948b3SAndroid Build Coastguard Worker     "../etc/automotive/proxy_config.json";
172*dd0948b3SAndroid Build Coastguard Worker 
main(int argc,char ** argv)173*dd0948b3SAndroid Build Coastguard Worker int main(int argc, char **argv ) {
174*dd0948b3SAndroid Build Coastguard Worker     android::automotive::proxyconfig::setProxyConfigFile(
175*dd0948b3SAndroid Build Coastguard Worker         (argc >= 2)?argv[1]:kProxyConfigFile);
176*dd0948b3SAndroid Build Coastguard Worker 
177*dd0948b3SAndroid Build Coastguard Worker     auto vmConfigs = android::automotive::proxyconfig::getAllVmProxyConfigs();
178*dd0948b3SAndroid Build Coastguard Worker 
179*dd0948b3SAndroid Build Coastguard Worker     std::vector<std::thread> routeThreads;
180*dd0948b3SAndroid Build Coastguard Worker     for (const auto& vmConfig: vmConfigs) {
181*dd0948b3SAndroid Build Coastguard Worker         for (const auto& service: vmConfig.services) {
182*dd0948b3SAndroid Build Coastguard Worker             routeThreads.push_back(std::thread(setupRoute, vmConfig.cid, service));
183*dd0948b3SAndroid Build Coastguard Worker         }
184*dd0948b3SAndroid Build Coastguard Worker     }
185*dd0948b3SAndroid Build Coastguard Worker 
186*dd0948b3SAndroid Build Coastguard Worker     for(auto& t: routeThreads) {
187*dd0948b3SAndroid Build Coastguard Worker         t.join();
188*dd0948b3SAndroid Build Coastguard Worker     }
189*dd0948b3SAndroid Build Coastguard Worker 
190*dd0948b3SAndroid Build Coastguard Worker     return 0;
191*dd0948b3SAndroid Build Coastguard Worker }
192