• 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 <thread>
19 #include <android-base/logging.h>
20 #include <gflags/gflags.h>
21 
22 #include "common/libs/fs/shared_fd.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 constexpr std::size_t kMaxPacketSize = 8192;
30 
31 DEFINE_string(server, "",
32               "The type of server to host, `vsock` or `tcp`. When hosting a server "
33               "of one type, the proxy will take inbound connections of this type and "
34               "make outbound connections of the other type.");
35 DEFINE_uint32(tcp_port, 0, "TCP port");
36 DEFINE_uint32(vsock_port, 0, "vsock port");
37 DEFINE_uint32(vsock_cid, 0, "Vsock cid to initiate connections to");
38 DEFINE_int32(adbd_events_fd, -1, "A file descriptor. If set it will wait for "
39                                  "AdbdStarted boot event from the kernel log "
40                                  "monitor before creating a tcp-vsock tunnel."
41                                  "This option is used by --server=tcp only "
42                                  "when socket_vsock_proxy runs as a host service");
43 DEFINE_int32(
44     server_fd, -1,
45     "A file descriptor. If set the passed file descriptor will be used as the "
46     "server and the corresponding port flag will be ignored");
47 
48 namespace {
49 // Sends packets, Shutdown(SHUT_WR) on destruction
50 class SocketSender {
51  public:
SocketSender(cuttlefish::SharedFD socket)52   explicit SocketSender(cuttlefish::SharedFD socket) : socket_{socket} {}
53 
54   SocketSender(SocketSender&&) = default;
55   SocketSender& operator=(SocketSender&&) = default;
56 
57   SocketSender(const SocketSender&&) = delete;
58   SocketSender& operator=(const SocketSender&) = delete;
59 
~SocketSender()60   ~SocketSender() {
61     if (socket_.operator->()) {  // check that socket_ was not moved-from
62       socket_->Shutdown(SHUT_WR);
63     }
64   }
65 
SendAll(const char * packet,ssize_t length)66   ssize_t SendAll(const char* packet, ssize_t length) {
67     ssize_t written{};
68     while (written < length) {
69       if (!socket_->IsOpen()) {
70         return -1;
71       }
72       auto just_written =
73           socket_->Send(packet + written,
74                         length - written, MSG_NOSIGNAL);
75       if (just_written <= 0) {
76         LOG(WARNING) << "Couldn't write to client: "
77                      << strerror(socket_->GetErrno());
78         return just_written;
79       }
80       written += just_written;
81     }
82     return written;
83   }
84 
85  private:
86   cuttlefish::SharedFD socket_;
87 };
88 
89 class SocketReceiver {
90  public:
SocketReceiver(cuttlefish::SharedFD socket)91   explicit SocketReceiver(cuttlefish::SharedFD socket) : socket_{socket} {}
92 
93   SocketReceiver(SocketReceiver&&) = default;
94   SocketReceiver& operator=(SocketReceiver&&) = default;
95 
96   SocketReceiver(const SocketReceiver&&) = delete;
97   SocketReceiver& operator=(const SocketReceiver&) = delete;
98 
99   // return value will be 0 if Read returns 0 or error
Recv(char * packet,ssize_t length)100   ssize_t Recv(char* packet, ssize_t length) {
101     auto size = socket_->Read(packet, length);
102     if (size < 0) {
103       size = 0;
104     }
105 
106     return size;
107   }
108 
109  private:
110   cuttlefish::SharedFD socket_;
111 };
112 
SocketToVsock(SocketReceiver socket_receiver,SocketSender vsock_sender)113 void SocketToVsock(SocketReceiver socket_receiver,
114                    SocketSender vsock_sender) {
115   char packet[kMaxPacketSize] = {};
116 
117   while (true) {
118     ssize_t length = socket_receiver.Recv(packet, kMaxPacketSize);
119     if (length == 0 || vsock_sender.SendAll(packet, length) < 0) {
120       break;
121     }
122   }
123   LOG(DEBUG) << "Socket to vsock exiting";
124 }
125 
VsockToSocket(SocketSender socket_sender,SocketReceiver vsock_receiver)126 void VsockToSocket(SocketSender socket_sender,
127                    SocketReceiver vsock_receiver) {
128   char packet[kMaxPacketSize] = {};
129 
130   while (true) {
131     ssize_t length = vsock_receiver.Recv(packet, kMaxPacketSize);
132     if (length == 0) {
133       break;
134     }
135     if (socket_sender.SendAll(packet, length) < 0) {
136       break;
137     }
138   }
139   LOG(DEBUG) << "Vsock to socket exiting";
140 }
141 
142 // One thread for reading from shm and writing into a socket.
143 // One thread for reading from a socket and writing into shm.
HandleConnection(cuttlefish::SharedFD vsock,cuttlefish::SharedFD socket)144 void HandleConnection(cuttlefish::SharedFD vsock,
145                       cuttlefish::SharedFD socket) {
146   auto socket_to_vsock =
147       std::thread(SocketToVsock, SocketReceiver{socket}, SocketSender{vsock});
148   VsockToSocket(SocketSender{socket}, SocketReceiver{vsock});
149   socket_to_vsock.join();
150 }
151 
WaitForAdbdToBeStarted(int events_fd)152 void WaitForAdbdToBeStarted(int events_fd) {
153   auto evt_shared_fd = cuttlefish::SharedFD::Dup(events_fd);
154   close(events_fd);
155   while (evt_shared_fd->IsOpen()) {
156     std::optional<monitor::ReadEventResult> read_result =
157         monitor::ReadEvent(evt_shared_fd);
158     if (!read_result) {
159       LOG(ERROR) << "Failed to read a complete kernel log adb event.";
160       // The file descriptor can't be trusted anymore, stop waiting and try to
161       // connect
162       return;
163     }
164 
165     if (read_result->event == monitor::Event::AdbdStarted) {
166       LOG(DEBUG) << "Adbd has started in the guest, connecting adb";
167       return;
168     }
169   }
170 }
171 
172 // intented to run as cuttlefish host service
TcpServer()173 [[noreturn]] void TcpServer() {
174   LOG(DEBUG) << "starting TCP server on " << FLAGS_tcp_port
175              << " for vsock port " << FLAGS_vsock_port;
176   cuttlefish::SharedFD server;
177   if (FLAGS_server_fd < 0) {
178     server =
179         cuttlefish::SharedFD::SocketLocalServer(FLAGS_tcp_port, SOCK_STREAM);
180   } else {
181     server = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
182     close(FLAGS_server_fd);
183   }
184   CHECK(server->IsOpen()) << "Could not start server on " << FLAGS_tcp_port;
185   LOG(DEBUG) << "Accepting client connections";
186   int last_failure_reason = 0;
187   while (true) {
188     auto client_socket = cuttlefish::SharedFD::Accept(*server);
189     CHECK(client_socket->IsOpen()) << "error creating client socket";
190     cuttlefish::SharedFD vsock_socket = cuttlefish::SharedFD::VsockClient(
191         FLAGS_vsock_cid, FLAGS_vsock_port, SOCK_STREAM);
192     if (vsock_socket->IsOpen()) {
193       last_failure_reason = 0;
194       LOG(DEBUG) << "Connected to vsock:" << FLAGS_vsock_cid << ":"
195                  << FLAGS_vsock_port;
196     } else {
197       // Don't log if the previous connection failed with the same error
198       if (last_failure_reason != vsock_socket->GetErrno()) {
199         last_failure_reason = vsock_socket->GetErrno();
200         LOG(ERROR) << "Unable to connect to vsock server: "
201                    << vsock_socket->StrError();
202       }
203       continue;
204     }
205     auto thread = std::thread(HandleConnection, std::move(vsock_socket),
206                               std::move(client_socket));
207     thread.detach();
208   }
209 }
210 
OpenSocketConnection()211 cuttlefish::SharedFD OpenSocketConnection() {
212   while (true) {
213     auto sock = cuttlefish::SharedFD::SocketLocalClient(FLAGS_tcp_port, SOCK_STREAM);
214     if (sock->IsOpen()) {
215       return sock;
216     }
217     LOG(WARNING) << "could not connect on port " << FLAGS_tcp_port
218                  << ". sleeping for 1 second";
219     sleep(1);
220   }
221 }
222 
socketErrorIsRecoverable(int error)223 bool socketErrorIsRecoverable(int error) {
224   std::set<int> unrecoverable{EACCES, EAFNOSUPPORT, EINVAL, EPROTONOSUPPORT};
225   return unrecoverable.find(error) == unrecoverable.end();
226 }
227 
SleepForever()228 [[noreturn]] static void SleepForever() {
229   while (true) {
230     sleep(std::numeric_limits<unsigned int>::max());
231   }
232 }
233 
234 // intended to run inside Android guest
VsockServer()235 [[noreturn]] void VsockServer() {
236   LOG(DEBUG) << "Starting vsock server on " << FLAGS_vsock_port;
237   cuttlefish::SharedFD vsock;
238   if (FLAGS_server_fd < 0) {
239     do {
240       vsock = cuttlefish::SharedFD::VsockServer(FLAGS_vsock_port, SOCK_STREAM);
241       if (!vsock->IsOpen() && !socketErrorIsRecoverable(vsock->GetErrno())) {
242         LOG(ERROR) << "Could not open vsock socket: " << vsock->StrError();
243         SleepForever();
244       }
245     } while (!vsock->IsOpen());
246   } else {
247     vsock = cuttlefish::SharedFD::Dup(FLAGS_server_fd);
248     close(FLAGS_server_fd);
249   }
250   CHECK(vsock->IsOpen()) << "Could not start server on " << FLAGS_vsock_port;
251   while (true) {
252     LOG(DEBUG) << "waiting for vsock connection";
253     auto vsock_client = cuttlefish::SharedFD::Accept(*vsock);
254     CHECK(vsock_client->IsOpen()) << "error creating vsock socket";
255     LOG(DEBUG) << "vsock socket accepted";
256     auto client = OpenSocketConnection();
257     CHECK(client->IsOpen()) << "error connecting to guest client";
258     auto thread = std::thread(HandleConnection, std::move(vsock_client),
259                               std::move(client));
260     thread.detach();
261   }
262 }
263 
264 }  // namespace
265 
main(int argc,char * argv[])266 int main(int argc, char* argv[]) {
267 #ifdef CUTTLEFISH_HOST
268   cuttlefish::DefaultSubprocessLogging(argv);
269 #else
270   ::android::base::InitLogging(argv, android::base::LogdLogger());
271 #endif
272   google::ParseCommandLineFlags(&argc, &argv, true);
273 
274   CHECK((FLAGS_server == "tcp" && FLAGS_server_fd >= 0) || FLAGS_tcp_port != 0)
275       << "Must specify -tcp_port or -server_fd (with -server=tcp) flag";
276   CHECK((FLAGS_server == "vsock" && FLAGS_server_fd >= 0) ||
277         FLAGS_vsock_port != 0)
278       << "Must specify -vsock_port or -server_fd (with -server=vsock) flag";
279 
280   if (FLAGS_adbd_events_fd >= 0) {
281     LOG(DEBUG) << "Wating AdbdStarted boot event from the kernel log";
282     WaitForAdbdToBeStarted(FLAGS_adbd_events_fd);
283   }
284 
285   if (FLAGS_server == "tcp") {
286     CHECK(FLAGS_vsock_cid != 0) << "Must specify -vsock_cid flag";
287     TcpServer();
288   } else if (FLAGS_server == "vsock") {
289     VsockServer();
290   } else {
291     LOG(FATAL) << "Unknown server type: " << FLAGS_server;
292   }
293 }
294