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