• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <poll.h>
18 #include <unistd.h>
19 #include <ios>
20 #include <mutex>
21 
22 #include <android-base/logging.h>
23 #include <gflags/gflags.h>
24 #include <thread>
25 
26 #include "common/libs/fs/shared_buf.h"
27 #include "common/libs/fs/shared_fd.h"
28 #include "host/libs/config/cuttlefish_config.h"
29 #include "host/libs/config/logging.h"
30 
31 DEFINE_int32(fifo_in, -1, "A pipe for incoming communication");
32 DEFINE_int32(fifo_out, -1, "A pipe for outgoing communication");
33 DEFINE_int32(data_port, -1, "A port for data");
34 DEFINE_int32(buffer_size, -1, "The buffer size");
35 DEFINE_int32(dump_packet_size, -1,
36              "Dump incoming/outgoing packets up to given size");
37 
OpenSocket(cuttlefish::SharedFD * fd,int port)38 void OpenSocket(cuttlefish::SharedFD* fd, int port) {
39   static std::mutex mutex;
40   std::unique_lock<std::mutex> lock(mutex);
41   for (;;) {
42     *fd = cuttlefish::SharedFD::SocketLocalClient(port, SOCK_STREAM);
43     if ((*fd)->IsOpen()) {
44       return;
45     }
46     LOG(ERROR) << "Failed to open socket: " << (*fd)->StrError();
47     // Wait a little and try again
48     sleep(1);
49   }
50 }
51 
DumpPackets(const char * prefix,char * buf,int size)52 void DumpPackets(const char* prefix, char* buf, int size) {
53   if (FLAGS_dump_packet_size < 0 || size <= 0) {
54     return;
55   }
56   char bytes_string[1001] = {0};
57   int len = FLAGS_dump_packet_size < size ? FLAGS_dump_packet_size : size;
58   for (int i = 0; i < len; i++) {
59     if ((i + 1) * 5 > sizeof(bytes_string)) {
60       // Buffer out of bounds
61       break;
62     }
63     sprintf(bytes_string + (i * 5), "0x%02x ", buf[i]);
64   }
65   if (len < size) {
66     LOG(DEBUG) << prefix << ": sz=" << size << ", first " << len << " bytes=["
67                << bytes_string << "...]";
68   } else {
69     LOG(DEBUG) << prefix << ": sz=" << size << ", bytes=[" << bytes_string
70                << "]";
71   }
72 }
73 
main(int argc,char ** argv)74 int main(int argc, char** argv) {
75   cuttlefish::DefaultSubprocessLogging(argv);
76   gflags::ParseCommandLineFlags(&argc, &argv, true);
77   auto fifo_in = cuttlefish::SharedFD::Dup(FLAGS_fifo_in);
78   if (!fifo_in->IsOpen()) {
79     LOG(ERROR) << "Error dupping fd " << FLAGS_fifo_in << ": "
80                << fifo_in->StrError();
81     return 1;
82   }
83   close(FLAGS_fifo_in);
84 
85   auto fifo_out = cuttlefish::SharedFD::Dup(FLAGS_fifo_out);
86   if (!fifo_out->IsOpen()) {
87     LOG(ERROR) << "Error dupping fd " << FLAGS_fifo_out << ": "
88                << fifo_out->StrError();
89     return 1;
90   }
91   close(FLAGS_fifo_out);
92   cuttlefish::SharedFD sock;
93   OpenSocket(&sock, FLAGS_data_port);
94 
95   auto guest_to_host = std::thread([&]() {
96     while (true) {
97       char buf[FLAGS_buffer_size];
98       auto read = fifo_in->Read(buf, sizeof(buf));
99       if (read < 0) {
100         LOG(WARNING) << "Error reading from guest: " << fifo_in->StrError();
101         sleep(1);
102         continue;
103       }
104       DumpPackets("Read from FIFO", buf, read);
105       while (cuttlefish::WriteAll(sock, buf, read) == -1) {
106         LOG(WARNING) << "Failed to write to host socket (will retry): "
107                      << sock->StrError();
108         // Wait for the host process to be ready
109         sleep(1);
110         OpenSocket(&sock, FLAGS_data_port);
111       }
112     }
113   });
114 
115   auto host_to_guest = std::thread([&]() {
116     while (true) {
117       char buf[FLAGS_buffer_size];
118       auto read = sock->Read(buf, sizeof(buf));
119       DumpPackets("Read from socket", buf, read);
120       if (read == -1) {
121         LOG(WARNING) << "Failed to read from host socket (will retry): "
122                      << sock->StrError();
123         // Wait for the host process to be ready
124         sleep(1);
125         OpenSocket(&sock, FLAGS_data_port);
126         continue;
127       }
128       auto wrote = cuttlefish::WriteAll(fifo_out, buf, read);
129       if (wrote < 0) {
130         LOG(WARNING) << "Failed to write to guest: " << fifo_out->StrError();
131         sleep(1);
132         continue;
133       }
134     }
135   });
136   guest_to_host.join();
137   host_to_guest.join();
138 }
139