[cdc_rsync] Use any available server port (#94)

Instead of calling netstat on the remote device to detect available
ports, simply call bind with port 0 to bind to any available port.
Since the port is not yet known when cdc_rsync_server.exe is called,
port forwarding needs to be started AFTER the server reports its port.
This commit is contained in:
Lutz Justen
2023-03-06 14:16:21 +01:00
committed by GitHub
parent 5fd86e4625
commit a8059e8572
10 changed files with 137 additions and 131 deletions

View File

@@ -63,7 +63,6 @@ jobs:
--test_output=errors --local_test_jobs=1 \ --test_output=errors --local_test_jobs=1 \
-- //... -//third_party/... -//cdc_rsync_server:file_finder_test -- //... -//third_party/... -//cdc_rsync_server:file_finder_test
# The artifact collector doesn't like the fact that bazel-bin is a symlink.
- name: Copy artifacts - name: Copy artifacts
run: | run: |
mkdir artifacts mkdir artifacts
@@ -152,7 +151,6 @@ jobs:
//manifest/... ` //manifest/... `
//metrics/... //metrics/...
# The artifact collector doesn't like the fact that bazel-bin is a symlink.
- name: Copy artifacts - name: Copy artifacts
run: | run: |
mkdir artifacts mkdir artifacts

View File

@@ -3,7 +3,7 @@ name: Lint
on: on:
push: push:
branches: branches:
- master - main
pull_request: pull_request:
jobs: jobs:

View File

@@ -118,7 +118,7 @@ CdcRsyncClient::CdcRsyncClient(const Options& options,
port_manager_ = std::make_unique<PortManager>( port_manager_ = std::make_unique<PortManager>(
"cdc_rsync_ports_f77bcdfe-368c-4c45-9f01-230c5e7e2132", "cdc_rsync_ports_f77bcdfe-368c-4c45-9f01-230c5e7e2132",
options.forward_port_first, options.forward_port_last, &process_factory_, options.forward_port_first, options.forward_port_last, &process_factory_,
remote_util_.get()); nullptr /* never reserve remote ports */);
} }
CdcRsyncClient::~CdcRsyncClient() { CdcRsyncClient::~CdcRsyncClient() {
@@ -127,19 +127,15 @@ CdcRsyncClient::~CdcRsyncClient() {
} }
absl::Status CdcRsyncClient::Run() { absl::Status CdcRsyncClient::Run() {
// If |remote_util_| is not set, it's a local sync. Otherwise, guess the // For local syncs, cdc_rsync_server runs on this machine. For remote syncs,
// architecture of the device that runs cdc_rsync_server from the destination // guess the architecture of the device that runs cdc_rsync_server from the
// path, e.g. "C:\path\to\dest" strongly indicates Windows. // destination path, e.g. "C:\path\to\dest" strongly indicates Windows.
ServerArch server_arch = !remote_util_ ServerArch server_arch = IsRemoteConnection()
? ServerArch::DetectFromLocalDevice() ? ServerArch::GuessFromDestination(destination_)
: ServerArch::GuessFromDestination(destination_); : ServerArch::DetectFromLocalDevice();
int port;
ASSIGN_OR_RETURN(port, FindAvailablePort(&server_arch),
"Failed to find available port");
// Start the server process. // Start the server process.
absl::Status status = StartServer(port, server_arch); absl::Status status = StartServer(server_arch);
if (HasTag(status, Tag::kDeployServer) && server_arch.IsGuess() && if (HasTag(status, Tag::kDeployServer) && server_arch.IsGuess() &&
server_exit_code_ != kServerExitCodeOutOfDate) { server_exit_code_ != kServerExitCodeOutOfDate) {
// Server couldn't be run, e.g. not found or failed to start. // Server couldn't be run, e.g. not found or failed to start.
@@ -155,7 +151,7 @@ absl::Status CdcRsyncClient::Run() {
if (server_arch.GetType() != old_type) { if (server_arch.GetType() != old_type) {
LOG_DEBUG("Guessed server arch type wrong, guessed %s, actual %s.", LOG_DEBUG("Guessed server arch type wrong, guessed %s, actual %s.",
GetArchTypeStr(old_type), server_arch.GetTypeStr()); GetArchTypeStr(old_type), server_arch.GetTypeStr());
status = StartServer(port, server_arch); status = StartServer(server_arch);
} }
} }
@@ -166,7 +162,7 @@ absl::Status CdcRsyncClient::Run() {
return WrapStatus(status, "Failed to deploy server"); return WrapStatus(status, "Failed to deploy server");
} }
status = StartServer(port, server_arch); status = StartServer(server_arch);
} }
if (!status.ok()) { if (!status.ok()) {
return WrapStatus(status, "Failed to start server"); return WrapStatus(status, "Failed to start server");
@@ -198,47 +194,7 @@ absl::Status CdcRsyncClient::Run() {
return status; return status;
} }
absl::StatusOr<int> CdcRsyncClient::FindAvailablePort(ServerArch* server_arch) { absl::Status CdcRsyncClient::StartServer(const ServerArch& arch) {
// Find available local and remote ports for port forwarding.
// If only one port is in the given range, try that without checking.
if (options_.forward_port_first >= options_.forward_port_last) {
return options_.forward_port_first;
}
assert(server_arch);
absl::StatusOr<int> port = port_manager_->ReservePort(
options_.connection_timeout_sec, server_arch->GetType());
if (absl::IsDeadlineExceeded(port.status())) {
// Server didn't respond in time.
return SetTag(port.status(), Tag::kConnectionTimeout);
}
if (absl::IsResourceExhausted(port.status())) {
// Port in use.
return SetTag(port.status(), Tag::kAddressInUse);
}
// If |server_arch| was guessed, calling netstat might have failed because
// the arch was wrong. Properly detect it and try again if it changed.
if (!port.ok() && server_arch->IsGuess()) {
const ArchType old_type = server_arch->GetType();
LOG_DEBUG(
"Failed to reserve port, retrying after detecting remote arch: %s",
port.status().ToString());
ASSIGN_OR_RETURN(*server_arch,
ServerArch::DetectFromRemoteDevice(remote_util_.get()));
assert(!server_arch->IsGuess());
if (server_arch->GetType() != old_type) {
LOG_DEBUG("Guessed server arch type wrong, guessed %s, actual %s.",
GetArchTypeStr(old_type), server_arch->GetTypeStr());
return FindAvailablePort(server_arch);
}
}
return port;
}
absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
assert(!server_process_); assert(!server_process_);
// Components are expected to reside in the same dir as the executable. // Components are expected to reside in the same dir as the executable.
@@ -262,20 +218,20 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
ProcessStartInfo start_info; ProcessStartInfo start_info;
start_info.name = "cdc_rsync_server"; start_info.name = "cdc_rsync_server";
if (remote_util_) { if (IsRemoteConnection()) {
// Run cdc_rsync_server on the remote instance. // Run cdc_rsync_server on the remote instance.
std::string remote_command = arch.GetStartServerCommand( std::string remote_command =
kExitCodeNotFound, absl::StrFormat("%i %s", port, component_args)); arch.GetStartServerCommand(kExitCodeNotFound, component_args);
start_info = remote_util_->BuildProcessStartInfoForSshPortForwardAndCommand( assert(remote_util_);
port, port, /*reverse=*/false, remote_command, arch.GetType()); start_info = remote_util_->BuildProcessStartInfoForSsh(remote_command,
arch.GetType());
} else { } else {
// Run cdc_rsync_server locally. // Run cdc_rsync_server locally.
std::string exe_dir; std::string exe_dir;
RETURN_IF_ERROR(path::GetExeDir(&exe_dir), "Failed to get exe directory"); RETURN_IF_ERROR(path::GetExeDir(&exe_dir), "Failed to get exe directory");
std::string server_path = path::Join(exe_dir, arch.CdcServerFilename()); std::string server_path = path::Join(exe_dir, arch.CdcServerFilename());
start_info.command = start_info.command = absl::StrFormat("%s %s", server_path, component_args);
absl::StrFormat("%s %i %s", server_path, port, component_args);
} }
// Capture stdout, but forward to stdout for debugging purposes. // Capture stdout, but forward to stdout for debugging purposes.
@@ -283,8 +239,8 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
return HandleServerOutput(data); return HandleServerOutput(data);
}; };
std::unique_ptr<Process> process = process_factory_.Create(start_info); std::unique_ptr<Process> srv_process = process_factory_.Create(start_info);
status = process->Start(); status = srv_process->Start();
if (!status.ok()) { if (!status.ok()) {
return WrapStatus(status, "Failed to start cdc_rsync_server process"); return WrapStatus(status, "Failed to start cdc_rsync_server process");
} }
@@ -292,13 +248,13 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
// Wait until the server process is listening. // Wait until the server process is listening.
Stopwatch timeout_timer; Stopwatch timeout_timer;
bool is_timeout = false; bool is_timeout = false;
auto detect_listening_or_timeout = [is_listening = &is_server_listening_, auto detect_listening_or_timeout = [port = &server_listen_port_,
timeout = options_.connection_timeout_sec, timeout = options_.connection_timeout_sec,
&timeout_timer, &is_timeout]() -> bool { &timeout_timer, &is_timeout]() -> bool {
is_timeout = timeout_timer.ElapsedSeconds() > timeout; is_timeout = timeout_timer.ElapsedSeconds() > timeout;
return *is_listening || is_timeout; return *port != 0 || is_timeout;
}; };
status = process->RunUntil(detect_listening_or_timeout); status = srv_process->RunUntil(detect_listening_or_timeout);
if (!status.ok()) { if (!status.ok()) {
// Some internal process error. Note that this does NOT mean that // Some internal process error. Note that this does NOT mean that
// cdc_rsync_server does not exist. In that case, the ssh process exits with // cdc_rsync_server does not exist. In that case, the ssh process exits with
@@ -310,10 +266,10 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
Tag::kConnectionTimeout); Tag::kConnectionTimeout);
} }
if (process->HasExited()) { if (srv_process->HasExited()) {
// Don't re-deploy for code > kServerExitCodeOutOfDate, which means that the // Don't re-deploy for code > kServerExitCodeOutOfDate, which means that the
// out-of-date check already passed on the server. // out-of-date check already passed on the server.
server_exit_code_ = process->ExitCode(); server_exit_code_ = srv_process->ExitCode();
if (server_exit_code_ > kServerExitCodeOutOfDate && if (server_exit_code_ > kServerExitCodeOutOfDate &&
server_exit_code_ <= kServerExitCodeMax) { server_exit_code_ <= kServerExitCodeMax) {
return GetServerExitStatus(server_exit_code_, server_error_); return GetServerExitStatus(server_exit_code_, server_error_);
@@ -321,7 +277,7 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
// Don't re-deploy if we're not copying to a remote device. We can start // Don't re-deploy if we're not copying to a remote device. We can start
// cdc_rsync_server from the original location directly. // cdc_rsync_server from the original location directly.
if (!remote_util_) { if (!IsRemoteConnection()) {
return GetServerExitStatus(server_exit_code_, server_error_); return GetServerExitStatus(server_exit_code_, server_error_);
} }
@@ -332,19 +288,58 @@ absl::Status CdcRsyncClient::StartServer(int port, const ServerArch& arch) {
return SetTag(MakeStatus("Redeploy server"), Tag::kDeployServer); return SetTag(MakeStatus("Redeploy server"), Tag::kDeployServer);
} }
// Now that we know which port the server is using, set up port forwarding.
std::unique_ptr<Process> fwd_process;
int local_port = server_listen_port_;
if (IsRemoteConnection()) {
absl::StatusOr<int> local_port_or = port_manager_->ReservePort(
options_.connection_timeout_sec, arch.GetType());
if (absl::IsResourceExhausted(local_port_or.status())) {
// Port in use.
return SetTag(local_port_or.status(), Tag::kAddressInUse);
}
if (!local_port_or.ok()) {
return local_port_or.status();
}
local_port = *local_port_or;
ProcessStartInfo start_info =
remote_util_->BuildProcessStartInfoForSshPortForward(
local_port, server_listen_port_, /*reverse=*/false);
start_info.forward_output_to_log = true;
fwd_process = process_factory_.Create(start_info);
RETURN_IF_ERROR(fwd_process->Start(),
"Failed to start cdc_rsync_server process");
}
// Connect to the socket with port |local_port|.
status = Socket::Initialize(); status = Socket::Initialize();
if (!status.ok()) { if (!status.ok()) {
return WrapStatus(status, "Failed to initialize sockets"); return WrapStatus(status, "Failed to initialize sockets");
} }
socket_finalizer_ = std::make_unique<SocketFinalizer>(); socket_finalizer_ = std::make_unique<SocketFinalizer>();
assert(is_server_listening_); // Poll until the port forwarding connection is set up.
status = socket_.Connect(port); timeout_timer.Reset();
if (!status.ok()) { for (;;) {
return WrapStatus(status, "Failed to initialize connection"); assert(local_port != 0);
status = socket_.Connect(local_port);
if (status.ok()) {
break;
} }
server_process_ = std::move(process); if (timeout_timer.ElapsedSeconds() > options_.connection_timeout_sec) {
return SetTag(
absl::DeadlineExceededError("Timeout while connecting to server"),
Tag::kConnectionTimeout);
}
Util::Sleep(10);
}
server_process_ = std::move(srv_process);
port_forwarding_process_ = std::move(fwd_process);
message_pump_.StartMessagePump(); message_pump_.StartMessagePump();
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -365,6 +360,7 @@ absl::Status CdcRsyncClient::StopServer() {
server_exit_code_ = server_process_->ExitCode(); server_exit_code_ = server_process_->ExitCode();
server_process_.reset(); server_process_.reset();
port_forwarding_process_.reset();
return absl::OkStatus(); return absl::OkStatus();
} }
@@ -396,10 +392,29 @@ absl::Status CdcRsyncClient::HandleServerOutput(const char* data) {
} }
printer_.Print(stdout_data, false, Util::GetConsoleWidth()); printer_.Print(stdout_data, false, Util::GetConsoleWidth());
if (!is_server_listening_) { if (server_listen_port_ == 0) {
server_output_.append(stdout_data); server_output_.append(stdout_data);
is_server_listening_ =
server_output_.find("Server is listening") != std::string::npos; // Parse port from "Port <n>: Server is listening".
size_t listening_pos = server_output_.find("Server is listening");
if (listening_pos != std::string::npos) {
// Search backwards until we find "Port ".
constexpr char port_key[] = "Port ";
size_t port_pos = server_output_.rfind(port_key, listening_pos);
if (port_pos == std::string::npos) {
return MakeStatus("Failed to find 'Port' marker in server output '%s'",
server_output_);
}
assert(listening_pos > port_pos);
server_listen_port_ = atoi(
server_output_
.substr(port_pos + strlen(port_key), listening_pos - port_pos)
.c_str());
if (server_listen_port_ == 0) {
return MakeStatus("Failed to parse port from server output '%s'",
server_output_);
}
}
} }
return absl::OkStatus(); return absl::OkStatus();
@@ -466,6 +481,7 @@ absl::Status CdcRsyncClient::Sync() {
absl::Status CdcRsyncClient::DeployServer(const ServerArch& arch) { absl::Status CdcRsyncClient::DeployServer(const ServerArch& arch) {
assert(!server_process_); assert(!server_process_);
assert(remote_util_); assert(remote_util_);
assert(IsRemoteConnection());
std::string exe_dir; std::string exe_dir;
absl::Status status = path::GetExeDir(&exe_dir); absl::Status status = path::GetExeDir(&exe_dir);

View File

@@ -78,14 +78,9 @@ class CdcRsyncClient {
absl::Status Run(); absl::Status Run();
private: private:
// Finds available local and remote ports for port forwarding.
// May update |server_arch| by properly detecting the architecture and retry
// if the architecture was guessed, i.e. if |server_arch|->IsGuess() is true.
absl::StatusOr<int> FindAvailablePort(ServerArch* server_arch);
// Starts the server process. If the method returns a status with tag // Starts the server process. If the method returns a status with tag
// |kTagDeployServer|, Run() calls DeployServer() and tries again. // |kTagDeployServer|, Run() calls DeployServer() and tries again.
absl::Status StartServer(int port, const ServerArch& arch); absl::Status StartServer(const ServerArch& arch);
// Stops the server process. // Stops the server process.
absl::Status StopServer(); absl::Status StopServer();
@@ -129,6 +124,9 @@ class CdcRsyncClient {
// Stops the zstd compression stream. // Stops the zstd compression stream.
absl::Status StopCompressionStream(); absl::Status StopCompressionStream();
// Returns true if the target is a remote target.
bool IsRemoteConnection() const { return remote_util_ != nullptr; }
Options options_; Options options_;
std::vector<std::string> sources_; std::vector<std::string> sources_;
const std::string destination_; const std::string destination_;
@@ -143,10 +141,11 @@ class CdcRsyncClient {
std::unique_ptr<ZstdStream> compression_stream_; std::unique_ptr<ZstdStream> compression_stream_;
std::unique_ptr<Process> server_process_; std::unique_ptr<Process> server_process_;
std::unique_ptr<Process> port_forwarding_process_;
std::string server_output_; // Written in a background thread. Do not access std::string server_output_; // Written in a background thread. Do not access
std::string server_error_; // while the server process is active. std::string server_error_; // while the server process is active.
int server_exit_code_ = 0; int server_exit_code_ = 0;
std::atomic_bool is_server_listening_{false}; std::atomic_int server_listen_port_{0};
bool is_server_error_ = false; bool is_server_error_ = false;
// All source files found on the client. // All source files found on the client.

View File

@@ -68,11 +68,10 @@ absl::Status ClientSocket::Connect(int port) {
int count = 0; int count = 0;
for (addrinfo* curr = addr_infos; curr; curr = curr->ai_next, count++) { for (addrinfo* curr = addr_infos; curr; curr = curr->ai_next, count++) {
socket_info_->socket = socket_info_->socket =
socket(addr_infos->ai_family, addr_infos->ai_socktype, socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
addr_infos->ai_protocol);
if (socket_info_->socket == INVALID_SOCKET) { if (socket_info_->socket == INVALID_SOCKET) {
LOG_DEBUG("socket() failed for addr_info %i: %s", count, LOG_DEBUG("socket() failed for addr_info %i: %s", count,
Util::GetWin32Error(WSAGetLastError()).c_str()); Util::GetWin32Error(WSAGetLastError()));
continue; continue;
} }
@@ -80,7 +79,8 @@ absl::Status ClientSocket::Connect(int port) {
result = connect(socket_info_->socket, curr->ai_addr, result = connect(socket_info_->socket, curr->ai_addr,
static_cast<int>(curr->ai_addrlen)); static_cast<int>(curr->ai_addrlen));
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
LOG_DEBUG("connect() failed for addr_info %i: %i", count, result); LOG_DEBUG("connect() failed for addr_info %i: %s", count,
Util::GetWin32Error(WSAGetLastError()));
closesocket(socket_info_->socket); closesocket(socket_info_->socket);
socket_info_->socket = INVALID_SOCKET; socket_info_->socket = INVALID_SOCKET;
continue; continue;

View File

@@ -288,7 +288,7 @@ bool CdcRsyncServer::CheckComponents(
return true; return true;
} }
absl::Status CdcRsyncServer::Run(int port) { absl::Status CdcRsyncServer::Run() {
absl::Status status = Socket::Initialize(); absl::Status status = Socket::Initialize();
if (!status.ok()) { if (!status.ok()) {
return WrapStatus(status, "Failed to initialize sockets"); return WrapStatus(status, "Failed to initialize sockets");
@@ -296,15 +296,15 @@ absl::Status CdcRsyncServer::Run(int port) {
socket_finalizer_ = std::make_unique<SocketFinalizer>(); socket_finalizer_ = std::make_unique<SocketFinalizer>();
socket_ = std::make_unique<ServerSocket>(); socket_ = std::make_unique<ServerSocket>();
int new_port; int port;
ASSIGN_OR_RETURN(new_port, socket_->StartListening(port), ASSIGN_OR_RETURN(port, socket_->StartListening(0),
"Failed to start listening on port %i", port); "Failed to start listening for connections");
assert(port != 0);
assert(port == new_port);
LOG_INFO("cdc_rsync_server listening on port %i", port); LOG_INFO("cdc_rsync_server listening on port %i", port);
// This is the marker for the client, so it knows it can connect. // This is the marker for the client, so it knows it can connect.
printf("Server is listening\n"); // Print port first so the client can easily parse it when it sees "Server is
// listening" without dealing with half-transmitted data.
printf("Port %i: Server is listening\n", port);
fflush(stdout); fflush(stdout);
status = socket_->WaitForConnection(); status = socket_->WaitForConnection();
@@ -607,7 +607,7 @@ absl::Status CdcRsyncServer::CreateMissingDirs() {
template <typename T> template <typename T>
absl::Status CdcRsyncServer::SendFileIndices(const char* file_type, absl::Status CdcRsyncServer::SendFileIndices(const char* file_type,
const std::vector<T>& files) { const std::vector<T>& files) {
LOG_INFO("Sending indices of missing files to client"); LOG_INFO("Sending indices of %s files to client", file_type);
constexpr char error_fmt[] = "Failed to send indices of %s files."; constexpr char error_fmt[] = "Failed to send indices of %s files.";
AddFileIndicesResponse response; AddFileIndicesResponse response;

View File

@@ -43,9 +43,10 @@ class CdcRsyncServer {
// up-to-date by checking their sizes and timestamps. // up-to-date by checking their sizes and timestamps.
bool CheckComponents(const std::vector<GameletComponent>& components); bool CheckComponents(const std::vector<GameletComponent>& components);
// Listens to |port|, accepts a connection from the client and runs the rsync // Listens to any available port, accepts a connection from the client and
// procedure. // runs the rsync procedure. Prints "Port <n>: Server is listening" to stdout,
absl::Status Run(int port); // so the client can retrieve the selected port.
absl::Status Run();
// Returns the verbosity sent from the client. 0 by default. // Returns the verbosity sent from the client. 0 by default.
int GetVerbosity() const { return verbosity_; } int GetVerbosity() const { return verbosity_; }

View File

@@ -62,29 +62,22 @@ ServerExitCode GetExitCode(const absl::Status& status) {
int main(int argc, const char** argv) { int main(int argc, const char** argv) {
if (argc < 5) { if (argc < 5) {
printf("cdc_rsync_server - Remote component of cdc_rsync. Version: %s\n\n", printf(R"("cdc_rsync_server - Remote component of cdc_rsync. Version: %s
BUILD_VERSION);
printf( Usage: cdc_rsync_server <build_version> cdc_rsync_server <size> <modified_time>
"Usage: cdc_rsync_server <port> <build_version> cdc_rsync_server " <build_version> build version embedded in the component
"<size> <time> \n"); <size> file size of the component
printf(" where <size> is the file size, <time> is the modified\n"); <modified_time> timestamp (Unix epoch) of the component)",
printf( BUILD_VERSION);
" timestamp (Unix epoch) and <build_version> is the build "
"version of the server.\n");
return cdc_ft::kServerExitCodeGenericStartup;
}
int port = atoi(argv[1]);
if (port == 0) {
SendErrorMessage(absl::StrFormat("Invalid port '%s'", argv[1]).c_str());
return cdc_ft::kServerExitCodeGenericStartup; return cdc_ft::kServerExitCodeGenericStartup;
} }
// The rest is expected to be sets of gamelet component info consisting of // The rest is expected to be sets of gamelet component info consisting of
// (filename, filesize, modified_time). This is used check whether the // (version, filename, size, modified_time). This is used check whether the
// components are up-to-date. // components are up-to-date.
std::vector<cdc_ft::GameletComponent> components = std::vector<cdc_ft::GameletComponent> components =
cdc_ft::GameletComponent::FromCommandLineArgs(argc - 2, argv + 2); cdc_ft::GameletComponent::FromCommandLineArgs(argc - 1, argv + 1);
cdc_ft::Log::Initialize( cdc_ft::Log::Initialize(
std::make_unique<cdc_ft::ConsoleLog>(cdc_ft::LogLevel::kWarning)); std::make_unique<cdc_ft::ConsoleLog>(cdc_ft::LogLevel::kWarning));
@@ -94,7 +87,7 @@ int main(int argc, const char** argv) {
return cdc_ft::kServerExitCodeOutOfDate; return cdc_ft::kServerExitCodeOutOfDate;
} }
absl::Status status = server.Run(port); absl::Status status = server.Run();
if (status.ok()) { if (status.ok()) {
return 0; return 0;
} }

View File

@@ -118,9 +118,8 @@ TEST_F(PortManagerTest, ReservePortLocalNetstatFails) {
absl::StatusOr<int> port = absl::StatusOr<int> port =
port_manager_.ReservePort(kTimeoutSec, ArchType::kLinux_x86_64); port_manager_.ReservePort(kTimeoutSec, ArchType::kLinux_x86_64);
EXPECT_NOT_OK(port); EXPECT_NOT_OK(port);
EXPECT_TRUE( EXPECT_TRUE(absl::StrContains(port.status().message(),
absl::StrContains(port.status().message(), "Failed to find available local ports"));
"Failed to find available ports on workstation"));
} }
TEST_F(PortManagerTest, ReservePortRemoteNetstatFails) { TEST_F(PortManagerTest, ReservePortRemoteNetstatFails) {
@@ -131,7 +130,7 @@ TEST_F(PortManagerTest, ReservePortRemoteNetstatFails) {
port_manager_.ReservePort(kTimeoutSec, ArchType::kLinux_x86_64); port_manager_.ReservePort(kTimeoutSec, ArchType::kLinux_x86_64);
EXPECT_NOT_OK(port); EXPECT_NOT_OK(port);
EXPECT_TRUE(absl::StrContains(port.status().message(), EXPECT_TRUE(absl::StrContains(port.status().message(),
"Failed to find available ports on instance")); "Failed to find available remote ports"));
} }
TEST_F(PortManagerTest, ReservePortRemoteNetstatTimesOut) { TEST_F(PortManagerTest, ReservePortRemoteNetstatTimesOut) {

View File

@@ -168,7 +168,7 @@ absl::StatusOr<int> PortManager::ReservePort(int remote_timeout_sec,
local_ports, local_ports,
FindAvailableLocalPorts(first_port_, last_port_, FindAvailableLocalPorts(first_port_, last_port_,
ArchType::kWindows_x86_64, process_factory_), ArchType::kWindows_x86_64, process_factory_),
"Failed to find available ports on workstation"); "Failed to find available local ports");
// Find available port on remote instance. // Find available port on remote instance.
std::unordered_set<int> remote_ports = local_ports; std::unordered_set<int> remote_ports = local_ports;
@@ -178,7 +178,7 @@ absl::StatusOr<int> PortManager::ReservePort(int remote_timeout_sec,
FindAvailableRemotePorts(first_port_, last_port_, remote_arch_type, FindAvailableRemotePorts(first_port_, last_port_, remote_arch_type,
process_factory_, remote_util_, process_factory_, remote_util_,
remote_timeout_sec, steady_clock_), remote_timeout_sec, steady_clock_),
"Failed to find available ports on instance"); "Failed to find available remote ports");
} }
// Fetch shared memory. // Fetch shared memory.
@@ -209,9 +209,9 @@ absl::StatusOr<int> PortManager::ReservePort(int remote_timeout_sec,
LOG_DEBUG("Trying to reserve port %i", port); LOG_DEBUG("Trying to reserve port %i", port);
// We have reserved this port. Double-check that it's actually not in use // We have reserved this port. Double-check that it's actually not in use
// on both the workstation and the server. // on both the local and the remote device
if (local_ports.find(port) == local_ports.end()) { if (local_ports.find(port) == local_ports.end()) {
LOG_DEBUG("Port %i not available on workstation", port); LOG_DEBUG("Local port %i not available", port);
InterlockedCompareExchange64(ts_ptr, now, port_timestamp); InterlockedCompareExchange64(ts_ptr, now, port_timestamp);
continue; continue;
} }
@@ -221,7 +221,7 @@ absl::StatusOr<int> PortManager::ReservePort(int remote_timeout_sec,
continue; continue;
} }
LOG_DEBUG("Port %i is available on workstation and instance", port); LOG_DEBUG("Port %i is available", port);
reserved_ports_.insert(port); reserved_ports_.insert(port);
return port; return port;
} }
@@ -269,7 +269,7 @@ absl::StatusOr<std::unordered_set<int>> PortManager::FindAvailableLocalPorts(
return WrapStatus(status, "Failed to run netstat:\n%s", errors); return WrapStatus(status, "Failed to run netstat:\n%s", errors);
} }
LOG_DEBUG("netstat (workstation) output:\n%s", output); LOG_DEBUG("netstat (local) output:\n%s", output);
return FindAvailablePorts(first_port, last_port, output, arch_type); return FindAvailablePorts(first_port, last_port, output, arch_type);
} }
@@ -316,7 +316,7 @@ absl::StatusOr<std::unordered_set<int>> PortManager::FindAvailableRemotePorts(
errors); errors);
} }
LOG_DEBUG("netstat (instance) output:\n%s", output); LOG_DEBUG("netstat (remote) output:\n%s", output);
return FindAvailablePorts(first_port, last_port, output, arch_type); return FindAvailablePorts(first_port, last_port, output, arch_type);
} }