#include #include #include #include #include #include #include "device_info.h" #include "internal/platform/implementation/atomic_boolean.h" #include "internal/platform/implementation/atomic_reference.h" #include "internal/platform/implementation/bluetooth_adapter.h" #include "internal/platform/implementation/count_down_latch.h" #include "internal/platform/implementation/http_loader.h" #include "internal/platform/implementation/input_file.h" #include "internal/platform/implementation/linux/atomic_boolean.h" #include "internal/platform/implementation/linux/atomic_uint32.h" #include "internal/platform/implementation/linux/ble_medium.h" #include "internal/platform/implementation/linux/ble_v2_medium.h" #include "internal/platform/implementation/linux/bluetooth_adapter.h" #include "internal/platform/implementation/linux/bluetooth_classic_medium.h" #include "internal/platform/implementation/linux/bluez.h" #include "internal/platform/implementation/linux/bluez_adapter_client_glue.h" #include "internal/platform/implementation/linux/condition_variable.h" #include "internal/platform/implementation/linux/dbus.h" #include "internal/platform/implementation/linux/mutex.h" #include "internal/platform/implementation/linux/preferences_manager.h" #include "internal/platform/implementation/linux/submittable_executor.h" #include "internal/platform/implementation/linux/timer.h" #include "internal/platform/implementation/linux/wifi_direct.h" #include "internal/platform/implementation/linux/wifi_hotspot.h" #include "internal/platform/implementation/linux/wifi_lan.h" #include "internal/platform/implementation/linux/wifi_medium.h" #include "internal/platform/implementation/platform.h" #include "internal/platform/implementation/shared/count_down_latch.h" #include "internal/platform/implementation/shared/file.h" #include "internal/platform/implementation/submittable_executor.h" #include "internal/platform/implementation/wifi_hotspot.h" #include "internal/platform/implementation/wifi_lan.h" #include "internal/platform/payload_id.h" #include "log_message.h" #include "scheduled_executor.h" namespace nearby { namespace api { std::string ImplementationPlatform::GetCustomSavePath(const std::string &parent_folder, const std::string &file_name) { auto fs = std::filesystem::path(parent_folder); return fs / file_name; } std::string ImplementationPlatform::GetDownloadPath(const std::string &parent_folder, const std::string &file_name) { auto downloads = std::filesystem::path(getenv("XDG_DOWNLOAD_DIR")); return downloads / std::filesystem::path(parent_folder).filename() / std::filesystem::path(file_name).filename(); } std::string ImplementationPlatform::GetDownloadPath(const std::string &file_name) { auto downloads = std::filesystem::path(getenv("XDG_DOWNLOAD_DIR")); return downloads / std::filesystem::path(file_name).filename(); } std::string ImplementationPlatform::GetAppDataPath(const std::string &file_name) { auto state = std::filesystem::path(getenv("XDG_STATE_HOME")); return state / std::filesystem::path(file_name).filename(); } OSName ImplementationPlatform::GetCurrentOS() { return OSName::kWindows; } std::unique_ptr ImplementationPlatform::CreateAtomicBoolean(bool initial_value) { return std::make_unique(initial_value); } std::unique_ptr ImplementationPlatform::CreateAtomicUint32(std::uint32_t value) { return std::make_unique(value); } std::unique_ptr ImplementationPlatform::CreateCountDownLatch(std::int32_t count) { return std::make_unique(count); } #pragma push_macro("CreateMutex") #undef CreateMutex std::unique_ptr ImplementationPlatform::CreateMutex(Mutex::Mode mode) { return std::make_unique(mode); } #pragma pop_macro("CreateMutex") std::unique_ptr ImplementationPlatform::CreateConditionVariable(api::Mutex *mutex) { return std::make_unique(mutex); } std::unique_ptr ImplementationPlatform::CreateInputFile(PayloadId id, std::int64_t total_size) { auto path = GetDownloadPath(std::to_string(id)); return nearby::shared::IOFile::CreateInputFile(path, total_size); } std::unique_ptr ImplementationPlatform::CreateInputFile(const std::string &file_path, size_t size) { return nearby::shared::IOFile::CreateInputFile(file_path, size); } std::unique_ptr ImplementationPlatform::CreateOutputFile(PayloadId payload_id) { return nearby::shared::IOFile::CreateOutputFile( GetDownloadPath("", std::to_string(payload_id))); } std::unique_ptr ImplementationPlatform::CreateOutputFile(const std::string &file_path) { std::filesystem::path path(file_path); try { std::filesystem::create_directories(path.parent_path()); } catch (std::filesystem::filesystem_error const &err) { NEARBY_LOGS(ERROR) << __func__ << ": error creating directory tree " << path.parent_path() << ": " << err.what(); } return nearby::shared::IOFile::CreateOutputFile(path.string()); } std::unique_ptr ImplementationPlatform::CreateLogMessage(const char *file, int line, LogMessage::Severity severity) { return std::make_unique(file, line, severity); } std::unique_ptr ImplementationPlatform::CreateSingleThreadExecutor() { return std::make_unique(); } std::unique_ptr ImplementationPlatform::CreateMultiThreadExecutor( std::int32_t max_concurrency) { return std::make_unique(max_concurrency); } std::unique_ptr ImplementationPlatform::CreateScheduledExecutor() { return std::make_unique(); } std::unique_ptr ImplementationPlatform::CreateBluetoothAdapter() { auto manager = linux::bluez::BluezObjectManager(linux::getSystemBusConnection()); try { auto interfaces = manager.GetManagedObjects(); for (auto &[object, properties] : interfaces) { if (properties.count(org::bluez::Adapter1_proxy::INTERFACE_NAME) == 1) { NEARBY_LOGS(INFO) << __func__ << ": found bluetooth adapter " << object; return std::make_unique( linux::getSystemBusConnection(), object); } } } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(&manager, "GetManagedObjects", e); return nullptr; } NEARBY_LOGS(ERROR) << __func__ << ": couldn't find a bluetooth adapter on this system"; return nullptr; } std::unique_ptr ImplementationPlatform::CreateBluetoothClassicMedium( BluetoothAdapter &adapter) { auto path = static_cast(&adapter)->GetObjectPath(); return std::make_unique( linux::getSystemBusConnection(), path); } std::unique_ptr ImplementationPlatform::CreateBleMedium(BluetoothAdapter &) { return std::make_unique(); } std::unique_ptr ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter &adapter) { return std::make_unique(); } static std::unique_ptr createWifiMedium(std::shared_ptr nm) { std::vector device_paths; try { device_paths = nm->GetAllDevices(); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(nm, "GetAllDevices", e); return nullptr; } auto manager = linux::NetworkManagerObjectManager(linux::getSystemBusConnection()); std::map>> objects; try { objects = manager.GetManagedObjects(); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(nm, "GetManagedObjects", e); return nullptr; } for (auto &device_path : device_paths) { if (objects.count(device_path) == 1) { auto device = objects[device_path]; if (device.count(org::freedesktop::NetworkManager::Device:: Wireless_proxy::INTERFACE_NAME) == 1) { NEARBY_LOGS(INFO) << __func__ << ": Found a wireless device at :" << device_path; return std::make_unique( nm, linux::getSystemBusConnection(), device_path); } } } NEARBY_LOGS(ERROR) << __func__ << ": couldn't find a wireless device on this system"; return nullptr; } std::unique_ptr ImplementationPlatform::CreateWifiMedium() { auto nm = std::make_shared(linux::getSystemBusConnection()); return createWifiMedium(nm); } std::unique_ptr ImplementationPlatform::CreateWifiLanMedium() { return std::make_unique( linux::getSystemBusConnection()); } std::unique_ptr ImplementationPlatform::CreateWifiHotspotMedium() { auto nm = std::make_shared(linux::getSystemBusConnection()); auto wifiMedium = createWifiMedium(nm); if (wifiMedium == nullptr) { NEARBY_LOGS(ERROR) << __func__ << ": Could not create a WiFi medium"; return nullptr; } return std::make_unique( linux::getSystemBusConnection(), nm, std::move(wifiMedium)); } std::unique_ptr ImplementationPlatform::CreateWifiDirectMedium() { auto nm = std::make_shared(linux::getSystemBusConnection()); auto wifiMedium = createWifiMedium(nm); if (wifiMedium == nullptr) { NEARBY_LOGS(ERROR) << __func__ << ": Could not create a WiFi medium"; return nullptr; } return std::make_unique( linux::getSystemBusConnection(), nm, std::move(wifiMedium)); } std::unique_ptr ImplementationPlatform::CreateTimer() { return std::make_unique(); } std::unique_ptr ImplementationPlatform::CreateDeviceInfo() { return std::make_unique(linux::getSystemBusConnection()); } absl::StatusOr ImplementationPlatform::SendRequest(const WebRequest &request) { if (request.body.size() >= (8 * 1024 * 1024)) { return absl::Status(absl::StatusCode::kResourceExhausted, "request body too large"); } CURL *handle = curl_easy_init(); char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; curl_easy_setopt(handle, CURLOPT_URL, request.url.c_str()); curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf); if (request.method == "GET") curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L); else if (request.method == "POST") curl_easy_setopt(handle, CURLOPT_POST, 1L); else curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, request.method.c_str()); curl_easy_setopt(handle, CURLOPT_UPLOAD, request.body.c_str()); struct curl_slist *headers_slist = nullptr; for (auto &[key, value] : request.headers) { auto hdr = absl::StrCat(key, ": ", value); auto temp = curl_slist_append(headers_slist, hdr.c_str()); if (temp == nullptr) { if (headers_slist != nullptr) { curl_slist_free_all(headers_slist); } return absl::Status(absl::StatusCode::kResourceExhausted, "failed to append header to slist"); } } curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers_slist); api::WebResponse response; if (curl_easy_perform(handle) != CURLE_OK) { NEARBY_LOGS(ERROR) << __func__ << ": Error performing HTTP request: " << errbuf; return absl::Status(absl::StatusCode::kUnknown, errbuf); } struct curl_header *prev = nullptr; struct curl_header *h; h = curl_easy_nextheader(handle, CURLH_HEADER, 0, prev); while (h != nullptr) { response.headers.emplace(h->name, h->value); } auto writefn = [](char *ptr, size_t size, size_t nmemb, void *userdata) { std::string *body = static_cast(userdata); body->append(ptr, size * nmemb); }; curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefn); curl_easy_setopt(handle, CURLOPT_WRITEDATA, static_cast(&response.body)); long status; curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &status); response.status_code = status; return response; } #ifndef NEARBY_CHROMIUM std::unique_ptr ImplementationPlatform::CreatePreferencesManager(absl::string_view path) { return std::make_unique(path); } #endif } // namespace api } // namespace nearby