• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <set>
18 #include <android-base/logging.h>
19 #include <gflags/gflags.h>
20 
21 #include "common/libs/fs/shared_fd.h"
22 #include "common/libs/utils/socket2socket_proxy.h"
23 #include "host/commands/kernel_log_monitor/utils.h"
24 
25 #ifdef CUTTLEFISH_HOST
26 #include "host/libs/config/logging.h"
27 #endif // CUTTLEFISH_HOST
28 
29 DEFINE_string(server, "",
30               "The type of server to host, `vsock` or `tcp`. When hosting a server "
31               "of one type, the proxy will take inbound connections of this type and "
32               "make outbound connections of the other type.");
33 DEFINE_uint32(tcp_port, 0, "TCP port");
34 DEFINE_uint32(vsock_port, 0, "vsock port");
35 DEFINE_uint32(vsock_cid, 0, "Vsock cid to initiate connections to");
36 DEFINE_int32(adbd_events_fd, -1, "A file descriptor. If set it will wait for "
37                                  "AdbdStarted boot event from the kernel log "
38                                  "monitor before creating a tcp-vsock tunnel."
39                                  "This option is used by --server=tcp only "
40                                  "when socket_vsock_proxy runs as a host service");
41 DEFINE_int32(
42     server_fd, -1,
43     "A file descriptor. If set the passed file descriptor will be used as the "
44     "server and the corresponding port flag will be ignored");
45 
46 namespace {
WaitForAdbdToBeStarted(int events_fd)47 void WaitForAdbdToBeStarted(int events_fd) {
48   auto evt_shared_fd = cuttlefish::SharedFD::Dup(events_fd);
49   close(events_fd);
50   while (evt_shared_fd->IsOpen()) {
51     std::optional<monitor::ReadEventResult> read_result =
52         monitor::ReadEvent(evt_shared_fd);
53     if (!read_result) {
54       LOG(ERROR) << "Failed to read a complete kernel log adb event.";
55       // The file descriptor can't be trusted anymore, stop waiting and try to
56       // connect
57       return;
58     }
59 
60     if (read_result->event == monitor::Event::AdbdStarted) {
61       LOG(DEBUG) << "Adbd has started in the guest, connecting adb";
62       return;
63     }
64   }
65 }
66 
67 // intented to run as cuttlefish host service
TcpServer()68 void TcpServer() {
69   LOG(DEBUG) << "starting TCP server on " << FLAGS_tcp_port
70              << " for vsock port " << FLAGS_vsock_port;
71   cuttlefish::SharedFD server;
72   if (FLAGS_server_fd < 0) {
73     server =
74         cuttlefish::SharedFD::SocketLocalServer(FLAGS_tcp_port, SOCK_STREAM);
75   } else {
76     server = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
77     close(FLAGS_server_fd);
78   }
79   CHECK(server->IsOpen()) << "Could not start server on " << FLAGS_tcp_port;
80   LOG(DEBUG) << "Accepting client connections";
81   int last_failure_reason = 0;
82   cuttlefish::Proxy(server, [&last_failure_reason]() {
83     auto vsock_socket = cuttlefish::SharedFD::VsockClient(
84         FLAGS_vsock_cid, FLAGS_vsock_port, SOCK_STREAM);
85     if (vsock_socket->IsOpen()) {
86       last_failure_reason = 0;
87       LOG(DEBUG) << "Connected to vsock:" << FLAGS_vsock_cid << ":"
88                  << FLAGS_vsock_port;
89     } else {
90       // Don't log if the previous connection failed with the same error
91       if (last_failure_reason != vsock_socket->GetErrno()) {
92         last_failure_reason = vsock_socket->GetErrno();
93         LOG(ERROR) << "Unable to connect to vsock server: "
94                    << vsock_socket->StrError();
95       }
96     }
97     return vsock_socket;
98   });
99 }
100 
OpenSocketConnection()101 cuttlefish::SharedFD OpenSocketConnection() {
102   while (true) {
103     auto sock = cuttlefish::SharedFD::SocketLocalClient(FLAGS_tcp_port, SOCK_STREAM);
104     if (sock->IsOpen()) {
105       return sock;
106     }
107     LOG(WARNING) << "could not connect on port " << FLAGS_tcp_port
108                  << ". sleeping for 1 second";
109     sleep(1);
110   }
111 }
112 
socketErrorIsRecoverable(int error)113 bool socketErrorIsRecoverable(int error) {
114   std::set<int> unrecoverable{EACCES, EAFNOSUPPORT, EINVAL, EPROTONOSUPPORT};
115   return unrecoverable.find(error) == unrecoverable.end();
116 }
117 
SleepForever()118 [[noreturn]] static void SleepForever() {
119   while (true) {
120     sleep(std::numeric_limits<unsigned int>::max());
121   }
122 }
123 
124 // intended to run inside Android guest
VsockServer()125 void VsockServer() {
126   LOG(DEBUG) << "Starting vsock server on " << FLAGS_vsock_port;
127   cuttlefish::SharedFD vsock;
128   if (FLAGS_server_fd < 0) {
129     do {
130       vsock = cuttlefish::SharedFD::VsockServer(FLAGS_vsock_port, SOCK_STREAM);
131       if (!vsock->IsOpen() && !socketErrorIsRecoverable(vsock->GetErrno())) {
132         LOG(ERROR) << "Could not open vsock socket: " << vsock->StrError();
133         SleepForever();
134       }
135     } while (!vsock->IsOpen());
136   } else {
137     vsock = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
138     close(FLAGS_server_fd);
139   }
140   CHECK(vsock->IsOpen()) << "Could not start server on " << FLAGS_vsock_port;
141   cuttlefish::Proxy(vsock, []() {
142     LOG(DEBUG) << "vsock socket accepted";
143     auto client = OpenSocketConnection();
144     CHECK(client->IsOpen()) << "error connecting to guest client";
145     return client;
146   });
147 }
148 
149 }  // namespace
150 
main(int argc,char * argv[])151 int main(int argc, char* argv[]) {
152 #ifdef CUTTLEFISH_HOST
153   cuttlefish::DefaultSubprocessLogging(argv);
154 #else
155   ::android::base::InitLogging(argv, android::base::LogdLogger());
156 #endif
157   google::ParseCommandLineFlags(&argc, &argv, true);
158 
159   CHECK((FLAGS_server == "tcp" && FLAGS_server_fd >= 0) || FLAGS_tcp_port != 0)
160       << "Must specify -tcp_port or -server_fd (with -server=tcp) flag";
161   CHECK((FLAGS_server == "vsock" && FLAGS_server_fd >= 0) ||
162         FLAGS_vsock_port != 0)
163       << "Must specify -vsock_port or -server_fd (with -server=vsock) flag";
164 
165   if (FLAGS_adbd_events_fd >= 0) {
166     LOG(DEBUG) << "Wating AdbdStarted boot event from the kernel log";
167     WaitForAdbdToBeStarted(FLAGS_adbd_events_fd);
168   }
169 
170   if (FLAGS_server == "tcp") {
171     CHECK(FLAGS_vsock_cid != 0) << "Must specify -vsock_cid flag";
172     TcpServer();
173   } else if (FLAGS_server == "vsock") {
174     VsockServer();
175   } else {
176     LOG(FATAL) << "Unknown server type: " << FLAGS_server;
177   }
178 }
179