socket_forward_proxy_[host_]ports to launch_cvd
launch_cvd will pass 5555 as the guest port, and a biased host port that
is bumped in increments of 2, (5555, 5557, 5559, ...).
I also needed to split strings in a few spots. I made the interface
match the most simple version of abseil::StrSplit in case we ever manage
to get those string utilities.
BUG: 73011528
Change-Id: Iba0dea36a45789b629d8c73e581a8d05021ef892
diff --git a/common/frontend/socket_forward_proxy/Android.bp b/common/frontend/socket_forward_proxy/Android.bp
index c70983e..caad62b 100644
--- a/common/frontend/socket_forward_proxy/Android.bp
+++ b/common/frontend/socket_forward_proxy/Android.bp
@@ -21,6 +21,7 @@
shared_libs: [
"libbase",
"libcuttlefish_fs",
+ "libcuttlefish_strings",
"cuttlefish_auto_resources",
"vsoc_lib",
"liblog",
diff --git a/common/frontend/socket_forward_proxy/main.cpp b/common/frontend/socket_forward_proxy/main.cpp
index ad1ca10..ed4196e 100644
--- a/common/frontend/socket_forward_proxy/main.cpp
+++ b/common/frontend/socket_forward_proxy/main.cpp
@@ -29,6 +29,7 @@
#include <unistd.h>
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/strings/str_split.h"
#include "common/vsoc/lib/socket_forward_region_view.h"
#ifdef CUTTLEFISH_HOST
@@ -39,9 +40,12 @@
using vsoc::socket_forward::SocketForwardRegionView;
#ifdef CUTTLEFISH_HOST
-DEFINE_string(ports, "",
- "Comma-separated list of ports from which to forward TCP "
- "connections.");
+DEFINE_string(guest_ports, "",
+ "Comma-separated list of ports on which to forward TCP "
+ "connections to the guest.");
+DEFINE_string(host_ports, "",
+ "Comma-separated list of ports on which to run TCP servers on "
+ "the host.");
#endif
namespace {
@@ -154,44 +158,53 @@
}
#ifdef CUTTLEFISH_HOST
+struct PortPair {
+ int guest_port;
+ int host_port;
+};
+
+
[[noreturn]] void host_impl(SocketForwardRegionView* shm,
- std::vector<int> ports, std::size_t index) {
+ std::vector<PortPair> ports, std::size_t index) {
// launch a worker for the following port before handling the current port.
// recursion (instead of a loop) removes the need fore any join() or having
// the main thread do no work.
if (index + 1 < ports.size()) {
std::thread(host_impl, shm, ports, index + 1).detach();
}
- auto remote_port = ports[index];
- auto local_port = vsoc::GetPerInstanceDefault(remote_port);
- LOG(INFO) << "starting server on " << local_port
- << " for guest port " << remote_port;
- auto server = cvd::SharedFD::SocketLocalServer(local_port, SOCK_STREAM);
- CHECK(server->IsOpen()) << "Could not start server on port " << local_port;
+ auto guest_port = ports[index].guest_port;
+ auto host_port = ports[index].host_port;
+ LOG(INFO) << "starting server on " << host_port
+ << " for guest port " << guest_port;
+ auto server = cvd::SharedFD::SocketLocalServer(host_port, SOCK_STREAM);
+ CHECK(server->IsOpen()) << "Could not start server on port " << host_port;
while (true) {
auto client_socket = cvd::SharedFD::Accept(*server);
CHECK(client_socket->IsOpen()) << "error creating client socket";
LOG(INFO) << "client socket accepted";
- auto conn = shm->OpenConnection(remote_port);
+ auto conn = shm->OpenConnection(guest_port);
LOG(INFO) << "shm connection opened";
LaunchWorkers(std::move(conn), std::move(client_socket));
}
}
[[noreturn]] void host(SocketForwardRegionView* shm,
- std::vector<int> ports) {
+ std::vector<PortPair> ports) {
CHECK(!ports.empty());
host_impl(shm, ports, 0);
}
-std::vector<int> ParsePortsList(const std::string& ports_flag) {
- std::istringstream ports_stream{ports_flag};
- std::vector<int> ports;
- std::string port_str{};
- while (std::getline(ports_stream, port_str, ',')) {
- ports.push_back(std::stoi(port_str));
+std::vector<PortPair> ParsePortsList(const std::string& guest_ports_str,
+ const std::string& host_ports_str) {
+ std::vector<PortPair> ports{};
+ auto guest_ports = cvd::StrSplit(guest_ports_str, ',');
+ auto host_ports = cvd::StrSplit(host_ports_str, ',');
+ CHECK(guest_ports.size() == host_ports.size());
+ for (std::size_t i = 0; i < guest_ports.size(); ++i) {
+ ports.push_back({std::stoi(guest_ports[i]), std::stoi(host_ports[i])});
}
return ports;
+
}
#else
@@ -250,8 +263,9 @@
auto worker = shm->StartWorker();
#ifdef CUTTLEFISH_HOST
- CHECK(!FLAGS_ports.empty()) << "Must specify --ports flag";
- host(shm, ParsePortsList(FLAGS_ports));
+ CHECK(!FLAGS_guest_ports.empty()) << "Must specify --guest_ports flag";
+ CHECK(!FLAGS_host_ports.empty()) << "Must specify --host_ports flag";
+ host(shm, ParsePortsList(FLAGS_guest_ports, FLAGS_host_ports));
#else
guest(shm);
#endif
diff --git a/common/libs/Android.bp b/common/libs/Android.bp
index b23571f..cb4ec3e 100644
--- a/common/libs/Android.bp
+++ b/common/libs/Android.bp
@@ -17,6 +17,7 @@
"auto_resources",
"fs",
"net",
+ "strings",
"tcp_socket",
"threads",
"time",
diff --git a/common/libs/strings/Android.bp b/common/libs/strings/Android.bp
new file mode 100644
index 0000000..273c79e
--- /dev/null
+++ b/common/libs/strings/Android.bp
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+ name: "libcuttlefish_strings",
+ srcs: [
+ "str_split.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ ],
+ defaults: ["cuttlefish_host_and_guest"],
+}
diff --git a/common/libs/strings/str_split.cpp b/common/libs/strings/str_split.cpp
new file mode 100644
index 0000000..d76acad
--- /dev/null
+++ b/common/libs/strings/str_split.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/libs/strings/str_split.h"
+
+#include <vector>
+#include <string>
+#include <sstream>
+
+std::vector<std::string> cvd::StrSplit(const std::string& src, char delimiter) {
+ std::istringstream stream{src};
+ std::vector<std::string> result;
+ for (std::string s; std::getline(stream, s, delimiter); s.clear()) {
+ result.push_back(std::move(s));
+ }
+ return result;
+}
diff --git a/common/libs/strings/str_split.h b/common/libs/strings/str_split.h
new file mode 100644
index 0000000..cd18d15
--- /dev/null
+++ b/common/libs/strings/str_split.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CUTTLEFISH_COMMON_COMMON_LIBS_STRINGS_STR_SPLIT_H_
+#define CUTTLEFISH_COMMON_COMMON_LIBS_STRINGS_STR_SPLIT_H_
+
+#include <vector>
+#include <string>
+
+namespace cvd {
+std::vector<std::string> StrSplit(const std::string& src, char delimiter);
+} // namespace cvd
+
+#endif
diff --git a/host/commands/launch/Android.bp b/host/commands/launch/Android.bp
index 420df07..ac38519 100644
--- a/host/commands/launch/Android.bp
+++ b/host/commands/launch/Android.bp
@@ -11,6 +11,7 @@
shared_libs: [
"vsoc_lib",
"libcuttlefish_fs",
+ "libcuttlefish_strings",
"cuttlefish_auto_resources",
"libicuuc",
"libbase",
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index eacd5da..416ebf1 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -22,15 +22,19 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <algorithm>
#include <fstream>
#include <iomanip>
#include <memory>
#include <sstream>
+#include <string>
+#include <vector>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "common/libs/fs/shared_select.h"
+#include "common/libs/strings/str_split.h"
#include "host/commands/launch/pre_launch_initializers.h"
#include "host/libs/config/file_partition.h"
#include "host/libs/config/guest_config.h"
@@ -112,17 +116,12 @@
StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
"/bin/vnc_server",
"Location of the vnc server binary.");
-DEFINE_int32(vnc_server_port, vsoc::GetPerInstanceDefault(6444),
+DEFINE_int32(vnc_server_port, GetPerInstanceDefault(6444),
"The port on which the vnc server should listen");
DEFINE_string(socket_forward_proxy_binary,
StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) +
"/bin/socket_forward_proxy",
"Location of the socket_forward_proxy binary.");
-DEFINE_string(socket_forward_proxy_ports, "5555", "Comma-separated list of "
- "ports on which to run the socket_forward_proxy server. These "
- "are the port numbers of the guest-side process. The "
- "host-side socket_forward_proxy process will bias the port "
- "numbers.");
DEFINE_bool(start_wifi_relay, true, "Whether to start the wifi_relay process.");
DEFINE_string(wifi_relay_binary,
@@ -309,6 +308,20 @@
"/bin/rm", "-f", file.c_str(), NULL};
subprocess(rm_command, NULL);
}
+
+
+// Emulators are discovered on odd numbered ports from 5555 to 5585
+constexpr int kFirstEmulatorPort = 5555;
+
+std::string GetGuestPortArg() {
+ return std::string{"--guest_ports="} + std::to_string(kFirstEmulatorPort);
+}
+
+std::string GetHostPortArg() {
+ return std::string{"--host_ports="} +
+ std::to_string(kFirstEmulatorPort + (vsoc::GetDefaultInstance() - 1) * 2);
+}
+
} // anonymous namespace
int main(int argc, char** argv) {
@@ -419,9 +432,14 @@
std::string entropy_source = "/dev/urandom";
- auto port_arg = std::string{"--ports="} + FLAGS_socket_forward_proxy_ports;
+ auto guest_port_arg = GetGuestPortArg();
+ auto host_port_arg = GetHostPortArg();
+
const char* const socket_proxy[] =
- {FLAGS_socket_forward_proxy_binary.c_str(), port_arg.c_str(), NULL};
+ {FLAGS_socket_forward_proxy_binary.c_str(),
+ guest_port_arg.c_str(),
+ host_port_arg.c_str(),
+ NULL};
subprocess(socket_proxy, nullptr, false);
config::GuestConfig cfg;