Files
nearby/sharing/linux/daemon/main.cc
T

166 lines
5.3 KiB
C++

#include <signal.h>
#include <unistd.h>
#include <atomic>
#include <condition_variable>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <optional>
#include <string>
#include <sdbus-c++/sdbus-c++.h>
#include "absl/time/time.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "internal/flags/nearby_flags.h"
#include "sharing/flags/generated/nearby_sharing_feature_flags.h"
#include "sharing/linux/daemon/nearby_sharing_dbus_service.h"
#include "sharing/linux/nearby_noop_analytics_recorder.h"
#include "sharing/linux/platform/linux_sharing_platform.h"
#include "sharing/nearby_sharing_service.h"
#include "sharing/nearby_sharing_service_factory.h"
#include "sharing/nearby_sharing_settings.h"
#include "sharing/proto/enums.pb.h"
namespace nearby::sharing::linux {
namespace {
std::atomic<bool> g_interrupted = false;
sdbus::IConnection* g_bus = nullptr;
void HandleSignal(int signal) {
static_cast<void>(signal);
g_interrupted = true;
if (g_bus != nullptr) {
g_bus->leaveEventLoop();
}
}
std::string GetHostname() {
char hostname[256] = {};
if (gethostname(hostname, sizeof(hostname)) == 0 && hostname[0] != '\0') {
return std::string(hostname);
}
return "LinuxShare";
}
std::string GetDeviceName(int argc, char** argv) {
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "--name" && i + 1 < argc) {
return argv[i + 1];
}
}
const char* env_name = std::getenv("NEARBY_DEVICE_NAME");
if (env_name != nullptr && *env_name != '\0') {
return env_name;
}
return GetHostname();
}
template <typename Invoker>
NearbySharingService::StatusCodes WaitForStatus(Invoker invoker) {
std::mutex mutex;
std::condition_variable cv;
std::optional<NearbySharingService::StatusCodes> status;
invoker([&](NearbySharingService::StatusCodes callback_status) {
{
std::lock_guard<std::mutex> lock(mutex);
status = callback_status;
}
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [&] { return status.has_value(); });
return *status;
}
void ConfigureFlags() {
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
nearby::sharing::config_package_nearby::nearby_sharing_feature::
kEnableBleForTransfer,
true);
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
nearby::connections::config_package_nearby::nearby_connections_feature::
kEnableBleL2cap,
true);
nearby::NearbyFlags::GetInstance().OverrideBoolFlagValue(
nearby::connections::config_package_nearby::nearby_connections_feature::
kRefactorBleL2cap,
true);
}
bool ConfigureSharingService(NearbySharingService& service,
const std::string& device_name) {
service.GetSettings()->SetDataUsage(proto::WIFI_ONLY_DATA_USAGE);
service.GetSettings()->SetDeviceName(
device_name, [](DeviceNameValidationResult validation_result) {
static_cast<void>(validation_result);
});
auto status = WaitForStatus([&](auto callback) {
service.SetVisibility(proto::DEVICE_VISIBILITY_EVERYONE,
absl::ZeroDuration(), std::move(callback));
});
if (status != NearbySharingService::StatusCodes::kOk) {
std::cerr << "SetVisibility failed: "
<< NearbySharingService::StatusCodeToString(status) << std::endl;
return false;
}
return true;
}
} // namespace
} // namespace nearby::sharing::linux
int main(int argc, char** argv) {
signal(SIGINT, nearby::sharing::linux::HandleSignal);
signal(SIGTERM, nearby::sharing::linux::HandleSignal);
nearby::sharing::linux::ConfigureFlags();
const std::string device_name =
nearby::sharing::linux::GetDeviceName(argc, argv);
auto analytics_recorder = nearby::sharing::linux::NoOpAnalyticsRecorder();
auto linux_platform =
nearby::sharing::linux::LinuxSharingPlatform(device_name);
auto* service =
nearby::sharing::NearbySharingServiceFactory::GetInstance()
->CreateSharingService(linux_platform, &analytics_recorder,
/*event_logger=*/nullptr,
/*supports_file_sync=*/false);
if (service == nullptr) {
std::cerr << "failed to create NearbySharingService" << std::endl;
return 1;
}
if (!nearby::sharing::linux::ConfigureSharingService(*service, device_name)) {
nearby::sharing::linux::WaitForStatus(
[&](auto callback) { service->Shutdown(std::move(callback)); });
return 1;
}
auto bus = sdbus::createSessionBusConnection(
sdbus::ServiceName("com.google.nearby.sharing"));
nearby::sharing::linux::g_bus = bus.get();
auto object = sdbus::createObject(
*bus, sdbus::ObjectPath("/com/google/nearby/sharing"));
nearby::sharing::linux::NearbySharingDbusService dbus_service(
*object, *service, [&bus]() { bus->leaveEventLoop(); });
dbus_service.EmitStatusChanged();
try {
bus->enterEventLoop();
} catch (const sdbus::Error& error) {
std::cerr << "D-Bus event loop failed: " << error.getName() << ": "
<< error.getMessage() << std::endl;
dbus_service.ShutdownService();
nearby::sharing::linux::g_bus = nullptr;
return 1;
}
dbus_service.ShutdownService();
nearby::sharing::linux::g_bus = nullptr;
return nearby::sharing::linux::g_interrupted ? 130 : 0;
}