From ff55edb5e418e387c17d909a70cb980b1fe64789 Mon Sep 17 00:00:00 2001 From: Vibhav Pant Date: Mon, 21 Aug 2023 23:19:01 +0530 Subject: [PATCH] Code dump. --- .../implementation/linux/atomic_boolean.h | 27 ++ .../implementation/linux/atomic_uint32.h | 28 ++ .../platform/implementation/linux/avahi.cc | 103 +++++ .../platform/implementation/linux/avahi.h | 78 ++++ .../linux/avahi_entrygroup_client_glue.h | 94 +++++ .../linux/avahi_server_client_glue.h | 399 ++++++++++++++++++ .../linux/avahi_servicebrowser_client_glue.h | 58 +++ .../linux/bluetooth_classic_socket.cc | 51 +-- .../linux/bluetooth_classic_socket.h | 41 +- .../implementation/linux/condition_variable.h | 36 ++ .../implementation/linux/credential_storage.h | 50 +++ .../platform/implementation/linux/dbus.cc | 35 ++ internal/platform/implementation/linux/dbus.h | 8 + .../implementation/linux/device_info.cc | 6 +- .../implementation/linux/log_message.cc | 111 +++++ .../implementation/linux/log_message.h | 118 ++++++ .../platform/implementation/linux/mutex.h | 56 +++ .../org.freedesktop.Avahi.EntryGroup.xml | 94 +++++ .../linux/org.freedesktop.Avahi.Server.xml | 398 +++++++++++++++++ .../org.freedesktop.Avahi.ServiceBrowser.xml | 58 +++ .../org.freedesktop.Avahi.ServiceResolver.xml | 57 +++ .../linux/org.freedesktop.LogControl1.xml | 17 + .../org_freedesktop_logcontrol_server_glue.h | 45 ++ .../platform/implementation/linux/platform.cc | 70 ++- .../platform/implementation/linux/stream.h | 40 ++ .../platform/implementation/linux/wifi_lan.cc | 240 +++++++++++ .../platform/implementation/linux/wifi_lan.h | 58 +++ .../linux/wifi_lan_server_socket.cc | 82 ++++ .../linux/wifi_lan_server_socket.h | 33 ++ .../implementation/linux/wifi_lan_socket.h | 42 ++ .../implementation/linux/wifi_medium.h | 8 +- .../implementation/linux/wifi_socket.h | 16 + 32 files changed, 2479 insertions(+), 78 deletions(-) create mode 100644 internal/platform/implementation/linux/atomic_boolean.h create mode 100644 internal/platform/implementation/linux/atomic_uint32.h create mode 100644 internal/platform/implementation/linux/avahi.cc create mode 100644 internal/platform/implementation/linux/avahi.h create mode 100644 internal/platform/implementation/linux/avahi_entrygroup_client_glue.h create mode 100644 internal/platform/implementation/linux/avahi_server_client_glue.h create mode 100644 internal/platform/implementation/linux/avahi_servicebrowser_client_glue.h create mode 100644 internal/platform/implementation/linux/condition_variable.h create mode 100644 internal/platform/implementation/linux/credential_storage.h create mode 100644 internal/platform/implementation/linux/dbus.cc create mode 100644 internal/platform/implementation/linux/log_message.cc create mode 100644 internal/platform/implementation/linux/log_message.h create mode 100644 internal/platform/implementation/linux/mutex.h create mode 100644 internal/platform/implementation/linux/org.freedesktop.Avahi.EntryGroup.xml create mode 100644 internal/platform/implementation/linux/org.freedesktop.Avahi.Server.xml create mode 100644 internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceBrowser.xml create mode 100644 internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceResolver.xml create mode 100644 internal/platform/implementation/linux/org.freedesktop.LogControl1.xml create mode 100644 internal/platform/implementation/linux/org_freedesktop_logcontrol_server_glue.h create mode 100644 internal/platform/implementation/linux/stream.h create mode 100644 internal/platform/implementation/linux/wifi_lan.cc create mode 100644 internal/platform/implementation/linux/wifi_lan.h create mode 100644 internal/platform/implementation/linux/wifi_lan_server_socket.cc create mode 100644 internal/platform/implementation/linux/wifi_lan_server_socket.h create mode 100644 internal/platform/implementation/linux/wifi_lan_socket.h create mode 100644 internal/platform/implementation/linux/wifi_socket.h diff --git a/internal/platform/implementation/linux/atomic_boolean.h b/internal/platform/implementation/linux/atomic_boolean.h new file mode 100644 index 00000000..61bc5565 --- /dev/null +++ b/internal/platform/implementation/linux/atomic_boolean.h @@ -0,0 +1,27 @@ +#ifndef PLATFORM_IMPL_LINUX_ATOMIC_BOOLEAN_H_ +#define PLATFORM_IMPL_LINUX_ATOMIC_BOOLEAN_H_ + +#include "internal/platform/implementation/atomic_boolean.h" +#include +namespace nearby { +namespace linux { +// A boolean value that may be updated atomically. +class AtomicBoolean : public api::AtomicBoolean { +public: + AtomicBoolean(bool initial_value) : atomic_boolean_(initial_value) {} + ~AtomicBoolean() override = default; + + // Atomically read and return current value. + bool Get() const override { return atomic_boolean_; }; + + // Atomically exchange original value with a new one. Return previous value. + bool Set(bool value) override { return atomic_boolean_.exchange(value); }; + +private: + std::atomic_bool atomic_boolean_ = false; +}; +} // namespace linux +} // namespace nearby + +#endif + diff --git a/internal/platform/implementation/linux/atomic_uint32.h b/internal/platform/implementation/linux/atomic_uint32.h new file mode 100644 index 00000000..f5fbf88b --- /dev/null +++ b/internal/platform/implementation/linux/atomic_uint32.h @@ -0,0 +1,28 @@ +#ifndef PLATFORM_IMPL_LINUX_ATOMIC_UINT32_H_ +#define PLATFORM_IMPL_LINUX_ATOMIC_UINT32_H_ + +#include "internal/platform/implementation/atomic_reference.h" +#include +#include + +namespace nearby { +namespace linux { +// A boolean value that may be updated atomically. +class AtomicUint32 : public api::AtomicUint32 { +public: + AtomicUint32(std::uint32_t initial_value) : atomic_uint_(initial_value) {} + ~AtomicUint32() override = default; + + // Atomically read and return current value. + std::uint32_t Get() const override { return atomic_uint_; }; + + // Atomically exchange original value with a new one. Return previous value. + void Set(std::uint32_t value) override { atomic_uint_ = value; }; + +private: + std::atomic_bool atomic_uint_ = false; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/avahi.cc b/internal/platform/implementation/linux/avahi.cc new file mode 100644 index 00000000..c762ccce --- /dev/null +++ b/internal/platform/implementation/linux/avahi.cc @@ -0,0 +1,103 @@ +#include "internal/platform/implementation/linux/avahi.h" +#include "internal/platform/implementation/linux/dbus.h" +#include "internal/platform/logging.h" +#include "internal/platform/nsd_service_info.h" + +namespace nearby { +namespace linux { +namespace avahi { +void ServiceBrowser::onItemNew(const int32_t &interface, + const int32_t &protocol, const std::string &name, + const std::string &type, + const std::string &domain, + const uint32_t &flags) { + NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath() + << ": Found new item through the ServiceBrowser: " + << "interface: " << interface << ", protocol: " + << protocol << ", name: '" << name << "', type: '" + << type << "', domain: '" << domain + << "', flags: " << flags; + + NsdServiceInfo info; + try { + auto [r_iface, r_protocol, r_name, r_type, r_domain, r_host, r_aprotocol, + r_address, r_port, r_txt, r_flags] = + server_->ResolveService(interface, protocol, name, type, domain, + 0, // AVAHI_PROTO_INET + flags); + info.SetServiceName(r_name); + info.SetIPAddress(r_address); + info.SetPort(r_port); + info.SetServiceType(r_type); + for (auto &attr : r_txt) { + auto attr_str = std::string(attr.begin(), attr.end()); + size_t pos = attr_str.find('='); + if (pos == 0 || pos == std::string::npos || pos == attr_str.size() - 1) { + NEARBY_LOGS(WARNING) << " found invalid text attribute: " << attr_str; + } + + info.SetTxtRecord(attr_str.substr(0, pos), attr_str.substr(pos + 1)); + } + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(server_, "ResolveService", e); + } + + discovery_cb_.service_discovered_cb(std::move(info)); +} + +void ServiceBrowser::onItemRemove(const int32_t &interface, const int32_t &protocol, + const std::string &name, const std::string &type, + const std::string &domain, const uint32_t &flags) { + // TODO: Can we even resolve removed items? + NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath() + << ": Item removed through the ServiceBrowser: " + << "interface: " << interface << ", protocol: " + << protocol << ", name: '" << name << "', type: '" + << type << "', domain: '" << domain + << "', flags: " << flags; + NsdServiceInfo info; + try { + auto [r_iface, r_protocol, r_name, r_type, r_domain, r_host, r_aprotocol, + r_address, r_port, r_txt, r_flags] = + server_->ResolveService(interface, protocol, name, type, domain, + 0, // AVAHI_PROTO_INET + flags); + info.SetServiceName(r_name); + info.SetIPAddress(r_address); + info.SetPort(r_port); + info.SetServiceType(r_type); + for (auto &attr : r_txt) { + auto attr_str = std::string(attr.begin(), attr.end()); + size_t pos = attr_str.find('='); + if (pos == 0 || pos == std::string::npos || pos == attr_str.size() - 1) { + NEARBY_LOGS(WARNING) << " found invalid text attribute: " << attr_str; + } + + info.SetTxtRecord(attr_str.substr(0, pos), attr_str.substr(pos + 1)); + } + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(server_, "ResolveService", e); + } + + discovery_cb_.service_lost_cb(std::move(info)); +} + +void ServiceBrowser::onFailure(const std::string &error) { + NEARBY_LOGS(ERROR) << __func__ << ": " << getObjectPath() + << ": ServiceBrowser reported a failure: " << error; +} + +void ServiceBrowser::onAllForNow() { + NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath() + << ": notified via ServiceBrowser that all records have " + "been added for now"; +} + +void ServiceBrowser::onCacheExhausted() { + NEARBY_LOGS(VERBOSE) << __func__ << ": " << getObjectPath() + << ": notified via ServiceBrowser of cache exhaustion"; +} + +} // namespace avahi +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/avahi.h b/internal/platform/implementation/linux/avahi.h new file mode 100644 index 00000000..a0ed8cec --- /dev/null +++ b/internal/platform/implementation/linux/avahi.h @@ -0,0 +1,78 @@ +#ifndef PLATFORM_IMPL_LINUX_AVAHI_H_ +#define PLATFORM_IMPL_LINUX_AVAHI_H_ + +#include +#include +#include + +#include "internal/platform/implementation/linux/avahi_entrygroup_client_glue.h" +#include "internal/platform/implementation/linux/avahi_server_client_glue.h" +#include "internal/platform/implementation/linux/avahi_servicebrowser_client_glue.h" +#include "internal/platform/implementation/wifi_lan.h" + +namespace nearby { +namespace linux { +namespace avahi { +class Server + : public sdbus::ProxyInterfaces { +public: + Server(sdbus::IConnection &system_bus) + : ProxyInterfaces(system_bus, "org.freedesktop.Avahi", "/") { + registerProxy(); + } + ~Server() { unregisterProxy(); } + +protected: + void onStateChanged(const int32_t &state, const std::string &error) override { + } +}; + +class EntryGroup + : public sdbus::ProxyInterfaces { +public: + EntryGroup(sdbus::IConnection &system_bus, + const sdbus::ObjectPath &entry_group_object_path) + : ProxyInterfaces(system_bus, "org.freedesktop.Avahi", + entry_group_object_path) { + registerProxy(); + } + ~EntryGroup() { unregisterProxy(); } + +protected: + void onStateChanged(const int32_t &state, const std::string &error) override { + } +}; + +class ServiceBrowser : public sdbus::ProxyInterfaces< + org::freedesktop::Avahi::ServiceBrowser_proxy> { +public: + ServiceBrowser(sdbus::IConnection &system_bus, + const sdbus::ObjectPath &service_browser_object_path, + api::WifiLanMedium::DiscoveredServiceCallback callback) + : ProxyInterfaces(system_bus, "org.freedesktop.Avahi", + service_browser_object_path), + discovery_cb_(std::move(callback)) { + registerProxy(); + } + ~ServiceBrowser() { unregisterProxy(); } + +protected: + void onItemNew(const int32_t &interface, const int32_t &protocol, + const std::string &name, const std::string &type, + const std::string &domain, const uint32_t &flags) override; + void onItemRemove(const int32_t &interface, const int32_t &protocol, + const std::string &name, const std::string &type, + const std::string &domain, const uint32_t &flags) override; + void onFailure(const std::string &error) override; + void onAllForNow() override; + void onCacheExhausted() override; + +private: + api::WifiLanMedium::DiscoveredServiceCallback discovery_cb_; + std::shared_ptr server_; +}; +} // namespace avahi +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/avahi_entrygroup_client_glue.h b/internal/platform/implementation/linux/avahi_entrygroup_client_glue.h new file mode 100644 index 00000000..8070deae --- /dev/null +++ b/internal/platform/implementation/linux/avahi_entrygroup_client_glue.h @@ -0,0 +1,94 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__avahi_entrygroup_client_glue_h__proxy__H__ +#define __sdbuscpp__avahi_entrygroup_client_glue_h__proxy__H__ + +#include +#include +#include + +namespace org { +namespace freedesktop { +namespace Avahi { + +class EntryGroup_proxy +{ +public: + static constexpr const char* INTERFACE_NAME = "org.freedesktop.Avahi.EntryGroup"; + +protected: + EntryGroup_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const int32_t& state, const std::string& error){ this->onStateChanged(state, error); }); + } + + ~EntryGroup_proxy() = default; + + virtual void onStateChanged(const int32_t& state, const std::string& error) = 0; + +public: + void Free() + { + proxy_.callMethod("Free").onInterface(INTERFACE_NAME); + } + + void Commit() + { + proxy_.callMethod("Commit").onInterface(INTERFACE_NAME); + } + + void Reset() + { + proxy_.callMethod("Reset").onInterface(INTERFACE_NAME); + } + + int32_t GetState() + { + int32_t result; + proxy_.callMethod("GetState").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + bool IsEmpty() + { + bool result; + proxy_.callMethod("IsEmpty").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + void AddService(const int32_t& interface, const int32_t& protocol, const uint32_t& flags, const std::string& name, const std::string& type, const std::string& domain, const std::string& host, const uint16_t& port, const std::vector>& txt) + { + proxy_.callMethod("AddService").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, type, domain, host, port, txt); + } + + void AddServiceSubtype(const int32_t& interface, const int32_t& protocol, const uint32_t& flags, const std::string& name, const std::string& type, const std::string& domain, const std::string& subtype) + { + proxy_.callMethod("AddServiceSubtype").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, type, domain, subtype); + } + + void UpdateServiceTxt(const int32_t& interface, const int32_t& protocol, const uint32_t& flags, const std::string& name, const std::string& type, const std::string& domain, const std::vector>& txt) + { + proxy_.callMethod("UpdateServiceTxt").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, type, domain, txt); + } + + void AddAddress(const int32_t& interface, const int32_t& protocol, const uint32_t& flags, const std::string& name, const std::string& address) + { + proxy_.callMethod("AddAddress").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, address); + } + + void AddRecord(const int32_t& interface, const int32_t& protocol, const uint32_t& flags, const std::string& name, const uint16_t& clazz, const uint16_t& type, const uint32_t& ttl, const std::vector& rdata) + { + proxy_.callMethod("AddRecord").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, clazz, type, ttl, rdata); + } + +private: + sdbus::IProxy& proxy_; +}; + +}}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/avahi_server_client_glue.h b/internal/platform/implementation/linux/avahi_server_client_glue.h new file mode 100644 index 00000000..6810ac8a --- /dev/null +++ b/internal/platform/implementation/linux/avahi_server_client_glue.h @@ -0,0 +1,399 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__avahi_server_client_glue_h__proxy__H__ +#define __sdbuscpp__avahi_server_client_glue_h__proxy__H__ + +#include +#include +#include + +namespace org { +namespace freedesktop { +namespace Avahi { + +class Server_proxy +{ +public: + static constexpr const char* INTERFACE_NAME = "org.freedesktop.Avahi.Server"; + +protected: + Server_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const int32_t& state, const std::string& error){ this->onStateChanged(state, error); }); + } + + ~Server_proxy() = default; + + virtual void onStateChanged(const int32_t& state, const std::string& error) = 0; + +public: + std::string GetVersionString() + { + std::string result; + proxy_.callMethod("GetVersionString").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + uint32_t GetAPIVersion() + { + uint32_t result; + proxy_.callMethod("GetAPIVersion").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetHostName() + { + std::string result; + proxy_.callMethod("GetHostName").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + void SetHostName(const std::string& name) + { + proxy_.callMethod("SetHostName").onInterface(INTERFACE_NAME).withArguments(name); + } + + std::string GetHostNameFqdn() + { + std::string result; + proxy_.callMethod("GetHostNameFqdn").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetDomainName() + { + std::string result; + proxy_.callMethod("GetDomainName").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + bool IsNSSSupportAvailable() + { + bool result; + proxy_.callMethod("IsNSSSupportAvailable").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + int32_t GetState() + { + int32_t result; + proxy_.callMethod("GetState").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + uint32_t GetLocalServiceCookie() + { + uint32_t result; + proxy_.callMethod("GetLocalServiceCookie").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetAlternativeHostName(const std::string& name) + { + std::string result; + proxy_.callMethod("GetAlternativeHostName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::string GetAlternativeServiceName(const std::string& name) + { + std::string result; + proxy_.callMethod("GetAlternativeServiceName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::string GetNetworkInterfaceNameByIndex(const int32_t& index) + { + std::string result; + proxy_.callMethod("GetNetworkInterfaceNameByIndex").onInterface(INTERFACE_NAME).withArguments(index).storeResultsTo(result); + return result; + } + + int32_t GetNetworkInterfaceIndexByName(const std::string& name) + { + int32_t result; + proxy_.callMethod("GetNetworkInterfaceIndexByName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::tuple ResolveHostName(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags) + { + std::tuple result; + proxy_.callMethod("ResolveHostName").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result); + return result; + } + + std::tuple ResolveAddress(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags) + { + std::tuple result; + proxy_.callMethod("ResolveAddress").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result); + return result; + } + + std::tuple>, uint32_t> ResolveService(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const int32_t& aprotocol, const uint32_t& flags) + { + std::tuple>, uint32_t> result; + proxy_.callMethod("ResolveService").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, type, domain, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath EntryGroupNew() + { + sdbus::ObjectPath result; + proxy_.callMethod("EntryGroupNew").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath DomainBrowserNew(const int32_t& interface, const int32_t& protocol, const std::string& domain, const int32_t& btype, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("DomainBrowserNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, domain, btype, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceTypeBrowserNew(const int32_t& interface, const int32_t& protocol, const std::string& domain, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceTypeBrowserNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, domain, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceBrowserNew(const int32_t& interface, const int32_t& protocol, const std::string& type, const std::string& domain, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceBrowserNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, type, domain, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceResolverNew(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const int32_t& aprotocol, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceResolverNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, type, domain, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath HostNameResolverNew(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("HostNameResolverNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath AddressResolverNew(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("AddressResolverNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath RecordBrowserNew(const int32_t& interface, const int32_t& protocol, const std::string& name, const uint16_t& clazz, const uint16_t& type, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("RecordBrowserNew").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, clazz, type, flags).storeResultsTo(result); + return result; + } + +private: + sdbus::IProxy& proxy_; +}; + +}}} // namespaces + +namespace org { +namespace freedesktop { +namespace Avahi { + +class Server2_proxy +{ +public: + static constexpr const char* INTERFACE_NAME = "org.freedesktop.Avahi.Server2"; + +protected: + Server2_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const int32_t& state, const std::string& error){ this->onStateChanged(state, error); }); + } + + ~Server2_proxy() = default; + + virtual void onStateChanged(const int32_t& state, const std::string& error) = 0; + +public: + std::string GetVersionString() + { + std::string result; + proxy_.callMethod("GetVersionString").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + uint32_t GetAPIVersion() + { + uint32_t result; + proxy_.callMethod("GetAPIVersion").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetHostName() + { + std::string result; + proxy_.callMethod("GetHostName").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + void SetHostName(const std::string& name) + { + proxy_.callMethod("SetHostName").onInterface(INTERFACE_NAME).withArguments(name); + } + + std::string GetHostNameFqdn() + { + std::string result; + proxy_.callMethod("GetHostNameFqdn").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetDomainName() + { + std::string result; + proxy_.callMethod("GetDomainName").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + bool IsNSSSupportAvailable() + { + bool result; + proxy_.callMethod("IsNSSSupportAvailable").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + int32_t GetState() + { + int32_t result; + proxy_.callMethod("GetState").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + uint32_t GetLocalServiceCookie() + { + uint32_t result; + proxy_.callMethod("GetLocalServiceCookie").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + std::string GetAlternativeHostName(const std::string& name) + { + std::string result; + proxy_.callMethod("GetAlternativeHostName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::string GetAlternativeServiceName(const std::string& name) + { + std::string result; + proxy_.callMethod("GetAlternativeServiceName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::string GetNetworkInterfaceNameByIndex(const int32_t& index) + { + std::string result; + proxy_.callMethod("GetNetworkInterfaceNameByIndex").onInterface(INTERFACE_NAME).withArguments(index).storeResultsTo(result); + return result; + } + + int32_t GetNetworkInterfaceIndexByName(const std::string& name) + { + int32_t result; + proxy_.callMethod("GetNetworkInterfaceIndexByName").onInterface(INTERFACE_NAME).withArguments(name).storeResultsTo(result); + return result; + } + + std::tuple ResolveHostName(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags) + { + std::tuple result; + proxy_.callMethod("ResolveHostName").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result); + return result; + } + + std::tuple ResolveAddress(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags) + { + std::tuple result; + proxy_.callMethod("ResolveAddress").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result); + return result; + } + + std::tuple>, uint32_t> ResolveService(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const int32_t& aprotocol, const uint32_t& flags) + { + std::tuple>, uint32_t> result; + proxy_.callMethod("ResolveService").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, type, domain, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath EntryGroupNew() + { + sdbus::ObjectPath result; + proxy_.callMethod("EntryGroupNew").onInterface(INTERFACE_NAME).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath DomainBrowserPrepare(const int32_t& interface, const int32_t& protocol, const std::string& domain, const int32_t& btype, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("DomainBrowserPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, domain, btype, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceTypeBrowserPrepare(const int32_t& interface, const int32_t& protocol, const std::string& domain, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceTypeBrowserPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, domain, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceBrowserPrepare(const int32_t& interface, const int32_t& protocol, const std::string& type, const std::string& domain, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceBrowserPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, type, domain, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath ServiceResolverPrepare(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const int32_t& aprotocol, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("ServiceResolverPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, type, domain, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath HostNameResolverPrepare(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("HostNameResolverPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath AddressResolverPrepare(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("AddressResolverPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result); + return result; + } + + sdbus::ObjectPath RecordBrowserPrepare(const int32_t& interface, const int32_t& protocol, const std::string& name, const uint16_t& clazz, const uint16_t& type, const uint32_t& flags) + { + sdbus::ObjectPath result; + proxy_.callMethod("RecordBrowserPrepare").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, clazz, type, flags).storeResultsTo(result); + return result; + } + +private: + sdbus::IProxy& proxy_; +}; + +}}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/avahi_servicebrowser_client_glue.h b/internal/platform/implementation/linux/avahi_servicebrowser_client_glue.h new file mode 100644 index 00000000..09206c00 --- /dev/null +++ b/internal/platform/implementation/linux/avahi_servicebrowser_client_glue.h @@ -0,0 +1,58 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__avahi_servicebrowser_client_glue_h__proxy__H__ +#define __sdbuscpp__avahi_servicebrowser_client_glue_h__proxy__H__ + +#include +#include +#include + +namespace org { +namespace freedesktop { +namespace Avahi { + +class ServiceBrowser_proxy +{ +public: + static constexpr const char* INTERFACE_NAME = "org.freedesktop.Avahi.ServiceBrowser"; + +protected: + ServiceBrowser_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_.uponSignal("ItemNew").onInterface(INTERFACE_NAME).call([this](const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const uint32_t& flags){ this->onItemNew(interface, protocol, name, type, domain, flags); }); + proxy_.uponSignal("ItemRemove").onInterface(INTERFACE_NAME).call([this](const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const uint32_t& flags){ this->onItemRemove(interface, protocol, name, type, domain, flags); }); + proxy_.uponSignal("Failure").onInterface(INTERFACE_NAME).call([this](const std::string& error){ this->onFailure(error); }); + proxy_.uponSignal("AllForNow").onInterface(INTERFACE_NAME).call([this](){ this->onAllForNow(); }); + proxy_.uponSignal("CacheExhausted").onInterface(INTERFACE_NAME).call([this](){ this->onCacheExhausted(); }); + } + + ~ServiceBrowser_proxy() = default; + + virtual void onItemNew(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const uint32_t& flags) = 0; + virtual void onItemRemove(const int32_t& interface, const int32_t& protocol, const std::string& name, const std::string& type, const std::string& domain, const uint32_t& flags) = 0; + virtual void onFailure(const std::string& error) = 0; + virtual void onAllForNow() = 0; + virtual void onCacheExhausted() = 0; + +public: + void Free() + { + proxy_.callMethod("Free").onInterface(INTERFACE_NAME); + } + + void Start() + { + proxy_.callMethod("Start").onInterface(INTERFACE_NAME); + } + +private: + sdbus::IProxy& proxy_; +}; + +}}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/bluetooth_classic_socket.cc b/internal/platform/implementation/linux/bluetooth_classic_socket.cc index 2ad0acec..68877889 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_socket.cc +++ b/internal/platform/implementation/linux/bluetooth_classic_socket.cc @@ -13,7 +13,7 @@ namespace nearby { namespace linux { -ExceptionOr BluetoothInputStream::Read(std::int64_t size) { +ExceptionOr InputStream::Read(std::int64_t size) { if (!fd_.has_value()) return Exception::kIo; @@ -30,33 +30,17 @@ ExceptionOr BluetoothInputStream::Read(std::int64_t size) { return ExceptionOr(ByteArray(data, size)); } -ExceptionOr BluetoothInputStream::Skip(std::size_t offset) { +Exception InputStream::Close() { if (!fd_.has_value()) - return Exception::kIo; + return Exception{Exception::kIo}; - auto off = lseek(fd_->get(), offset, SEEK_CUR); - if (off != offset) { - auto end = lseek(fd_->get(), 0, SEEK_END); - return off == end ? ExceptionOr((std::size_t)off) : Exception::kIo; - } - return ExceptionOr((std::size_t)(off)); + auto ret = close(fd_->get()) < 0 ? Exception{Exception::kIo} + : Exception{Exception::kSuccess}; + fd_.reset(); + return ret; } -ExceptionOr BluetoothInputStream::ReadExactly(std::size_t size) { - if (!fd_.has_value()) - return Exception::kIo; - - char *data = new char[size]; - ssize_t ret = read(fd_->get(), data, size); - if (ret < 0) { - delete[] data; - return Exception::kIo; - } - - return ExceptionOr(ByteArray(data, size)); -} - -Exception BluetoothOutputStream::Write(const ByteArray &data) { +Exception OutputStream::Write(const ByteArray &data) { if (!fd_.has_value()) return Exception{Exception::kIo}; @@ -71,18 +55,21 @@ Exception BluetoothOutputStream::Write(const ByteArray &data) { return Exception{Exception::kSuccess}; } -Exception BluetoothOutputStream::Flush() { - return Exception{Exception::kSuccess}; -} +Exception OutputStream::Flush() { return Exception{Exception::kSuccess}; } -Exception BluetoothOutputStream::Close() { - return close(fd_->get()) < 0 ? Exception{Exception::kIo} - : Exception{Exception::kSuccess}; +Exception OutputStream::Close() { + if (!fd_.has_value()) + return Exception{Exception::kIo}; + + auto ret = close(fd_->get()) < 0 ? Exception{Exception::kIo} + : Exception{Exception::kSuccess}; + fd_.reset(); + return ret; } Exception BluetoothSocket::Close() { - input_stream_.fd_.reset(); - output_stream_.fd_.reset(); + input_stream_.Close(); + output_stream_.Close(); return Exception{Exception::kSuccess}; } diff --git a/internal/platform/implementation/linux/bluetooth_classic_socket.h b/internal/platform/implementation/linux/bluetooth_classic_socket.h index a64ea74a..fefe55e7 100644 --- a/internal/platform/implementation/linux/bluetooth_classic_socket.h +++ b/internal/platform/implementation/linux/bluetooth_classic_socket.h @@ -7,57 +7,26 @@ #include #include -#include "internal/platform/byte_array.h" #include "internal/platform/exception.h" #include "internal/platform/implementation/bluetooth_classic.h" +#include "internal/platform/implementation/linux/stream.h" namespace nearby { namespace linux { - -class BluetoothInputStream : public InputStream { -public: - BluetoothInputStream(sdbus::UnixFd &fd) : fd_(fd){}; - - ExceptionOr Read(std::int64_t size) override; - ExceptionOr Skip(size_t offset) override; - ExceptionOr ReadExactly(std::size_t size); - - Exception Close() override; - -private: - friend class BluetoothSocket; - - std::optional fd_; -}; - -class BluetoothOutputStream : public OutputStream { -public: - BluetoothOutputStream(sdbus::UnixFd &fd) : fd_(fd){}; - - Exception Write(const ByteArray &data) override; - Exception Flush() override; - Exception Close() override; - -private: - friend class BluetoothSocket; - - std::optional fd_; -}; - class BluetoothSocket : public api::BluetoothSocket { public: BluetoothSocket(api::BluetoothDevice &device, sdbus::UnixFd fd) : device_(device), output_stream_(fd), input_stream_(fd) {} - InputStream &GetInputStream() override { return input_stream_; } - OutputStream &GetOutputStream() override { return output_stream_; } + nearby::InputStream &GetInputStream() override { return input_stream_; } + nearby::OutputStream &GetOutputStream() override { return output_stream_; } Exception Close() override; api::BluetoothDevice *GetRemoteDevice() override { return &device_; }; private: api::BluetoothDevice &device_; - BluetoothOutputStream output_stream_; - BluetoothInputStream input_stream_; + OutputStream output_stream_; + InputStream input_stream_; }; } // namespace linux } // namespace nearby diff --git a/internal/platform/implementation/linux/condition_variable.h b/internal/platform/implementation/linux/condition_variable.h new file mode 100644 index 00000000..b1b545b5 --- /dev/null +++ b/internal/platform/implementation/linux/condition_variable.h @@ -0,0 +1,36 @@ +#ifndef PLATFORM_IMPL_LINUX_CONDITION_VARIABLE_H_ +#define PLATFORM_IMPL_LINUX_CONDITION_VARIABLE_H_ + +#include "absl/synchronization/mutex.h" +#include "internal/platform/implementation/condition_variable.h" +#include "internal/platform/implementation/linux/mutex.h" +#include "internal/platform/implementation/mutex.h" + +namespace nearby { +namespace linux { +class ConditionVariable : public api::ConditionVariable { +public: + explicit ConditionVariable(api::Mutex *mutex) + : mutex_(static_cast(mutex)->GetRegularMutex()) {} + ~ConditionVariable() = default; + + Exception Wait() override { + cond_var_.Wait(mutex_); + return {Exception::kSuccess}; + } + + Exception Wait(absl::Duration timeout) override { + cond_var_.WaitWithTimeout(mutex_, timeout); + return {Exception::kSuccess}; + } + + void Notify() override { cond_var_.SignalAll(); } + +private: + absl::Mutex *mutex_; + absl::CondVar cond_var_; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/credential_storage.h b/internal/platform/implementation/linux/credential_storage.h new file mode 100644 index 00000000..8730dd1b --- /dev/null +++ b/internal/platform/implementation/linux/credential_storage.h @@ -0,0 +1,50 @@ +#ifndef PLATFORM_IMPL_LINUX_CREDENTIAL_STORAGE_H_ +#define PLATFORM_IMPL_LINUX_CREDENTIAL_STORAGE_H_ +#include + +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "internal/platform/implementation/credential_storage.h" + +namespace nearby { +namespace linux { +class CredentialStorage : public api::CredentialStorage { + using LocalCredential = ::nearby::internal::LocalCredential; + using SharedCredential = ::nearby::internal::SharedCredential; + using PublicCredentialType = ::nearby::presence::PublicCredentialType; + using SaveCredentialsResultCallback = + ::nearby::presence::SaveCredentialsResultCallback; + using CredentialSelector = ::nearby::presence::CredentialSelector; + using GetLocalCredentialsResultCallback = + ::nearby::presence::GetLocalCredentialsResultCallback; + using GetPublicCredentialsResultCallback = + ::nearby::presence::GetPublicCredentialsResultCallback; + + CredentialStorage(sdbus::IConnection &connection); + ~CredentialStorage() override = default; + + void SaveCredentials(absl::string_view manager_app_id, + absl::string_view account_name, + const std::vector &Local_credentials, + const std::vector &Shared_credentials, + PublicCredentialType public_credential_type, + SaveCredentialsResultCallback callback) override; + void UpdateLocalCredential(absl::string_view manager_app_id, + absl::string_view account_name, + nearby::internal::LocalCredential credential, + SaveCredentialsResultCallback callback) override; + void + GetPublicCredentials(const CredentialSelector &credential_selector, + PublicCredentialType public_credential_type, + GetPublicCredentialsResultCallback callback) override; + +private: + std::unique_ptr proxy; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/dbus.cc b/internal/platform/implementation/linux/dbus.cc new file mode 100644 index 00000000..b329a8a9 --- /dev/null +++ b/internal/platform/implementation/linux/dbus.cc @@ -0,0 +1,35 @@ +#include +#include + +#include + +#include "internal/platform/implementation/linux/dbus.h" +#include "absl/base/call_once.h" + +namespace nearby { +namespace linux { +static std::unique_ptr global_system_bus_connection = + nullptr; +static std::unique_ptr global_default_bus_connection = + nullptr; +static absl::once_flag bus_connection_init_; + +static void initBusConnections() { + global_system_bus_connection = + sdbus::createSystemBusConnection("/com/github/google/nearby"); + global_default_bus_connection = + sdbus::createDefaultBusConnection("/com/github/google/nearby"); +} + +sdbus::IConnection &getSystemBusConnection() { + absl::call_once(bus_connection_init_, initBusConnections); + assert(global_system_bus_connection != nullptr); + return *global_system_bus_connection; +} +sdbus::IConnection &getDefaultBusConnection() { + absl::call_once(bus_connection_init_, initBusConnections); + assert(global_default_bus_connection != nullptr); + return *global_default_bus_connection; +} +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/dbus.h b/internal/platform/implementation/linux/dbus.h index 53e57212..547cd2b9 100644 --- a/internal/platform/implementation/linux/dbus.h +++ b/internal/platform/implementation/linux/dbus.h @@ -1,6 +1,8 @@ #ifndef PLATFORM_IMPL_LINUX_DBUS_H_ #define PLATFORM_IMPL_LINUX_DBUS_H_ + #include "internal/platform/logging.h" +#include #define DBUS_LOG_METHOD_CALL_ERROR(p, m, e) \ do { \ @@ -26,4 +28,10 @@ << " on object " << (p)->getObjectPath(); \ } while (false) +namespace nearby { +namespace linux { +extern sdbus::IConnection &getSystemBusConnection(); +extern sdbus::IConnection &getDefaultBusConnection(); +} // namespace linux +} // namespace nearby #endif diff --git a/internal/platform/implementation/linux/device_info.cc b/internal/platform/implementation/linux/device_info.cc index f492c56c..ef86ca67 100644 --- a/internal/platform/implementation/linux/device_info.cc +++ b/internal/platform/implementation/linux/device_info.cc @@ -91,10 +91,6 @@ std::optional DeviceInfo::GetProfileUserName() const { std::optional DeviceInfo::GetDownloadPath() const { char *dir = getenv("XDG_DOWNLOAD_DIR"); - if (dir == NULL) { - std::filesystem::path home_path(std::string(getenv("HOME"))); - return home_path / "Desktop"; - } return std::filesystem::path(std::string(dir)); } @@ -103,7 +99,7 @@ std::optional DeviceInfo::GetLocalAppDataPath() const { if (dir == NULL) { return std::filesystem::path("/tmp"); } - return std::filesystem::path(std::string(dir)) / "com.github.google.nearby"; + return std::filesystem::path(std::string(dir)) / "Google Nearby"; } std::optional DeviceInfo::GetTemporaryPath() const { diff --git a/internal/platform/implementation/linux/log_message.cc b/internal/platform/implementation/linux/log_message.cc new file mode 100644 index 00000000..f2825d92 --- /dev/null +++ b/internal/platform/implementation/linux/log_message.cc @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SD_JOURNAL_SUPPRESS_LOCATION true +#include + +#include "absl/base/call_once.h" +#include "internal/platform/implementation/linux/dbus.h" +#include "internal/platform/implementation/linux/log_message.h" + +namespace nearby { +static std::unique_ptr global_log_control_; +static absl::once_flag log_control_init_; + +static void init_log_control() { + global_log_control_ = + std::make_unique(linux::getDefaultBusConnection()); +} + +namespace api { +void LogMessage::SetMinLogSeverity(Severity severity) { + absl::call_once(log_control_init_, init_log_control, nullptr); + assert(global_log_control_ != nullptr); + global_log_control_->LogLevel(severity); +} + +bool LogMessage::ShouldCreateLogMessage(Severity severity) { + absl::call_once(log_control_init_, init_log_control, nullptr); + assert(global_log_control_ != nullptr); + return severity >= global_log_control_->GetLogLevel(); +} + +} // namespace api +namespace linux { + +static inline int ConvertSeverityToSyslog(google::LogSeverity severity) { + switch (severity) { + case google::GLOG_WARNING: + return LOG_WARNING; + case google::GLOG_ERROR: + return LOG_ERR; + case google::GLOG_FATAL: + return LOG_EMERG; + case google::GLOG_INFO: + default: + return LOG_INFO; + } +} + +void LogControl::send(google::LogSeverity severity, const char *full_filename, + const char *base_filename, int line, + const struct ::tm *tm_time, const char *message, + size_t message_len) { + switch (log_target_) { + case kJournal: + sd_journal_send("MESSAGE=%s", message, "PRIORITY=%d", + ConvertSeverityToSyslog(severity), "CODE_FILE=%s", + base_filename, "CODE_LINE=%d", line, NULL); + break; + case kSyslog: { + auto str = LogSink::ToString(severity, base_filename, line, tm_time, + message, message_len); + syslog(ConvertSeverityToSyslog(severity), "%s", str.c_str()); + } + case kConsole: + default: + std::cout << LogSink::ToString(severity, base_filename, line, tm_time, + message, message_len) + << "\n"; + break; + } +} + +static inline google::LogSeverity +ConvertSeverity(api::LogMessage::Severity severity) { + switch (severity) { + case api::LogMessage::Severity::kVerbose: + case api::LogMessage::Severity::kInfo: + return google::GLOG_INFO; + case api::LogMessage::Severity::kWarning: + return google::GLOG_WARNING; + case api::LogMessage::Severity::kError: + return google::GLOG_ERROR; + case api::LogMessage::Severity::kFatal: + return google::GLOG_FATAL; + } +} + +// TODO: Set a LogSink depending on the target set by LogControl +LogMessage::LogMessage(const char *file, int line, Severity severity) + : log_streamer_(file, line, ConvertSeverity(severity), + global_log_control_.get(), false) {} + +void LogMessage::Print(const char *format, ...) { + va_list ap; + va_start(ap, format); + char *buf = nullptr; + vasprintf(&buf, format, ap); + va_end(ap); + log_streamer_.stream() << std::string(buf); +} + +std::ostream &LogMessage::Stream() { return log_streamer_.stream(); } + +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/log_message.h b/internal/platform/implementation/linux/log_message.h new file mode 100644 index 00000000..56093a64 --- /dev/null +++ b/internal/platform/implementation/linux/log_message.h @@ -0,0 +1,118 @@ +#ifndef PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ +#define PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ + +#include "absl/synchronization/mutex.h" +#include "glog/logging.h" +#include "internal/platform/implementation/linux/org_freedesktop_logcontrol_server_glue.h" +#include "internal/platform/implementation/log_message.h" +#include +#include + +namespace nearby { +namespace linux { + +// See documentation in +// cpp/platform/api/log_message.h +class LogMessage : public api::LogMessage { +public: + LogMessage(const char *file, int line, Severity severity); + ~LogMessage() override; + + void Print(const char *format, ...) override; + + std::ostream &Stream() override; + +private: + google::LogMessage log_streamer_; + static api::LogMessage::Severity min_log_severity_; +}; + +class LogControl + : public sdbus::AdaptorInterfaces, + public google::LogSink { +public: + LogControl(sdbus::IConnection &system_bus) + : AdaptorInterfaces(system_bus, "/com/github/google/nearby"), + severity_(api::LogMessage::LogMessage::Severity::kVerbose) { + registerAdaptor(); + } + ~LogControl() { unregisterAdaptor(); } + + void LogLevel(const LogMessage::Severity &severity) { severity_ = severity; } + + LogMessage::Severity GetLogLevel() { return severity_; } + +protected: + std::string LogLevel() override { + switch (severity_) { + case api::LogMessage::Severity::kVerbose: + return "debug"; + break; + case api::LogMessage::Severity::kInfo: + return "info"; + break; + case api::LogMessage::Severity::kWarning: + return "warning"; + break; + case api::LogMessage::Severity::kError: + return "err"; + case api::LogMessage::Severity::kFatal: + return "emerg"; + } + } + + void LogLevel(const std::string &value) override { + if (value == "debug") + severity_ = api::LogMessage::Severity::kVerbose; + else if (value == "info") + severity_ = api::LogMessage::Severity::kInfo; + else if (value == "warning") + severity_ = api::LogMessage::Severity::kWarning; + else if (value == "err") + severity_ = api::LogMessage::Severity::kError; + else if (value == "crit" || value == "alert" || value == "emerg") + severity_ = api::LogMessage::Severity::kFatal; + } + + enum LogTarget { kConsole, kKernel, kJournal, kSyslog }; + + std::string LogTarget() override { + switch (log_target_) { + case kConsole: + return "console"; + case kKernel: + return "kmsg"; + case kJournal: + return "journal"; + case kSyslog: + return "syslog"; + } + } + + void LogTarget(const std::string &value) override { + if (value == "console") + log_target_ = kConsole; + else if (value == "kmsg") + log_target_ = kKernel; + else if (value == "journal") + log_target_ = kJournal; + else if (value == "syslog") + log_target_ = kSyslog; + } + + std::string SyslogIdentifier() override { + return "com.github.com.google.nearby"; + } + + void send(google::LogSeverity severity, const char *full_filename, + const char *base_filename, int line, const struct ::tm *tm_time, + const char *message, size_t message_len) override; + +private: + std::atomic severity_; + std::atomic log_target_; +}; +} // namespace linux +} // namespace nearby + +#endif // PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ diff --git a/internal/platform/implementation/linux/mutex.h b/internal/platform/implementation/linux/mutex.h new file mode 100644 index 00000000..7007aee4 --- /dev/null +++ b/internal/platform/implementation/linux/mutex.h @@ -0,0 +1,56 @@ +#ifndef PLATFORM_IMPL_LINUX_MUTEX_H_ +#define PLATFORM_IMPL_LINUX_MUTEX_H_ + +#include +#include + +#include "absl/synchronization/mutex.h" +#include "internal/platform/implementation/mutex.h" + +namespace nearby { +namespace linux { +class ABSL_LOCKABLE Mutex : public api::Mutex { +public: + explicit Mutex(Mode mode) : mode_(mode) { + if (mode == Mode::kRecursive) + mutex_.emplace(); + else + mutex_.emplace(); + } + + ~Mutex() override = default; + Mutex(Mutex &&) = delete; + Mutex &operator=(Mutex &&) = delete; + Mutex(const Mutex &) = delete; + Mutex &operator=(const Mutex &) = delete; + + void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() override { + if (auto mutex = std::get_if(&mutex_); mutex != nullptr) { + if (mode_ == Mode::kRegularNoCheck) { + mutex->ForgetDeadlockInfo(); + } + mutex->Lock(); + } else { + std::get_if(&mutex_)->lock(); + } + } + + void Unlock() ABSL_UNLOCK_FUNCTION() override { + if (auto mutex = std::get_if(&mutex_); mutex != nullptr) { + mutex->Unlock(); + } else { + std::get_if(&mutex_)->unlock(); + } + } + + absl::Mutex *GetRegularMutex() { + return std::get_if(&mutex_); + } + +private: + std::variant mutex_; + Mode mode_; +}; +} // namespace linux +} // namespace nearby +#endif diff --git a/internal/platform/implementation/linux/org.freedesktop.Avahi.EntryGroup.xml b/internal/platform/implementation/linux/org.freedesktop.Avahi.EntryGroup.xml new file mode 100644 index 00000000..434cc0f8 --- /dev/null +++ b/internal/platform/implementation/linux/org.freedesktop.Avahi.EntryGroup.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/org.freedesktop.Avahi.Server.xml b/internal/platform/implementation/linux/org.freedesktop.Avahi.Server.xml new file mode 100644 index 00000000..5485a972 --- /dev/null +++ b/internal/platform/implementation/linux/org.freedesktop.Avahi.Server.xml @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceBrowser.xml b/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceBrowser.xml new file mode 100644 index 00000000..4e2e240f --- /dev/null +++ b/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceBrowser.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceResolver.xml b/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceResolver.xml new file mode 100644 index 00000000..898287ce --- /dev/null +++ b/internal/platform/implementation/linux/org.freedesktop.Avahi.ServiceResolver.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/org.freedesktop.LogControl1.xml b/internal/platform/implementation/linux/org.freedesktop.LogControl1.xml new file mode 100644 index 00000000..2c32116f --- /dev/null +++ b/internal/platform/implementation/linux/org.freedesktop.LogControl1.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/internal/platform/implementation/linux/org_freedesktop_logcontrol_server_glue.h b/internal/platform/implementation/linux/org_freedesktop_logcontrol_server_glue.h new file mode 100644 index 00000000..f74e3d1a --- /dev/null +++ b/internal/platform/implementation/linux/org_freedesktop_logcontrol_server_glue.h @@ -0,0 +1,45 @@ + +/* + * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! + */ + +#ifndef __sdbuscpp__org_freedesktop_logcontrol_server_glue_h__adaptor__H__ +#define __sdbuscpp__org_freedesktop_logcontrol_server_glue_h__adaptor__H__ + +#include +#include +#include + +namespace org { +namespace freedesktop { + +class LogControl1_adaptor +{ +public: + static constexpr const char* INTERFACE_NAME = "org.freedesktop.LogControl1"; + +protected: + LogControl1_adaptor(sdbus::IObject& object) + : object_(object) + { + object_.registerProperty("LogLevel").onInterface(INTERFACE_NAME).withGetter([this](){ return this->LogLevel(); }).withSetter([this](const std::string& value){ this->LogLevel(value); }).withUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL).markAsPrivileged(); + object_.registerProperty("LogTarget").onInterface(INTERFACE_NAME).withGetter([this](){ return this->LogTarget(); }).withSetter([this](const std::string& value){ this->LogTarget(value); }).withUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL).markAsPrivileged(); + object_.registerProperty("SyslogIdentifier").onInterface(INTERFACE_NAME).withGetter([this](){ return this->SyslogIdentifier(); }).withUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL); + } + + ~LogControl1_adaptor() = default; + +private: + virtual std::string LogLevel() = 0; + virtual void LogLevel(const std::string& value) = 0; + virtual std::string LogTarget() = 0; + virtual void LogTarget(const std::string& value) = 0; + virtual std::string SyslogIdentifier() = 0; + +private: + sdbus::IObject& object_; +}; + +}} // namespaces + +#endif diff --git a/internal/platform/implementation/linux/platform.cc b/internal/platform/implementation/linux/platform.cc index 11b37bcf..2bfb771d 100644 --- a/internal/platform/implementation/linux/platform.cc +++ b/internal/platform/implementation/linux/platform.cc @@ -1,12 +1,74 @@ -#include "internal/platform/implementation/platform.h" - #include +#include #include +#include "internal/platform/implementation/linux/condition_variable.h" +#include "internal/platform/implementation/linux/mutex.h" +#include "internal/platform/implementation/platform.h" +#include "internal/platform/implementation/atomic_boolean.h" +#include "internal/platform/implementation/atomic_reference.h" +#include "internal/platform/implementation/count_down_latch.h" +#include "internal/platform/implementation/linux/atomic_boolean.h" +#include "internal/platform/implementation/linux/atomic_uint32.h" +#include "internal/platform/implementation/shared/count_down_latch.h" +#include "log_message.h" + namespace nearby { namespace api { -namespace { - std::string ImplementationPlatform::GetCustomSavePath() +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 GetCurrentOS() { return OSName::kWindows; } + +std::unique_ptr CreateAtomicBoolean(bool initial_value) { + return std::make_unique(initial_value); +} + +std::unique_ptr 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::CreateLogMessage( + const char *file, int line, LogMessage::Severity severity + ) { + return std::make_unique(file, line, severity); +} + + + } // namespace api } // namespace nearby diff --git a/internal/platform/implementation/linux/stream.h b/internal/platform/implementation/linux/stream.h new file mode 100644 index 00000000..e761442f --- /dev/null +++ b/internal/platform/implementation/linux/stream.h @@ -0,0 +1,40 @@ +#ifndef PLATFORM_IMPL_LINUX_STREAM_H_ +#define PLATFORM_IMPL_LINUX_STREAM_H_ + +#include + +#include + +#include "internal/platform/input_stream.h" +#include "internal/platform/output_stream.h" + +namespace nearby { +namespace linux { +class InputStream : public nearby::InputStream { +public: + InputStream(sdbus::UnixFd &fd) : fd_(fd){}; + + ExceptionOr Read(std::int64_t size) override; + + Exception Close() override; + +private: + std::optional fd_; +}; + +class OutputStream : public nearby::OutputStream { +public: + OutputStream(sdbus::UnixFd &fd) : fd_(fd){}; + + Exception Write(const ByteArray &data) override; + Exception Flush() override; + Exception Close() override; + +private: + std::optional fd_; +}; + +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/wifi_lan.cc b/internal/platform/implementation/linux/wifi_lan.cc new file mode 100644 index 00000000..2d5d3f4b --- /dev/null +++ b/internal/platform/implementation/linux/wifi_lan.cc @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "absl/strings/substitute.h" +#include "internal/platform/implementation/linux/avahi.h" +#include "internal/platform/implementation/linux/dbus.h" +#include "internal/platform/implementation/linux/wifi_lan.h" +#include "internal/platform/implementation/linux/wifi_lan_server_socket.h" +#include "internal/platform/implementation/linux/wifi_lan_socket.h" +#include "internal/platform/implementation/wifi_lan.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace linux { +WifiLanMedium::WifiLanMedium(sdbus::IConnection &system_bus, + NetworkManager &network_manager) + : system_bus_(system_bus), network_manager_(network_manager), + avahi_(std::make_shared(system_bus)), + entry_group_(nullptr) {} + +WifiLanMedium::~WifiLanMedium() { + if (entry_group_ != nullptr) { + entry_group_->Free(); + } +} + +bool WifiLanMedium::IsNetworkConnected() const { + auto state = network_manager_.getState(); + return state >= 50; // NM_STATE_CONNECTED_LOCAL +} + +bool WifiLanMedium::StartAdvertising(const NsdServiceInfo &nsd_service_info) { + if (entry_group_ == nullptr) { + try { + auto object_path = avahi_->EntryGroupNew(); + entry_group_ = + std::make_unique(system_bus_, object_path); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(avahi_, "EntryGroupNew", e); + NEARBY_LOGS(ERROR) << __func__ << ": Could not create a new entry group."; + return false; + } + } + + if (advertising_) { + NEARBY_LOGS(ERROR) << __func__ + << ": Cannot advertise while we are already advertising"; + return false; + } + + auto txt_records_map = nsd_service_info.GetTxtRecords(); + std::vector> txt_records(txt_records_map.size()); + std::size_t i = 0; + + for (auto [key, value] : nsd_service_info.GetTxtRecords()) { + std::string entry = absl::Substitute("$0=$1", key, value); + txt_records[i++] = std::vector(entry.begin(), entry.end()); + } + + try { + entry_group_->AddService(-1, // AVAHI_IF_UNSPEC + -1, // AVAHI_PROTO_UNSPED + 0, nsd_service_info.GetServiceName(), + nsd_service_info.GetServiceType(), std::string(), + nsd_service_info.GetIPAddress(), + nsd_service_info.GetPort(), txt_records); + entry_group_->Commit(); + } catch (const sdbus::Error &e) { + NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName() + << "' with message '" << e.getMessage() + << "' while adding service"; + } + + advertising_ = true; + return true; +} + +bool WifiLanMedium::StopAdvertising(const NsdServiceInfo &nsd_service_info) { + if (!advertising_) { + NEARBY_LOGS(ERROR) << __func__ << ": Advertising is already stopped."; + return false; + } + if (entry_group_ == nullptr) { + NEARBY_LOGS(ERROR) << __func__ << ": No entry group registered."; + return false; + } + + try { + if (entry_group_->IsEmpty()) { + NEARBY_LOGS(ERROR) + << __func__ << ": Cannot stop advertising on an empty entry group."; + return false; + } + entry_group_->Reset(); + entry_group_->Commit(); + } catch (const sdbus::Error &e) { + NEARBY_LOGS(ERROR) << __func__ << ": Got error '" << e.getName() + << "' with message '" << e.getMessage() + << "' while removing service"; + } + + advertising_ = false; + return true; +} + +bool WifiLanMedium::StartDiscovery( + const std::string &service_type, + api::WifiLanMedium::DiscoveredServiceCallback callback) { + if (service_browsers_.count(service_type) != 0) { + auto &object = service_browsers_[service_type]; + NEARBY_LOGS(ERROR) << __func__ << ": A service browser for service type " + << service_type << " already exists at " + << object->getObjectPath(); + return false; + } + + try { + sdbus::ObjectPath browser_object_path = + avahi_->ServiceBrowserPrepare(-1, // AVAHI_IF_UNSPEC + -1, // AVAHI_PROTO_UNSPED + service_type, std::string(), 0); + NEARBY_LOGS(VERBOSE) + << __func__ + << ": Created a new org.freedesktop.Avahi.ServiceBrowser object at " + << browser_object_path; + service_browsers_.emplace(service_type, system_bus_, browser_object_path, + std::move(callback)); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(avahi_, "ServiceBrowserPrepare", e); + } + + auto &browser = service_browsers_[service_type]; + try { + NEARBY_LOGS(VERBOSE) << __func__ << ": Starting service discovery for " + << browser->getObjectPath(); + browser->Start(); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(browser, "Start", e); + } + + return true; +} + +bool WifiLanMedium::StopDiscovery(const std::string &service_type) { + if (service_browsers_.count(service_type) == 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Service type " << service_type + << " has not been registered for discovery"; + return false; + } + + auto &browser = service_browsers_[service_type]; + try { + browser->Free(); + } catch (const sdbus::Error &e) { + DBUS_LOG_METHOD_CALL_ERROR(browser, "Free", e); + } + + service_browsers_.erase(service_type); + + return true; +} + +std::unique_ptr +WifiLanMedium::ConnectToService(const std::string &ip_address, int port, + CancellationFlag *cancellation_flag) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return nullptr; + } + + NEARBY_LOGS(VERBOSE) << __func__ << ": Connecting to " << ip_address << ":" + << port; + struct sockaddr_in addr; + addr.sin_addr.s_addr = inet_addr(ip_address.c_str()); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + auto ret = + connect(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error connecting to socket: " + << std::strerror(errno); + return nullptr; + } + + sdbus::UnixFd fd(sock); + return std::make_unique(std::move(fd)); +} + +std::unique_ptr ListenForService(int port = 0) { + auto sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error opening socket: " << std::strerror(errno); + return nullptr; + } + + NEARBY_LOGS(VERBOSE) << __func__ << "Listening for services "; + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + auto ret = + bind(sock, reinterpret_cast(&addr), sizeof(addr)); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error binding to socket: " << std::strerror(errno); + return nullptr; + } + + ret = listen(sock, 0); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error listening on socket: " + << std::strerror(errno); + return nullptr; + } + + return std::make_unique(sdbus::UnixFd(sock)); +} + +absl::optional> + GetDynamicPortRange() { + return absl::nullopt; +} + +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/wifi_lan.h b/internal/platform/implementation/linux/wifi_lan.h new file mode 100644 index 00000000..8059512e --- /dev/null +++ b/internal/platform/implementation/linux/wifi_lan.h @@ -0,0 +1,58 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_H_ +#define PLATFORM_IMPL_LINUX_WIFI_LAN_H_ +#include +#include + +#include "absl/container/flat_hash_map.h" +#include "internal/platform/implementation/linux/avahi.h" +#include "internal/platform/implementation/linux/wifi_medium.h" +#include "internal/platform/implementation/wifi_lan.h" +#include "internal/platform/nsd_service_info.h" + +namespace nearby { +namespace linux { +class WifiLanMedium : public api::WifiLanMedium { +public: + WifiLanMedium(sdbus::IConnection &system_bus, + NetworkManager &network_manager); + ~WifiLanMedium() override; + + bool IsNetworkConnected() const override; + bool StartAdvertising(const NsdServiceInfo &nsd_service_info) override; + bool StopAdvertising(const NsdServiceInfo &nsd_service_info) override; + bool StartDiscovery(const std::string &service_type, + DiscoveredServiceCallback callback) override; + bool StopDiscovery(const std::string &service_type) override; + std::unique_ptr + ConnectToService(const NsdServiceInfo &remote_service_info, + CancellationFlag *cancellation_flag) override { + return ConnectToService(remote_service_info.GetIPAddress(), + remote_service_info.GetPort(), cancellation_flag); + }; + std::unique_ptr + ConnectToService(const std::string &ip_address, int port, + CancellationFlag *cancellation_flag) override; + std::unique_ptr + ListenForService(int port = 0) override; + absl::optional> + GetDynamicPortRange() override; + +private: + DiscoveredServiceCallback discovery_cb_; + + sdbus::IConnection &system_bus_; + + NetworkManager &network_manager_; + + std::shared_ptr avahi_; + std::unique_ptr entry_group_; + + absl::flat_hash_map> + service_browsers_; + + bool advertising_; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/wifi_lan_server_socket.cc b/internal/platform/implementation/linux/wifi_lan_server_socket.cc new file mode 100644 index 00000000..71927deb --- /dev/null +++ b/internal/platform/implementation/linux/wifi_lan_server_socket.cc @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "internal/platform/implementation/linux/wifi_lan_server_socket.h" +#include "internal/platform/exception.h" +#include "internal/platform/implementation/linux/wifi_lan_socket.h" +#include "internal/platform/logging.h" + +namespace nearby { +namespace linux { +std::string WifiLanServerSocket::GetIPAddress() const { + struct ifaddrs *addrs = nullptr; + getifaddrs(&addrs); + + for (auto ifaddr = addrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) { + if (ifaddr->ifa_addr == nullptr) { + continue; + } + if (ifaddr->ifa_addr->sa_family == AF_INET) { + auto addr = + &(reinterpret_cast(ifaddr->ifa_addr))->sin_addr; + char buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN); + + return std::string(buf); + } + } + + return std::string(); +} + +int WifiLanServerSocket::GetPort() const { + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + auto ret = + getsockname(fd_.get(), reinterpret_cast(&sin), &len); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error getting information for socket " + << fd_.get() << ": " << std::strerror(errno); + return 0; + } + + return ntohs(sin.sin_port); +} + +std::unique_ptr WifiLanServerSocket::Accept() { + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + auto conn = + accept(fd_.get(), reinterpret_cast(&addr), &len); + if (conn < 0) { + NEARBY_LOGS(ERROR) << __func__ + << ": Error accepting incoming connections on socket " + << fd_.get() << ": " << std::strerror(errno); + return nullptr; + } + + return std::make_unique(sdbus::UnixFd(conn)); +} + +Exception WifiLanServerSocket::Close() { + int fd = fd_.release(); + auto ret = close(fd); + if (ret < 0) { + NEARBY_LOGS(ERROR) << __func__ << ": Error closing socket " << fd << ": " + << std::strerror(errno); + return {Exception::kFailed}; + } + + return {Exception::kSuccess}; +} +} // namespace linux +} // namespace nearby diff --git a/internal/platform/implementation/linux/wifi_lan_server_socket.h b/internal/platform/implementation/linux/wifi_lan_server_socket.h new file mode 100644 index 00000000..5bed26ce --- /dev/null +++ b/internal/platform/implementation/linux/wifi_lan_server_socket.h @@ -0,0 +1,33 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_SERVER_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_WIFI_LAN_SERVER_SOCKET_H_ + +#include + +#include + +#include "internal/platform/exception.h" +#include "internal/platform/implementation/wifi_lan.h" + +namespace nearby { +namespace linux { +class WifiLanServerSocket : public api::WifiLanServerSocket { +public: + WifiLanServerSocket(int socket) { + fd_ = sdbus::UnixFd(socket); + } + + ~WifiLanServerSocket() override = default; + + std::string GetIPAddress() const override; + + int GetPort() const override; + + std::unique_ptr Accept() override; + + Exception Close() override; + + sdbus::UnixFd fd_; +}; +} // namespace linux +} // namespace nearby +#endif diff --git a/internal/platform/implementation/linux/wifi_lan_socket.h b/internal/platform/implementation/linux/wifi_lan_socket.h new file mode 100644 index 00000000..198c97da --- /dev/null +++ b/internal/platform/implementation/linux/wifi_lan_socket.h @@ -0,0 +1,42 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_ + +#include + +#include + +#include "internal/platform/implementation/linux/stream.h" +#include "internal/platform/implementation/wifi_lan.h" +#include "internal/platform/input_stream.h" +#include "internal/platform/output_stream.h" + +namespace nearby { +namespace linux { +class WifiLanSocket : public api::WifiLanSocket { +public: + WifiLanSocket(sdbus::UnixFd fd) + : fd_(fd), output_stream_(fd), input_stream_(fd) {} + ~WifiLanSocket() = default; + + nearby::InputStream &GetInputStream() override { + return input_stream_; + }; + nearby::OutputStream &GetOutputStream() override { + return output_stream_; + }; + Exception Close() override { + input_stream_.Close(); + output_stream_.Close(); + + return Exception{Exception::kSuccess}; + }; + +private: + sdbus::UnixFd fd_; + OutputStream output_stream_; + InputStream input_stream_; +}; +} // namespace linux +} // namespace nearby + +#endif diff --git a/internal/platform/implementation/linux/wifi_medium.h b/internal/platform/implementation/linux/wifi_medium.h index 9d432012..97c1555e 100644 --- a/internal/platform/implementation/linux/wifi_medium.h +++ b/internal/platform/implementation/linux/wifi_medium.h @@ -1,6 +1,7 @@ #ifndef PLATFORM_IMPL_LINUX_WIFI_MEDIUM_H_ #define PLATFORM_IMPL_LINUX_WIFI_MEDIUM_H_ +#include #include #include #include @@ -29,11 +30,16 @@ public: } ~NetworkManager() { unregisterProxy(); } + std::uint32_t getState() const { return state_; } + protected: void onCheckPermissions() override {} - void onStateChanged(const uint32_t &state) override {} + void onStateChanged(const uint32_t &state) override { state_ = state; } void onDeviceAdded(const sdbus::ObjectPath &device_path) override {} void onDeviceRemoved(const sdbus::ObjectPath &device_path) override {} + +private: + std::atomic_uint32_t state_; }; class NetworkManagerIP4Config diff --git a/internal/platform/implementation/linux/wifi_socket.h b/internal/platform/implementation/linux/wifi_socket.h new file mode 100644 index 00000000..0d70b4c7 --- /dev/null +++ b/internal/platform/implementation/linux/wifi_socket.h @@ -0,0 +1,16 @@ +#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_ +#define PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_ + +namespace nearby { + namespace api { + class WifiLanSocket { + public: + ~WifiLanSocket() = default; + + private: + int fd; + }; + } +} + +#endif