[cdc_stream] Use ephemeral ports (#100)

Instead of running netstat/ss on local and remote systems, just bind
with port 0 to find an ephemeral port. This is much more robust,
simpler and a bit faster. Since the remote port is only known after
running cdc_fuse_fs, port forwarding has to be set up after running
cdc_fuse_fs.
This commit is contained in:
Lutz Justen
2023-06-23 11:19:36 +02:00
committed by GitHub
parent 678ee0ffaf
commit 370023a944
13 changed files with 214 additions and 134 deletions

View File

@@ -9,8 +9,10 @@ cc_binary(
":cdc_fuse_fs_lib",
":constants",
"//absl_helper:jedec_size_flag",
"//common:client_socket",
"//common:gamelet_component",
"//common:log",
"//common:server_socket",
"//data_store:data_provider",
"//data_store:disk_data_store",
"//data_store:grpc_reader",

View File

@@ -19,15 +19,22 @@
namespace cdc_ft {
// FUSE prints this to stdout when the binary timestamp and file size match the
// file on the workstation.
static constexpr char kFuseUpToDate[] = "cdc_fuse_fs is up-to-date";
// FUSE prints
// Port 12345 cdc_fuse_fs is up-to-date
// to stdout when its version matches the version (=build version or
// size/timestamp for DEV builds) on the local device. The port is the gRPC port
// that FUSE will try to connect to.
static constexpr char kFusePortPrefix[] = "Port ";
static constexpr char kFuseUpToDate[] = " cdc_fuse_fs is up-to-date";
// FUSE prints this to stdout when the binary timestamp or file size does not
// match the file on the workstation. It indicates that the binary has to be
// redeployed.
// FUSE prints this to stdout when its version does not match the version on the
// local device. It indicates that the binary has to be redeployed.
static constexpr char kFuseNotUpToDate[] = "cdc_fuse_fs is not up-to-date";
// FUSE prints this to stdout when it can connect to its port. This means that
// port forwarding has finished setting up, and startup is finished.
static constexpr char kFuseConnected[] = "cdc_fuse_fs is connected";
} // namespace cdc_ft
#endif // CDC_FUSE_FS_CONSTANTS_H_

View File

@@ -21,9 +21,11 @@
#include "cdc_fuse_fs/cdc_fuse_fs.h"
#include "cdc_fuse_fs/config_stream_client.h"
#include "cdc_fuse_fs/constants.h"
#include "common/client_socket.h"
#include "common/gamelet_component.h"
#include "common/log.h"
#include "common/path.h"
#include "common/server_socket.h"
#include "data_store/data_provider.h"
#include "data_store/disk_data_store.h"
#include "data_store/grpc_reader.h"
@@ -37,6 +39,8 @@ namespace {
constexpr char kFuseFilename[] = "cdc_fuse_fs";
constexpr char kLibFuseFilename[] = "libfuse.so";
constexpr absl::Duration kConnectionTimeout = absl::Seconds(60);
bool IsUpToDate(const std::string& components_arg) {
// Components are expected to reside in the same dir as the executable.
std::string component_dir;
@@ -107,7 +111,6 @@ ABSL_FLAG(
"Whitespace-separated triples filename, size and timestamp of the "
"workstation version of this binary and dependencies. Used for a fast "
"up-to-date check.");
ABSL_FLAG(uint16_t, port, 0, "Port to connect to on localhost");
ABSL_FLAG(cdc_ft::JedecSize, prefetch_size, cdc_ft::JedecSize(512 << 10),
"Additional data to request from the server when a FUSE read of "
"maximum size is detected. This amount is added to the original "
@@ -138,7 +141,6 @@ int main(int argc, char* argv[]) {
std::vector<char*> mount_args = absl::ParseCommandLine(argc, argv);
std::string instance = absl::GetFlag(FLAGS_instance);
std::string components = absl::GetFlag(FLAGS_components);
uint16_t port = absl::GetFlag(FLAGS_port);
std::string cache_dir = absl::GetFlag(FLAGS_cache_dir);
int cache_dir_levels = absl::GetFlag(FLAGS_cache_dir_levels);
int verbosity = absl::GetFlag(FLAGS_verbosity);
@@ -159,7 +161,18 @@ int main(int argc, char* argv[]) {
printf("%s\n", cdc_ft::kFuseNotUpToDate);
return 0;
}
printf("%s\n", cdc_ft::kFuseUpToDate);
// Find an available port.
absl::StatusOr<int> port_or = cdc_ft::ServerSocket::FindAvailablePort();
if (!port_or.ok()) {
LOG_ERROR("Failed to find available port: %s\n",
port_or.status().ToString());
return 1;
}
int port = *port_or;
// Write marker for the server.
printf("%s%i%s\n", cdc_ft::kFusePortPrefix, port, cdc_ft::kFuseUpToDate);
fflush(stdout);
// Create mount dir if it doesn't exist yet.
@@ -189,6 +202,18 @@ int main(int argc, char* argv[]) {
store.value()->SetCapacity(cache_capacity);
LOG_INFO("Caching chunks in '%s'", store.value()->RootDir());
// Wait for port forwarding to listen to |port|.
status =
cdc_ft::ClientSocket::WaitForConnection(port, cdc_ft::kConnectionTimeout);
if (!status.ok()) {
LOG_ERROR("Failed to connect to port %i: %s", port, status.ToString());
return static_cast<int>(status.code());
}
// Write another marker for the server.
printf("%s\n", cdc_ft::kFuseConnected);
fflush(stdout);
// Start a gRpc client.
std::string client_address = absl::StrFormat("localhost:%u", port);
grpc::ChannelArguments channel_args;